rtnetlink: Honour NLM_F_ECHO flag in rtnl_delete_link

This patch use the new helper unregister_netdevice_many_notify() for
rtnl_delete_link(), so that the kernel could reply unicast when userspace
 set NLM_F_ECHO flag to request the new created interface info.

At the same time, the parameters of rtnl_delete_link() need to be updated
since we need nlmsghdr and portid info.

Suggested-by: Guillaume Nault <gnault@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Reviewed-by: Guillaume Nault <gnault@redhat.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Hangbin Liu 2022-10-28 04:42:24 -04:00 committed by Jakub Kicinski
parent d88e136cab
commit f3a63cce1b
6 changed files with 9 additions and 8 deletions

View File

@ -186,7 +186,7 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
const struct rtnl_link_ops *ops, const struct rtnl_link_ops *ops,
struct nlattr *tb[], struct nlattr *tb[],
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int rtnl_delete_link(struct net_device *dev); int rtnl_delete_link(struct net_device *dev, u32 portid, const struct nlmsghdr *nlh);
int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm, int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm,
u32 portid, const struct nlmsghdr *nlh); u32 portid, const struct nlmsghdr *nlh);

View File

@ -3110,7 +3110,7 @@ static int rtnl_group_dellink(const struct net *net, int group)
return 0; return 0;
} }
int rtnl_delete_link(struct net_device *dev) int rtnl_delete_link(struct net_device *dev, u32 portid, const struct nlmsghdr *nlh)
{ {
const struct rtnl_link_ops *ops; const struct rtnl_link_ops *ops;
LIST_HEAD(list_kill); LIST_HEAD(list_kill);
@ -3120,7 +3120,7 @@ int rtnl_delete_link(struct net_device *dev)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ops->dellink(dev, &list_kill); ops->dellink(dev, &list_kill);
unregister_netdevice_many(&list_kill); unregister_netdevice_many_notify(&list_kill, portid, nlh);
return 0; return 0;
} }
@ -3130,6 +3130,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
u32 portid = NETLINK_CB(skb).portid;
struct net *tgt_net = net; struct net *tgt_net = net;
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct ifinfomsg *ifm; struct ifinfomsg *ifm;
@ -3171,7 +3172,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out; goto out;
} }
err = rtnl_delete_link(dev); err = rtnl_delete_link(dev, portid, nlh);
out: out:
if (netnsid >= 0) if (netnsid >= 0)

View File

@ -91,7 +91,7 @@ static struct vport *geneve_tnl_create(const struct vport_parms *parms)
err = dev_change_flags(dev, dev->flags | IFF_UP, NULL); err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
if (err < 0) { if (err < 0) {
rtnl_delete_link(dev); rtnl_delete_link(dev, 0, NULL);
rtnl_unlock(); rtnl_unlock();
ovs_vport_free(vport); ovs_vport_free(vport);
goto error; goto error;

View File

@ -57,7 +57,7 @@ static struct vport *gre_tnl_create(const struct vport_parms *parms)
err = dev_change_flags(dev, dev->flags | IFF_UP, NULL); err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
if (err < 0) { if (err < 0) {
rtnl_delete_link(dev); rtnl_delete_link(dev, 0, NULL);
rtnl_unlock(); rtnl_unlock();
ovs_vport_free(vport); ovs_vport_free(vport);
return ERR_PTR(err); return ERR_PTR(err);

View File

@ -172,7 +172,7 @@ void ovs_netdev_tunnel_destroy(struct vport *vport)
* if it's not already shutting down. * if it's not already shutting down.
*/ */
if (vport->dev->reg_state == NETREG_REGISTERED) if (vport->dev->reg_state == NETREG_REGISTERED)
rtnl_delete_link(vport->dev); rtnl_delete_link(vport->dev, 0, NULL);
netdev_put(vport->dev, &vport->dev_tracker); netdev_put(vport->dev, &vport->dev_tracker);
vport->dev = NULL; vport->dev = NULL;
rtnl_unlock(); rtnl_unlock();

View File

@ -120,7 +120,7 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
err = dev_change_flags(dev, dev->flags | IFF_UP, NULL); err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
if (err < 0) { if (err < 0) {
rtnl_delete_link(dev); rtnl_delete_link(dev, 0, NULL);
rtnl_unlock(); rtnl_unlock();
ovs_vport_free(vport); ovs_vport_free(vport);
goto error; goto error;