* [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event()
@ 2017-05-05 20:52 Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V3 net-next 1/2] rtnl: Add support for netdev event to link messages Vladislav Yasevich
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Vladislav Yasevich @ 2017-05-05 20:52 UTC (permalink / raw)
To: netdev; +Cc: roopa, dsa, jiri, Vladislav Yasevich
This is a version 4 series came out of the conversation that started
as a result my first attempt to add netdevice event info to netlink messages.
First is the patch to add IFLA_EVENT attribute to the netlink message. It
supports only currently white-listed events.
Like before, this is just an attribute that gets added to the rtnetlink
message only when the messaged was generated as a result of a netdev event.
In my case, this is necessary since I want to trap NETDEV_NOTIFY_PEERS
event (also possibly NETDEV_RESEND_IGMP event) and perform certain actions
in user space. This is not possible since the messages generated as
a result of netdev events do not usually contain any changed data. They
are just notifications. This patch exposes this notification type to
userspace.
Second, I remove duplicate messages that a result of a change to bonding
options. If netlink is used to configure bonding options, 2 messages
are generated, one as a result NETDEV_CHANGEINFODATA event triggered by
bonding code and one a result of device state changes triggered by
netdev_state_change (called from do_setlink).
I will also update my patch to iproute that will show this data
through 'ip monitor'.
V4:
* Removed the patch the removed NETDEV_CHANGENAME from event whitelist.
It doesn't trigger duplicate messages since name changes can only be
done while device is down and netdev_state_change() doesn't report
changes while device is down.
* Added a patch to clean-up duplicate messages on bonding option changes.
V3: Rebased. Cleaned-up duplicate event.
V2: Added missed events (from David Ahern)
Vladislav Yasevich (2):
rtnl: Add support for netdev event to link messages
bonding: Prevent duplicate userspace notification
drivers/net/bonding/bond_main.c | 3 +-
drivers/net/bonding/bond_options.c | 27 +++++++++++++++--
include/linux/rtnetlink.h | 3 +-
include/net/bond_options.h | 2 ++
include/uapi/linux/if_link.h | 11 +++++++
net/core/dev.c | 2 +-
net/core/rtnetlink.c | 62 ++++++++++++++++++++++++++++++++------
7 files changed, 96 insertions(+), 14 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH V3 net-next 1/2] rtnl: Add support for netdev event to link messages
2017-05-05 20:52 [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Vladislav Yasevich
@ 2017-05-05 20:52 ` Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V4 net-next 2/2] bonding: Prevent duplicate userspace notification Vladislav Yasevich
2017-05-06 10:51 ` [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Jiri Pirko
2 siblings, 0 replies; 4+ messages in thread
From: Vladislav Yasevich @ 2017-05-05 20:52 UTC (permalink / raw)
To: netdev; +Cc: roopa, dsa, jiri, Vladislav Yasevich
When netdev events happen, a rtnetlink_event() handler will send
messages for every event in it's white list. These messages contain
current information about a particular device, but they do not include
the iformation about which event just happened. So, it is impossible
to tell what just happend for these events.
This patch adds a new extension to RTM_NEWLINK message called IFLA_EVENT
that would have an encoding of event that triggered this
message. This would allow the the message consumer to easily determine
if it needs to perform certain actions.
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
---
include/linux/rtnetlink.h | 3 ++-
include/uapi/linux/if_link.h | 11 ++++++++
net/core/dev.c | 2 +-
net/core/rtnetlink.c | 62 +++++++++++++++++++++++++++++++++++++-------
4 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 57e5484..0459018 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 8e56ac7..0d4501e 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
};
@@ -902,4 +903,14 @@ enum {
#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
+enum {
+ IFLA_EVENT_UNSPEC,
+ IFLA_EVENT_REBOOT,
+ IFLA_EVENT_FEAT_CHANGE,
+ IFLA_EVENT_BONDING_FAILOVER,
+ IFLA_EVENT_NOTIFY_PEERS,
+ IFLA_EVENT_RESEND_IGMP,
+ IFLA_EVENT_CHANGE_INFO_DATA,
+};
+
#endif /* _UAPI_LINUX_IF_LINK_H */
diff --git a/net/core/dev.c b/net/core/dev.c
index d07aa5f..e111521 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6988,7 +6988,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 6e67315..43d2223 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -942,6 +942,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() /* IFLA_XDP */
+ + nla_total_size(4) /* IFLA_EVENT */
+ nla_total_size(1); /* IFLA_PROTO_DOWN */
}
@@ -1286,9 +1287,40 @@ 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_FEAT_CHANGE:
+ rtnl_event = IFLA_EVENT_FEAT_CHANGE;
+ break;
+ case NETDEV_BONDING_FAILOVER:
+ rtnl_event = IFLA_EVENT_BONDING_FAILOVER;
+ break;
+ case NETDEV_NOTIFY_PEERS:
+ rtnl_event = IFLA_EVENT_NOTIFY_PEERS;
+ break;
+ case NETDEV_RESEND_IGMP:
+ rtnl_event = IFLA_EVENT_RESEND_IGMP;
+ break;
+ case NETDEV_CHANGEINFODATA:
+ rtnl_event = IFLA_EVENT_CHANGE_INFO_DATA;
+ 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;
@@ -1337,6 +1369,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;
@@ -1471,6 +1506,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] = {
@@ -1630,7 +1666,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
*/
@@ -2733,7 +2769,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);
@@ -2805,7 +2841,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;
@@ -2816,7 +2853,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);
@@ -2837,18 +2874,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,
@@ -4152,7 +4196,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
case NETDEV_NOTIFY_PEERS:
case NETDEV_RESEND_IGMP:
case NETDEV_CHANGEINFODATA:
- rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL);
+ rtmsg_ifinfo_event(RTM_NEWLINK, dev, 0, event, GFP_KERNEL);
break;
default:
break;
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH V4 net-next 2/2] bonding: Prevent duplicate userspace notification
2017-05-05 20:52 [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V3 net-next 1/2] rtnl: Add support for netdev event to link messages Vladislav Yasevich
@ 2017-05-05 20:52 ` Vladislav Yasevich
2017-05-06 10:51 ` [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Jiri Pirko
2 siblings, 0 replies; 4+ messages in thread
From: Vladislav Yasevich @ 2017-05-05 20:52 UTC (permalink / raw)
To: netdev; +Cc: roopa, dsa, jiri, Vladislav Yasevich
Whenever a user changes bonding options, a NETDEV_CHANGEINFODATA
notificatin is generated which results in a rtnelink message to
be sent. While runnig 'ip monitor', we can actually see 2 messages,
one a result of the event, and the other a result of state change
that is generated bo netdev_state_change(). However, this is not
always the case. If bonding changes were done via sysfs or ifenslave
(old ioctl interface), then only 1 message is seen.
This patch removes duplicate messages in the case of using netlink
to configure bonding. It introduceds a separte function that
triggers a netdev event and uses that function in the syfs and ioctl
cases.
This was discovered while auditing all the different envents and
continues the effort of cleaning up duplicated netlink messages.
CC: David Ahern <dsa@cumulusnetworks.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
---
drivers/net/bonding/bond_main.c | 3 ++-
drivers/net/bonding/bond_options.c | 27 +++++++++++++++++++++++++--
include/net/bond_options.h | 2 ++
3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2be7880..ac2e425 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3481,7 +3481,8 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
case BOND_CHANGE_ACTIVE_OLD:
case SIOCBONDCHANGEACTIVE:
bond_opt_initstr(&newval, slave_dev->name);
- res = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
+ res = __bond_opt_set_notify(bond, BOND_OPT_ACTIVE_SLAVE,
+ &newval);
break;
default:
res = -EOPNOTSUPP;
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 1bcbb89..8ca6833 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -673,7 +673,30 @@ int __bond_opt_set(struct bonding *bond,
out:
if (ret)
bond_opt_error_interpret(bond, opt, ret, val);
- else if (bond->dev->reg_state == NETREG_REGISTERED)
+
+ return ret;
+}
+/**
+ * __bond_opt_set_notify - set a bonding option
+ * @bond: target bond device
+ * @option: option to set
+ * @val: value to set it to
+ *
+ * This function is used to change the bond's option value and trigger
+ * a notification to user sapce. It can be used for both enabling/changing
+ * an option and for disabling it. RTNL lock must be obtained before calling
+ * this function.
+ */
+int __bond_opt_set_notify(struct bonding *bond,
+ unsigned int option, struct bond_opt_value *val)
+{
+ int ret = -ENOENT;
+
+ ASSERT_RTNL();
+
+ ret = __bond_opt_set(bond, option, val);
+
+ if (!ret && (bond->dev->reg_state == NETREG_REGISTERED))
call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
return ret;
@@ -696,7 +719,7 @@ int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf)
if (!rtnl_trylock())
return restart_syscall();
bond_opt_initstr(&optval, buf);
- ret = __bond_opt_set(bond, option, &optval);
+ ret = __bond_opt_set_notify(bond, option, &optval);
rtnl_unlock();
return ret;
diff --git a/include/net/bond_options.h b/include/net/bond_options.h
index 1797235..d79d28f 100644
--- a/include/net/bond_options.h
+++ b/include/net/bond_options.h
@@ -104,6 +104,8 @@ struct bond_option {
int __bond_opt_set(struct bonding *bond, unsigned int option,
struct bond_opt_value *val);
+int __bond_opt_set_notify(struct bonding *bond, unsigned int option,
+ struct bond_opt_value *val);
int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf);
const struct bond_opt_value *bond_opt_parse(const struct bond_option *opt,
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event()
2017-05-05 20:52 [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V3 net-next 1/2] rtnl: Add support for netdev event to link messages Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V4 net-next 2/2] bonding: Prevent duplicate userspace notification Vladislav Yasevich
@ 2017-05-06 10:51 ` Jiri Pirko
2 siblings, 0 replies; 4+ messages in thread
From: Jiri Pirko @ 2017-05-06 10:51 UTC (permalink / raw)
To: Vladislav Yasevich; +Cc: netdev, roopa, dsa, Vladislav Yasevich
Fri, May 05, 2017 at 10:52:47PM CEST, vyasevich@gmail.com wrote:
>This is a version 4 series came out of the conversation that started
>as a result my first attempt to add netdevice event info to netlink messages.
>
>First is the patch to add IFLA_EVENT attribute to the netlink message. It
>supports only currently white-listed events.
>Like before, this is just an attribute that gets added to the rtnetlink
>message only when the messaged was generated as a result of a netdev event.
>In my case, this is necessary since I want to trap NETDEV_NOTIFY_PEERS
>event (also possibly NETDEV_RESEND_IGMP event) and perform certain actions
>in user space. This is not possible since the messages generated as
What are you trying to do in userspace if I may ask.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-05-06 10:51 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-05 20:52 [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V3 net-next 1/2] rtnl: Add support for netdev event to link messages Vladislav Yasevich
2017-05-05 20:52 ` [PATCH V4 net-next 2/2] bonding: Prevent duplicate userspace notification Vladislav Yasevich
2017-05-06 10:51 ` [PATCH v4 net-next 0/2] rtnetlink: Updates to rtnetlink_event() Jiri Pirko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).