Commit 67c8e4bb authored by Justin Iurman's avatar Justin Iurman Committed by David S. Miller
Browse files

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: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarJustin Iurman <justin.iurman@uliege.be>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5fa918a3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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 */
+64 −0
Original line number Diff line number Diff line
@@ -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,
};