Commit 66400d54 authored by WANG Cong's avatar WANG Cong Committed by David S. Miller
Browse files

net: allow to delete a whole device group



With dev group, we can change a batch of net devices,
so we should allow to delete them together too.

Group 0 is not allowed to be deleted since it is
the default group.

Cc: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 27ed44a5
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -1836,6 +1836,42 @@ errout:
	return err;
}

static int rtnl_group_dellink(const struct net *net, int group)
{
	struct net_device *dev, *aux;
	LIST_HEAD(list_kill);
	bool found = false;

	if (!group)
		return -EPERM;

	for_each_netdev(net, dev) {
		if (dev->group == group) {
			const struct rtnl_link_ops *ops;

			found = true;
			ops = dev->rtnl_link_ops;
			if (!ops || !ops->dellink)
				return -EOPNOTSUPP;
		}
	}

	if (!found)
		return -ENODEV;

	for_each_netdev_safe(net, dev, aux) {
		if (dev->group == group) {
			const struct rtnl_link_ops *ops;

			ops = dev->rtnl_link_ops;
			ops->dellink(dev, &list_kill);
		}
	}
	unregister_netdevice_many(&list_kill);

	return 0;
}

static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	struct net *net = sock_net(skb->sk);
@@ -1859,6 +1895,8 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
		dev = __dev_get_by_index(net, ifm->ifi_index);
	else if (tb[IFLA_IFNAME])
		dev = __dev_get_by_name(net, ifname);
	else if (tb[IFLA_GROUP])
		return rtnl_group_dellink(net, nla_get_u32(tb[IFLA_GROUP]));
	else
		return -EINVAL;