forked from mirrors/linux
		
	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:
		
							parent
							
								
									d88e136cab
								
							
						
					
					
						commit
						f3a63cce1b
					
				
					 6 changed files with 9 additions and 8 deletions
				
			
		| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue