Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e507e24 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'rtnetlink-event-type'



Vladislav Yasevich says:

====================
rtnetlink: Updates to rtnetlink_event()

This series came out of the conversation that started as a result
my first attempt to add netdevice event info to netlink messages.

This series converts event processing to a 'white list', where
we explicitely permit events to generate netlink messages.  This
is meant to make people take a closer look and determine wheter
these events should really trigger netlink messages.

I am also adding a V2 of my patch to add event type to the netlink
message.  This version supports all events that we currently generate.

I will also update my patch to iproute that will show this data
through 'ip monitor'.

I actually need the ability to trap NETDEV_NOTIFY_PEERS event
(as well as possible NETDEV_RESEND_IGMP) to support hanlding of
macvtap on top of bonding.  I hope others will also find this info usefull.

V2: Added missed events (from David Ahern)
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 589c49cb def12888
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,

void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change, gfp_t flags);
struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
				       unsigned change, gfp_t flags);
				       unsigned change, unsigned long event,
				       gfp_t flags);
void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev,
		       gfp_t flags);

+21 −0
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ enum {
	IFLA_GSO_MAX_SIZE,
	IFLA_PAD,
	IFLA_XDP,
	IFLA_EVENT,
	__IFLA_MAX
};

@@ -899,4 +900,24 @@ enum {

#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)

enum {
	IFLA_EVENT_UNSPEC,
	IFLA_EVENT_REBOOT,
	IFLA_EVENT_CHANGE_MTU,
	IFLA_EVENT_CHANGE_ADDR,
	IFLA_EVENT_CHANGE_NAME,
	IFLA_EVENT_FEAT_CHANGE,
	IFLA_EVENT_BONDING_FAILOVER,
	IFLA_EVENT_POST_TYPE_CHANGE,
	IFLA_EVENT_NOTIFY_PEERS,
	IFLA_EVENT_CHANGE_UPPER,
	IFLA_EVENT_RESEND_IGMP,
	IFLA_EVENT_PRE_CHANGE_MTU,
	IFLA_EVENT_CHANGE_INFO_DATA,
	IFLA_EVENT_PRE_CHANGE_UPPER,
	IFLA_EVENT_CHANGE_LOWER_STATE,
	IFLA_EVENT_UDP_TUNNEL_PUSH_INFO,
	IFLA_EVENT_CHANGE_TX_QUEUE_LEN,
};

#endif /* _UAPI_LINUX_IF_LINK_H */
+1 −1
Original line number Diff line number Diff line
@@ -6840,7 +6840,7 @@ static void rollback_registered_many(struct list_head *head)

		if (!dev->rtnl_link_ops ||
		    dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
			skb = rtmsg_ifinfo_build_skb(RTM_DELLINK, dev, ~0U,
			skb = rtmsg_ifinfo_build_skb(RTM_DELLINK, dev, ~0U, 0,
						     GFP_KERNEL);

		/*
+99 −22
Original line number Diff line number Diff line
@@ -944,6 +944,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
	       + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_SWITCH_ID */
	       + nla_total_size(IFNAMSIZ) /* IFLA_PHYS_PORT_NAME */
	       + rtnl_xdp_size(dev) /* IFLA_XDP */
	       + nla_total_size(4)  /* IFLA_EVENT */
	       + nla_total_size(1); /* IFLA_PROTO_DOWN */

}
@@ -1276,9 +1277,70 @@ static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
	return err;
}

static int rtnl_fill_link_event(struct sk_buff *skb, unsigned long event)
{
	u32 rtnl_event;

	switch (event) {
	case NETDEV_REBOOT:
		rtnl_event = IFLA_EVENT_REBOOT;
		break;
	case NETDEV_CHANGEMTU:
		rtnl_event = IFLA_EVENT_CHANGE_MTU;
		break;
	case NETDEV_CHANGEADDR:
		rtnl_event = IFLA_EVENT_CHANGE_ADDR;
		break;
	case NETDEV_CHANGENAME:
		rtnl_event = IFLA_EVENT_CHANGE_NAME;
		break;
	case NETDEV_FEAT_CHANGE:
		rtnl_event = IFLA_EVENT_FEAT_CHANGE;
		break;
	case NETDEV_BONDING_FAILOVER:
		rtnl_event = IFLA_EVENT_BONDING_FAILOVER;
		break;
	case NETDEV_POST_TYPE_CHANGE:
		rtnl_event = IFLA_EVENT_POST_TYPE_CHANGE;
		break;
	case NETDEV_NOTIFY_PEERS:
		rtnl_event = IFLA_EVENT_NOTIFY_PEERS;
		break;
	case NETDEV_CHANGEUPPER:
		rtnl_event = IFLA_EVENT_CHANGE_UPPER;
		break;
	case NETDEV_RESEND_IGMP:
		rtnl_event = IFLA_EVENT_RESEND_IGMP;
		break;
	case NETDEV_PRECHANGEMTU:
		rtnl_event = IFLA_EVENT_PRE_CHANGE_MTU;
		break;
	case NETDEV_CHANGEINFODATA:
		rtnl_event = IFLA_EVENT_CHANGE_INFO_DATA;
		break;
	case NETDEV_PRECHANGEUPPER:
		rtnl_event = IFLA_EVENT_PRE_CHANGE_UPPER;
		break;
	case NETDEV_CHANGELOWERSTATE:
		rtnl_event = IFLA_EVENT_CHANGE_LOWER_STATE;
		break;
	case NETDEV_UDP_TUNNEL_PUSH_INFO:
		rtnl_event = IFLA_EVENT_UDP_TUNNEL_PUSH_INFO;
		break;
	case NETDEV_CHANGE_TX_QUEUE_LEN:
		rtnl_event = IFLA_EVENT_CHANGE_TX_QUEUE_LEN;
		break;
	default:
		return 0;
	}

	return nla_put_u32(skb, IFLA_EVENT, rtnl_event);
}

static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
			    int type, u32 pid, u32 seq, u32 change,
			    unsigned int flags, u32 ext_filter_mask)
			    unsigned int flags, u32 ext_filter_mask,
			    unsigned long event)
{
	struct ifinfomsg *ifm;
	struct nlmsghdr *nlh;
@@ -1327,6 +1389,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
	    nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down))
		goto nla_put_failure;

	if (rtnl_fill_link_event(skb, event))
		goto nla_put_failure;

	if (rtnl_fill_link_ifmap(skb, dev))
		goto nla_put_failure;

