Commit 376cd9a2 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-improve-netns-handling-in-rtnetlink'

Xiao Liang says:

====================
net: Improve netns handling in rtnetlink

This patch series includes some netns-related improvements and fixes for
rtnetlink, to make link creation more intuitive:

 1) Creating link in another net namespace doesn't conflict with link
    names in current one.
 2) Refector rtnetlink link creation. Create link in target namespace
    directly.

So that

  # ip link add netns ns1 link-netns ns2 tun0 type gre ...

will create tun0 in ns1, rather than create it in ns2 and move to ns1.
And don't conflict with another interface named "tun0" in current netns.

Patch 01 avoids link name conflict in different netns.

To achieve 2), there're mainly 3 steps:

 - Patch 02 packs newlink() parameters into a struct, including
   the original "src_net" along with more netns context. No semantic
   changes are introduced.
 - Patch 03 ~ 09 converts device drivers to use the explicit netns
   extracted from params.
 - Patch 10 ~ 11 removes the old netns parameter, and converts
   rtnetlink to create device in target netns directly.

Patch 12 ~ 13 adds some tests for link name and link netns.

---

Please note there're some issues found in current code:

- In amt_newlink() drivers/net/amt.c:

    amt->net = net;
    ...
    amt->stream_dev = dev_get_by_index(net, ...

  Uses net, but amt_lookup_upper_dev() only searches in dev_net.
  So the AMT device may not be properly deleted if it's in a different
  netns from lower dev.

- In lowpan_newlink() in net/ieee802154/6lowpan/core.c:

    wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK]));

  Looks for IFLA_LINK in dev_net, but in theory the ifindex is defined
  in link netns.

And thanks to Kuniyuki for fixing related issues in gtp and pfcp:
https://lore.kernel.org/netdev/20250110014754.33847-1-kuniyu@amazon.com/

v9: https://lore.kernel.org/20250210133002.883422-1-shaw.leon@gmail.com
v8: https://lore.kernel.org/20250113143719.7948-1-shaw.leon@gmail.com
v7: https://lore.kernel.org/20250104125732.17335-1-shaw.leon@gmail.com
v6: https://lore.kernel.org/20241218130909.2173-1-shaw.leon@gmail.com
v5: https://lore.kernel.org/20241209140151.231257-1-shaw.leon@gmail.com
v4: https://lore.kernel.org/20241118143244.1773-1-shaw.leon@gmail.com
v3: https://lore.kernel.org/20241113125715.150201-1-shaw.leon@gmail.com
v2: https://lore.kernel.org/20241107133004.7469-1-shaw.leon@gmail.com
v1: https://lore.kernel.org/20241023023146.372653-1-shaw.leon@gmail.com
====================

Link: https://patch.msgid.link/20250219125039.18024-1-shaw.leon@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4fe67dd2 85cb3711
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -97,10 +97,13 @@ static int ipoib_changelink(struct net_device *dev, struct nlattr *tb[],
	return ret;
}

static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
				struct nlattr *tb[], struct nlattr *data[],
static int ipoib_new_child_link(struct net_device *dev,
				struct rtnl_newlink_params *params,
				struct netlink_ext_ack *extack)
{
	struct net *link_net = rtnl_newlink_link_net(params);
	struct nlattr **data = params->data;
	struct nlattr **tb = params->tb;
	struct net_device *pdev;
	struct ipoib_dev_priv *ppriv;
	u16 child_pkey;
@@ -109,7 +112,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
	if (!tb[IFLA_LINK])
		return -EINVAL;

	pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
	pdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK]));
	if (!pdev || pdev->type != ARPHRD_INFINIBAND)
		return -ENODEV;

+7 −4
Original line number Diff line number Diff line
@@ -3161,14 +3161,17 @@ static int amt_validate(struct nlattr *tb[], struct nlattr *data[],
	return 0;
}

static int amt_newlink(struct net *net, struct net_device *dev,
		       struct nlattr *tb[], struct nlattr *data[],
static int amt_newlink(struct net_device *dev,
		       struct rtnl_newlink_params *params,
		       struct netlink_ext_ack *extack)
{
	struct net *link_net = rtnl_newlink_link_net(params);
	struct amt_dev *amt = netdev_priv(dev);
	struct nlattr **data = params->data;
	struct nlattr **tb = params->tb;
	int err = -EINVAL;

	amt->net = net;
	amt->net = link_net;
	amt->mode = nla_get_u32(data[IFLA_AMT_MODE]);

	if (data[IFLA_AMT_MAX_TUNNELS] &&
@@ -3183,7 +3186,7 @@ static int amt_newlink(struct net *net, struct net_device *dev,
	amt->hash_buckets = AMT_HSIZE;
	amt->nr_tunnels = 0;
	get_random_bytes(&amt->hash_seed, sizeof(amt->hash_seed));
	amt->stream_dev = dev_get_by_index(net,
	amt->stream_dev = dev_get_by_index(link_net,
					   nla_get_u32(data[IFLA_AMT_LINK]));
	if (!amt->stream_dev) {
		NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_LINK],
+6 −3
Original line number Diff line number Diff line
@@ -698,10 +698,13 @@ static void bareudp_dellink(struct net_device *dev, struct list_head *head)
	unregister_netdevice_queue(dev, head);
}

static int bareudp_newlink(struct net *net, struct net_device *dev,
			   struct nlattr *tb[], struct nlattr *data[],
static int bareudp_newlink(struct net_device *dev,
			   struct rtnl_newlink_params *params,
			   struct netlink_ext_ack *extack)
{
	struct net *link_net = rtnl_newlink_link_net(params);
	struct nlattr **data = params->data;
	struct nlattr **tb = params->tb;
	struct bareudp_conf conf;
	int err;

@@ -709,7 +712,7 @@ static int bareudp_newlink(struct net *net, struct net_device *dev,
	if (err)
		return err;

	err = bareudp_configure(net, dev, &conf, extack);
	err = bareudp_configure(link_net, dev, &conf, extack);
	if (err)
		return err;

+4 −2
Original line number Diff line number Diff line
@@ -564,10 +564,12 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
	return 0;
}

static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
			struct nlattr *tb[], struct nlattr *data[],
static int bond_newlink(struct net_device *bond_dev,
			struct rtnl_newlink_params *params,
			struct netlink_ext_ack *extack)
{
	struct nlattr **data = params->data;
	struct nlattr **tb = params->tb;
	int err;

	err = bond_changelink(bond_dev, tb, data, extack);
+2 −2
Original line number Diff line number Diff line
@@ -624,8 +624,8 @@ static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
	return -EMSGSIZE;
}

static int can_newlink(struct net *src_net, struct net_device *dev,
		       struct nlattr *tb[], struct nlattr *data[],
static int can_newlink(struct net_device *dev,
		       struct rtnl_newlink_params *params,
		       struct netlink_ext_ack *extack)
{
	return -EOPNOTSUPP;
Loading