diff options
author | David S. Miller <davem@davemloft.net> | 2017-04-05 08:14:14 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-04-05 08:14:14 -0700 |
commit | 2e507e24c90631f36b1c259d05b45f20630a2ad7 (patch) | |
tree | 30ec7b462b43d443fdb11712ee99ad953b5cf17c | |
parent | 589c49cbf9674808fd4ac9b7c17155abc0686f86 (diff) | |
parent | def12888c161e6fec0702e5ec9c3962846e3a21d (diff) | |
download | linux-2e507e24c90631f36b1c259d05b45f20630a2ad7.tar.bz2 |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/rtnetlink.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/if_link.h | 21 | ||||
-rw-r--r-- | net/core/dev.c | 2 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 121 |
4 files changed, 123 insertions, 24 deletions
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 57e54847b0b9..0459018173cf 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -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); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 8b405afb2376..97f6d302f627 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -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 */ diff --git a/net/core/dev.c b/net/core/dev.c index ef9fe60ee294..7efb4178ffef 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -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); /* diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9c3947a43eff..b2bd4c9ee860 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -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 @@ err_cancel: 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,18 +2881,25 @@ 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, - gfp_t flags) +static void rtmsg_ifinfo_event(int type, struct net_device *dev, + unsigned int change, unsigned long event, + gfp_t flags) { struct sk_buff *skb; 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; |