Lines Matching +full:static +full:- +full:trace +full:- +full:id

1 // SPDX-License-Identifier: GPL-2.0+
23 static void ioam6_ns_release(struct ioam6_namespace *ns) in ioam6_ns_release()
28 static void ioam6_sc_release(struct ioam6_schema *sc) in ioam6_sc_release()
33 static void ioam6_free_ns(void *ptr, void *arg) in ioam6_free_ns()
41 static void ioam6_free_sc(void *ptr, void *arg) in ioam6_free_sc()
49 static int ioam6_ns_cmpfn(struct rhashtable_compare_arg *arg, const void *obj) in ioam6_ns_cmpfn()
53 return (ns->id != *(__be16 *)arg->key); in ioam6_ns_cmpfn()
56 static int ioam6_sc_cmpfn(struct rhashtable_compare_arg *arg, const void *obj) in ioam6_sc_cmpfn()
60 return (sc->id != *(u32 *)arg->key); in ioam6_sc_cmpfn()
63 static const struct rhashtable_params rht_ns_params = {
65 .key_offset = offsetof(struct ioam6_namespace, id),
71 static const struct rhashtable_params rht_sc_params = {
73 .key_offset = offsetof(struct ioam6_schema, id),
79 static struct genl_family ioam6_genl_family;
81 static const struct nla_policy ioam6_genl_policy_addns[] = {
87 static const struct nla_policy ioam6_genl_policy_delns[] = {
91 static const struct nla_policy ioam6_genl_policy_addsc[] = {
97 static const struct nla_policy ioam6_genl_policy_delsc[] = {
101 static const struct nla_policy ioam6_genl_policy_ns_sc[] = {
107 static int ioam6_genl_addns(struct sk_buff *skb, struct genl_info *info) in ioam6_genl_addns()
113 __be16 id; in ioam6_genl_addns() local
116 if (!info->attrs[IOAM6_ATTR_NS_ID]) in ioam6_genl_addns()
117 return -EINVAL; in ioam6_genl_addns()
119 id = cpu_to_be16(nla_get_u16(info->attrs[IOAM6_ATTR_NS_ID])); in ioam6_genl_addns()
122 mutex_lock(&nsdata->lock); in ioam6_genl_addns()
124 ns = rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params); in ioam6_genl_addns()
126 err = -EEXIST; in ioam6_genl_addns()
132 err = -ENOMEM; in ioam6_genl_addns()
136 ns->id = id; in ioam6_genl_addns()
138 data32 = nla_get_u32_default(info->attrs[IOAM6_ATTR_NS_DATA], in ioam6_genl_addns()
141 data64 = nla_get_u64_default(info->attrs[IOAM6_ATTR_NS_DATA_WIDE], in ioam6_genl_addns()
144 ns->data = cpu_to_be32(data32); in ioam6_genl_addns()
145 ns->data_wide = cpu_to_be64(data64); in ioam6_genl_addns()
147 err = rhashtable_lookup_insert_fast(&nsdata->namespaces, &ns->head, in ioam6_genl_addns()
153 mutex_unlock(&nsdata->lock); in ioam6_genl_addns()
157 static int ioam6_genl_delns(struct sk_buff *skb, struct genl_info *info) in ioam6_genl_delns()
162 __be16 id; in ioam6_genl_delns() local
165 if (!info->attrs[IOAM6_ATTR_NS_ID]) in ioam6_genl_delns()
166 return -EINVAL; in ioam6_genl_delns()
168 id = cpu_to_be16(nla_get_u16(info->attrs[IOAM6_ATTR_NS_ID])); in ioam6_genl_delns()
171 mutex_lock(&nsdata->lock); in ioam6_genl_delns()
173 ns = rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params); in ioam6_genl_delns()
175 err = -ENOENT; in ioam6_genl_delns()
179 sc = rcu_dereference_protected(ns->schema, in ioam6_genl_delns()
180 lockdep_is_held(&nsdata->lock)); in ioam6_genl_delns()
182 err = rhashtable_remove_fast(&nsdata->namespaces, &ns->head, in ioam6_genl_delns()
188 rcu_assign_pointer(sc->ns, NULL); in ioam6_genl_delns()
193 mutex_unlock(&nsdata->lock); in ioam6_genl_delns()
197 static int __ioam6_genl_dumpns_element(struct ioam6_namespace *ns, in __ioam6_genl_dumpns_element()
211 return -ENOMEM; in __ioam6_genl_dumpns_element()
213 data32 = be32_to_cpu(ns->data); in __ioam6_genl_dumpns_element()
214 data64 = be64_to_cpu(ns->data_wide); in __ioam6_genl_dumpns_element()
216 if (nla_put_u16(skb, IOAM6_ATTR_NS_ID, be16_to_cpu(ns->id)) || in __ioam6_genl_dumpns_element()
226 sc = rcu_dereference(ns->schema); in __ioam6_genl_dumpns_element()
227 if (sc && nla_put_u32(skb, IOAM6_ATTR_SC_ID, sc->id)) { in __ioam6_genl_dumpns_element()
239 return -EMSGSIZE; in __ioam6_genl_dumpns_element()
242 static int ioam6_genl_dumpns_start(struct netlink_callback *cb) in ioam6_genl_dumpns_start()
244 struct ioam6_pernet_data *nsdata = ioam6_pernet(sock_net(cb->skb->sk)); in ioam6_genl_dumpns_start()
245 struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0]; in ioam6_genl_dumpns_start()
250 return -ENOMEM; in ioam6_genl_dumpns_start()
252 cb->args[0] = (long)iter; in ioam6_genl_dumpns_start()
255 rhashtable_walk_enter(&nsdata->namespaces, iter); in ioam6_genl_dumpns_start()
260 static int ioam6_genl_dumpns_done(struct netlink_callback *cb) in ioam6_genl_dumpns_done()
262 struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0]; in ioam6_genl_dumpns_done()
270 static int ioam6_genl_dumpns(struct sk_buff *skb, struct netlink_callback *cb) in ioam6_genl_dumpns()
276 iter = (struct rhashtable_iter *)cb->args[0]; in ioam6_genl_dumpns()
283 if (PTR_ERR(ns) == -EAGAIN) in ioam6_genl_dumpns()
292 NETLINK_CB(cb->skb).portid, in ioam6_genl_dumpns()
293 cb->nlh->nlmsg_seq, in ioam6_genl_dumpns()
301 err = skb->len; in ioam6_genl_dumpns()
308 static int ioam6_genl_addsc(struct sk_buff *skb, struct genl_info *info) in ioam6_genl_addsc()
313 u32 id; in ioam6_genl_addsc() local
315 if (!info->attrs[IOAM6_ATTR_SC_ID] || !info->attrs[IOAM6_ATTR_SC_DATA]) in ioam6_genl_addsc()
316 return -EINVAL; in ioam6_genl_addsc()
318 id = nla_get_u32(info->attrs[IOAM6_ATTR_SC_ID]); in ioam6_genl_addsc()
321 mutex_lock(&nsdata->lock); in ioam6_genl_addsc()
323 sc = rhashtable_lookup_fast(&nsdata->schemas, &id, rht_sc_params); in ioam6_genl_addsc()
325 err = -EEXIST; in ioam6_genl_addsc()
329 len = nla_len(info->attrs[IOAM6_ATTR_SC_DATA]); in ioam6_genl_addsc()
334 err = -ENOMEM; in ioam6_genl_addsc()
338 sc->id = id; in ioam6_genl_addsc()
339 sc->len = len_aligned; in ioam6_genl_addsc()
340 sc->hdr = cpu_to_be32(sc->id | ((u8)(sc->len / 4) << 24)); in ioam6_genl_addsc()
341 nla_memcpy(sc->data, info->attrs[IOAM6_ATTR_SC_DATA], len); in ioam6_genl_addsc()
343 err = rhashtable_lookup_insert_fast(&nsdata->schemas, &sc->head, in ioam6_genl_addsc()
349 mutex_unlock(&nsdata->lock); in ioam6_genl_addsc()
356 static int ioam6_genl_delsc(struct sk_buff *skb, struct genl_info *info) in ioam6_genl_delsc()
362 u32 id; in ioam6_genl_delsc() local
364 if (!info->attrs[IOAM6_ATTR_SC_ID]) in ioam6_genl_delsc()
365 return -EINVAL; in ioam6_genl_delsc()
367 id = nla_get_u32(info->attrs[IOAM6_ATTR_SC_ID]); in ioam6_genl_delsc()
370 mutex_lock(&nsdata->lock); in ioam6_genl_delsc()
372 sc = rhashtable_lookup_fast(&nsdata->schemas, &id, rht_sc_params); in ioam6_genl_delsc()
374 err = -ENOENT; in ioam6_genl_delsc()
378 ns = rcu_dereference_protected(sc->ns, lockdep_is_held(&nsdata->lock)); in ioam6_genl_delsc()
380 err = rhashtable_remove_fast(&nsdata->schemas, &sc->head, in ioam6_genl_delsc()
386 rcu_assign_pointer(ns->schema, NULL); in ioam6_genl_delsc()
391 mutex_unlock(&nsdata->lock); in ioam6_genl_delsc()
395 static int __ioam6_genl_dumpsc_element(struct ioam6_schema *sc, in __ioam6_genl_dumpsc_element()
404 return -ENOMEM; in __ioam6_genl_dumpsc_element()
406 if (nla_put_u32(skb, IOAM6_ATTR_SC_ID, sc->id) || in __ioam6_genl_dumpsc_element()
407 nla_put(skb, IOAM6_ATTR_SC_DATA, sc->len, sc->data)) in __ioam6_genl_dumpsc_element()
412 ns = rcu_dereference(sc->ns); in __ioam6_genl_dumpsc_element()
413 if (ns && nla_put_u16(skb, IOAM6_ATTR_NS_ID, be16_to_cpu(ns->id))) { in __ioam6_genl_dumpsc_element()
425 return -EMSGSIZE; in __ioam6_genl_dumpsc_element()
428 static int ioam6_genl_dumpsc_start(struct netlink_callback *cb) in ioam6_genl_dumpsc_start()
430 struct ioam6_pernet_data *nsdata = ioam6_pernet(sock_net(cb->skb->sk)); in ioam6_genl_dumpsc_start()
431 struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0]; in ioam6_genl_dumpsc_start()
436 return -ENOMEM; in ioam6_genl_dumpsc_start()
438 cb->args[0] = (long)iter; in ioam6_genl_dumpsc_start()
441 rhashtable_walk_enter(&nsdata->schemas, iter); in ioam6_genl_dumpsc_start()
446 static int ioam6_genl_dumpsc_done(struct netlink_callback *cb) in ioam6_genl_dumpsc_done()
448 struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0]; in ioam6_genl_dumpsc_done()
456 static int ioam6_genl_dumpsc(struct sk_buff *skb, struct netlink_callback *cb) in ioam6_genl_dumpsc()
462 iter = (struct rhashtable_iter *)cb->args[0]; in ioam6_genl_dumpsc()
469 if (PTR_ERR(sc) == -EAGAIN) in ioam6_genl_dumpsc()
478 NETLINK_CB(cb->skb).portid, in ioam6_genl_dumpsc()
479 cb->nlh->nlmsg_seq, in ioam6_genl_dumpsc()
487 err = skb->len; in ioam6_genl_dumpsc()
494 static int ioam6_genl_ns_set_schema(struct sk_buff *skb, struct genl_info *info) in ioam6_genl_ns_set_schema()
503 if (!info->attrs[IOAM6_ATTR_NS_ID] || in ioam6_genl_ns_set_schema()
504 (!info->attrs[IOAM6_ATTR_SC_ID] && in ioam6_genl_ns_set_schema()
505 !info->attrs[IOAM6_ATTR_SC_NONE])) in ioam6_genl_ns_set_schema()
506 return -EINVAL; in ioam6_genl_ns_set_schema()
508 ns_id = cpu_to_be16(nla_get_u16(info->attrs[IOAM6_ATTR_NS_ID])); in ioam6_genl_ns_set_schema()
511 mutex_lock(&nsdata->lock); in ioam6_genl_ns_set_schema()
513 ns = rhashtable_lookup_fast(&nsdata->namespaces, &ns_id, rht_ns_params); in ioam6_genl_ns_set_schema()
515 err = -ENOENT; in ioam6_genl_ns_set_schema()
519 if (info->attrs[IOAM6_ATTR_SC_NONE]) { in ioam6_genl_ns_set_schema()
522 sc_id = nla_get_u32(info->attrs[IOAM6_ATTR_SC_ID]); in ioam6_genl_ns_set_schema()
523 sc = rhashtable_lookup_fast(&nsdata->schemas, &sc_id, in ioam6_genl_ns_set_schema()
526 err = -ENOENT; in ioam6_genl_ns_set_schema()
531 sc_ref = rcu_dereference_protected(ns->schema, in ioam6_genl_ns_set_schema()
532 lockdep_is_held(&nsdata->lock)); in ioam6_genl_ns_set_schema()
534 rcu_assign_pointer(sc_ref->ns, NULL); in ioam6_genl_ns_set_schema()
535 rcu_assign_pointer(ns->schema, sc); in ioam6_genl_ns_set_schema()
538 ns_ref = rcu_dereference_protected(sc->ns, in ioam6_genl_ns_set_schema()
539 lockdep_is_held(&nsdata->lock)); in ioam6_genl_ns_set_schema()
541 rcu_assign_pointer(ns_ref->schema, NULL); in ioam6_genl_ns_set_schema()
542 rcu_assign_pointer(sc->ns, ns); in ioam6_genl_ns_set_schema()
548 mutex_unlock(&nsdata->lock); in ioam6_genl_ns_set_schema()
552 static const struct genl_ops ioam6_genl_ops[] = {
559 .maxattr = ARRAY_SIZE(ioam6_genl_policy_addns) - 1,
567 .maxattr = ARRAY_SIZE(ioam6_genl_policy_delns) - 1,
583 .maxattr = ARRAY_SIZE(ioam6_genl_policy_addsc) - 1,
591 .maxattr = ARRAY_SIZE(ioam6_genl_policy_delsc) - 1,
607 .maxattr = ARRAY_SIZE(ioam6_genl_policy_ns_sc) - 1,
613 static const struct genl_multicast_group ioam6_mcgrps[] = {
618 static int ioam6_event_put_trace(struct sk_buff *skb, in ioam6_event_put_trace()
619 struct ioam6_trace_hdr *trace, in ioam6_event_put_trace() argument
623 be16_to_cpu(trace->namespace_id)) || in ioam6_event_put_trace()
624 nla_put_u8(skb, IOAM6_EVENT_ATTR_TRACE_NODELEN, trace->nodelen) || in ioam6_event_put_trace()
626 be32_to_cpu(trace->type_be32)) || in ioam6_event_put_trace()
628 len - sizeof(struct ioam6_trace_hdr) - trace->remlen * 4, in ioam6_event_put_trace()
629 trace->data + trace->remlen * 4)) in ioam6_event_put_trace()
673 static struct genl_family ioam6_genl_family __ro_after_init = {
686 struct ioam6_namespace *ioam6_namespace(struct net *net, __be16 id) in ioam6_namespace() argument
690 return rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params); in ioam6_namespace()
693 static void __ioam6_fill_trace_data(struct sk_buff *skb, in __ioam6_fill_trace_data()
695 struct ioam6_trace_hdr *trace, in __ioam6_fill_trace_data() argument
707 data = trace->data + trace->remlen * 4 - trace->nodelen * 4 - sclen * 4; in __ioam6_fill_trace_data()
710 if (trace->type.bit0) { in __ioam6_fill_trace_data()
711 byte = ipv6_hdr(skb)->hop_limit; in __ioam6_fill_trace_data()
713 byte--; in __ioam6_fill_trace_data()
715 raw32 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id; in __ioam6_fill_trace_data()
722 if (trace->type.bit1) { in __ioam6_fill_trace_data()
723 if (!skb->dev) in __ioam6_fill_trace_data()
726 raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_id); in __ioam6_fill_trace_data()
731 if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) in __ioam6_fill_trace_data()
734 raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id); in __ioam6_fill_trace_data()
741 if (trace->type.bit2) { in __ioam6_fill_trace_data()
742 if (!skb->dev) { in __ioam6_fill_trace_data()
754 if (trace->type.bit3) { in __ioam6_fill_trace_data()
755 if (!skb->dev) { in __ioam6_fill_trace_data()
758 if (!trace->type.bit2) { in __ioam6_fill_trace_data()
769 if (trace->type.bit4) { in __ioam6_fill_trace_data()
775 if (trace->type.bit5) { in __ioam6_fill_trace_data()
776 *(__be32 *)data = ns->data; in __ioam6_fill_trace_data()
781 if (trace->type.bit6) { in __ioam6_fill_trace_data()
786 if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) { in __ioam6_fill_trace_data()
789 queue = skb_get_tx_queue(skb_dst(skb)->dev, skb); in __ioam6_fill_trace_data()
790 qdisc = rcu_dereference(queue->qdisc); in __ioam6_fill_trace_data()
799 if (trace->type.bit7) { in __ioam6_fill_trace_data()
805 if (trace->type.bit8) { in __ioam6_fill_trace_data()
806 byte = ipv6_hdr(skb)->hop_limit; in __ioam6_fill_trace_data()
808 byte--; in __ioam6_fill_trace_data()
810 raw64 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id_wide; in __ioam6_fill_trace_data()
817 if (trace->type.bit9) { in __ioam6_fill_trace_data()
818 if (!skb->dev) in __ioam6_fill_trace_data()
821 raw32 = READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_id_wide); in __ioam6_fill_trace_data()
826 if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) in __ioam6_fill_trace_data()
829 raw32 = READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id_wide); in __ioam6_fill_trace_data()
836 if (trace->type.bit10) { in __ioam6_fill_trace_data()
837 *(__be64 *)data = ns->data_wide; in __ioam6_fill_trace_data()
842 if (trace->type.bit11) { in __ioam6_fill_trace_data()
848 if (trace->type.bit12) { in __ioam6_fill_trace_data()
854 if (trace->type.bit13) { in __ioam6_fill_trace_data()
860 if (trace->type.bit14) { in __ioam6_fill_trace_data()
866 if (trace->type.bit15) { in __ioam6_fill_trace_data()
872 if (trace->type.bit16) { in __ioam6_fill_trace_data()
878 if (trace->type.bit17) { in __ioam6_fill_trace_data()
884 if (trace->type.bit18) { in __ioam6_fill_trace_data()
890 if (trace->type.bit19) { in __ioam6_fill_trace_data()
896 if (trace->type.bit20) { in __ioam6_fill_trace_data()
902 if (trace->type.bit21) { in __ioam6_fill_trace_data()
908 if (trace->type.bit22) { in __ioam6_fill_trace_data()
912 *(__be32 *)data = sc->hdr; in __ioam6_fill_trace_data()
915 memcpy(data, sc->data, sc->len); in __ioam6_fill_trace_data()
923 struct ioam6_trace_hdr *trace, in ioam6_fill_trace_data() argument
931 if (trace->overflow) in ioam6_fill_trace_data()
938 sc = rcu_dereference(ns->schema); in ioam6_fill_trace_data()
939 if (trace->type.bit22) { in ioam6_fill_trace_data()
943 sclen += sc->len / 4; in ioam6_fill_trace_data()
947 * skip without filling the trace in ioam6_fill_trace_data()
949 if (!trace->remlen || trace->remlen < trace->nodelen + sclen) { in ioam6_fill_trace_data()
950 trace->overflow = 1; in ioam6_fill_trace_data()
954 __ioam6_fill_trace_data(skb, ns, trace, sc, sclen, is_input); in ioam6_fill_trace_data()
955 trace->remlen -= trace->nodelen + sclen; in ioam6_fill_trace_data()
958 static int __net_init ioam6_net_init(struct net *net) in ioam6_net_init()
961 int err = -ENOMEM; in ioam6_net_init()
967 mutex_init(&nsdata->lock); in ioam6_net_init()
968 net->ipv6.ioam6_data = nsdata; in ioam6_net_init()
970 err = rhashtable_init(&nsdata->namespaces, &rht_ns_params); in ioam6_net_init()
974 err = rhashtable_init(&nsdata->schemas, &rht_sc_params); in ioam6_net_init()
981 rhashtable_destroy(&nsdata->namespaces); in ioam6_net_init()
984 net->ipv6.ioam6_data = NULL; in ioam6_net_init()
988 static void __net_exit ioam6_net_exit(struct net *net) in ioam6_net_exit()
992 rhashtable_free_and_destroy(&nsdata->namespaces, ioam6_free_ns, NULL); in ioam6_net_exit()
993 rhashtable_free_and_destroy(&nsdata->schemas, ioam6_free_sc, NULL); in ioam6_net_exit()
998 static struct pernet_operations ioam6_net_ops = {
1019 pr_info("In-situ OAM (IOAM) with IPv6\n"); in ioam6_init()