From 5fa918a33563e050d45fb8f260f9240b2039f432 Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Mon, 26 Feb 2024 14:14:10 +0100 Subject: uapi: ioam6: API for netlink multicast events Add new api to support ioam6 events for generic netlink multicast. A first "trace" event is added to the list of ioam6 events, which will represent an IOAM Pre-allocated Trace Option-Type. It provides another solution to share IOAM data with user space. Reviewed-by: David Ahern Signed-off-by: Justin Iurman Signed-off-by: David S. Miller --- include/uapi/linux/ioam6_genl.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/uapi/linux/ioam6_genl.h b/include/uapi/linux/ioam6_genl.h index ca4b22833754..1733fbc51fb5 100644 --- a/include/uapi/linux/ioam6_genl.h +++ b/include/uapi/linux/ioam6_genl.h @@ -49,4 +49,24 @@ enum { #define IOAM6_CMD_MAX (__IOAM6_CMD_MAX - 1) +#define IOAM6_GENL_EV_GRP_NAME "ioam6_events" + +enum ioam6_event_type { + IOAM6_EVENT_UNSPEC, + IOAM6_EVENT_TRACE, +}; + +enum ioam6_event_attr { + IOAM6_EVENT_ATTR_UNSPEC, + + IOAM6_EVENT_ATTR_TRACE_NAMESPACE, /* u16 */ + IOAM6_EVENT_ATTR_TRACE_NODELEN, /* u8 */ + IOAM6_EVENT_ATTR_TRACE_TYPE, /* u32 */ + IOAM6_EVENT_ATTR_TRACE_DATA, /* Binary */ + + __IOAM6_EVENT_ATTR_MAX +}; + +#define IOAM6_EVENT_ATTR_MAX (__IOAM6_EVENT_ATTR_MAX - 1) + #endif /* _UAPI_LINUX_IOAM6_GENL_H */ -- cgit From 67c8e4bb4f54ad22ca0ce4700c8728ffd73acb66 Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Mon, 26 Feb 2024 14:14:11 +0100 Subject: net: ioam6: multicast event Add a multicast group to the ioam6 generic netlink family and provide ioam6_event() to send an ioam6 event to the multicast group. Reviewed-by: David Ahern Signed-off-by: Justin Iurman Signed-off-by: David S. Miller --- include/net/ioam6.h | 4 ++++ net/ipv6/ioam6.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/net/ioam6.h b/include/net/ioam6.h index 781d2d8b2f29..2cbbee6e806a 100644 --- a/include/net/ioam6.h +++ b/include/net/ioam6.h @@ -12,6 +12,7 @@ #include #include #include +#include #include struct ioam6_namespace { @@ -65,4 +66,7 @@ void ioam6_exit(void); int ioam6_iptunnel_init(void); void ioam6_iptunnel_exit(void); +void ioam6_event(enum ioam6_event_type type, struct net *net, gfp_t gfp, + void *opt, unsigned int opt_len); + #endif /* _NET_IOAM6_H */ diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c index 571f0e4d9cf3..5fa923f06632 100644 --- a/net/ipv6/ioam6.c +++ b/net/ipv6/ioam6.c @@ -612,6 +612,68 @@ static const struct genl_ops ioam6_genl_ops[] = { }, }; +#define IOAM6_GENL_EV_GRP_OFFSET 0 + +static const struct genl_multicast_group ioam6_mcgrps[] = { + [IOAM6_GENL_EV_GRP_OFFSET] = { .name = IOAM6_GENL_EV_GRP_NAME, + .flags = GENL_MCAST_CAP_NET_ADMIN }, +}; + +static int ioam6_event_put_trace(struct sk_buff *skb, + struct ioam6_trace_hdr *trace, + unsigned int len) +{ + if (nla_put_u16(skb, IOAM6_EVENT_ATTR_TRACE_NAMESPACE, + be16_to_cpu(trace->namespace_id)) || + nla_put_u8(skb, IOAM6_EVENT_ATTR_TRACE_NODELEN, trace->nodelen) || + nla_put_u32(skb, IOAM6_EVENT_ATTR_TRACE_TYPE, + be32_to_cpu(trace->type_be32)) || + nla_put(skb, IOAM6_EVENT_ATTR_TRACE_DATA, + len - sizeof(struct ioam6_trace_hdr) - trace->remlen * 4, + trace->data + trace->remlen * 4)) + return 1; + + return 0; +} + +void ioam6_event(enum ioam6_event_type type, struct net *net, gfp_t gfp, + void *opt, unsigned int opt_len) +{ + struct nlmsghdr *nlh; + struct sk_buff *skb; + + if (!genl_has_listeners(&ioam6_genl_family, net, + IOAM6_GENL_EV_GRP_OFFSET)) + return; + + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!skb) + return; + + nlh = genlmsg_put(skb, 0, 0, &ioam6_genl_family, 0, type); + if (!nlh) + goto nla_put_failure; + + switch (type) { + case IOAM6_EVENT_UNSPEC: + WARN_ON_ONCE(1); + break; + case IOAM6_EVENT_TRACE: + if (ioam6_event_put_trace(skb, (struct ioam6_trace_hdr *)opt, + opt_len)) + goto nla_put_failure; + break; + } + + genlmsg_end(skb, nlh); + genlmsg_multicast_netns(&ioam6_genl_family, net, skb, 0, + IOAM6_GENL_EV_GRP_OFFSET, gfp); + return; + +nla_put_failure: + nlmsg_free(skb); +} + static struct genl_family ioam6_genl_family __ro_after_init = { .name = IOAM6_GENL_NAME, .version = IOAM6_GENL_VERSION, @@ -620,6 +682,8 @@ static struct genl_family ioam6_genl_family __ro_after_init = { .ops = ioam6_genl_ops, .n_ops = ARRAY_SIZE(ioam6_genl_ops), .resv_start_op = IOAM6_CMD_NS_SET_SCHEMA + 1, + .mcgrps = ioam6_mcgrps, + .n_mcgrps = ARRAY_SIZE(ioam6_mcgrps), .module = THIS_MODULE, }; -- cgit From f655c78d6225f585ef60a9d93ffb79d507ff3ad3 Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Mon, 26 Feb 2024 14:14:12 +0100 Subject: net: exthdrs: ioam6: send trace event If we're processing an IOAM Pre-allocated Trace Option-Type (the only one supported currently), then send the trace as an ioam6 event to the netlink multicast group. This way, user space apps will be able to collect IOAM data. Reviewed-by: David Ahern Signed-off-by: Justin Iurman Signed-off-by: David S. Miller --- net/ipv6/exthdrs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 02e9ffb63af1..727792907d6c 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -50,6 +50,7 @@ #endif #include #include +#include #include #include @@ -954,6 +955,9 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff) + optoff + sizeof(*hdr)); ioam6_fill_trace_data(skb, ns, trace, true); + + ioam6_event(IOAM6_EVENT_TRACE, dev_net(skb->dev), + GFP_ATOMIC, (void *)trace, hdr->opt_len - 2); break; default: break; -- cgit