net: ioam6: multicast event
authorJustin Iurman <justin.iurman@uliege.be>
Mon, 26 Feb 2024 13:14:11 +0000 (14:14 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Feb 2024 11:19:41 +0000 (11:19 +0000)
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 <dsahern@kernel.org>
Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ioam6.h
net/ipv6/ioam6.c

index 781d2d8b2f29d96fc6614eb3ce19377533db13fb..2cbbee6e806aab71105df6d874092aa28078ec4b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/net.h>
 #include <linux/ipv6.h>
 #include <linux/ioam6.h>
+#include <linux/ioam6_genl.h>
 #include <linux/rhashtable-types.h>
 
 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 */
index 571f0e4d9cf3d085bf19a6497aa33623d1532aeb..5fa923f0663214df4783344e0f790b368a2bf1bf 100644 (file)
@@ -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,
 };