From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lorenzo Bianconi Subject: [PATCH net-next] veth: report NEWLINK event when moving the peer device in a new namespace Date: Fri, 31 Aug 2018 13:43:50 +0200 Message-ID: <51722660f2ef860779e227541dab77046496f135.1535712096.git.lorenzo.bianconi@redhat.com> References: Cc: netdev@vger.kernel.org To: davem@davemloft.net Return-path: Received: from mail-wm0-f66.google.com ([74.125.82.66]:34995 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727474AbeHaPvL (ORCPT ); Fri, 31 Aug 2018 11:51:11 -0400 Received: by mail-wm0-f66.google.com with SMTP id o18-v6so5075320wmc.0 for ; Fri, 31 Aug 2018 04:44:05 -0700 (PDT) In-Reply-To: Sender: netdev-owner@vger.kernel.org List-ID: When moving a veth device to another namespace, userspace receives a RTM_DELLINK message indicating the device has been removed from current netns. However, the other peer does not receive a netlink event containing new values for IFLA_LINK_NETNSID and IFLA_LINK veth attributes. Fix that behaviour sending to userspace a RTM_NEWLINK message in the peer namespace to report new IFLA_LINK_NETNSID/IFLA_LINK values Reviewed-by: Stefano Brivio Signed-off-by: Lorenzo Bianconi --- Changes since RFC: - export rtmsg_ifinfo_build_skb() symbol and do not use rtmsg_ifinfo_newnet() directly --- drivers/net/veth.c | 66 +++++++++++++++++++++++++++++++++++++++++++- net/core/rtnetlink.c | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 8d679c8b7f25..0caffc93d74d 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1242,18 +1242,82 @@ static struct rtnl_link_ops veth_link_ops = { .get_link_net = veth_get_link_net, }; +static int veth_notify(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *peer, *dev = netdev_notifier_info_to_dev(ptr); + struct net *peer_net, *net = dev_net(dev); + int nsid, ret = NOTIFY_DONE; + struct veth_priv *priv; + struct sk_buff *skb; + + if (dev->netdev_ops != &veth_netdev_ops) + return NOTIFY_DONE; + + if (event != NETDEV_REGISTER) + return NOTIFY_DONE; + + priv = netdev_priv(dev); + + rcu_read_lock(); + + peer = rcu_dereference(priv->peer); + if (!peer) + goto out; + + peer_net = dev_net(peer); + /* do not forward events if both veth devices + * are in the same namespace + */ + if (peer_net == net) + goto out; + + /* notify on peer namespace new IFLA_LINK_NETNSID + * and IFLA_LINK values + */ + nsid = peernet2id_alloc(peer_net, net); + skb = rtmsg_ifinfo_build_skb(RTM_NEWLINK, peer, ~0U, + IFLA_EVENT_NONE, GFP_ATOMIC, + &nsid, dev->ifindex); + if (skb) { + rtnl_notify(skb, peer_net, 0, RTNLGRP_LINK, NULL, + GFP_ATOMIC); + ret = NOTIFY_OK; + } + +out: + rcu_read_unlock(); + + return ret; +} + +static struct notifier_block veth_notifier = { + .notifier_call = veth_notify, +}; + /* * init/fini */ static __init int veth_init(void) { - return rtnl_link_register(&veth_link_ops); + int err; + + err = register_netdevice_notifier(&veth_notifier); + if (err < 0) + return err; + + err = rtnl_link_register(&veth_link_ops); + if (err < 0) + unregister_netdevice_notifier(&veth_notifier); + + return err; } static __exit void veth_exit(void) { rtnl_link_unregister(&veth_link_ops); + unregister_netdevice_notifier(&veth_notifier); } module_init(veth_init); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 24431e578310..b2df84db7670 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3326,6 +3326,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, rtnl_set_sk_err(net, RTNLGRP_LINK, err); return NULL; } +EXPORT_SYMBOL(rtmsg_ifinfo_build_skb); void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags) { -- 2.17.1