@@ -1461,6 +1526,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
	[IFLA_LINK_NETNSID]	= { .type = NLA_S32 },
	[IFLA_PROTO_DOWN]	= { .type = NLA_U8 },
	[IFLA_XDP]		= { .type = NLA_NESTED },
	[IFLA_EVENT]		= { .type = NLA_U32 },
};

static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -1619,7 +1685,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
					       NETLINK_CB(cb->skb).portid,
					       cb->nlh->nlmsg_seq, 0,
					       flags,
					       ext_filter_mask);
					       ext_filter_mask, 0);
			/* If we ran out of room on the first message,
			 * we're in trouble
			 */
@@ -2710,7 +2776,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh)
		return -ENOBUFS;

	err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).portid,
			       nlh->nlmsg_seq, 0, 0, ext_filter_mask);
			       nlh->nlmsg_seq, 0, 0, ext_filter_mask, 0);
	if (err < 0) {
		/* -EMSGSIZE implies BUG in if_nlmsg_size */
		WARN_ON(err == -EMSGSIZE);
@@ -2782,7 +2848,8 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
}

struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
				       unsigned int change, gfp_t flags)
				       unsigned int change,
				       unsigned long event, gfp_t flags)
{
	struct net *net = dev_net(dev);
	struct sk_buff *skb;
@@ -2793,7 +2860,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
	if (skb == NULL)
		goto errout;

	err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0, 0);
	err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0, 0, event);
	if (err < 0) {
		/* -EMSGSIZE implies BUG in if_nlmsg_size() */
		WARN_ON(err == -EMSGSIZE);
@@ -2814,7 +2881,8 @@ void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags)
	rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags);
}

void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
static void rtmsg_ifinfo_event(int type, struct net_device *dev,
			       unsigned int change, unsigned long event,
			       gfp_t flags)
{
	struct sk_buff *skb;
@@ -2822,10 +2890,16 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
	if (dev->reg_state != NETREG_REGISTERED)
		return;

	skb = rtmsg_ifinfo_build_skb(type, dev, change, flags);
	skb = rtmsg_ifinfo_build_skb(type, dev, change, event, flags);
	if (skb)
		rtmsg_ifinfo_send(skb, dev, flags);
}

void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
		  gfp_t flags)
{
	rtmsg_ifinfo_event(type, dev, change, 0, flags);
}
EXPORT_SYMBOL(rtmsg_ifinfo);

static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
@@ -4116,22 +4190,25 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);

	switch (event) {
	case NETDEV_UP:
	case NETDEV_DOWN:
	case NETDEV_PRE_UP:
	case NETDEV_POST_INIT:
	case NETDEV_REGISTER:
	case NETDEV_CHANGE:
	case NETDEV_PRE_TYPE_CHANGE:
	case NETDEV_GOING_DOWN:
	case NETDEV_UNREGISTER:
	case NETDEV_UNREGISTER_FINAL:
	case NETDEV_RELEASE:
	case NETDEV_JOIN:
	case NETDEV_BONDING_INFO:
	case NETDEV_REBOOT:
	case NETDEV_CHANGEMTU:
	case NETDEV_CHANGEADDR:
	case NETDEV_CHANGENAME:
	case NETDEV_FEAT_CHANGE:
	case NETDEV_BONDING_FAILOVER:
	case NETDEV_POST_TYPE_CHANGE:
	case NETDEV_NOTIFY_PEERS:
	case NETDEV_CHANGEUPPER:
	case NETDEV_RESEND_IGMP:
	case NETDEV_PRECHANGEMTU:
	case NETDEV_CHANGEINFODATA:
	case NETDEV_PRECHANGEUPPER:
	case NETDEV_CHANGELOWERSTATE:
	case NETDEV_UDP_TUNNEL_PUSH_INFO:
	case NETDEV_CHANGE_TX_QUEUE_LEN:
		rtmsg_ifinfo_event(RTM_NEWLINK, dev, 0, event, GFP_KERNEL);
		break;
	default:
		rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL);
		break;
	}
	return NOTIFY_DONE;