From shaw.leon at gmail.com Mon Feb 10 13:30:19 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:30:19 -0000 Subject: [PATCH net-next v9 00/11] net: Improve netns handling in rtnetlink Message-ID: <20250210133002.883422-1-shaw.leon@gmail.com> 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 ~ 07 converts device drivers to use the explicit netns extracted from params. - Patch 08 ~ 09 removes the old netns parameter, and converts rtnetlink to create device in target netns directly. Patch 10 ~ 11 adds some tests for link name and link netns. BTW 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 at amazon.com/ --- v9: - Change the prototype of macvlan_common_newlink(). - Minor fixes of coding style and local variables. v8: link: https://lore.kernel.org/all/20250113143719.7948-1-shaw.leon at gmail.com/ - Move dev and ext_ack out from param struct. - Validate link_net and dev_net are identical for 6lowpan. v7: link: https://lore.kernel.org/all/20250104125732.17335-1-shaw.leon at gmail.com/ - Add selftest kconfig. - Remove a duplicated test of ip6gre. v6: link: https://lore.kernel.org/all/20241218130909.2173-1-shaw.leon at gmail.com/ - Split prototype, driver and rtnetlink changes. - Add more tests for link netns. - Fix IPv6 tunnel net overwriten in ndo_init(). - Reorder variable declarations. - Exclude a ip_tunnel-specific patch. v5: link: https://lore.kernel.org/all/20241209140151.231257-1-shaw.leon at gmail.com/ - Fix function doc in batman-adv. - Include peer_net in rtnl newlink parameters. v4: link: https://lore.kernel.org/all/20241118143244.1773-1-shaw.leon at gmail.com/ - Pack newlink() parameters to a single struct. - Use ynl async_msg_queue.empty() in selftest. v3: link: https://lore.kernel.org/all/20241113125715.150201-1-shaw.leon at gmail.com/ - Drop "netns_atomic" flag and module parameter. Add netns parameter to newlink() instead, and convert drivers accordingly. - Move python NetNSEnter helper to net selftest lib. v2: link: https://lore.kernel.org/all/20241107133004.7469-1-shaw.leon at gmail.com/ - Check NLM_F_EXCL to ensure only link creation is affected. - Add self tests for link name/ifindex conflict and notifications in different netns. - Changes in dummy driver and ynl in order to add the test case. v1: link: https://lore.kernel.org/all/20241023023146.372653-1-shaw.leon at gmail.com/ Xiao Liang (11): rtnetlink: Lookup device in target netns when creating link rtnetlink: Pack newlink() params into struct net: Use link netns in newlink() of rtnl_link_ops ieee802154: 6lowpan: Validate link netns in newlink() of rtnl_link_ops net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops net: ipv6: Use link netns in newlink() of rtnl_link_ops net: xfrm: Use link netns in newlink() of rtnl_link_ops rtnetlink: Remove "net" from newlink params rtnetlink: Create link directly in target net namespace selftests: net: Add python context manager for netns entering selftests: net: Add test cases for link and peer netns drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 9 +- drivers/net/amt.c | 11 +- drivers/net/bareudp.c | 9 +- drivers/net/bonding/bond_netlink.c | 6 +- drivers/net/can/dev/netlink.c | 4 +- drivers/net/can/vxcan.c | 7 +- .../ethernet/qualcomm/rmnet/rmnet_config.c | 9 +- drivers/net/geneve.c | 9 +- drivers/net/gtp.c | 10 +- drivers/net/ipvlan/ipvlan.h | 3 +- drivers/net/ipvlan/ipvlan_main.c | 8 +- drivers/net/ipvlan/ipvtap.c | 6 +- drivers/net/macsec.c | 9 +- drivers/net/macvlan.c | 21 +-- drivers/net/macvtap.c | 6 +- drivers/net/netkit.c | 14 +- drivers/net/pfcp.c | 9 +- drivers/net/ppp/ppp_generic.c | 9 +- drivers/net/team/team_core.c | 6 +- drivers/net/veth.c | 7 +- drivers/net/vrf.c | 5 +- drivers/net/vxlan/vxlan_core.c | 9 +- drivers/net/wireguard/device.c | 7 +- drivers/net/wireless/virtual/virt_wifi.c | 8 +- drivers/net/wwan/wwan_core.c | 16 +- include/linux/if_macvlan.h | 6 +- include/net/ip_tunnels.h | 5 +- include/net/rtnetlink.h | 40 ++++- net/8021q/vlan_netlink.c | 9 +- net/batman-adv/soft-interface.c | 9 +- net/bridge/br_netlink.c | 6 +- net/caif/chnl_net.c | 5 +- net/core/rtnetlink.c | 34 +++-- net/hsr/hsr_netlink.c | 12 +- net/ieee802154/6lowpan/core.c | 7 +- net/ipv4/ip_gre.c | 22 ++- net/ipv4/ip_tunnel.c | 10 +- net/ipv4/ip_vti.c | 9 +- net/ipv4/ipip.c | 9 +- net/ipv6/ip6_gre.c | 30 ++-- net/ipv6/ip6_tunnel.c | 19 ++- net/ipv6/ip6_vti.c | 15 +- net/ipv6/sit.c | 17 ++- net/xfrm/xfrm_interface_core.c | 15 +- tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/config | 5 + .../testing/selftests/net/lib/py/__init__.py | 2 +- tools/testing/selftests/net/lib/py/netns.py | 18 +++ tools/testing/selftests/net/link_netns.py | 141 ++++++++++++++++++ tools/testing/selftests/net/netns-name.sh | 10 ++ 50 files changed, 494 insertions(+), 179 deletions(-) create mode 100755 tools/testing/selftests/net/link_netns.py -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:30:28 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:30:28 -0000 Subject: [PATCH net-next v9 01/11] rtnetlink: Lookup device in target netns when creating link In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-2-shaw.leon@gmail.com> When creating link, lookup for existing device in target net namespace instead of current one. For example, two links created by: # ip link add dummy1 type dummy # ip link add netns ns1 dummy1 type dummy should have no conflict since they are in different namespaces. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima --- net/core/rtnetlink.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index cb7fad8d1f95..3b3398283a8f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3866,20 +3866,26 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, { struct nlattr ** const tb = tbs->tb; struct net *net = sock_net(skb->sk); + struct net *device_net; struct net_device *dev; struct ifinfomsg *ifm; bool link_specified; + /* When creating, lookup for existing device in target net namespace */ + device_net = (nlh->nlmsg_flags & NLM_F_CREATE) && + (nlh->nlmsg_flags & NLM_F_EXCL) ? + tgt_net : net; + ifm = nlmsg_data(nlh); if (ifm->ifi_index > 0) { link_specified = true; - dev = __dev_get_by_index(net, ifm->ifi_index); + dev = __dev_get_by_index(device_net, ifm->ifi_index); } else if (ifm->ifi_index < 0) { NL_SET_ERR_MSG(extack, "ifindex can't be negative"); return -EINVAL; } else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) { link_specified = true; - dev = rtnl_dev_get(net, tb); + dev = rtnl_dev_get(device_net, tb); } else { link_specified = false; dev = NULL; -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:30:38 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:30:38 -0000 Subject: [PATCH net-next v9 02/11] rtnetlink: Pack newlink() params into struct In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-3-shaw.leon@gmail.com> There are 4 net namespaces involved when creating links: - source netns - where the netlink socket resides, - target netns - where to put the device being created, - link netns - netns associated with the device (backend), - peer netns - netns of peer device. Currently, two nets are passed to newlink() callback - "src_net" parameter and "dev_net" (implicitly in net_device). They are set as follows, depending on netlink attributes in the request. +------------+-------------------+---------+---------+ | peer netns | IFLA_LINK_NETNSID | src_net | dev_net | +------------+-------------------+---------+---------+ | | absent | source | target | | absent +-------------------+---------+---------+ | | present | link | link | +------------+-------------------+---------+---------+ | | absent | peer | target | | present +-------------------+---------+---------+ | | present | peer | link | +------------+-------------------+---------+---------+ When IFLA_LINK_NETNSID is present, the device is created in link netns first and then moved to target netns. This has some side effects, including extra ifindex allocation, ifname validation and link events. These could be avoided if we create it in target netns from the beginning. On the other hand, the meaning of src_net parameter is ambiguous. It varies depending on how parameters are passed. It is the effective link (or peer netns) by design, but some drivers ignore it and use dev_net instead. This patch packs existing newlink() parameters, along with the source netns, link netns and peer netns, into a struct. The old "src_net" is renamed to "net" to avoid confusion with real source netns, and will be deprecated later. The use of src_net are converted to params->net trivially. To make the semantics more clear, two helper functions - rtnl_newlink_link_net() and rtnl_newlink_peer_net() - are provided for netns fallback logic. Peer netns falls back to link netns, and link netns falls back to source netns. In following patches, to prepare for creating link in target netns directly: - For device drivers that are aware of the old "src_net", the use of it are replace with one of the two helper functions. - And for those that takes dev_net() as link netns, we try params->link_net and then dev_net(), in order to maintain compatibility with the old behavior. Signed-off-by: Xiao Liang --- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 7 +++- drivers/net/amt.c | 7 +++- drivers/net/bareudp.c | 7 +++- drivers/net/bonding/bond_netlink.c | 6 ++- drivers/net/can/dev/netlink.c | 4 +- drivers/net/can/vxcan.c | 7 +++- .../ethernet/qualcomm/rmnet/rmnet_config.c | 7 +++- drivers/net/geneve.c | 7 +++- drivers/net/gtp.c | 6 ++- drivers/net/ipvlan/ipvlan.h | 3 +- drivers/net/ipvlan/ipvlan_main.c | 6 ++- drivers/net/ipvlan/ipvtap.c | 6 +-- drivers/net/macsec.c | 7 +++- drivers/net/macvlan.c | 19 +++++---- drivers/net/macvtap.c | 6 +-- drivers/net/netkit.c | 14 ++++--- drivers/net/pfcp.c | 5 ++- drivers/net/ppp/ppp_generic.c | 7 +++- drivers/net/team/team_core.c | 6 ++- drivers/net/veth.c | 7 +++- drivers/net/vrf.c | 5 ++- drivers/net/vxlan/vxlan_core.c | 7 +++- drivers/net/wireguard/device.c | 5 ++- drivers/net/wireless/virtual/virt_wifi.c | 6 ++- drivers/net/wwan/wwan_core.c | 16 +++++-- include/linux/if_macvlan.h | 6 ++- include/net/rtnetlink.h | 42 +++++++++++++++++-- net/8021q/vlan_netlink.c | 7 +++- net/batman-adv/soft-interface.c | 9 ++-- net/bridge/br_netlink.c | 6 ++- net/caif/chnl_net.c | 5 ++- net/core/rtnetlink.c | 15 +++++-- net/hsr/hsr_netlink.c | 6 ++- net/ieee802154/6lowpan/core.c | 5 ++- net/ipv4/ip_gre.c | 16 ++++--- net/ipv4/ip_vti.c | 6 ++- net/ipv4/ipip.c | 6 ++- net/ipv6/ip6_gre.c | 14 +++++-- net/ipv6/ip6_tunnel.c | 6 ++- net/ipv6/ip6_vti.c | 5 ++- net/ipv6/sit.c | 6 ++- net/xfrm/xfrm_interface_core.c | 7 ++-- 42 files changed, 240 insertions(+), 110 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 9ad8d9856275..16cb8ced9f35 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -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 nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *pdev; struct ipoib_dev_priv *ppriv; u16 child_pkey; diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 98c6205ed19f..96b7ec9a2c13 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -3161,11 +3161,14 @@ 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 amt_dev *amt = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; int err = -EINVAL; amt->net = net; diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index 70814303aab8..fc21dcfb4848 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -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 nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; struct bareudp_conf conf; int err; diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 2a6a424806aa..ac5e402c34bc 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -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); diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 01aacdcda260..f1db9b7ffd4d 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -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; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index ca8811941085..6f8ebb1cfd7b 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -172,10 +172,13 @@ static void vxcan_setup(struct net_device *dev) /* forward declaration for rtnl_create_link() */ static struct rtnl_link_ops vxcan_link_ops; -static int vxcan_newlink(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vxcan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *peer_net = params->net; + struct nlattr **tb = params->tb; struct vxcan_priv *priv; struct net_device *peer; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index f3bea196a8f9..8151e91395e2 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -117,11 +117,14 @@ static void rmnet_unregister_bridge(struct rmnet_port *port) rmnet_unregister_real_device(bridge_dev); } -static int rmnet_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int rmnet_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION; + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *real_dev; int mode = RMNET_EPMODE_VND; struct rmnet_endpoint *ep; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 642155cb8315..d373a851930c 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1614,10 +1614,13 @@ static void geneve_link_config(struct net_device *dev, geneve_change_mtu(dev, ldev_mtu - info->options_len); } -static int geneve_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int geneve_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; struct geneve_config cfg = { .df = GENEVE_DF_UNSET, .use_udp6_rx_checksums = false, diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index d64740bf44ed..d6d4326cb908 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1462,10 +1462,12 @@ static int gtp_create_sockets(struct gtp_dev *gtp, const struct nlattr *nla, #define GTP_TH_MAXLEN (sizeof(struct udphdr) + sizeof(struct gtp0_header)) #define GTP_IPV6_MAXLEN (sizeof(struct ipv6hdr) + GTP_TH_MAXLEN) -static int gtp_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int gtp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; unsigned int role = GTP_ROLE_GGSN; struct gtp_dev *gtp; struct gtp_net *gn; diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 025e0c19ec25..50de3ee204db 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -166,8 +166,7 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type); void ipvlan_count_rx(const struct ipvl_dev *ipvlan, unsigned int len, bool success, bool mcast); -int ipvlan_link_new(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); void ipvlan_link_delete(struct net_device *dev, struct list_head *head); void ipvlan_link_setup(struct net_device *dev); diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index da3a97a65507..19ce19ca7e32 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -532,11 +532,13 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb, return ret; } -int ipvlan_link_new(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ipvl_dev *ipvlan = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct ipvl_port *port; struct net_device *phy_dev; int err; diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c index 1afc4c47be73..edd13916831a 100644 --- a/drivers/net/ipvlan/ipvtap.c +++ b/drivers/net/ipvlan/ipvtap.c @@ -73,8 +73,8 @@ static void ipvtap_update_features(struct tap_dev *tap, netdev_update_features(vlan->dev); } -static int ipvtap_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipvtap_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ipvtap_dev *vlantap = netdev_priv(dev); @@ -97,7 +97,7 @@ static int ipvtap_newlink(struct net *src_net, struct net_device *dev, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - err = ipvlan_link_new(src_net, dev, tb, data, extack); + err = ipvlan_link_new(dev, params, extack); if (err) { netdev_rx_handler_unregister(dev); return err; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1bc1e5993f56..1869b0513f57 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -4141,11 +4141,14 @@ static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len) static struct lock_class_key macsec_netdev_addr_lock_key; -static int macsec_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macsec_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macsec_dev *macsec = macsec_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; rx_handler_func_t *rx_handler; u8 icv_len = MACSEC_DEFAULT_ICV_LEN; struct net_device *real_dev; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fed4fe2a4748..f903b414eaeb 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1440,16 +1440,19 @@ static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode, return 0; } -int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int macvlan_common_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macvlan_dev *vlan = netdev_priv(dev); - struct macvlan_port *port; + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *lowerdev; - int err; - int macmode; + struct macvlan_port *port; bool create = false; + int macmode; + int err; if (!tb[IFLA_LINK]) return -EINVAL; @@ -1565,11 +1568,11 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, } EXPORT_SYMBOL_GPL(macvlan_common_newlink); -static int macvlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macvlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { - return macvlan_common_newlink(src_net, dev, tb, data, extack); + return macvlan_common_newlink(dev, params, extack); } void macvlan_dellink(struct net_device *dev, struct list_head *head) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 29a5929d48e5..b391a0f740a3 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -77,8 +77,8 @@ static void macvtap_update_features(struct tap_dev *tap, netdev_update_features(vlan->dev); } -static int macvtap_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macvtap_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macvtap_dev *vlantap = netdev_priv(dev); @@ -105,7 +105,7 @@ static int macvtap_newlink(struct net *src_net, struct net_device *dev, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - err = macvlan_common_newlink(src_net, dev, tb, data, extack); + err = macvlan_common_newlink(dev, params, extack); if (err) { netdev_rx_handler_unregister(dev); return err; diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index 1e1b00756be7..640a2dbbbd28 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -327,17 +327,20 @@ static int netkit_validate(struct nlattr *tb[], struct nlattr *data[], static struct rtnl_link_ops netkit_link_ops; -static int netkit_new_link(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int netkit_new_link(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { - struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb, *attr; - enum netkit_action policy_prim = NETKIT_PASS; - enum netkit_action policy_peer = NETKIT_PASS; enum netkit_scrub scrub_prim = NETKIT_SCRUB_DEFAULT; enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT; + struct nlattr *peer_tb[IFLA_MAX + 1], **tbp, *attr; + enum netkit_action policy_prim = NETKIT_PASS; + enum netkit_action policy_peer = NETKIT_PASS; + struct nlattr **data = params->data; + struct net *peer_net = params->net; enum netkit_mode mode = NETKIT_L3; unsigned char ifname_assign_type; + struct nlattr **tb = params->tb; u16 headroom = 0, tailroom = 0; struct ifinfomsg *ifmp = NULL; struct net_device *peer; @@ -345,6 +348,7 @@ static int netkit_new_link(struct net *peer_net, struct net_device *dev, struct netkit *nk; int err; + tbp = tb; if (data) { if (data[IFLA_NETKIT_MODE]) mode = nla_get_u32(data[IFLA_NETKIT_MODE]); diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 68d0d9e92a22..7b0575940e1d 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -184,11 +184,12 @@ static int pfcp_add_sock(struct pfcp_dev *pfcp) return PTR_ERR_OR_ZERO(pfcp->sock); } -static int pfcp_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int pfcp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct pfcp_dev *pfcp = netdev_priv(dev); + struct net *net = params->net; struct pfcp_net *pn; int err; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 4583e15ad03a..b3340f8a6149 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1303,10 +1303,13 @@ static int ppp_nl_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int ppp_nl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ppp_nl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct ppp_config conf = { .unit = -1, .ifname_is_set = true, diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index dc7cbd6a9798..10e03fa33530 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -2218,10 +2218,12 @@ static void team_setup(struct net_device *dev) dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; } -static int team_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int team_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **tb = params->tb; + if (tb[IFLA_ADDRESS] == NULL) eth_hw_addr_random(dev); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 01251868a9c2..7dfda89f072f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1765,10 +1765,13 @@ static int veth_init_queues(struct net_device *dev, struct nlattr *tb[]) return 0; } -static int veth_newlink(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int veth_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *peer_net = params->net; + struct nlattr **tb = params->tb; int err; struct net_device *peer; struct veth_priv *priv; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index ca81b212a246..b2cf13ac0e47 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1677,11 +1677,12 @@ static void vrf_dellink(struct net_device *dev, struct list_head *head) unregister_netdevice_queue(dev, head); } -static int vrf_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vrf_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct net_vrf *vrf = netdev_priv(dev); + struct nlattr **data = params->data; struct netns_vrf *nn_vrf; bool *add_fib_rules; struct net *net; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 44eba7aa831a..69ee76172cd2 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -4397,10 +4397,13 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int vxlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vxlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct vxlan_config conf; int err; diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 6cf173a008e7..404cf05bd72b 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -307,11 +307,12 @@ static void wg_setup(struct net_device *dev) wg->dev = dev; } -static int wg_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int wg_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct wg_device *wg = netdev_priv(dev); + struct net *src_net = params->net; int ret = -ENOMEM; rcu_assign_pointer(wg->creating_net, src_net); diff --git a/drivers/net/wireless/virtual/virt_wifi.c b/drivers/net/wireless/virtual/virt_wifi.c index 4ee374080466..26905b2b3ba3 100644 --- a/drivers/net/wireless/virtual/virt_wifi.c +++ b/drivers/net/wireless/virtual/virt_wifi.c @@ -519,11 +519,13 @@ static rx_handler_result_t virt_wifi_rx_handler(struct sk_buff **pskb) } /* Called with rtnl lock held. */ -static int virt_wifi_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int virt_wifi_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + struct net *src_net = params->net; + struct nlattr **tb = params->tb; int err; if (!tb[IFLA_LINK]) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index a51e2755991a..a05c49b4e7f8 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -967,15 +967,18 @@ static struct net_device *wwan_rtnl_alloc(struct nlattr *tb[], return dev; } -static int wwan_rtnl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int wwan_rtnl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct wwan_device *wwandev = wwan_dev_get_by_parent(dev->dev.parent); - u32 link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); struct wwan_netdev_priv *priv = netdev_priv(dev); + struct nlattr **data = params->data; + u32 link_id; int ret; + link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); + if (IS_ERR(wwandev)) return PTR_ERR(wwandev); @@ -1061,6 +1064,11 @@ static void wwan_create_default_link(struct wwan_device *wwandev, { struct nlattr *tb[IFLA_MAX + 1], *linkinfo[IFLA_INFO_MAX + 1]; struct nlattr *data[IFLA_WWAN_MAX + 1]; + struct rtnl_newlink_params params = { + .net = &init_net, + .tb = tb, + .data = data, + }; struct net_device *dev; struct nlmsghdr *nlh; struct sk_buff *msg; @@ -1105,7 +1113,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev, if (WARN_ON(IS_ERR(dev))) goto unlock; - if (WARN_ON(wwan_rtnl_newlink(&init_net, dev, tb, data, NULL))) { + if (WARN_ON(wwan_rtnl_newlink(dev, ¶ms, NULL))) { free_netdev(dev); goto unlock; } diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 523025106a64..0f7281e3e448 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, extern void macvlan_common_setup(struct net_device *dev); -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +struct rtnl_newlink_params; + +extern int macvlan_common_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); extern void macvlan_dellink(struct net_device *dev, struct list_head *head); diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index bc0069a8b6ea..00c086ca0c11 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -69,6 +69,42 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) return AF_UNSPEC; } +/** + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() + * + * @net: Netns of interest + * @src_net: Source netns of rtnetlink socket + * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified + * @peer_net: Peer netns + * @tb: IFLA_* attributes + * @data: IFLA_INFO_DATA attributes + */ +struct rtnl_newlink_params { + struct net *net; + struct net *src_net; + struct net *link_net; + struct net *peer_net; + struct nlattr **tb; + struct nlattr **data; +}; + +/* Get effective link netns from newlink params. Generally, this is link_net + * and falls back to src_net. But for compatibility, a driver may * choose to + * use dev_net(dev) instead. + */ +static inline struct net *rtnl_newlink_link_net(struct rtnl_newlink_params *p) +{ + return p->link_net ? : p->src_net; +} + +/* Get peer netns from newlink params. Fallback to link netns if peer netns is + * not specified explicitly. + */ +static inline struct net *rtnl_newlink_peer_net(struct rtnl_newlink_params *p) +{ + return p->peer_net ? : rtnl_newlink_link_net(p); +} + /** * struct rtnl_link_ops - rtnetlink link operations * @@ -125,10 +161,8 @@ struct rtnl_link_ops { struct nlattr *data[], struct netlink_ext_ack *extack); - int (*newlink)(struct net *src_net, - struct net_device *dev, - struct nlattr *tb[], - struct nlattr *data[], + int (*newlink)(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); int (*changelink)(struct net_device *dev, struct nlattr *tb[], diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 134419667d59..91df0f96e32a 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -135,11 +135,14 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], return 0; } -static int vlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *real_dev; unsigned int max_mtu; __be16 proto; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 822d788a5f86..d893c8013261 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -1077,19 +1077,18 @@ static int batadv_softif_validate(struct nlattr *tb[], struct nlattr *data[], /** * batadv_softif_newlink() - pre-initialize and register new batadv link - * @src_net: the applicable net namespace * @dev: network device to register - * @tb: IFLA_INFO_DATA netlink attributes - * @data: enum batadv_ifla_attrs attributes + * @params: rtnl newlink parameters * @extack: extended ACK report struct * * Return: 0 if successful or error otherwise. */ -static int batadv_softif_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int batadv_softif_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct batadv_priv *bat_priv = netdev_priv(dev); + struct nlattr **data = params->data; const char *algo_name; int err; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 3e0f47203f2a..6e337937d0d7 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1553,11 +1553,13 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], return 0; } -static int br_dev_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int br_dev_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct net_bridge *br = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; int err; err = register_netdevice(dev); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 94ad09e36df2..fa6a3c2634a8 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -438,10 +438,11 @@ static void caif_netlink_parms(struct nlattr *data[], } } -static int ipcaif_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipcaif_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; int ret; struct chnl_net *caifdev; ASSERT_RTNL(); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 3b3398283a8f..7e98f3cd102b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3766,7 +3766,13 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, struct netlink_ext_ack *extack) { unsigned char name_assign_type = NET_NAME_USER; - struct net *net = sock_net(skb->sk); + struct rtnl_newlink_params params = { + .src_net = sock_net(skb->sk), + .link_net = link_net, + .peer_net = peer_net, + .tb = tb, + .data = data, + }; u32 portid = NETLINK_CB(skb).portid; struct net_device *dev; char ifname[IFNAMSIZ]; @@ -3791,13 +3797,14 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, dev->ifindex = ifm->ifi_index; + params.net = params.src_net; if (link_net) - net = link_net; + params.net = link_net; if (peer_net) - net = peer_net; + params.net = peer_net; if (ops->newlink) - err = ops->newlink(net, dev, tb, data, extack); + err = ops->newlink(dev, ¶ms, extack); else err = register_netdevice(dev); if (err < 0) { diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index b68f2f71d0e1..39add538ba99 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -29,10 +29,12 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { /* Here, it seems a netdevice has already been allocated for us, and the * hsr_dev_setup routine has been executed. Nice! */ -static int hsr_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int hsr_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; enum hsr_version proto_version; unsigned char multicast_spec; u8 proto = HSR_PROTOCOL_HSR; diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 175efd860f7b..704bf9e3f097 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -129,10 +129,11 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int lowpan_newlink(struct net *src_net, struct net_device *ldev, - struct nlattr *tb[], struct nlattr *data[], +static int lowpan_newlink(struct net_device *ldev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **tb = params->tb; struct net_device *wdev; int ret; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c9f11a046c26..1fe9b13d351c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1396,10 +1396,12 @@ ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[]) return 0; } -static int ipgre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipgre_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; int err; @@ -1414,10 +1416,12 @@ static int ipgre_newlink(struct net *src_net, struct net_device *dev, return ip_tunnel_newlink(dev, tb, &p, fwmark); } -static int erspan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int erspan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; int err; @@ -1697,6 +1701,7 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = { struct net_device *gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { + struct rtnl_newlink_params params = { .net = net }; struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; LIST_HEAD(list_kill); @@ -1704,6 +1709,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, int err; memset(&tb, 0, sizeof(tb)); + params.tb = tb; dev = rtnl_create_link(net, name, name_assign_type, &ipgre_tap_ops, tb, NULL); @@ -1714,7 +1720,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, t = netdev_priv(dev); t->collect_md = true; - err = ipgre_newlink(net, dev, tb, NULL, NULL); + err = ipgre_newlink(dev, ¶ms, NULL); if (err < 0) { free_netdev(dev); return ERR_PTR(err); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index f0b4419cef34..b901bee03e6d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -575,11 +575,13 @@ static void vti_netlink_parms(struct nlattr *data[], *fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]); } -static int vti_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vti_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct ip_tunnel_parm_kern parms; + struct nlattr **tb = params->tb; __u32 fwmark = 0; vti_netlink_parms(data, &parms, &fwmark); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index dc0db5895e0e..a8b844bcfc64 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -436,11 +436,13 @@ static void ipip_netlink_parms(struct nlattr *data[], *fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); } -static int ipip_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipip_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip_tunnel *t = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_encap ipencap; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 235808cfec70..863852abe8ea 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -2005,11 +2005,14 @@ static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev, return err; } -static int ip6gre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6gre_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip6_tnl *nt = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2241,11 +2244,14 @@ static void ip6erspan_tap_setup(struct net_device *dev) netif_keep_dst(dev); } -static int ip6erspan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6erspan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip6_tnl *nt = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 48fd53b98972..54b843d20870 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -2002,10 +2002,12 @@ static void ip6_tnl_netlink_parms(struct nlattr *data[], parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); } -static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6_tnl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); struct ip_tunnel_encap ipencap; diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 590737c27537..993f85aeb882 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -997,10 +997,11 @@ static void vti6_netlink_parms(struct nlattr *data[], parms->fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]); } -static int vti6_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vti6_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct net *net = dev_net(dev); struct ip6_tnl *nt; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 39bd8951bfca..e2bd52cabdee 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1550,10 +1550,12 @@ static bool ipip6_netlink_6rd_parms(struct nlattr *data[], } #endif -static int ipip6_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipip6_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip_tunnel *nt; struct ip_tunnel_encap ipencap; diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index c397eb99d867..5659a6cadd51 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -814,10 +814,11 @@ static void xfrmi_netlink_parms(struct nlattr *data[], parms->collect_md = true; } -static int xfrmi_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) +static int xfrmi_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, + struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct net *net = dev_net(dev); struct xfrm_if_parms p = {}; struct xfrm_if *xi; -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:30:47 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:30:47 -0000 Subject: [PATCH net-next v9 03/11] net: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-4-shaw.leon@gmail.com> These netdevice drivers already uses netns parameter in newlink() callback. Convert them to use rtnl_newlink_link_net() or rtnl_newlink_peer_net() for clarity and deprecate params->net. Signed-off-by: Xiao Liang --- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 4 ++-- drivers/net/amt.c | 6 +++--- drivers/net/bareudp.c | 4 ++-- drivers/net/can/vxcan.c | 2 +- drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 4 ++-- drivers/net/geneve.c | 4 ++-- drivers/net/gtp.c | 6 +++--- drivers/net/ipvlan/ipvlan_main.c | 4 ++-- drivers/net/macsec.c | 4 ++-- drivers/net/macvlan.c | 4 ++-- drivers/net/netkit.c | 2 +- drivers/net/pfcp.c | 6 +++--- drivers/net/ppp/ppp_generic.c | 4 ++-- drivers/net/veth.c | 2 +- drivers/net/vxlan/vxlan_core.c | 4 ++-- drivers/net/wireguard/device.c | 4 ++-- drivers/net/wireless/virtual/virt_wifi.c | 4 ++-- drivers/net/wwan/wwan_core.c | 2 +- net/8021q/vlan_netlink.c | 4 ++-- net/hsr/hsr_netlink.c | 8 ++++---- 20 files changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 16cb8ced9f35..53db7c8191e3 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -101,8 +101,8 @@ 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 net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *pdev; struct ipoib_dev_priv *ppriv; @@ -112,7 +112,7 @@ static int ipoib_new_child_link(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; diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 96b7ec9a2c13..53899b70fae1 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -3165,13 +3165,13 @@ 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; - struct net *net = params->net; 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] && @@ -3186,7 +3186,7 @@ static int amt_newlink(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], diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index fc21dcfb4848..d1473c5f8eef 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -702,9 +702,9 @@ 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 net *net = params->net; struct bareudp_conf conf; int err; @@ -712,7 +712,7 @@ static int bareudp_newlink(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; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 6f8ebb1cfd7b..99a78a757167 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -176,8 +176,8 @@ static int vxcan_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *peer_net = rtnl_newlink_peer_net(params); struct nlattr **data = params->data; - struct net *peer_net = params->net; struct nlattr **tb = params->tb; struct vxcan_priv *priv; struct net_device *peer; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index 8151e91395e2..ab7e5b6649b2 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -122,8 +122,8 @@ static int rmnet_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION; + struct net *link_net = rtnl_newlink_link_net(params); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *real_dev; int mode = RMNET_EPMODE_VND; @@ -137,7 +137,7 @@ static int rmnet_newlink(struct net_device *dev, return -EINVAL; } - real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) { NL_SET_ERR_MSG_MOD(extack, "link does not exist"); return -ENODEV; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index d373a851930c..c7700deefb00 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1618,9 +1618,9 @@ static int geneve_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 net *net = params->net; struct geneve_config cfg = { .df = GENEVE_DF_UNSET, .use_udp6_rx_checksums = false, @@ -1634,7 +1634,7 @@ static int geneve_newlink(struct net_device *dev, if (err) return err; - err = geneve_configure(net, dev, extack, &cfg); + err = geneve_configure(link_net, dev, extack, &cfg); if (err) return err; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index d6d4326cb908..2cf43e7d0edc 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1466,8 +1466,8 @@ static int gtp_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 net *src_net = params->net; unsigned int role = GTP_ROLE_GGSN; struct gtp_dev *gtp; struct gtp_net *gn; @@ -1498,7 +1498,7 @@ static int gtp_newlink(struct net_device *dev, gtp->restart_count = nla_get_u8_default(data[IFLA_GTP_RESTART_COUNT], 0); - gtp->net = src_net; + gtp->net = link_net; err = gtp_hashtable_new(gtp, hashsize); if (err < 0) @@ -1528,7 +1528,7 @@ static int gtp_newlink(struct net_device *dev, goto out_encap; } - gn = net_generic(src_net, gtp_net_id); + gn = net_generic(link_net, gtp_net_id); list_add(>p->list, &gn->gtp_dev_list); dev->priv_destructor = gtp_destructor; diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 19ce19ca7e32..b56144ca2fde 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -535,9 +535,9 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb, int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *link_net = rtnl_newlink_link_net(params); struct ipvl_dev *ipvlan = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct ipvl_port *port; struct net_device *phy_dev; @@ -547,7 +547,7 @@ int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, if (!tb[IFLA_LINK]) return -EINVAL; - phy_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + phy_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!phy_dev) return -ENODEV; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1869b0513f57..4de5d63fd577 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -4145,10 +4145,10 @@ static int macsec_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 macsec_dev *macsec = macsec_priv(dev); struct nlattr **data = params->data; struct nlattr **tb = params->tb; - struct net *net = params->net; rx_handler_func_t *rx_handler; u8 icv_len = MACSEC_DEFAULT_ICV_LEN; struct net_device *real_dev; @@ -4157,7 +4157,7 @@ static int macsec_newlink(struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) return -ENODEV; if (real_dev->type != ARPHRD_ETHER) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index f903b414eaeb..4e9d54be887c 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1444,9 +1444,9 @@ int macvlan_common_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 macvlan_dev *vlan = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *lowerdev; struct macvlan_port *port; @@ -1457,7 +1457,7 @@ int macvlan_common_newlink(struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + lowerdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (lowerdev == NULL) return -ENODEV; diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index 640a2dbbbd28..751347392570 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -331,13 +331,13 @@ static int netkit_new_link(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *peer_net = rtnl_newlink_peer_net(params); enum netkit_scrub scrub_prim = NETKIT_SCRUB_DEFAULT; enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT; struct nlattr *peer_tb[IFLA_MAX + 1], **tbp, *attr; enum netkit_action policy_prim = NETKIT_PASS; enum netkit_action policy_peer = NETKIT_PASS; struct nlattr **data = params->data; - struct net *peer_net = params->net; enum netkit_mode mode = NETKIT_L3; unsigned char ifname_assign_type; struct nlattr **tb = params->tb; diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 7b0575940e1d..f873a92d2445 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -188,12 +188,12 @@ static int pfcp_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 pfcp_dev *pfcp = netdev_priv(dev); - struct net *net = params->net; struct pfcp_net *pn; int err; - pfcp->net = net; + pfcp->net = link_net; err = pfcp_add_sock(pfcp); if (err) { @@ -207,7 +207,7 @@ static int pfcp_newlink(struct net_device *dev, goto exit_del_pfcp_sock; } - pn = net_generic(net, pfcp_net_id); + pn = net_generic(link_net, pfcp_net_id); list_add(&pfcp->list, &pn->pfcp_dev_list); netdev_dbg(dev, "registered new PFCP interface\n"); diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index b3340f8a6149..6220866258fc 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1307,8 +1307,8 @@ static int ppp_nl_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 net *src_net = params->net; struct nlattr **tb = params->tb; struct ppp_config conf = { .unit = -1, @@ -1346,7 +1346,7 @@ static int ppp_nl_newlink(struct net_device *dev, if (!tb[IFLA_IFNAME] || !nla_len(tb[IFLA_IFNAME]) || !*(char *)nla_data(tb[IFLA_IFNAME])) conf.ifname_is_set = false; - err = ppp_dev_configure(src_net, dev, &conf); + err = ppp_dev_configure(link_net, dev, &conf); out_unlock: mutex_unlock(&ppp_mutex); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 7dfda89f072f..ba3ae2d8092f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1769,8 +1769,8 @@ static int veth_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *peer_net = rtnl_newlink_peer_net(params); struct nlattr **data = params->data; - struct net *peer_net = params->net; struct nlattr **tb = params->tb; int err; struct net_device *peer; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 69ee76172cd2..d342ba899a69 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -4401,8 +4401,8 @@ static int vxlan_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 net *src_net = params->net; struct nlattr **tb = params->tb; struct vxlan_config conf; int err; @@ -4411,7 +4411,7 @@ static int vxlan_newlink(struct net_device *dev, if (err) return err; - return __vxlan_dev_create(src_net, dev, &conf, extack); + return __vxlan_dev_create(link_net, dev, &conf, extack); } static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 404cf05bd72b..c496d35b266d 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -311,11 +311,11 @@ static int wg_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 wg_device *wg = netdev_priv(dev); - struct net *src_net = params->net; int ret = -ENOMEM; - rcu_assign_pointer(wg->creating_net, src_net); + rcu_assign_pointer(wg->creating_net, link_net); init_rwsem(&wg->static_identity.lock); mutex_init(&wg->socket_update_lock); mutex_init(&wg->device_update_lock); diff --git a/drivers/net/wireless/virtual/virt_wifi.c b/drivers/net/wireless/virtual/virt_wifi.c index 26905b2b3ba3..f9d11a023313 100644 --- a/drivers/net/wireless/virtual/virt_wifi.c +++ b/drivers/net/wireless/virtual/virt_wifi.c @@ -524,7 +524,7 @@ static int virt_wifi_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); - struct net *src_net = params->net; + struct net *link_net = rtnl_newlink_link_net(params); struct nlattr **tb = params->tb; int err; @@ -534,7 +534,7 @@ static int virt_wifi_newlink(struct net_device *dev, netif_carrier_off(dev); priv->upperdev = dev; - priv->lowerdev = __dev_get_by_index(src_net, + priv->lowerdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!priv->lowerdev) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index a05c49b4e7f8..63a47d420bc5 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -1065,7 +1065,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev, struct nlattr *tb[IFLA_MAX + 1], *linkinfo[IFLA_INFO_MAX + 1]; struct nlattr *data[IFLA_WWAN_MAX + 1]; struct rtnl_newlink_params params = { - .net = &init_net, + .src_net = &init_net, .tb = tb, .data = data, }; diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 91df0f96e32a..a000b1ef0520 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -139,9 +139,9 @@ static int vlan_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 vlan_dev_priv *vlan = vlan_dev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *real_dev; unsigned int max_mtu; @@ -158,7 +158,7 @@ static int vlan_newlink(struct net_device *dev, return -EINVAL; } - real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) { NL_SET_ERR_MSG_MOD(extack, "link does not exist"); return -ENODEV; diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 39add538ba99..b120470246cc 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -33,8 +33,8 @@ static int hsr_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 net *src_net = params->net; enum hsr_version proto_version; unsigned char multicast_spec; u8 proto = HSR_PROTOCOL_HSR; @@ -48,7 +48,7 @@ static int hsr_newlink(struct net_device *dev, NL_SET_ERR_MSG_MOD(extack, "Slave1 device not specified"); return -EINVAL; } - link[0] = __dev_get_by_index(src_net, + link[0] = __dev_get_by_index(link_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); if (!link[0]) { NL_SET_ERR_MSG_MOD(extack, "Slave1 does not exist"); @@ -58,7 +58,7 @@ static int hsr_newlink(struct net_device *dev, NL_SET_ERR_MSG_MOD(extack, "Slave2 device not specified"); return -EINVAL; } - link[1] = __dev_get_by_index(src_net, + link[1] = __dev_get_by_index(link_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); if (!link[1]) { NL_SET_ERR_MSG_MOD(extack, "Slave2 does not exist"); @@ -71,7 +71,7 @@ static int hsr_newlink(struct net_device *dev, } if (data[IFLA_HSR_INTERLINK]) - interlink = __dev_get_by_index(src_net, + interlink = __dev_get_by_index(link_net, nla_get_u32(data[IFLA_HSR_INTERLINK])); if (interlink && interlink == link[0]) { -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:30:56 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:30:56 -0000 Subject: [PATCH net-next v9 04/11] ieee802154: 6lowpan: Validate link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-5-shaw.leon@gmail.com> Device denoted by IFLA_LINK is in link_net (IFLA_LINK_NETNSID) or source netns by design, but 6lowpan uses dev_net. Note dev->netns_local is set to true and currently link_net is implemented via a netns change. These together effectively reject IFLA_LINK_NETNSID. This patch adds a validation to ensure link_net is either NULL or identical to dev_net. Thus it would be fine to continue using dev_net when rtnetlink core begins to create devices directly in target netns. Signed-off-by: Xiao Liang --- net/ieee802154/6lowpan/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 704bf9e3f097..ee318d46817d 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -143,6 +143,8 @@ static int lowpan_newlink(struct net_device *ldev, if (!tb[IFLA_LINK]) return -EINVAL; + if (params->link_net && !net_eq(params->link_net, dev_net(ldev))) + return -EINVAL; /* find and hold wpan device */ wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK])); if (!wdev) -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:31:05 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:31:05 -0000 Subject: [PATCH net-next v9 05/11] net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-6-shaw.leon@gmail.com> When link_net is set, use it as link netns instead of dev_net(). This prepares for rtnetlink core to create device in target netns directly, in which case the two namespaces may be different. Convert common ip_tunnel_newlink() to accept an extra link netns argument. Don't overwrite ip_tunnel.net in ip_tunnel_init(). Signed-off-by: Xiao Liang --- include/net/ip_tunnels.h | 5 +++-- net/ipv4/ip_gre.c | 8 +++++--- net/ipv4/ip_tunnel.c | 10 ++++++---- net/ipv4/ip_vti.c | 3 ++- net/ipv4/ipip.c | 3 ++- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 1aa31bdb2b31..ae1f2dda4533 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -406,8 +406,9 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, bool log_ecn_error); int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm_kern *p, __u32 fwmark); -int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], - struct ip_tunnel_parm_kern *p, __u32 fwmark); +int ip_tunnel_newlink(struct net *net, struct net_device *dev, + struct nlattr *tb[], struct ip_tunnel_parm_kern *p, + __u32 fwmark); void ip_tunnel_setup(struct net_device *dev, unsigned int net_id); bool ip_tunnel_netlink_encap_parms(struct nlattr *data[], diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 1fe9b13d351c..26d15f907551 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1413,7 +1413,8 @@ static int ipgre_newlink(struct net_device *dev, err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); if (err < 0) return err; - return ip_tunnel_newlink(dev, tb, &p, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, + fwmark); } static int erspan_newlink(struct net_device *dev, @@ -1433,7 +1434,8 @@ static int erspan_newlink(struct net_device *dev, err = erspan_netlink_parms(dev, data, tb, &p, &fwmark); if (err) return err; - return ip_tunnel_newlink(dev, tb, &p, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, + fwmark); } static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], @@ -1701,7 +1703,7 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = { struct net_device *gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { - struct rtnl_newlink_params params = { .net = net }; + struct rtnl_newlink_params params = { .src_net = net }; struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; LIST_HEAD(list_kill); diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 09b73acf037a..618a50d5c0c2 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -1213,11 +1213,11 @@ void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id, } EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets); -int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], - struct ip_tunnel_parm_kern *p, __u32 fwmark) +int ip_tunnel_newlink(struct net *net, struct net_device *dev, + struct nlattr *tb[], struct ip_tunnel_parm_kern *p, + __u32 fwmark) { struct ip_tunnel *nt; - struct net *net = dev_net(dev); struct ip_tunnel_net *itn; int mtu; int err; @@ -1326,7 +1326,9 @@ int ip_tunnel_init(struct net_device *dev) } tunnel->dev = dev; - tunnel->net = dev_net(dev); + if (!tunnel->net) + tunnel->net = dev_net(dev); + strscpy(tunnel->parms.name, dev->name); iph->version = 4; iph->ihl = 5; diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index b901bee03e6d..159b4473290e 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -585,7 +585,8 @@ static int vti_newlink(struct net_device *dev, __u32 fwmark = 0; vti_netlink_parms(data, &parms, &fwmark); - return ip_tunnel_newlink(dev, tb, &parms, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, + &parms, fwmark); } static int vti_changelink(struct net_device *dev, struct nlattr *tb[], diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index a8b844bcfc64..bab0bf90c908 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -455,7 +455,8 @@ static int ipip_newlink(struct net_device *dev, } ipip_netlink_parms(data, &p, &t->collect_md, &fwmark); - return ip_tunnel_newlink(dev, tb, &p, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, + fwmark); } static int ipip_changelink(struct net_device *dev, struct nlattr *tb[], -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:31:14 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:31:14 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-7-shaw.leon@gmail.com> When link_net is set, use it as link netns instead of dev_net(). This prepares for rtnetlink core to create device in target netns directly, in which case the two namespaces may be different. Set correct netns in priv before registering device, and avoid overwriting it in ndo_init() path. Signed-off-by: Xiao Liang --- net/ipv6/ip6_gre.c | 20 ++++++++++---------- net/ipv6/ip6_tunnel.c | 13 ++++++++----- net/ipv6/ip6_vti.c | 10 ++++++---- net/ipv6/sit.c | 11 +++++++---- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 863852abe8ea..108600dc716f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) tunnel = netdev_priv(dev); tunnel->dev = dev; - tunnel->net = dev_net(dev); + if (!tunnel->net) + tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); @@ -1882,7 +1883,8 @@ static int ip6erspan_tap_init(struct net_device *dev) tunnel = netdev_priv(dev); tunnel->dev = dev; - tunnel->net = dev_net(dev); + if (!tunnel->net) + tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); @@ -1971,7 +1973,7 @@ static bool ip6gre_netlink_encap_parms(struct nlattr *data[], return ret; } -static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev, +static int ip6gre_newlink_common(struct net *link_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { @@ -1992,7 +1994,7 @@ static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev, eth_hw_addr_random(dev); nt->dev = dev; - nt->net = dev_net(dev); + nt->net = link_net; err = register_netdevice(dev); if (err) @@ -2009,11 +2011,10 @@ static int ip6gre_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *net = params->link_net ? : dev_net(dev); struct ip6_tnl *nt = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2028,7 +2029,7 @@ static int ip6gre_newlink(struct net_device *dev, return -EEXIST; } - err = ip6gre_newlink_common(src_net, dev, tb, data, extack); + err = ip6gre_newlink_common(net, dev, tb, data, extack); if (!err) { ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]); ip6gre_tunnel_link_md(ign, nt); @@ -2248,11 +2249,10 @@ static int ip6erspan_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *net = params->link_net ? : dev_net(dev); struct ip6_tnl *nt = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2268,7 +2268,7 @@ static int ip6erspan_newlink(struct net_device *dev, return -EEXIST; } - err = ip6gre_newlink_common(src_net, dev, tb, data, extack); + err = ip6gre_newlink_common(net, dev, tb, data, extack); if (!err) { ip6erspan_tnl_link_config(nt, !tb[IFLA_MTU]); ip6erspan_tunnel_link_md(ign, nt); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 54b843d20870..2438dc627e02 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -253,8 +253,7 @@ static void ip6_dev_free(struct net_device *dev) static int ip6_tnl_create2(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct net *net = dev_net(dev); - struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip6_tnl_net *ip6n = net_generic(t->net, ip6_tnl_net_id); int err; dev->rtnl_link_ops = &ip6_link_ops; @@ -1878,7 +1877,8 @@ ip6_tnl_dev_init_gen(struct net_device *dev) int t_hlen; t->dev = dev; - t->net = dev_net(dev); + if (!t->net) + t->net = dev_net(dev); ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); if (ret) @@ -2008,13 +2008,16 @@ static int ip6_tnl_newlink(struct net_device *dev, { struct nlattr **data = params->data; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); - struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); struct ip_tunnel_encap ipencap; + struct ip6_tnl_net *ip6n; struct ip6_tnl *nt, *t; + struct net *net; int err; + net = params->link_net ? : dev_net(dev); + ip6n = net_generic(net, ip6_tnl_net_id); nt = netdev_priv(dev); + nt->net = net; if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { err = ip6_tnl_encap_setup(nt, &ipencap); diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 993f85aeb882..4aa1e7821951 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -177,8 +177,7 @@ vti6_tnl_unlink(struct vti6_net *ip6n, struct ip6_tnl *t) static int vti6_tnl_create2(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct net *net = dev_net(dev); - struct vti6_net *ip6n = net_generic(net, vti6_net_id); + struct vti6_net *ip6n = net_generic(t->net, vti6_net_id); int err; dev->rtnl_link_ops = &vti6_link_ops; @@ -925,7 +924,8 @@ static inline int vti6_dev_init_gen(struct net_device *dev) struct ip6_tnl *t = netdev_priv(dev); t->dev = dev; - t->net = dev_net(dev); + if (!t->net) + t->net = dev_net(dev); netdev_hold(dev, &t->dev_tracker, GFP_KERNEL); netdev_lockdep_set_classes(dev); return 0; @@ -1002,13 +1002,15 @@ static int vti6_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { struct nlattr **data = params->data; - struct net *net = dev_net(dev); struct ip6_tnl *nt; + struct net *net; + net = params->link_net ? : dev_net(dev); nt = netdev_priv(dev); vti6_netlink_parms(data, &nt->parms); nt->parms.proto = IPPROTO_IPV6; + nt->net = net; if (vti6_locate(net, &nt->parms, 0)) return -EEXIST; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e2bd52cabdee..e870271ed04a 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -201,8 +201,7 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) static int ipip6_tunnel_create(struct net_device *dev) { struct ip_tunnel *t = netdev_priv(dev); - struct net *net = dev_net(dev); - struct sit_net *sitn = net_generic(net, sit_net_id); + struct sit_net *sitn = net_generic(t->net, sit_net_id); int err; __dev_addr_set(dev, &t->parms.iph.saddr, 4); @@ -270,6 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, nt = netdev_priv(dev); nt->parms = *parms; + nt->net = net; if (ipip6_tunnel_create(dev) < 0) goto failed_free; @@ -1449,7 +1449,8 @@ static int ipip6_tunnel_init(struct net_device *dev) int err; tunnel->dev = dev; - tunnel->net = dev_net(dev); + if (!tunnel->net) + tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ipip6_tunnel_bind_dev(dev); @@ -1556,15 +1557,17 @@ static int ipip6_newlink(struct net_device *dev, { struct nlattr **data = params->data; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); struct ip_tunnel *nt; struct ip_tunnel_encap ipencap; #ifdef CONFIG_IPV6_SIT_6RD struct ip_tunnel_6rd ip6rd; #endif + struct net *net; int err; + net = params->link_net ? : dev_net(dev); nt = netdev_priv(dev); + nt->net = net; if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { err = ip_tunnel_encap_setup(nt, &ipencap); -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:31:22 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:31:22 -0000 Subject: [PATCH net-next v9 07/11] net: xfrm: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-8-shaw.leon@gmail.com> When link_net is set, use it as link netns instead of dev_net(). This prepares for rtnetlink core to create device in target netns directly, in which case the two namespaces may be different. Signed-off-by: Xiao Liang --- net/xfrm/xfrm_interface_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index 5659a6cadd51..622445f041d3 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -242,10 +242,9 @@ static void xfrmi_dev_free(struct net_device *dev) gro_cells_destroy(&xi->gro_cells); } -static int xfrmi_create(struct net_device *dev) +static int xfrmi_create(struct net *net, struct net_device *dev) { struct xfrm_if *xi = netdev_priv(dev); - struct net *net = dev_net(dev); struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); int err; @@ -819,11 +818,12 @@ static int xfrmi_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { struct nlattr **data = params->data; - struct net *net = dev_net(dev); struct xfrm_if_parms p = {}; struct xfrm_if *xi; + struct net *net; int err; + net = params->link_net ? : dev_net(dev); xfrmi_netlink_parms(data, &p); if (p.collect_md) { struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); @@ -852,7 +852,7 @@ static int xfrmi_newlink(struct net_device *dev, xi->net = net; xi->dev = dev; - err = xfrmi_create(dev); + err = xfrmi_create(net, dev); return err; } -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:31:33 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:31:33 -0000 Subject: [PATCH net-next v9 08/11] rtnetlink: Remove "net" from newlink params In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-9-shaw.leon@gmail.com> Now that devices have been converted to use the specific netns instead of ambiguous "net", let's remove it from newlink parameters. Signed-off-by: Xiao Liang --- include/net/rtnetlink.h | 2 -- net/core/rtnetlink.c | 6 ------ 2 files changed, 8 deletions(-) diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 00c086ca0c11..dd51240431b8 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -72,7 +72,6 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) /** * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() * - * @net: Netns of interest * @src_net: Source netns of rtnetlink socket * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified * @peer_net: Peer netns @@ -80,7 +79,6 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) * @data: IFLA_INFO_DATA attributes */ struct rtnl_newlink_params { - struct net *net; struct net *src_net; struct net *link_net; struct net *peer_net; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 7e98f3cd102b..e9af0775fa6b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3797,12 +3797,6 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, dev->ifindex = ifm->ifi_index; - params.net = params.src_net; - if (link_net) - params.net = link_net; - if (peer_net) - params.net = peer_net; - if (ops->newlink) err = ops->newlink(dev, ¶ms, extack); else -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:31:41 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:31:41 -0000 Subject: [PATCH net-next v9 09/11] rtnetlink: Create link directly in target net namespace In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-10-shaw.leon@gmail.com> Make rtnl_newlink_create() create device in target namespace directly. Avoid extra netns change when link netns is provided. Device drivers has been converted to be aware of link netns, that is not assuming device netns is and link netns is the same when ops->newlink() is called. Signed-off-by: Xiao Liang --- net/core/rtnetlink.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e9af0775fa6b..a11b2c1f0985 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3788,8 +3788,8 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, name_assign_type = NET_NAME_ENUM; } - dev = rtnl_create_link(link_net ? : tgt_net, ifname, - name_assign_type, ops, tb, extack); + dev = rtnl_create_link(tgt_net, ifname, name_assign_type, ops, tb, + extack); if (IS_ERR(dev)) { err = PTR_ERR(dev); goto out; @@ -3809,11 +3809,6 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, err = rtnl_configure_link(dev, ifm, portid, nlh); if (err < 0) goto out_unregister; - if (link_net) { - err = dev_change_net_namespace(dev, tgt_net, ifname); - if (err < 0) - goto out_unregister; - } if (tb[IFLA_MASTER]) { err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack); if (err) -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:31:50 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:31:50 -0000 Subject: [PATCH net-next v9 10/11] selftests: net: Add python context manager for netns entering In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-11-shaw.leon@gmail.com> Change netns of current thread and switch back on context exit. For example: with NetNSEnter("ns1"): ip("link add dummy0 type dummy") The command be executed in netns "ns1". Signed-off-by: Xiao Liang --- tools/testing/selftests/net/lib/py/__init__.py | 2 +- tools/testing/selftests/net/lib/py/netns.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py index 54d8f5eba810..e2d6c7b63019 100644 --- a/tools/testing/selftests/net/lib/py/__init__.py +++ b/tools/testing/selftests/net/lib/py/__init__.py @@ -2,7 +2,7 @@ from .consts import KSRC from .ksft import * -from .netns import NetNS +from .netns import NetNS, NetNSEnter from .nsim import * from .utils import * from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily diff --git a/tools/testing/selftests/net/lib/py/netns.py b/tools/testing/selftests/net/lib/py/netns.py index ecff85f9074f..8e9317044eef 100644 --- a/tools/testing/selftests/net/lib/py/netns.py +++ b/tools/testing/selftests/net/lib/py/netns.py @@ -1,9 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 from .utils import ip +import ctypes import random import string +libc = ctypes.cdll.LoadLibrary('libc.so.6') + class NetNS: def __init__(self, name=None): @@ -29,3 +32,18 @@ class NetNS: def __repr__(self): return f"NetNS({self.name})" + + +class NetNSEnter: + def __init__(self, ns_name): + self.ns_path = f"/run/netns/{ns_name}" + + def __enter__(self): + self.saved = open("/proc/thread-self/ns/net") + with open(self.ns_path) as ns_file: + libc.setns(ns_file.fileno(), 0) + return self + + def __exit__(self, exc_type, exc_value, traceback): + libc.setns(self.saved.fileno(), 0) + self.saved.close() -- 2.48.1 From shaw.leon at gmail.com Mon Feb 10 13:32:01 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Mon, 10 Feb 2025 13:32:01 -0000 Subject: [PATCH net-next v9 11/11] selftests: net: Add test cases for link and peer netns In-Reply-To: <20250210133002.883422-1-shaw.leon@gmail.com> References: <20250210133002.883422-1-shaw.leon@gmail.com> Message-ID: <20250210133002.883422-12-shaw.leon@gmail.com> - Add test for creating link in another netns when a link of the same name and ifindex exists in current netns. - Add test to verify that link is created in target netns directly - no link new/del events should be generated in link netns or current netns. - Add test cases to verify that link-netns is set as expected for various drivers and combination of namespace-related parameters. Signed-off-by: Xiao Liang --- tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/config | 5 + tools/testing/selftests/net/link_netns.py | 141 ++++++++++++++++++++++ tools/testing/selftests/net/netns-name.sh | 10 ++ 4 files changed, 157 insertions(+) create mode 100755 tools/testing/selftests/net/link_netns.py diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 73ee88d6b043..df07a38f884f 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -35,6 +35,7 @@ TEST_PROGS += cmsg_so_mark.sh TEST_PROGS += cmsg_so_priority.sh TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh TEST_PROGS += netns-name.sh +TEST_PROGS += link_netns.py TEST_PROGS += nl_netdev.py TEST_PROGS += srv6_end_dt46_l3vpn_test.sh TEST_PROGS += srv6_end_dt4_l3vpn_test.sh diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config index 5b9baf708950..ab55270669ec 100644 --- a/tools/testing/selftests/net/config +++ b/tools/testing/selftests/net/config @@ -107,3 +107,8 @@ CONFIG_XFRM_INTERFACE=m CONFIG_XFRM_USER=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IPVLAN=m +CONFIG_CAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_VXCAN=m +CONFIG_NETKIT=y diff --git a/tools/testing/selftests/net/link_netns.py b/tools/testing/selftests/net/link_netns.py new file mode 100755 index 000000000000..aab043c59d69 --- /dev/null +++ b/tools/testing/selftests/net/link_netns.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +import time + +from lib.py import ksft_run, ksft_exit, ksft_true +from lib.py import ip +from lib.py import NetNS, NetNSEnter +from lib.py import RtnlFamily + + +LINK_NETNSID = 100 + + +def test_event() -> None: + with NetNS() as ns1, NetNS() as ns2: + with NetNSEnter(str(ns2)): + rtnl = RtnlFamily() + + rtnl.ntf_subscribe("rtnlgrp-link") + + ip(f"netns set {ns2} {LINK_NETNSID}", ns=str(ns1)) + ip(f"link add netns {ns1} link-netnsid {LINK_NETNSID} dummy1 type dummy") + ip(f"link add netns {ns1} dummy2 type dummy", ns=str(ns2)) + + ip("link del dummy1", ns=str(ns1)) + ip("link del dummy2", ns=str(ns1)) + + time.sleep(1) + rtnl.check_ntf() + ksft_true(rtnl.async_msg_queue.empty(), + "Received unexpected link notification") + + +def validate_link_netns(netns, ifname, link_netnsid) -> bool: + link_info = ip(f"-d link show dev {ifname}", ns=netns, json=True) + if not link_info: + return False + return link_info[0].get("link_netnsid") == link_netnsid + + +def test_link_net() -> None: + configs = [ + # type, common args, type args, fallback to dev_net + ("ipvlan", "link dummy1", "", False), + ("macsec", "link dummy1", "", False), + ("macvlan", "link dummy1", "", False), + ("macvtap", "link dummy1", "", False), + ("vlan", "link dummy1", "id 100", False), + ("gre", "", "local 192.0.2.1", True), + ("vti", "", "local 192.0.2.1", True), + ("ipip", "", "local 192.0.2.1", True), + ("ip6gre", "", "local 2001:db8::1", True), + ("ip6tnl", "", "local 2001:db8::1", True), + ("vti6", "", "local 2001:db8::1", True), + ("sit", "", "local 192.0.2.1", True), + ("xfrm", "", "if_id 1", True), + ] + + with NetNS() as ns1, NetNS() as ns2, NetNS() as ns3: + net1, net2, net3 = str(ns1), str(ns2), str(ns3) + + # prepare link netnsid and a dummy link needed by certain drivers + ip(f"netns set {net3} {LINK_NETNSID}", ns=str(net2)) + ip("link add dummy1 type dummy", ns=net3) + + cases = [ + # source, "netns", "link-netns", expected link-netns + (net3, None, None, None, None), + (net3, net2, None, None, LINK_NETNSID), + (net2, None, net3, LINK_NETNSID, LINK_NETNSID), + (net1, net2, net3, LINK_NETNSID, LINK_NETNSID), + ] + + for src_net, netns, link_netns, exp1, exp2 in cases: + tgt_net = netns or src_net + for typ, cargs, targs, fb_dev_net in configs: + cmd = "link add" + if netns: + cmd += f" netns {netns}" + if link_netns: + cmd += f" link-netns {link_netns}" + cmd += f" {cargs} foo type {typ} {targs}" + ip(cmd, ns=src_net) + if fb_dev_net: + ksft_true(validate_link_netns(tgt_net, "foo", exp1), + f"{typ} link_netns validation failed") + else: + ksft_true(validate_link_netns(tgt_net, "foo", exp2), + f"{typ} link_netns validation failed") + ip(f"link del foo", ns=tgt_net) + + +def test_peer_net() -> None: + types = [ + "vxcan", + "netkit", + "veth", + ] + + with NetNS() as ns1, NetNS() as ns2, NetNS() as ns3, NetNS() as ns4: + net1, net2, net3, net4 = str(ns1), str(ns2), str(ns3), str(ns4) + + ip(f"netns set {net3} {LINK_NETNSID}", ns=str(net2)) + + cases = [ + # source, "netns", "link-netns", "peer netns", expected + (net1, None, None, None, None), + (net1, net2, None, None, None), + (net2, None, net3, None, LINK_NETNSID), + (net1, net2, net3, None, None), + (net2, None, None, net3, LINK_NETNSID), + (net1, net2, None, net3, LINK_NETNSID), + (net2, None, net2, net3, LINK_NETNSID), + (net1, net2, net4, net3, LINK_NETNSID), + ] + + for src_net, netns, link_netns, peer_netns, exp in cases: + tgt_net = netns or src_net + for typ in types: + cmd = "link add" + if netns: + cmd += f" netns {netns}" + if link_netns: + cmd += f" link-netns {link_netns}" + cmd += f" foo type {typ}" + if peer_netns: + cmd += f" peer netns {peer_netns}" + ip(cmd, ns=src_net) + ksft_true(validate_link_netns(tgt_net, "foo", exp), + f"{typ} peer_netns validation failed") + ip(f"link del foo", ns=tgt_net) + + +def main() -> None: + ksft_run([test_event, test_link_net, test_peer_net]) + ksft_exit() + + +if __name__ == "__main__": + main() diff --git a/tools/testing/selftests/net/netns-name.sh b/tools/testing/selftests/net/netns-name.sh index 6974474c26f3..0be1905d1f2f 100755 --- a/tools/testing/selftests/net/netns-name.sh +++ b/tools/testing/selftests/net/netns-name.sh @@ -78,6 +78,16 @@ ip -netns $NS link show dev $ALT_NAME 2> /dev/null && fail "Can still find alt-name after move" ip -netns $test_ns link del $DEV || fail +# +# Test no conflict of the same name/ifindex in different netns +# +ip -netns $NS link add name $DEV index 100 type dummy || fail +ip -netns $NS link add netns $test_ns name $DEV index 100 type dummy || + fail "Can create in netns without moving" +ip -netns $test_ns link show dev $DEV >> /dev/null || fail "Device not found" +ip -netns $NS link del $DEV || fail +ip -netns $test_ns link del $DEV || fail + echo -ne "$(basename $0) \t\t\t\t" if [ $RET_CODE -eq 0 ]; then echo "[ OK ]" -- 2.48.1 From shaw.leon at gmail.com Thu Feb 13 08:27:59 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Thu, 13 Feb 2025 08:27:59 -0000 Subject: [PATCH net-next v9 05/11] net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250213062031.4547-1-kuniyu@amazon.com> References: <20250210133002.883422-6-shaw.leon@gmail.com> <20250213062031.4547-1-kuniyu@amazon.com> Message-ID: On Thu, Feb 13, 2025 at 2:20?PM Kuniyuki Iwashima wrote: > > From: Xiao Liang > Date: Mon, 10 Feb 2025 21:29:56 +0800 > > When link_net is set, use it as link netns instead of dev_net(). This > > prepares for rtnetlink core to create device in target netns directly, > > in which case the two namespaces may be different. > > > > Convert common ip_tunnel_newlink() to accept an extra link netns > > argument. Don't overwrite ip_tunnel.net in ip_tunnel_init(). > > Why... ? see a comment below. > > > [...] > > diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c > > index 1fe9b13d351c..26d15f907551 100644 > > --- a/net/ipv4/ip_gre.c > > +++ b/net/ipv4/ip_gre.c > > @@ -1413,7 +1413,8 @@ static int ipgre_newlink(struct net_device *dev, > > err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); > > if (err < 0) > > return err; > > - return ip_tunnel_newlink(dev, tb, &p, fwmark); > > + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, > > This is duplicate at all call sites, let's move it into > ip_tunnel_newlink() by passing params. > Existing tunnels use `params->link_net ? : dev_net(dev)` for backward compatibility. But I think we can leave the choice of netns to future tunnel drivers because rtnl_newlink_link_net() is preferred in general. > > > + fwmark); > > } > > > > static int erspan_newlink(struct net_device *dev, > > > > > > diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c > > index 09b73acf037a..618a50d5c0c2 100644 > > --- a/net/ipv4/ip_tunnel.c > > +++ b/net/ipv4/ip_tunnel.c > > @@ -1213,11 +1213,11 @@ void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id, > > } > > EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets); > > > > -int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], > > - struct ip_tunnel_parm_kern *p, __u32 fwmark) > > +int ip_tunnel_newlink(struct net *net, struct net_device *dev, > > + struct nlattr *tb[], struct ip_tunnel_parm_kern *p, > > + __u32 fwmark) > > { > > struct ip_tunnel *nt; > > - struct net *net = dev_net(dev); > > struct ip_tunnel_net *itn; > > int mtu; > > int err; > > @@ -1326,7 +1326,9 @@ int ip_tunnel_init(struct net_device *dev) > > } > > > > tunnel->dev = dev; > > - tunnel->net = dev_net(dev); > > + if (!tunnel->net) > > + tunnel->net = dev_net(dev); > > Isn't tunnel->net always non-NULL ? > > ip_tunnel_newlink > -> netdev_priv(dev)->net = net > -> register_netdevice(dev) > -> dev->netdev_ops->ndo_init(dev) > -> ip_tunnel_init(dev) > -> netdev_priv(dev)->net = dev_net(dev) Didn't find a path that can leave tunnel->net to NULL either. I think we can remove this. Thanks. From shaw.leon at gmail.com Thu Feb 13 08:36:41 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Thu, 13 Feb 2025 08:36:41 -0000 Subject: [PATCH net-next v9 02/11] rtnetlink: Pack newlink() params into struct In-Reply-To: <20250213065348.8507-1-kuniyu@amazon.com> References: <20250210133002.883422-3-shaw.leon@gmail.com> <20250213065348.8507-1-kuniyu@amazon.com> Message-ID: On Thu, Feb 13, 2025 at 2:54?PM Kuniyuki Iwashima wrote: > [...] > > diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h > > index 523025106a64..0f7281e3e448 100644 > > --- a/include/linux/if_macvlan.h > > +++ b/include/linux/if_macvlan.h > > @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, > > > > extern void macvlan_common_setup(struct net_device *dev); > > > > -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, > > - struct nlattr *tb[], struct nlattr *data[], > > +struct rtnl_newlink_params; > > You can just include and remove it from .c > files, then this forward declaration will be unnecessary. OK. Was not sure if it's desirable to include include/net files from include/linux. > > > > + > > +extern int macvlan_common_newlink(struct net_device *dev, > > + struct rtnl_newlink_params *params, > > struct netlink_ext_ack *extack); > > > > extern void macvlan_dellink(struct net_device *dev, struct list_head *head); > > > [...] > > diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h > > index bc0069a8b6ea..00c086ca0c11 100644 > > --- a/include/net/rtnetlink.h > > +++ b/include/net/rtnetlink.h > > @@ -69,6 +69,42 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) > > return AF_UNSPEC; > > } > > > > +/** > > + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() > > The '\t' after '*' should be single '\s'. > > Same for lines below. > This is copied from other structs in the same file. Should I change it? > > > + * > > + * @net: Netns of interest > > + * @src_net: Source netns of rtnetlink socket > > + * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified > > + * @peer_net: Peer netns > > + * @tb: IFLA_* attributes > > + * @data: IFLA_INFO_DATA attributes > > + */ > > +struct rtnl_newlink_params { > > [...] > > +/* Get effective link netns from newlink params. Generally, this is link_net > > + * and falls back to src_net. But for compatibility, a driver may * choose to > > + * use dev_net(dev) instead. > > + */ > > +static inline struct net *rtnl_newlink_link_net(struct rtnl_newlink_params *p) > > +{ > > + return p->link_net ? : p->src_net; > > +} > > + > > +/* Get peer netns from newlink params. Fallback to link netns if peer netns is > > + * not specified explicitly. > > + */ > > +static inline struct net *rtnl_newlink_peer_net(struct rtnl_newlink_params *p) > > +{ > > + return p->peer_net ? : rtnl_newlink_link_net(p); > > +} > > These helpers should belong to patch 2 ? I was trying to split API and driver changes. Can move this to next patch if it's better. From shaw.leon at gmail.com Thu Feb 13 08:38:11 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Thu, 13 Feb 2025 08:38:11 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250213070533.9926-1-kuniyu@amazon.com> References: <20250210133002.883422-7-shaw.leon@gmail.com> <20250213070533.9926-1-kuniyu@amazon.com> Message-ID: On Thu, Feb 13, 2025 at 3:05?PM Kuniyuki Iwashima wrote: > [...] > > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c > > index 863852abe8ea..108600dc716f 100644 > > --- a/net/ipv6/ip6_gre.c > > +++ b/net/ipv6/ip6_gre.c > > @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) > > tunnel = netdev_priv(dev); > > > > tunnel->dev = dev; > > - tunnel->net = dev_net(dev); > > + if (!tunnel->net) > > + tunnel->net = dev_net(dev); > > Same question as patch 5 for here and other parts. > Do we need this check and assignment ? > > ip6gre_newlink_common > -> nt->net = dev_net(dev) > -> register_netdevice > -> ndo_init / ip6gre_tunnel_init() > -> ip6gre_tunnel_init_common > -> tunnel->net = dev_net(dev) Will remove this line. From pabeni at redhat.com Thu Feb 13 09:17:59 2025 From: pabeni at redhat.com (Paolo Abeni) Date: Thu, 13 Feb 2025 09:17:59 -0000 Subject: [PATCH net-next v9 02/11] rtnetlink: Pack newlink() params into struct In-Reply-To: References: <20250210133002.883422-3-shaw.leon@gmail.com> <20250213065348.8507-1-kuniyu@amazon.com> Message-ID: <2c294c0a-26c4-4ec5-992d-a2fd98829b16@redhat.com> On 2/13/25 9:36 AM, Xiao Liang wrote: > On Thu, Feb 13, 2025 at 2:54?PM Kuniyuki Iwashima wrote: > [...] >>> diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h >>> index 523025106a64..0f7281e3e448 100644 >>> --- a/include/linux/if_macvlan.h >>> +++ b/include/linux/if_macvlan.h >>> @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, >>> >>> extern void macvlan_common_setup(struct net_device *dev); >>> >>> -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, >>> - struct nlattr *tb[], struct nlattr *data[], >>> +struct rtnl_newlink_params; >> >> You can just include and remove it from .c >> files, then this forward declaration will be unnecessary. > > OK. Was not sure if it's desirable to include include/net files from > include/linux. I think we are better of with the forward declaration instead of adding more intra header dependencies, which will slow down the build and will produces artifacts in the CI runs (increases of reported warning in the incremental build, as any warns from the included header will be 'propagated' to more files). >>> +extern int macvlan_common_newlink(struct net_device *dev, >>> + struct rtnl_newlink_params *params, >>> struct netlink_ext_ack *extack); >>> >>> extern void macvlan_dellink(struct net_device *dev, struct list_head *head); >> >> >> [...] >>> diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h >>> index bc0069a8b6ea..00c086ca0c11 100644 >>> --- a/include/net/rtnetlink.h >>> +++ b/include/net/rtnetlink.h >>> @@ -69,6 +69,42 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) >>> return AF_UNSPEC; >>> } >>> >>> +/** >>> + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() >> >> The '\t' after '*' should be single '\s'. >> >> Same for lines below. > > This is copied from other structs in the same file. Should I change it? https://elixir.bootlin.com/linux/v6.13.2/source/Documentation/process/maintainer-netdev.rst#L376 In this series, just use the good formatting for the new code. Thanks, Paolo From shaw.leon at gmail.com Thu Feb 13 09:56:10 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Thu, 13 Feb 2025 09:56:10 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: References: <20250210133002.883422-7-shaw.leon@gmail.com> <20250213070533.9926-1-kuniyu@amazon.com> Message-ID: On Thu, Feb 13, 2025 at 4:37?PM Xiao Liang wrote: > > On Thu, Feb 13, 2025 at 3:05?PM Kuniyuki Iwashima wrote: > > > [...] > > > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c > > > index 863852abe8ea..108600dc716f 100644 > > > --- a/net/ipv6/ip6_gre.c > > > +++ b/net/ipv6/ip6_gre.c > > > @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) > > > tunnel = netdev_priv(dev); > > > > > > tunnel->dev = dev; > > > - tunnel->net = dev_net(dev); > > > + if (!tunnel->net) > > > + tunnel->net = dev_net(dev); > > > > Same question as patch 5 for here and other parts. > > Do we need this check and assignment ? > > > > ip6gre_newlink_common > > -> nt->net = dev_net(dev) > > -> register_netdevice > > -> ndo_init / ip6gre_tunnel_init() > > -> ip6gre_tunnel_init_common > > -> tunnel->net = dev_net(dev) > > Will remove this line. However, fb tunnel of ip6_tunnel, ip6_vti and sit can have tunnel->net == NULL here. Take ip6_tunnel for example: ip6_tnl_init_net() -> ip6_fb_tnl_dev_init() -> register_netdev() -> register_netdevice() -> ip6_tnl_dev_init() This code path (including ip6_fb_tnl_dev_init()) doesn't set tunnel->net. But for ip6_gre, ip6gre_fb_tunnel_init() does. From shaw.leon at gmail.com Thu Feb 13 10:01:38 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Thu, 13 Feb 2025 10:01:38 -0000 Subject: [PATCH net-next v9 02/11] rtnetlink: Pack newlink() params into struct In-Reply-To: <2c294c0a-26c4-4ec5-992d-a2fd98829b16@redhat.com> References: <20250210133002.883422-3-shaw.leon@gmail.com> <20250213065348.8507-1-kuniyu@amazon.com> <2c294c0a-26c4-4ec5-992d-a2fd98829b16@redhat.com> Message-ID: On Thu, Feb 13, 2025 at 5:17?PM Paolo Abeni wrote: > > On 2/13/25 9:36 AM, Xiao Liang wrote: > > On Thu, Feb 13, 2025 at 2:54?PM Kuniyuki Iwashima wrote: > > [...] > >>> diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h > >>> index 523025106a64..0f7281e3e448 100644 > >>> --- a/include/linux/if_macvlan.h > >>> +++ b/include/linux/if_macvlan.h > >>> @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, > >>> > >>> extern void macvlan_common_setup(struct net_device *dev); > >>> > >>> -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, > >>> - struct nlattr *tb[], struct nlattr *data[], > >>> +struct rtnl_newlink_params; > >> > >> You can just include and remove it from .c > >> files, then this forward declaration will be unnecessary. > > > > OK. Was not sure if it's desirable to include include/net files from > > include/linux. > > I think we are better of with the forward declaration instead of adding > more intra header dependencies, which will slow down the build and will > produces artifacts in the CI runs (increases of reported warning in the > incremental build, as any warns from the included header will be > 'propagated' to more files). > > >>> +extern int macvlan_common_newlink(struct net_device *dev, > >>> + struct rtnl_newlink_params *params, > >>> struct netlink_ext_ack *extack); > >>> > >>> extern void macvlan_dellink(struct net_device *dev, struct list_head *head); > >> > >> > >> [...] > >>> diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h > >>> index bc0069a8b6ea..00c086ca0c11 100644 > >>> --- a/include/net/rtnetlink.h > >>> +++ b/include/net/rtnetlink.h > >>> @@ -69,6 +69,42 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) > >>> return AF_UNSPEC; > >>> } > >>> > >>> +/** > >>> + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() > >> > >> The '\t' after '*' should be single '\s'. > >> > >> Same for lines below. > > > > This is copied from other structs in the same file. Should I change it? > > https://elixir.bootlin.com/linux/v6.13.2/source/Documentation/process/maintainer-netdev.rst#L376 > > In this series, just use the good formatting for the new code. Got it. Thanks. > > Thanks, > > Paolo > From shaw.leon at gmail.com Fri Feb 14 09:23:07 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Fri, 14 Feb 2025 09:23:07 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250213110004.38415-1-kuniyu@amazon.com> References: <20250213110004.38415-1-kuniyu@amazon.com> Message-ID: On Thu, Feb 13, 2025 at 7:00?PM Kuniyuki Iwashima wrote: > > From: Xiao Liang > Date: Thu, 13 Feb 2025 17:55:32 +0800 > > On Thu, Feb 13, 2025 at 4:37?PM Xiao Liang wrote: > > > > > > On Thu, Feb 13, 2025 at 3:05?PM Kuniyuki Iwashima wrote: > > > > > > > [...] > > > > > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c > > > > > index 863852abe8ea..108600dc716f 100644 > > > > > --- a/net/ipv6/ip6_gre.c > > > > > +++ b/net/ipv6/ip6_gre.c > > > > > @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) > > > > > tunnel = netdev_priv(dev); > > > > > > > > > > tunnel->dev = dev; > > > > > - tunnel->net = dev_net(dev); > > > > > + if (!tunnel->net) > > > > > + tunnel->net = dev_net(dev); > > > > > > > > Same question as patch 5 for here and other parts. > > > > Do we need this check and assignment ? > > > > > > > > ip6gre_newlink_common > > > > -> nt->net = dev_net(dev) > > > > -> register_netdevice > > > > -> ndo_init / ip6gre_tunnel_init() > > > > -> ip6gre_tunnel_init_common > > > > -> tunnel->net = dev_net(dev) > > > > > > Will remove this line. > > > > However, fb tunnel of ip6_tunnel, ip6_vti and sit can have > > tunnel->net == NULL here. Take ip6_tunnel for example: > > > > ip6_tnl_init_net() > > -> ip6_fb_tnl_dev_init() > > -> register_netdev() > > -> register_netdevice() > > -> ip6_tnl_dev_init() > > > > This code path (including ip6_fb_tnl_dev_init()) doesn't set > > tunnel->net. But for ip6_gre, ip6gre_fb_tunnel_init() does. > > Ah, okay. Then, let's set net in a single place, which would > be better than spreading net assignment and adding null check > in ->ndo_init(), and maybe apply the same to IPv4 tunnels ? Tunnels are created in three ways: a) rtnetlink newlink, b) ioctl SIOCADDTUNNEL and c) during per netns init (fb). The code paths don't have much in common, and refactoring to set net in a single place is somewhat beyond the scope of this series. But for now I think we could put a general rule: net should be set prior to register_netdevice(). For IPv4 tunnels, tunnel->net of a) is set in ip_tunnel_newlink(). b) and c) are set in __ip_tunnel_create(): ip_tunnel_init_net() -> __ip_tunnel_create() ip_tunnel_ctl() -> ip_tunnel_create() -> __ip_tunnel_create() So net has already been initialized when register_netdevice() is called. But it varies for IPv6 tunnels. Some set net for a) or c) while some don't. This patch has "fixed" for a). As for c) we can adopt the way of ip6_gre - setting net in *_fb_tunnel_init(), then remove the check in ndo_init(). Is it reasonable? Thanks. From shaw.leon at gmail.com Wed Feb 19 12:50:56 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:50:56 -0000 Subject: [PATCH net-next v10 00/13] net: Improve netns handling in rtnetlink Message-ID: <20250219125039.18024-1-shaw.leon@gmail.com> 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. --- BTW 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 at amazon.com/ --- v10: - Move link/peer net helper functions to from patch 02 to 03. - Remove redundant tunnel->net assignment for IPv4 tunnels (patch 05). - Initialize tunnel->net before calling register_netdevice() for IPv6 tunnels (patch 07). - Coding style fixes. v9: link: https://lore.kernel.org/all/20250210133002.883422-1-shaw.leon at gmail.com/ - Change the prototype of macvlan_common_newlink(). - Minor fixes of coding style and local variables. v8: link: https://lore.kernel.org/all/20250113143719.7948-1-shaw.leon at gmail.com/ - Move dev and ext_ack out from param struct. - Validate link_net and dev_net are identical for 6lowpan. v7: link: https://lore.kernel.org/all/20250104125732.17335-1-shaw.leon at gmail.com/ - Add selftest kconfig. - Remove a duplicated test of ip6gre. v6: link: https://lore.kernel.org/all/20241218130909.2173-1-shaw.leon at gmail.com/ - Split prototype, driver and rtnetlink changes. - Add more tests for link netns. - Fix IPv6 tunnel net overwriten in ndo_init(). - Reorder variable declarations. - Exclude a ip_tunnel-specific patch. v5: link: https://lore.kernel.org/all/20241209140151.231257-1-shaw.leon at gmail.com/ - Fix function doc in batman-adv. - Include peer_net in rtnl newlink parameters. v4: link: https://lore.kernel.org/all/20241118143244.1773-1-shaw.leon at gmail.com/ - Pack newlink() parameters to a single struct. - Use ynl async_msg_queue.empty() in selftest. v3: link: https://lore.kernel.org/all/20241113125715.150201-1-shaw.leon at gmail.com/ - Drop "netns_atomic" flag and module parameter. Add netns parameter to newlink() instead, and convert drivers accordingly. - Move python NetNSEnter helper to net selftest lib. v2: link: https://lore.kernel.org/all/20241107133004.7469-1-shaw.leon at gmail.com/ - Check NLM_F_EXCL to ensure only link creation is affected. - Add self tests for link name/ifindex conflict and notifications in different netns. - Changes in dummy driver and ynl in order to add the test case. v1: link: https://lore.kernel.org/all/20241023023146.372653-1-shaw.leon at gmail.com/ Xiao Liang (13): rtnetlink: Lookup device in target netns when creating link rtnetlink: Pack newlink() params into struct net: Use link/peer netns in newlink() of rtnl_link_ops ieee802154: 6lowpan: Validate link netns in newlink() of rtnl_link_ops net: ip_tunnel: Don't set tunnel->net in ip_tunnel_init() net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops net: ipv6: Init tunnel link-netns before registering dev net: ipv6: Use link netns in newlink() of rtnl_link_ops net: xfrm: Use link netns in newlink() of rtnl_link_ops rtnetlink: Remove "net" from newlink params rtnetlink: Create link directly in target net namespace selftests: net: Add python context manager for netns entering selftests: net: Add test cases for link and peer netns drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 9 +- drivers/net/amt.c | 11 +- drivers/net/bareudp.c | 9 +- drivers/net/bonding/bond_netlink.c | 6 +- drivers/net/can/dev/netlink.c | 4 +- drivers/net/can/vxcan.c | 7 +- .../ethernet/qualcomm/rmnet/rmnet_config.c | 9 +- drivers/net/geneve.c | 9 +- drivers/net/gtp.c | 10 +- drivers/net/ipvlan/ipvlan.h | 3 +- drivers/net/ipvlan/ipvlan_main.c | 8 +- drivers/net/ipvlan/ipvtap.c | 6 +- drivers/net/macsec.c | 9 +- drivers/net/macvlan.c | 21 +-- drivers/net/macvtap.c | 6 +- drivers/net/netkit.c | 14 +- drivers/net/pfcp.c | 9 +- drivers/net/ppp/ppp_generic.c | 9 +- drivers/net/team/team_core.c | 6 +- drivers/net/veth.c | 7 +- drivers/net/vrf.c | 5 +- drivers/net/vxlan/vxlan_core.c | 9 +- drivers/net/wireguard/device.c | 7 +- drivers/net/wireless/virtual/virt_wifi.c | 8 +- drivers/net/wwan/wwan_core.c | 16 +- include/linux/if_macvlan.h | 6 +- include/net/ip_tunnels.h | 5 +- include/net/rtnetlink.h | 40 ++++- net/8021q/vlan_netlink.c | 9 +- net/batman-adv/soft-interface.c | 9 +- net/bridge/br_netlink.c | 6 +- net/caif/chnl_net.c | 5 +- net/core/rtnetlink.c | 34 +++-- net/hsr/hsr_netlink.c | 12 +- net/ieee802154/6lowpan/core.c | 7 +- net/ipv4/ip_gre.c | 22 ++- net/ipv4/ip_tunnel.c | 7 +- net/ipv4/ip_vti.c | 9 +- net/ipv4/ipip.c | 9 +- net/ipv6/ip6_gre.c | 26 ++-- net/ipv6/ip6_tunnel.c | 18 ++- net/ipv6/ip6_vti.c | 14 +- net/ipv6/sit.c | 20 ++- net/xfrm/xfrm_interface_core.c | 15 +- tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/config | 5 + .../testing/selftests/net/lib/py/__init__.py | 2 +- tools/testing/selftests/net/lib/py/netns.py | 18 +++ tools/testing/selftests/net/link_netns.py | 141 ++++++++++++++++++ tools/testing/selftests/net/netns-name.sh | 10 ++ 50 files changed, 486 insertions(+), 181 deletions(-) create mode 100755 tools/testing/selftests/net/link_netns.py -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:05 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:05 -0000 Subject: [PATCH net-next v10 01/13] rtnetlink: Lookup device in target netns when creating link In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-2-shaw.leon@gmail.com> When creating link, lookup for existing device in target net namespace instead of current one. For example, two links created by: # ip link add dummy1 type dummy # ip link add netns ns1 dummy1 type dummy should have no conflict since they are in different namespaces. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima --- net/core/rtnetlink.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index abe1a461ea67..0f3e2c6021de 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3867,20 +3867,26 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, { struct nlattr ** const tb = tbs->tb; struct net *net = sock_net(skb->sk); + struct net *device_net; struct net_device *dev; struct ifinfomsg *ifm; bool link_specified; + /* When creating, lookup for existing device in target net namespace */ + device_net = (nlh->nlmsg_flags & NLM_F_CREATE) && + (nlh->nlmsg_flags & NLM_F_EXCL) ? + tgt_net : net; + ifm = nlmsg_data(nlh); if (ifm->ifi_index > 0) { link_specified = true; - dev = __dev_get_by_index(net, ifm->ifi_index); + dev = __dev_get_by_index(device_net, ifm->ifi_index); } else if (ifm->ifi_index < 0) { NL_SET_ERR_MSG(extack, "ifindex can't be negative"); return -EINVAL; } else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) { link_specified = true; - dev = rtnl_dev_get(net, tb); + dev = rtnl_dev_get(device_net, tb); } else { link_specified = false; dev = NULL; -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:15 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:15 -0000 Subject: [PATCH net-next v10 02/13] rtnetlink: Pack newlink() params into struct In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-3-shaw.leon@gmail.com> There are 4 net namespaces involved when creating links: - source netns - where the netlink socket resides, - target netns - where to put the device being created, - link netns - netns associated with the device (backend), - peer netns - netns of peer device. Currently, two nets are passed to newlink() callback - "src_net" parameter and "dev_net" (implicitly in net_device). They are set as follows, depending on netlink attributes in the request. +------------+-------------------+---------+---------+ | peer netns | IFLA_LINK_NETNSID | src_net | dev_net | +------------+-------------------+---------+---------+ | | absent | source | target | | absent +-------------------+---------+---------+ | | present | link | link | +------------+-------------------+---------+---------+ | | absent | peer | target | | present +-------------------+---------+---------+ | | present | peer | link | +------------+-------------------+---------+---------+ When IFLA_LINK_NETNSID is present, the device is created in link netns first and then moved to target netns. This has some side effects, including extra ifindex allocation, ifname validation and link events. These could be avoided if we create it in target netns from the beginning. On the other hand, the meaning of src_net parameter is ambiguous. It varies depending on how parameters are passed. It is the effective link (or peer netns) by design, but some drivers ignore it and use dev_net instead. To provide more netns context for drivers, this patch packs existing newlink() parameters, along with the source netns, link netns and peer netns, into a struct. The old "src_net" is renamed to "net" to avoid confusion with real source netns, and will be deprecated later. The use of src_net are converted to params->net trivially. Signed-off-by: Xiao Liang --- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 7 ++++-- drivers/net/amt.c | 7 ++++-- drivers/net/bareudp.c | 7 ++++-- drivers/net/bonding/bond_netlink.c | 6 +++-- drivers/net/can/dev/netlink.c | 4 +-- drivers/net/can/vxcan.c | 7 ++++-- .../ethernet/qualcomm/rmnet/rmnet_config.c | 7 ++++-- drivers/net/geneve.c | 7 ++++-- drivers/net/gtp.c | 6 +++-- drivers/net/ipvlan/ipvlan.h | 3 +-- drivers/net/ipvlan/ipvlan_main.c | 6 +++-- drivers/net/ipvlan/ipvtap.c | 6 ++--- drivers/net/macsec.c | 7 ++++-- drivers/net/macvlan.c | 19 ++++++++------ drivers/net/macvtap.c | 6 ++--- drivers/net/netkit.c | 14 +++++++---- drivers/net/pfcp.c | 5 ++-- drivers/net/ppp/ppp_generic.c | 7 ++++-- drivers/net/team/team_core.c | 6 +++-- drivers/net/veth.c | 7 ++++-- drivers/net/vrf.c | 5 ++-- drivers/net/vxlan/vxlan_core.c | 7 ++++-- drivers/net/wireguard/device.c | 5 ++-- drivers/net/wireless/virtual/virt_wifi.c | 6 +++-- drivers/net/wwan/wwan_core.c | 16 +++++++++--- include/linux/if_macvlan.h | 6 +++-- include/net/rtnetlink.h | 25 ++++++++++++++++--- net/8021q/vlan_netlink.c | 7 ++++-- net/batman-adv/soft-interface.c | 9 +++---- net/bridge/br_netlink.c | 6 +++-- net/caif/chnl_net.c | 5 ++-- net/core/rtnetlink.c | 15 ++++++++--- net/hsr/hsr_netlink.c | 6 +++-- net/ieee802154/6lowpan/core.c | 5 ++-- net/ipv4/ip_gre.c | 16 ++++++++---- net/ipv4/ip_vti.c | 6 +++-- net/ipv4/ipip.c | 6 +++-- net/ipv6/ip6_gre.c | 14 ++++++++--- net/ipv6/ip6_tunnel.c | 6 +++-- net/ipv6/ip6_vti.c | 5 ++-- net/ipv6/sit.c | 6 +++-- net/xfrm/xfrm_interface_core.c | 7 +++--- 42 files changed, 223 insertions(+), 110 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 9ad8d9856275..16cb8ced9f35 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -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 nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *pdev; struct ipoib_dev_priv *ppriv; u16 child_pkey; diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 98c6205ed19f..96b7ec9a2c13 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -3161,11 +3161,14 @@ 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 amt_dev *amt = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; int err = -EINVAL; amt->net = net; diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index 70814303aab8..fc21dcfb4848 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -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 nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; struct bareudp_conf conf; int err; diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 2a6a424806aa..ac5e402c34bc 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -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); diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 01aacdcda260..f1db9b7ffd4d 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -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; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index ca8811941085..6f8ebb1cfd7b 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -172,10 +172,13 @@ static void vxcan_setup(struct net_device *dev) /* forward declaration for rtnl_create_link() */ static struct rtnl_link_ops vxcan_link_ops; -static int vxcan_newlink(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vxcan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *peer_net = params->net; + struct nlattr **tb = params->tb; struct vxcan_priv *priv; struct net_device *peer; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index f3bea196a8f9..8151e91395e2 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -117,11 +117,14 @@ static void rmnet_unregister_bridge(struct rmnet_port *port) rmnet_unregister_real_device(bridge_dev); } -static int rmnet_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int rmnet_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION; + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *real_dev; int mode = RMNET_EPMODE_VND; struct rmnet_endpoint *ep; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 642155cb8315..d373a851930c 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1614,10 +1614,13 @@ static void geneve_link_config(struct net_device *dev, geneve_change_mtu(dev, ldev_mtu - info->options_len); } -static int geneve_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int geneve_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; struct geneve_config cfg = { .df = GENEVE_DF_UNSET, .use_udp6_rx_checksums = false, diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index d64740bf44ed..d6d4326cb908 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1462,10 +1462,12 @@ static int gtp_create_sockets(struct gtp_dev *gtp, const struct nlattr *nla, #define GTP_TH_MAXLEN (sizeof(struct udphdr) + sizeof(struct gtp0_header)) #define GTP_IPV6_MAXLEN (sizeof(struct ipv6hdr) + GTP_TH_MAXLEN) -static int gtp_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int gtp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; unsigned int role = GTP_ROLE_GGSN; struct gtp_dev *gtp; struct gtp_net *gn; diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 025e0c19ec25..50de3ee204db 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -166,8 +166,7 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type); void ipvlan_count_rx(const struct ipvl_dev *ipvlan, unsigned int len, bool success, bool mcast); -int ipvlan_link_new(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); void ipvlan_link_delete(struct net_device *dev, struct list_head *head); void ipvlan_link_setup(struct net_device *dev); diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index da3a97a65507..19ce19ca7e32 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -532,11 +532,13 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb, return ret; } -int ipvlan_link_new(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ipvl_dev *ipvlan = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct ipvl_port *port; struct net_device *phy_dev; int err; diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c index 1afc4c47be73..edd13916831a 100644 --- a/drivers/net/ipvlan/ipvtap.c +++ b/drivers/net/ipvlan/ipvtap.c @@ -73,8 +73,8 @@ static void ipvtap_update_features(struct tap_dev *tap, netdev_update_features(vlan->dev); } -static int ipvtap_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipvtap_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ipvtap_dev *vlantap = netdev_priv(dev); @@ -97,7 +97,7 @@ static int ipvtap_newlink(struct net *src_net, struct net_device *dev, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - err = ipvlan_link_new(src_net, dev, tb, data, extack); + err = ipvlan_link_new(dev, params, extack); if (err) { netdev_rx_handler_unregister(dev); return err; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1bc1e5993f56..1869b0513f57 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -4141,11 +4141,14 @@ static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len) static struct lock_class_key macsec_netdev_addr_lock_key; -static int macsec_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macsec_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macsec_dev *macsec = macsec_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; rx_handler_func_t *rx_handler; u8 icv_len = MACSEC_DEFAULT_ICV_LEN; struct net_device *real_dev; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fed4fe2a4748..f903b414eaeb 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1440,16 +1440,19 @@ static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode, return 0; } -int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int macvlan_common_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macvlan_dev *vlan = netdev_priv(dev); - struct macvlan_port *port; + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *lowerdev; - int err; - int macmode; + struct macvlan_port *port; bool create = false; + int macmode; + int err; if (!tb[IFLA_LINK]) return -EINVAL; @@ -1565,11 +1568,11 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, } EXPORT_SYMBOL_GPL(macvlan_common_newlink); -static int macvlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macvlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { - return macvlan_common_newlink(src_net, dev, tb, data, extack); + return macvlan_common_newlink(dev, params, extack); } void macvlan_dellink(struct net_device *dev, struct list_head *head) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 29a5929d48e5..b391a0f740a3 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -77,8 +77,8 @@ static void macvtap_update_features(struct tap_dev *tap, netdev_update_features(vlan->dev); } -static int macvtap_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macvtap_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macvtap_dev *vlantap = netdev_priv(dev); @@ -105,7 +105,7 @@ static int macvtap_newlink(struct net *src_net, struct net_device *dev, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - err = macvlan_common_newlink(src_net, dev, tb, data, extack); + err = macvlan_common_newlink(dev, params, extack); if (err) { netdev_rx_handler_unregister(dev); return err; diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index 1e1b00756be7..640a2dbbbd28 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -327,17 +327,20 @@ static int netkit_validate(struct nlattr *tb[], struct nlattr *data[], static struct rtnl_link_ops netkit_link_ops; -static int netkit_new_link(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int netkit_new_link(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { - struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb, *attr; - enum netkit_action policy_prim = NETKIT_PASS; - enum netkit_action policy_peer = NETKIT_PASS; enum netkit_scrub scrub_prim = NETKIT_SCRUB_DEFAULT; enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT; + struct nlattr *peer_tb[IFLA_MAX + 1], **tbp, *attr; + enum netkit_action policy_prim = NETKIT_PASS; + enum netkit_action policy_peer = NETKIT_PASS; + struct nlattr **data = params->data; + struct net *peer_net = params->net; enum netkit_mode mode = NETKIT_L3; unsigned char ifname_assign_type; + struct nlattr **tb = params->tb; u16 headroom = 0, tailroom = 0; struct ifinfomsg *ifmp = NULL; struct net_device *peer; @@ -345,6 +348,7 @@ static int netkit_new_link(struct net *peer_net, struct net_device *dev, struct netkit *nk; int err; + tbp = tb; if (data) { if (data[IFLA_NETKIT_MODE]) mode = nla_get_u32(data[IFLA_NETKIT_MODE]); diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 68d0d9e92a22..7b0575940e1d 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -184,11 +184,12 @@ static int pfcp_add_sock(struct pfcp_dev *pfcp) return PTR_ERR_OR_ZERO(pfcp->sock); } -static int pfcp_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int pfcp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct pfcp_dev *pfcp = netdev_priv(dev); + struct net *net = params->net; struct pfcp_net *pn; int err; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 4583e15ad03a..b3340f8a6149 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1303,10 +1303,13 @@ static int ppp_nl_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int ppp_nl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ppp_nl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct ppp_config conf = { .unit = -1, .ifname_is_set = true, diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index f4019815f473..78edb8186b6d 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -2218,10 +2218,12 @@ static void team_setup(struct net_device *dev) dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; } -static int team_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int team_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **tb = params->tb; + if (tb[IFLA_ADDRESS] == NULL) eth_hw_addr_random(dev); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 01251868a9c2..7dfda89f072f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1765,10 +1765,13 @@ static int veth_init_queues(struct net_device *dev, struct nlattr *tb[]) return 0; } -static int veth_newlink(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int veth_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *peer_net = params->net; + struct nlattr **tb = params->tb; int err; struct net_device *peer; struct veth_priv *priv; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 5f21ce1013c4..849c3ced2690 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1675,11 +1675,12 @@ static void vrf_dellink(struct net_device *dev, struct list_head *head) unregister_netdevice_queue(dev, head); } -static int vrf_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vrf_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct net_vrf *vrf = netdev_priv(dev); + struct nlattr **data = params->data; struct netns_vrf *nn_vrf; bool *add_fib_rules; struct net *net; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index ac5bc78edfd7..09a4a5bf1038 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -4400,10 +4400,13 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int vxlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vxlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct vxlan_config conf; int err; diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 6cf173a008e7..404cf05bd72b 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -307,11 +307,12 @@ static void wg_setup(struct net_device *dev) wg->dev = dev; } -static int wg_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int wg_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct wg_device *wg = netdev_priv(dev); + struct net *src_net = params->net; int ret = -ENOMEM; rcu_assign_pointer(wg->creating_net, src_net); diff --git a/drivers/net/wireless/virtual/virt_wifi.c b/drivers/net/wireless/virtual/virt_wifi.c index 4ee374080466..26905b2b3ba3 100644 --- a/drivers/net/wireless/virtual/virt_wifi.c +++ b/drivers/net/wireless/virtual/virt_wifi.c @@ -519,11 +519,13 @@ static rx_handler_result_t virt_wifi_rx_handler(struct sk_buff **pskb) } /* Called with rtnl lock held. */ -static int virt_wifi_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int virt_wifi_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + struct net *src_net = params->net; + struct nlattr **tb = params->tb; int err; if (!tb[IFLA_LINK]) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index a51e2755991a..a05c49b4e7f8 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -967,15 +967,18 @@ static struct net_device *wwan_rtnl_alloc(struct nlattr *tb[], return dev; } -static int wwan_rtnl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int wwan_rtnl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct wwan_device *wwandev = wwan_dev_get_by_parent(dev->dev.parent); - u32 link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); struct wwan_netdev_priv *priv = netdev_priv(dev); + struct nlattr **data = params->data; + u32 link_id; int ret; + link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); + if (IS_ERR(wwandev)) return PTR_ERR(wwandev); @@ -1061,6 +1064,11 @@ static void wwan_create_default_link(struct wwan_device *wwandev, { struct nlattr *tb[IFLA_MAX + 1], *linkinfo[IFLA_INFO_MAX + 1]; struct nlattr *data[IFLA_WWAN_MAX + 1]; + struct rtnl_newlink_params params = { + .net = &init_net, + .tb = tb, + .data = data, + }; struct net_device *dev; struct nlmsghdr *nlh; struct sk_buff *msg; @@ -1105,7 +1113,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev, if (WARN_ON(IS_ERR(dev))) goto unlock; - if (WARN_ON(wwan_rtnl_newlink(&init_net, dev, tb, data, NULL))) { + if (WARN_ON(wwan_rtnl_newlink(dev, ¶ms, NULL))) { free_netdev(dev); goto unlock; } diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 523025106a64..0f7281e3e448 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, extern void macvlan_common_setup(struct net_device *dev); -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +struct rtnl_newlink_params; + +extern int macvlan_common_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); extern void macvlan_dellink(struct net_device *dev, struct list_head *head); diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index bc0069a8b6ea..563a6a27436c 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -69,6 +69,25 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) return AF_UNSPEC; } +/** + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() + * + * @net: Netns of interest + * @src_net: Source netns of rtnetlink socket + * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified + * @peer_net: Peer netns + * @tb: IFLA_* attributes + * @data: IFLA_INFO_DATA attributes + */ +struct rtnl_newlink_params { + struct net *net; + struct net *src_net; + struct net *link_net; + struct net *peer_net; + struct nlattr **tb; + struct nlattr **data; +}; + /** * struct rtnl_link_ops - rtnetlink link operations * @@ -125,10 +144,8 @@ struct rtnl_link_ops { struct nlattr *data[], struct netlink_ext_ack *extack); - int (*newlink)(struct net *src_net, - struct net_device *dev, - struct nlattr *tb[], - struct nlattr *data[], + int (*newlink)(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); int (*changelink)(struct net_device *dev, struct nlattr *tb[], diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 134419667d59..91df0f96e32a 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -135,11 +135,14 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], return 0; } -static int vlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *real_dev; unsigned int max_mtu; __be16 proto; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 822d788a5f86..d893c8013261 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -1077,19 +1077,18 @@ static int batadv_softif_validate(struct nlattr *tb[], struct nlattr *data[], /** * batadv_softif_newlink() - pre-initialize and register new batadv link - * @src_net: the applicable net namespace * @dev: network device to register - * @tb: IFLA_INFO_DATA netlink attributes - * @data: enum batadv_ifla_attrs attributes + * @params: rtnl newlink parameters * @extack: extended ACK report struct * * Return: 0 if successful or error otherwise. */ -static int batadv_softif_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int batadv_softif_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct batadv_priv *bat_priv = netdev_priv(dev); + struct nlattr **data = params->data; const char *algo_name; int err; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 3e0f47203f2a..6e337937d0d7 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1553,11 +1553,13 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], return 0; } -static int br_dev_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int br_dev_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct net_bridge *br = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; int err; err = register_netdevice(dev); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 94ad09e36df2..fa6a3c2634a8 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -438,10 +438,11 @@ static void caif_netlink_parms(struct nlattr *data[], } } -static int ipcaif_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipcaif_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; int ret; struct chnl_net *caifdev; ASSERT_RTNL(); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 0f3e2c6021de..9ebbde0d131c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3767,7 +3767,13 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, struct netlink_ext_ack *extack) { unsigned char name_assign_type = NET_NAME_USER; - struct net *net = sock_net(skb->sk); + struct rtnl_newlink_params params = { + .src_net = sock_net(skb->sk), + .link_net = link_net, + .peer_net = peer_net, + .tb = tb, + .data = data, + }; u32 portid = NETLINK_CB(skb).portid; struct net_device *dev; char ifname[IFNAMSIZ]; @@ -3792,13 +3798,14 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, dev->ifindex = ifm->ifi_index; + params.net = params.src_net; if (link_net) - net = link_net; + params.net = link_net; if (peer_net) - net = peer_net; + params.net = peer_net; if (ops->newlink) - err = ops->newlink(net, dev, tb, data, extack); + err = ops->newlink(dev, ¶ms, extack); else err = register_netdevice(dev); if (err < 0) { diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index b68f2f71d0e1..39add538ba99 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -29,10 +29,12 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { /* Here, it seems a netdevice has already been allocated for us, and the * hsr_dev_setup routine has been executed. Nice! */ -static int hsr_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int hsr_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; enum hsr_version proto_version; unsigned char multicast_spec; u8 proto = HSR_PROTOCOL_HSR; diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 175efd860f7b..704bf9e3f097 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -129,10 +129,11 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int lowpan_newlink(struct net *src_net, struct net_device *ldev, - struct nlattr *tb[], struct nlattr *data[], +static int lowpan_newlink(struct net_device *ldev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **tb = params->tb; struct net_device *wdev; int ret; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c9f11a046c26..1fe9b13d351c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1396,10 +1396,12 @@ ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[]) return 0; } -static int ipgre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipgre_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; int err; @@ -1414,10 +1416,12 @@ static int ipgre_newlink(struct net *src_net, struct net_device *dev, return ip_tunnel_newlink(dev, tb, &p, fwmark); } -static int erspan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int erspan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; int err; @@ -1697,6 +1701,7 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = { struct net_device *gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { + struct rtnl_newlink_params params = { .net = net }; struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; LIST_HEAD(list_kill); @@ -1704,6 +1709,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, int err; memset(&tb, 0, sizeof(tb)); + params.tb = tb; dev = rtnl_create_link(net, name, name_assign_type, &ipgre_tap_ops, tb, NULL); @@ -1714,7 +1720,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, t = netdev_priv(dev); t->collect_md = true; - err = ipgre_newlink(net, dev, tb, NULL, NULL); + err = ipgre_newlink(dev, ¶ms, NULL); if (err < 0) { free_netdev(dev); return ERR_PTR(err); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index f0b4419cef34..b901bee03e6d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -575,11 +575,13 @@ static void vti_netlink_parms(struct nlattr *data[], *fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]); } -static int vti_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vti_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct ip_tunnel_parm_kern parms; + struct nlattr **tb = params->tb; __u32 fwmark = 0; vti_netlink_parms(data, &parms, &fwmark); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index dc0db5895e0e..a8b844bcfc64 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -436,11 +436,13 @@ static void ipip_netlink_parms(struct nlattr *data[], *fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); } -static int ipip_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipip_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip_tunnel *t = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_encap ipencap; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 235808cfec70..863852abe8ea 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -2005,11 +2005,14 @@ static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev, return err; } -static int ip6gre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6gre_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip6_tnl *nt = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2241,11 +2244,14 @@ static void ip6erspan_tap_setup(struct net_device *dev) netif_keep_dst(dev); } -static int ip6erspan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6erspan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip6_tnl *nt = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 48fd53b98972..54b843d20870 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -2002,10 +2002,12 @@ static void ip6_tnl_netlink_parms(struct nlattr *data[], parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); } -static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6_tnl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); struct ip_tunnel_encap ipencap; diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 590737c27537..993f85aeb882 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -997,10 +997,11 @@ static void vti6_netlink_parms(struct nlattr *data[], parms->fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]); } -static int vti6_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vti6_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct net *net = dev_net(dev); struct ip6_tnl *nt; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 39bd8951bfca..e2bd52cabdee 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1550,10 +1550,12 @@ static bool ipip6_netlink_6rd_parms(struct nlattr *data[], } #endif -static int ipip6_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipip6_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip_tunnel *nt; struct ip_tunnel_encap ipencap; diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index c397eb99d867..5659a6cadd51 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -814,10 +814,11 @@ static void xfrmi_netlink_parms(struct nlattr *data[], parms->collect_md = true; } -static int xfrmi_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) +static int xfrmi_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, + struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct net *net = dev_net(dev); struct xfrm_if_parms p = {}; struct xfrm_if *xi; -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:23 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:23 -0000 Subject: [PATCH net-next v10 03/13] net: Use link/peer netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-4-shaw.leon@gmail.com> Add two helper functions - rtnl_newlink_link_net() and rtnl_newlink_peer_net() for netns fallback logic. Peer netns falls back to link netns, and link netns falls back to source netns. Convert the use of params->net in netdevice drivers to one of the helper functions for clarity. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima --- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 4 ++-- drivers/net/amt.c | 6 +++--- drivers/net/bareudp.c | 4 ++-- drivers/net/can/vxcan.c | 2 +- .../net/ethernet/qualcomm/rmnet/rmnet_config.c | 4 ++-- drivers/net/geneve.c | 4 ++-- drivers/net/gtp.c | 6 +++--- drivers/net/ipvlan/ipvlan_main.c | 4 ++-- drivers/net/macsec.c | 4 ++-- drivers/net/macvlan.c | 4 ++-- drivers/net/netkit.c | 2 +- drivers/net/pfcp.c | 6 +++--- drivers/net/ppp/ppp_generic.c | 4 ++-- drivers/net/veth.c | 2 +- drivers/net/vxlan/vxlan_core.c | 4 ++-- drivers/net/wireguard/device.c | 4 ++-- drivers/net/wireless/virtual/virt_wifi.c | 4 ++-- drivers/net/wwan/wwan_core.c | 2 +- include/net/rtnetlink.h | 17 +++++++++++++++++ net/8021q/vlan_netlink.c | 4 ++-- net/hsr/hsr_netlink.c | 8 ++++---- 21 files changed, 58 insertions(+), 41 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 16cb8ced9f35..53db7c8191e3 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -101,8 +101,8 @@ 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 net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *pdev; struct ipoib_dev_priv *ppriv; @@ -112,7 +112,7 @@ static int ipoib_new_child_link(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; diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 96b7ec9a2c13..53899b70fae1 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -3165,13 +3165,13 @@ 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; - struct net *net = params->net; 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] && @@ -3186,7 +3186,7 @@ static int amt_newlink(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], diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index fc21dcfb4848..d1473c5f8eef 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -702,9 +702,9 @@ 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 net *net = params->net; struct bareudp_conf conf; int err; @@ -712,7 +712,7 @@ static int bareudp_newlink(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; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 6f8ebb1cfd7b..99a78a757167 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -176,8 +176,8 @@ static int vxcan_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *peer_net = rtnl_newlink_peer_net(params); struct nlattr **data = params->data; - struct net *peer_net = params->net; struct nlattr **tb = params->tb; struct vxcan_priv *priv; struct net_device *peer; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index 8151e91395e2..ba8763cac9d9 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -121,9 +121,9 @@ static int rmnet_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *link_net = rtnl_newlink_link_net(params); u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION; struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *real_dev; int mode = RMNET_EPMODE_VND; @@ -137,7 +137,7 @@ static int rmnet_newlink(struct net_device *dev, return -EINVAL; } - real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) { NL_SET_ERR_MSG_MOD(extack, "link does not exist"); return -ENODEV; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index d373a851930c..c7700deefb00 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1618,9 +1618,9 @@ static int geneve_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 net *net = params->net; struct geneve_config cfg = { .df = GENEVE_DF_UNSET, .use_udp6_rx_checksums = false, @@ -1634,7 +1634,7 @@ static int geneve_newlink(struct net_device *dev, if (err) return err; - err = geneve_configure(net, dev, extack, &cfg); + err = geneve_configure(link_net, dev, extack, &cfg); if (err) return err; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index d6d4326cb908..2cf43e7d0edc 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1466,8 +1466,8 @@ static int gtp_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 net *src_net = params->net; unsigned int role = GTP_ROLE_GGSN; struct gtp_dev *gtp; struct gtp_net *gn; @@ -1498,7 +1498,7 @@ static int gtp_newlink(struct net_device *dev, gtp->restart_count = nla_get_u8_default(data[IFLA_GTP_RESTART_COUNT], 0); - gtp->net = src_net; + gtp->net = link_net; err = gtp_hashtable_new(gtp, hashsize); if (err < 0) @@ -1528,7 +1528,7 @@ static int gtp_newlink(struct net_device *dev, goto out_encap; } - gn = net_generic(src_net, gtp_net_id); + gn = net_generic(link_net, gtp_net_id); list_add(>p->list, &gn->gtp_dev_list); dev->priv_destructor = gtp_destructor; diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 19ce19ca7e32..b56144ca2fde 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -535,9 +535,9 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb, int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *link_net = rtnl_newlink_link_net(params); struct ipvl_dev *ipvlan = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct ipvl_port *port; struct net_device *phy_dev; @@ -547,7 +547,7 @@ int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, if (!tb[IFLA_LINK]) return -EINVAL; - phy_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + phy_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!phy_dev) return -ENODEV; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1869b0513f57..4de5d63fd577 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -4145,10 +4145,10 @@ static int macsec_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 macsec_dev *macsec = macsec_priv(dev); struct nlattr **data = params->data; struct nlattr **tb = params->tb; - struct net *net = params->net; rx_handler_func_t *rx_handler; u8 icv_len = MACSEC_DEFAULT_ICV_LEN; struct net_device *real_dev; @@ -4157,7 +4157,7 @@ static int macsec_newlink(struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) return -ENODEV; if (real_dev->type != ARPHRD_ETHER) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index f903b414eaeb..4e9d54be887c 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1444,9 +1444,9 @@ int macvlan_common_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 macvlan_dev *vlan = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *lowerdev; struct macvlan_port *port; @@ -1457,7 +1457,7 @@ int macvlan_common_newlink(struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + lowerdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (lowerdev == NULL) return -ENODEV; diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index 640a2dbbbd28..751347392570 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -331,13 +331,13 @@ static int netkit_new_link(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *peer_net = rtnl_newlink_peer_net(params); enum netkit_scrub scrub_prim = NETKIT_SCRUB_DEFAULT; enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT; struct nlattr *peer_tb[IFLA_MAX + 1], **tbp, *attr; enum netkit_action policy_prim = NETKIT_PASS; enum netkit_action policy_peer = NETKIT_PASS; struct nlattr **data = params->data; - struct net *peer_net = params->net; enum netkit_mode mode = NETKIT_L3; unsigned char ifname_assign_type; struct nlattr **tb = params->tb; diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 7b0575940e1d..f873a92d2445 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -188,12 +188,12 @@ static int pfcp_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 pfcp_dev *pfcp = netdev_priv(dev); - struct net *net = params->net; struct pfcp_net *pn; int err; - pfcp->net = net; + pfcp->net = link_net; err = pfcp_add_sock(pfcp); if (err) { @@ -207,7 +207,7 @@ static int pfcp_newlink(struct net_device *dev, goto exit_del_pfcp_sock; } - pn = net_generic(net, pfcp_net_id); + pn = net_generic(link_net, pfcp_net_id); list_add(&pfcp->list, &pn->pfcp_dev_list); netdev_dbg(dev, "registered new PFCP interface\n"); diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index b3340f8a6149..6220866258fc 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1307,8 +1307,8 @@ static int ppp_nl_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 net *src_net = params->net; struct nlattr **tb = params->tb; struct ppp_config conf = { .unit = -1, @@ -1346,7 +1346,7 @@ static int ppp_nl_newlink(struct net_device *dev, if (!tb[IFLA_IFNAME] || !nla_len(tb[IFLA_IFNAME]) || !*(char *)nla_data(tb[IFLA_IFNAME])) conf.ifname_is_set = false; - err = ppp_dev_configure(src_net, dev, &conf); + err = ppp_dev_configure(link_net, dev, &conf); out_unlock: mutex_unlock(&ppp_mutex); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 7dfda89f072f..ba3ae2d8092f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1769,8 +1769,8 @@ static int veth_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *peer_net = rtnl_newlink_peer_net(params); struct nlattr **data = params->data; - struct net *peer_net = params->net; struct nlattr **tb = params->tb; int err; struct net_device *peer; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 09a4a5bf1038..f1212a9256f6 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -4404,8 +4404,8 @@ static int vxlan_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 net *src_net = params->net; struct nlattr **tb = params->tb; struct vxlan_config conf; int err; @@ -4414,7 +4414,7 @@ static int vxlan_newlink(struct net_device *dev, if (err) return err; - return __vxlan_dev_create(src_net, dev, &conf, extack); + return __vxlan_dev_create(link_net, dev, &conf, extack); } static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 404cf05bd72b..c496d35b266d 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -311,11 +311,11 @@ static int wg_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 wg_device *wg = netdev_priv(dev); - struct net *src_net = params->net; int ret = -ENOMEM; - rcu_assign_pointer(wg->creating_net, src_net); + rcu_assign_pointer(wg->creating_net, link_net); init_rwsem(&wg->static_identity.lock); mutex_init(&wg->socket_update_lock); mutex_init(&wg->device_update_lock); diff --git a/drivers/net/wireless/virtual/virt_wifi.c b/drivers/net/wireless/virtual/virt_wifi.c index 26905b2b3ba3..f9d11a023313 100644 --- a/drivers/net/wireless/virtual/virt_wifi.c +++ b/drivers/net/wireless/virtual/virt_wifi.c @@ -524,7 +524,7 @@ static int virt_wifi_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); - struct net *src_net = params->net; + struct net *link_net = rtnl_newlink_link_net(params); struct nlattr **tb = params->tb; int err; @@ -534,7 +534,7 @@ static int virt_wifi_newlink(struct net_device *dev, netif_carrier_off(dev); priv->upperdev = dev; - priv->lowerdev = __dev_get_by_index(src_net, + priv->lowerdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!priv->lowerdev) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index a05c49b4e7f8..63a47d420bc5 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -1065,7 +1065,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev, struct nlattr *tb[IFLA_MAX + 1], *linkinfo[IFLA_INFO_MAX + 1]; struct nlattr *data[IFLA_WWAN_MAX + 1]; struct rtnl_newlink_params params = { - .net = &init_net, + .src_net = &init_net, .tb = tb, .data = data, }; diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 563a6a27436c..b22a106621fb 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -88,6 +88,23 @@ struct rtnl_newlink_params { struct nlattr **data; }; +/* Get effective link netns from newlink params. Generally, this is link_net + * and falls back to src_net. But for compatibility, a driver may * choose to + * use dev_net(dev) instead. + */ +static inline struct net *rtnl_newlink_link_net(struct rtnl_newlink_params *p) +{ + return p->link_net ? : p->src_net; +} + +/* Get peer netns from newlink params. Fallback to link netns if peer netns is + * not specified explicitly. + */ +static inline struct net *rtnl_newlink_peer_net(struct rtnl_newlink_params *p) +{ + return p->peer_net ? : rtnl_newlink_link_net(p); +} + /** * struct rtnl_link_ops - rtnetlink link operations * diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 91df0f96e32a..a000b1ef0520 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -139,9 +139,9 @@ static int vlan_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 vlan_dev_priv *vlan = vlan_dev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; struct net_device *real_dev; unsigned int max_mtu; @@ -158,7 +158,7 @@ static int vlan_newlink(struct net_device *dev, return -EINVAL; } - real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); + real_dev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) { NL_SET_ERR_MSG_MOD(extack, "link does not exist"); return -ENODEV; diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 39add538ba99..b120470246cc 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -33,8 +33,8 @@ static int hsr_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 net *src_net = params->net; enum hsr_version proto_version; unsigned char multicast_spec; u8 proto = HSR_PROTOCOL_HSR; @@ -48,7 +48,7 @@ static int hsr_newlink(struct net_device *dev, NL_SET_ERR_MSG_MOD(extack, "Slave1 device not specified"); return -EINVAL; } - link[0] = __dev_get_by_index(src_net, + link[0] = __dev_get_by_index(link_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); if (!link[0]) { NL_SET_ERR_MSG_MOD(extack, "Slave1 does not exist"); @@ -58,7 +58,7 @@ static int hsr_newlink(struct net_device *dev, NL_SET_ERR_MSG_MOD(extack, "Slave2 device not specified"); return -EINVAL; } - link[1] = __dev_get_by_index(src_net, + link[1] = __dev_get_by_index(link_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); if (!link[1]) { NL_SET_ERR_MSG_MOD(extack, "Slave2 does not exist"); @@ -71,7 +71,7 @@ static int hsr_newlink(struct net_device *dev, } if (data[IFLA_HSR_INTERLINK]) - interlink = __dev_get_by_index(src_net, + interlink = __dev_get_by_index(link_net, nla_get_u32(data[IFLA_HSR_INTERLINK])); if (interlink && interlink == link[0]) { -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:32 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:32 -0000 Subject: [PATCH net-next v10 04/13] ieee802154: 6lowpan: Validate link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-5-shaw.leon@gmail.com> Device denoted by IFLA_LINK is in link_net (IFLA_LINK_NETNSID) or source netns by design, but 6lowpan uses dev_net. Note dev->netns_local is set to true and currently link_net is implemented via a netns change. These together effectively reject IFLA_LINK_NETNSID. This patch adds a validation to ensure link_net is either NULL or identical to dev_net. Thus it would be fine to continue using dev_net when rtnetlink core begins to create devices directly in target netns. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima --- net/ieee802154/6lowpan/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 704bf9e3f097..ee318d46817d 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -143,6 +143,8 @@ static int lowpan_newlink(struct net_device *ldev, if (!tb[IFLA_LINK]) return -EINVAL; + if (params->link_net && !net_eq(params->link_net, dev_net(ldev))) + return -EINVAL; /* find and hold wpan device */ wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK])); if (!wdev) -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:41 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:41 -0000 Subject: [PATCH net-next v10 05/13] net: ip_tunnel: Don't set tunnel->net in ip_tunnel_init() In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-6-shaw.leon@gmail.com> ip_tunnel_init() is called from register_netdevice(). In all code paths reaching here, tunnel->net should already have been set (either in ip_tunnel_newlink() or __ip_tunnel_create()). So don't set it again. Signed-off-by: Xiao Liang --- net/ipv4/ip_tunnel.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 09b73acf037a..dd4b4e5be998 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -1326,7 +1326,6 @@ int ip_tunnel_init(struct net_device *dev) } tunnel->dev = dev; - tunnel->net = dev_net(dev); strscpy(tunnel->parms.name, dev->name); iph->version = 4; iph->ihl = 5; -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:50 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:50 -0000 Subject: [PATCH net-next v10 06/13] net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-7-shaw.leon@gmail.com> When link_net is set, use it as link netns instead of dev_net(). This prepares for rtnetlink core to create device in target netns directly, in which case the two namespaces may be different. Convert common ip_tunnel_newlink() to accept an extra link netns argument. Signed-off-by: Xiao Liang --- include/net/ip_tunnels.h | 5 +++-- net/ipv4/ip_gre.c | 8 +++++--- net/ipv4/ip_tunnel.c | 6 +++--- net/ipv4/ip_vti.c | 3 ++- net/ipv4/ipip.c | 3 ++- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 1aa31bdb2b31..ae1f2dda4533 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -406,8 +406,9 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, bool log_ecn_error); int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], struct ip_tunnel_parm_kern *p, __u32 fwmark); -int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], - struct ip_tunnel_parm_kern *p, __u32 fwmark); +int ip_tunnel_newlink(struct net *net, struct net_device *dev, + struct nlattr *tb[], struct ip_tunnel_parm_kern *p, + __u32 fwmark); void ip_tunnel_setup(struct net_device *dev, unsigned int net_id); bool ip_tunnel_netlink_encap_parms(struct nlattr *data[], diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 1fe9b13d351c..26d15f907551 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1413,7 +1413,8 @@ static int ipgre_newlink(struct net_device *dev, err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); if (err < 0) return err; - return ip_tunnel_newlink(dev, tb, &p, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, + fwmark); } static int erspan_newlink(struct net_device *dev, @@ -1433,7 +1434,8 @@ static int erspan_newlink(struct net_device *dev, err = erspan_netlink_parms(dev, data, tb, &p, &fwmark); if (err) return err; - return ip_tunnel_newlink(dev, tb, &p, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, + fwmark); } static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], @@ -1701,7 +1703,7 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = { struct net_device *gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { - struct rtnl_newlink_params params = { .net = net }; + struct rtnl_newlink_params params = { .src_net = net }; struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; LIST_HEAD(list_kill); diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index dd4b4e5be998..011f2a5aab3b 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -1213,11 +1213,11 @@ void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id, } EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets); -int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], - struct ip_tunnel_parm_kern *p, __u32 fwmark) +int ip_tunnel_newlink(struct net *net, struct net_device *dev, + struct nlattr *tb[], struct ip_tunnel_parm_kern *p, + __u32 fwmark) { struct ip_tunnel *nt; - struct net *net = dev_net(dev); struct ip_tunnel_net *itn; int mtu; int err; diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index b901bee03e6d..159b4473290e 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -585,7 +585,8 @@ static int vti_newlink(struct net_device *dev, __u32 fwmark = 0; vti_netlink_parms(data, &parms, &fwmark); - return ip_tunnel_newlink(dev, tb, &parms, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, + &parms, fwmark); } static int vti_changelink(struct net_device *dev, struct nlattr *tb[], diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index a8b844bcfc64..bab0bf90c908 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -455,7 +455,8 @@ static int ipip_newlink(struct net_device *dev, } ipip_netlink_parms(data, &p, &t->collect_md, &fwmark); - return ip_tunnel_newlink(dev, tb, &p, fwmark); + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, + fwmark); } static int ipip_changelink(struct net_device *dev, struct nlattr *tb[], -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:51:59 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:51:59 -0000 Subject: [PATCH net-next v10 07/13] net: ipv6: Init tunnel link-netns before registering dev In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-8-shaw.leon@gmail.com> Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in ndo_init(), which is called in register_netdevice(). However, it lacks the context of link-netns when we enable cross-net tunnels at device registration time. Let's move the init of tunnel link-netns before register_netdevice(). ip6_gre has already initialized netns, so just remove the redundant assignment. Signed-off-by: Xiao Liang --- net/ipv6/ip6_gre.c | 2 -- net/ipv6/ip6_tunnel.c | 3 ++- net/ipv6/ip6_vti.c | 3 ++- net/ipv6/sit.c | 8 +++++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 863852abe8ea..d9e6b1fd9917 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1498,7 +1498,6 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) tunnel = netdev_priv(dev); tunnel->dev = dev; - tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); @@ -1882,7 +1881,6 @@ static int ip6erspan_tap_init(struct net_device *dev) tunnel = netdev_priv(dev); tunnel->dev = dev; - tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 54b843d20870..111a8777c2f7 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1878,7 +1878,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) int t_hlen; t->dev = dev; - t->net = dev_net(dev); ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); if (ret) @@ -1940,6 +1939,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + t->net = net; t->parms.proto = IPPROTO_IPV6; rcu_assign_pointer(ip6n->tnls_wc[0], t); @@ -2015,6 +2015,7 @@ static int ip6_tnl_newlink(struct net_device *dev, int err; nt = netdev_priv(dev); + nt->net = net; if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { err = ip6_tnl_encap_setup(nt, &ipencap); diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 993f85aeb882..16e0d74f99dd 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -925,7 +925,6 @@ static inline int vti6_dev_init_gen(struct net_device *dev) struct ip6_tnl *t = netdev_priv(dev); t->dev = dev; - t->net = dev_net(dev); netdev_hold(dev, &t->dev_tracker, GFP_KERNEL); netdev_lockdep_set_classes(dev); return 0; @@ -958,6 +957,7 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) struct net *net = dev_net(dev); struct vti6_net *ip6n = net_generic(net, vti6_net_id); + t->net = net; t->parms.proto = IPPROTO_IPV6; rcu_assign_pointer(ip6n->tnls_wc[0], t); @@ -1009,6 +1009,7 @@ static int vti6_newlink(struct net_device *dev, vti6_netlink_parms(data, &nt->parms); nt->parms.proto = IPPROTO_IPV6; + nt->net = net; if (vti6_locate(net, &nt->parms, 0)) return -EEXIST; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e2bd52cabdee..20453671ac50 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -269,6 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, nt = netdev_priv(dev); + nt->net = net; nt->parms = *parms; if (ipip6_tunnel_create(dev) < 0) goto failed_free; @@ -1449,7 +1450,6 @@ static int ipip6_tunnel_init(struct net_device *dev) int err; tunnel->dev = dev; - tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ipip6_tunnel_bind_dev(dev); @@ -1565,6 +1565,7 @@ static int ipip6_newlink(struct net_device *dev, int err; nt = netdev_priv(dev); + nt->net = net; if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { err = ip_tunnel_encap_setup(nt, &ipencap); @@ -1860,6 +1861,9 @@ static int __net_init sit_init_net(struct net *net) */ sitn->fb_tunnel_dev->netns_local = true; + t = netdev_priv(sitn->fb_tunnel_dev); + t->net = net; + err = register_netdev(sitn->fb_tunnel_dev); if (err) goto err_reg_dev; @@ -1867,8 +1871,6 @@ static int __net_init sit_init_net(struct net *net) ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); - t = netdev_priv(sitn->fb_tunnel_dev); - strcpy(t->parms.name, sitn->fb_tunnel_dev->name); return 0; -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:52:16 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:52:16 -0000 Subject: [PATCH net-next v10 09/13] net: xfrm: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-10-shaw.leon@gmail.com> When link_net is set, use it as link netns instead of dev_net(). This prepares for rtnetlink core to create device in target netns directly, in which case the two namespaces may be different. Signed-off-by: Xiao Liang --- net/xfrm/xfrm_interface_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index 5659a6cadd51..622445f041d3 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -242,10 +242,9 @@ static void xfrmi_dev_free(struct net_device *dev) gro_cells_destroy(&xi->gro_cells); } -static int xfrmi_create(struct net_device *dev) +static int xfrmi_create(struct net *net, struct net_device *dev) { struct xfrm_if *xi = netdev_priv(dev); - struct net *net = dev_net(dev); struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); int err; @@ -819,11 +818,12 @@ static int xfrmi_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { struct nlattr **data = params->data; - struct net *net = dev_net(dev); struct xfrm_if_parms p = {}; struct xfrm_if *xi; + struct net *net; int err; + net = params->link_net ? : dev_net(dev); xfrmi_netlink_parms(data, &p); if (p.collect_md) { struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); @@ -852,7 +852,7 @@ static int xfrmi_newlink(struct net_device *dev, xi->net = net; xi->dev = dev; - err = xfrmi_create(dev); + err = xfrmi_create(net, dev); return err; } -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:52:25 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:52:25 -0000 Subject: [PATCH net-next v10 10/13] rtnetlink: Remove "net" from newlink params In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-11-shaw.leon@gmail.com> Now that devices have been converted to use the specific netns instead of ambiguous "net", let's remove it from newlink parameters. Signed-off-by: Xiao Liang --- include/net/rtnetlink.h | 2 -- net/core/rtnetlink.c | 6 ------ 2 files changed, 8 deletions(-) diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index b22a106621fb..ec65a8cebb99 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -72,7 +72,6 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) /** * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() * - * @net: Netns of interest * @src_net: Source netns of rtnetlink socket * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified * @peer_net: Peer netns @@ -80,7 +79,6 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) * @data: IFLA_INFO_DATA attributes */ struct rtnl_newlink_params { - struct net *net; struct net *src_net; struct net *link_net; struct net *peer_net; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9ebbde0d131c..e980481bdd28 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3798,12 +3798,6 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, dev->ifindex = ifm->ifi_index; - params.net = params.src_net; - if (link_net) - params.net = link_net; - if (peer_net) - params.net = peer_net; - if (ops->newlink) err = ops->newlink(dev, ¶ms, extack); else -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:52:35 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:52:35 -0000 Subject: [PATCH net-next v10 11/13] rtnetlink: Create link directly in target net namespace In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-12-shaw.leon@gmail.com> Make rtnl_newlink_create() create device in target namespace directly. Avoid extra netns change when link netns is provided. Device drivers has been converted to be aware of link netns, that is not assuming device netns is and link netns is the same when ops->newlink() is called. Signed-off-by: Xiao Liang --- net/core/rtnetlink.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e980481bdd28..b52e610e157e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3789,8 +3789,8 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, name_assign_type = NET_NAME_ENUM; } - dev = rtnl_create_link(link_net ? : tgt_net, ifname, - name_assign_type, ops, tb, extack); + dev = rtnl_create_link(tgt_net, ifname, name_assign_type, ops, tb, + extack); if (IS_ERR(dev)) { err = PTR_ERR(dev); goto out; @@ -3810,11 +3810,6 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, err = rtnl_configure_link(dev, ifm, portid, nlh); if (err < 0) goto out_unregister; - if (link_net) { - err = dev_change_net_namespace(dev, tgt_net, ifname); - if (err < 0) - goto out_unregister; - } if (tb[IFLA_MASTER]) { err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack); if (err) -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:52:43 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:52:43 -0000 Subject: [PATCH net-next v10 12/13] selftests: net: Add python context manager for netns entering In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-13-shaw.leon@gmail.com> Change netns of current thread and switch back on context exit. For example: with NetNSEnter("ns1"): ip("link add dummy0 type dummy") The command be executed in netns "ns1". Signed-off-by: Xiao Liang --- tools/testing/selftests/net/lib/py/__init__.py | 2 +- tools/testing/selftests/net/lib/py/netns.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py index 729457859316..8697bd27dc30 100644 --- a/tools/testing/selftests/net/lib/py/__init__.py +++ b/tools/testing/selftests/net/lib/py/__init__.py @@ -2,7 +2,7 @@ from .consts import KSRC from .ksft import * -from .netns import NetNS +from .netns import NetNS, NetNSEnter from .nsim import * from .utils import * from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily diff --git a/tools/testing/selftests/net/lib/py/netns.py b/tools/testing/selftests/net/lib/py/netns.py index ecff85f9074f..8e9317044eef 100644 --- a/tools/testing/selftests/net/lib/py/netns.py +++ b/tools/testing/selftests/net/lib/py/netns.py @@ -1,9 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 from .utils import ip +import ctypes import random import string +libc = ctypes.cdll.LoadLibrary('libc.so.6') + class NetNS: def __init__(self, name=None): @@ -29,3 +32,18 @@ class NetNS: def __repr__(self): return f"NetNS({self.name})" + + +class NetNSEnter: + def __init__(self, ns_name): + self.ns_path = f"/run/netns/{ns_name}" + + def __enter__(self): + self.saved = open("/proc/thread-self/ns/net") + with open(self.ns_path) as ns_file: + libc.setns(ns_file.fileno(), 0) + return self + + def __exit__(self, exc_type, exc_value, traceback): + libc.setns(self.saved.fileno(), 0) + self.saved.close() -- 2.48.1 From shaw.leon at gmail.com Wed Feb 19 12:52:52 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:52:52 -0000 Subject: [PATCH net-next v10 13/13] selftests: net: Add test cases for link and peer netns In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-14-shaw.leon@gmail.com> - Add test for creating link in another netns when a link of the same name and ifindex exists in current netns. - Add test to verify that link is created in target netns directly - no link new/del events should be generated in link netns or current netns. - Add test cases to verify that link-netns is set as expected for various drivers and combination of namespace-related parameters. Signed-off-by: Xiao Liang --- tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/config | 5 + tools/testing/selftests/net/link_netns.py | 141 ++++++++++++++++++++++ tools/testing/selftests/net/netns-name.sh | 10 ++ 4 files changed, 157 insertions(+) create mode 100755 tools/testing/selftests/net/link_netns.py diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 8d6116b80cf1..aeb96c085614 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -36,6 +36,7 @@ TEST_PROGS += cmsg_so_priority.sh TEST_PROGS += test_so_rcv.sh TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh TEST_PROGS += netns-name.sh +TEST_PROGS += link_netns.py TEST_PROGS += nl_netdev.py TEST_PROGS += rtnetlink.py TEST_PROGS += srv6_end_dt46_l3vpn_test.sh diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config index 5b9baf708950..ab55270669ec 100644 --- a/tools/testing/selftests/net/config +++ b/tools/testing/selftests/net/config @@ -107,3 +107,8 @@ CONFIG_XFRM_INTERFACE=m CONFIG_XFRM_USER=m CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IPVLAN=m +CONFIG_CAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_VXCAN=m +CONFIG_NETKIT=y diff --git a/tools/testing/selftests/net/link_netns.py b/tools/testing/selftests/net/link_netns.py new file mode 100755 index 000000000000..aab043c59d69 --- /dev/null +++ b/tools/testing/selftests/net/link_netns.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +import time + +from lib.py import ksft_run, ksft_exit, ksft_true +from lib.py import ip +from lib.py import NetNS, NetNSEnter +from lib.py import RtnlFamily + + +LINK_NETNSID = 100 + + +def test_event() -> None: + with NetNS() as ns1, NetNS() as ns2: + with NetNSEnter(str(ns2)): + rtnl = RtnlFamily() + + rtnl.ntf_subscribe("rtnlgrp-link") + + ip(f"netns set {ns2} {LINK_NETNSID}", ns=str(ns1)) + ip(f"link add netns {ns1} link-netnsid {LINK_NETNSID} dummy1 type dummy") + ip(f"link add netns {ns1} dummy2 type dummy", ns=str(ns2)) + + ip("link del dummy1", ns=str(ns1)) + ip("link del dummy2", ns=str(ns1)) + + time.sleep(1) + rtnl.check_ntf() + ksft_true(rtnl.async_msg_queue.empty(), + "Received unexpected link notification") + + +def validate_link_netns(netns, ifname, link_netnsid) -> bool: + link_info = ip(f"-d link show dev {ifname}", ns=netns, json=True) + if not link_info: + return False + return link_info[0].get("link_netnsid") == link_netnsid + + +def test_link_net() -> None: + configs = [ + # type, common args, type args, fallback to dev_net + ("ipvlan", "link dummy1", "", False), + ("macsec", "link dummy1", "", False), + ("macvlan", "link dummy1", "", False), + ("macvtap", "link dummy1", "", False), + ("vlan", "link dummy1", "id 100", False), + ("gre", "", "local 192.0.2.1", True), + ("vti", "", "local 192.0.2.1", True), + ("ipip", "", "local 192.0.2.1", True), + ("ip6gre", "", "local 2001:db8::1", True), + ("ip6tnl", "", "local 2001:db8::1", True), + ("vti6", "", "local 2001:db8::1", True), + ("sit", "", "local 192.0.2.1", True), + ("xfrm", "", "if_id 1", True), + ] + + with NetNS() as ns1, NetNS() as ns2, NetNS() as ns3: + net1, net2, net3 = str(ns1), str(ns2), str(ns3) + + # prepare link netnsid and a dummy link needed by certain drivers + ip(f"netns set {net3} {LINK_NETNSID}", ns=str(net2)) + ip("link add dummy1 type dummy", ns=net3) + + cases = [ + # source, "netns", "link-netns", expected link-netns + (net3, None, None, None, None), + (net3, net2, None, None, LINK_NETNSID), + (net2, None, net3, LINK_NETNSID, LINK_NETNSID), + (net1, net2, net3, LINK_NETNSID, LINK_NETNSID), + ] + + for src_net, netns, link_netns, exp1, exp2 in cases: + tgt_net = netns or src_net + for typ, cargs, targs, fb_dev_net in configs: + cmd = "link add" + if netns: + cmd += f" netns {netns}" + if link_netns: + cmd += f" link-netns {link_netns}" + cmd += f" {cargs} foo type {typ} {targs}" + ip(cmd, ns=src_net) + if fb_dev_net: + ksft_true(validate_link_netns(tgt_net, "foo", exp1), + f"{typ} link_netns validation failed") + else: + ksft_true(validate_link_netns(tgt_net, "foo", exp2), + f"{typ} link_netns validation failed") + ip(f"link del foo", ns=tgt_net) + + +def test_peer_net() -> None: + types = [ + "vxcan", + "netkit", + "veth", + ] + + with NetNS() as ns1, NetNS() as ns2, NetNS() as ns3, NetNS() as ns4: + net1, net2, net3, net4 = str(ns1), str(ns2), str(ns3), str(ns4) + + ip(f"netns set {net3} {LINK_NETNSID}", ns=str(net2)) + + cases = [ + # source, "netns", "link-netns", "peer netns", expected + (net1, None, None, None, None), + (net1, net2, None, None, None), + (net2, None, net3, None, LINK_NETNSID), + (net1, net2, net3, None, None), + (net2, None, None, net3, LINK_NETNSID), + (net1, net2, None, net3, LINK_NETNSID), + (net2, None, net2, net3, LINK_NETNSID), + (net1, net2, net4, net3, LINK_NETNSID), + ] + + for src_net, netns, link_netns, peer_netns, exp in cases: + tgt_net = netns or src_net + for typ in types: + cmd = "link add" + if netns: + cmd += f" netns {netns}" + if link_netns: + cmd += f" link-netns {link_netns}" + cmd += f" foo type {typ}" + if peer_netns: + cmd += f" peer netns {peer_netns}" + ip(cmd, ns=src_net) + ksft_true(validate_link_netns(tgt_net, "foo", exp), + f"{typ} peer_netns validation failed") + ip(f"link del foo", ns=tgt_net) + + +def main() -> None: + ksft_run([test_event, test_link_net, test_peer_net]) + ksft_exit() + + +if __name__ == "__main__": + main() diff --git a/tools/testing/selftests/net/netns-name.sh b/tools/testing/selftests/net/netns-name.sh index 6974474c26f3..0be1905d1f2f 100755 --- a/tools/testing/selftests/net/netns-name.sh +++ b/tools/testing/selftests/net/netns-name.sh @@ -78,6 +78,16 @@ ip -netns $NS link show dev $ALT_NAME 2> /dev/null && fail "Can still find alt-name after move" ip -netns $test_ns link del $DEV || fail +# +# Test no conflict of the same name/ifindex in different netns +# +ip -netns $NS link add name $DEV index 100 type dummy || fail +ip -netns $NS link add netns $test_ns name $DEV index 100 type dummy || + fail "Can create in netns without moving" +ip -netns $test_ns link show dev $DEV >> /dev/null || fail "Device not found" +ip -netns $NS link del $DEV || fail +ip -netns $test_ns link del $DEV || fail + echo -ne "$(basename $0) \t\t\t\t" if [ $RET_CODE -eq 0 ]; then echo "[ OK ]" -- 2.48.1 From kuba at kernel.org Fri Feb 21 23:47:55 2025 From: kuba at kernel.org (Jakub Kicinski) Date: Fri, 21 Feb 2025 23:47:55 -0000 Subject: [PATCH net-next v10 00/13] net: Improve netns handling in rtnetlink In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250221154751.54318ae5@kernel.org> On Wed, 19 Feb 2025 20:50:26 +0800 Xiao Liang wrote: > 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. Nice work, thank you! From shaw.leon at gmail.com Fri Feb 21 07:35:05 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Fri, 21 Feb 2025 07:35:05 -0000 Subject: [PATCH net-next v10 07/13] net: ipv6: Init tunnel link-netns before registering dev In-Reply-To: <20250221040641.77646-1-kuniyu@amazon.com> References: <20250219125039.18024-8-shaw.leon@gmail.com> <20250221040641.77646-1-kuniyu@amazon.com> Message-ID: On Fri, Feb 21, 2025 at 12:07?PM Kuniyuki Iwashima wrote: > > From: Xiao Liang > Date: Wed, 19 Feb 2025 20:50:33 +0800 > > Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in > > ndo_init(), which is called in register_netdevice(). However, it lacks > > the context of link-netns when we enable cross-net tunnels at device > > registration time. > > > > Let's move the init of tunnel link-netns before register_netdevice(). > > > > ip6_gre has already initialized netns, so just remove the redundant > > assignment. > > > > Signed-off-by: Xiao Liang > > Reviewed-by: Kuniyuki Iwashima > > left a small comment, but not a blocker. > > > > @@ -1565,6 +1565,7 @@ static int ipip6_newlink(struct net_device *dev, > > int err; > > > > nt = netdev_priv(dev); > > + nt->net = net; > > This hunk is not necessary as we'll call ipip6_tunnel_locate(), > but it's harmless and not worth reposting the whole series given > we are alredy in v10. You can just post a follow-up patch after > the series is applied. Seems ipip6_tunnel_locate() only sets netns for newly created devices (for ioctl). ipip6_newlink() is calling it to check for conflicts, so we might need this line. Thanks for your review! From patchwork-bot+netdevbpf at kernel.org Fri Feb 21 23:50:04 2025 From: patchwork-bot+netdevbpf at kernel.org (patchwork-bot+netdevbpf at kernel.org) Date: Fri, 21 Feb 2025 23:50:04 -0000 Subject: [PATCH net-next v10 00/13] net: Improve netns handling in rtnetlink In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <174018183327.2240430.4249639047640655494.git-patchwork-notify@kernel.org> Hello: This series was applied to netdev/net-next.git (main) by Jakub Kicinski : On Wed, 19 Feb 2025 20:50:26 +0800 you wrote: > 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. > > [...] Here is the summary with links: - [net-next,v10,01/13] rtnetlink: Lookup device in target netns when creating link https://git.kernel.org/netdev/net-next/c/ec061546c6cf - [net-next,v10,02/13] rtnetlink: Pack newlink() params into struct https://git.kernel.org/netdev/net-next/c/69c7be1b903f - [net-next,v10,03/13] net: Use link/peer netns in newlink() of rtnl_link_ops https://git.kernel.org/netdev/net-next/c/cf517ac16ad9 - [net-next,v10,04/13] ieee802154: 6lowpan: Validate link netns in newlink() of rtnl_link_ops https://git.kernel.org/netdev/net-next/c/3533717581dd - [net-next,v10,05/13] net: ip_tunnel: Don't set tunnel->net in ip_tunnel_init() https://git.kernel.org/netdev/net-next/c/9e17b2a1a097 - [net-next,v10,06/13] net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops https://git.kernel.org/netdev/net-next/c/eacb1160536e - [net-next,v10,07/13] net: ipv6: Init tunnel link-netns before registering dev https://git.kernel.org/netdev/net-next/c/db014522f356 - [net-next,v10,08/13] net: ipv6: Use link netns in newlink() of rtnl_link_ops https://git.kernel.org/netdev/net-next/c/5e72ce3e3980 - [net-next,v10,09/13] net: xfrm: Use link netns in newlink() of rtnl_link_ops https://git.kernel.org/netdev/net-next/c/5314e3d68455 - [net-next,v10,10/13] rtnetlink: Remove "net" from newlink params https://git.kernel.org/netdev/net-next/c/9c0fc091dc01 - [net-next,v10,11/13] rtnetlink: Create link directly in target net namespace https://git.kernel.org/netdev/net-next/c/7ca486d08a30 - [net-next,v10,12/13] selftests: net: Add python context manager for netns entering https://git.kernel.org/netdev/net-next/c/030329416232 - [net-next,v10,13/13] selftests: net: Add test cases for link and peer netns https://git.kernel.org/netdev/net-next/c/85cb3711acb8 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html From syzbot+list4d08105289e0b54474d4 at syzkaller.appspotmail.com Wed Feb 26 15:11:20 2025 From: syzbot+list4d08105289e0b54474d4 at syzkaller.appspotmail.com (syzbot) Date: Wed, 26 Feb 2025 15:11:20 -0000 Subject: [syzbot] Monthly wireguard report (Feb 2025) Message-ID: <67bf2f16.050a0220.1ebef.0020.GAE@google.com> Hello wireguard maintainers/developers, This is a 31-day syzbot report for the wireguard subsystem. All related reports/information can be found at: https://syzkaller.appspot.com/upstream/s/wireguard During the period, 0 new issues were detected and 0 were fixed. In total, 5 issues are still open and 19 have already been fixed. Some of the still happening issues: Ref Crashes Repro Title <1> 356 No INFO: task hung in wg_netns_pre_exit (5) https://syzkaller.appspot.com/bug?extid=f2fbf7478a35a94c8b7c <2> 125 No INFO: task hung in netdev_run_todo (4) https://syzkaller.appspot.com/bug?extid=894cca71fa925aabfdb2 <3> 121 Yes INFO: task hung in wg_destruct (2) https://syzkaller.appspot.com/bug?extid=7da6c19dc528c2ebc612 --- This report is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. To disable reminders for individual bugs, reply with the following command: #syz set no-reminders To change bug's subsystems, reply with: #syz set subsystems: new-subsystem You may send multiple commands in a single email message. From Jason at zx2c4.com Mon Feb 24 16:59:32 2025 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Mon, 24 Feb 2025 16:59:32 -0000 Subject: [RESEND PATCH v2] wireguard: selftests: Cleanup CONFIG_UBSAN_SANITIZE_ALL In-Reply-To: <6945896DD80A71BD+20250224041238.45039-1-wangyuli@uniontech.com> References: <6945896DD80A71BD+20250224041238.45039-1-wangyuli@uniontech.com> Message-ID: Applied, thanks. From shaw.leon at gmail.com Wed Feb 19 12:52:08 2025 From: shaw.leon at gmail.com (Xiao Liang) Date: Wed, 19 Feb 2025 12:52:08 -0000 Subject: [PATCH net-next v10 08/13] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-1-shaw.leon@gmail.com> References: <20250219125039.18024-1-shaw.leon@gmail.com> Message-ID: <20250219125039.18024-9-shaw.leon@gmail.com> When link_net is set, use it as link netns instead of dev_net(). This prepares for rtnetlink core to create device in target netns directly, in which case the two namespaces may be different. Signed-off-by: Xiao Liang --- net/ipv6/ip6_gre.c | 14 ++++++-------- net/ipv6/ip6_tunnel.c | 9 +++++---- net/ipv6/ip6_vti.c | 6 +++--- net/ipv6/sit.c | 6 +++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index d9e6b1fd9917..d31a4ce3b19f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1969,7 +1969,7 @@ static bool ip6gre_netlink_encap_parms(struct nlattr *data[], return ret; } -static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev, +static int ip6gre_newlink_common(struct net *link_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { @@ -1990,7 +1990,7 @@ static int ip6gre_newlink_common(struct net *src_net, struct net_device *dev, eth_hw_addr_random(dev); nt->dev = dev; - nt->net = dev_net(dev); + nt->net = link_net; err = register_netdevice(dev); if (err) @@ -2007,11 +2007,10 @@ static int ip6gre_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *net = params->link_net ? : dev_net(dev); struct ip6_tnl *nt = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2026,7 +2025,7 @@ static int ip6gre_newlink(struct net_device *dev, return -EEXIST; } - err = ip6gre_newlink_common(src_net, dev, tb, data, extack); + err = ip6gre_newlink_common(net, dev, tb, data, extack); if (!err) { ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]); ip6gre_tunnel_link_md(ign, nt); @@ -2246,11 +2245,10 @@ static int ip6erspan_newlink(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct net *net = params->link_net ? : dev_net(dev); struct ip6_tnl *nt = netdev_priv(dev); struct nlattr **data = params->data; - struct net *src_net = params->net; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2266,7 +2264,7 @@ static int ip6erspan_newlink(struct net_device *dev, return -EEXIST; } - err = ip6gre_newlink_common(src_net, dev, tb, data, extack); + err = ip6gre_newlink_common(net, dev, tb, data, extack); if (!err) { ip6erspan_tnl_link_config(nt, !tb[IFLA_MTU]); ip6erspan_tunnel_link_md(ign, nt); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 111a8777c2f7..89d206731af0 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -253,8 +253,7 @@ static void ip6_dev_free(struct net_device *dev) static int ip6_tnl_create2(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct net *net = dev_net(dev); - struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct ip6_tnl_net *ip6n = net_generic(t->net, ip6_tnl_net_id); int err; dev->rtnl_link_ops = &ip6_link_ops; @@ -2008,12 +2007,14 @@ static int ip6_tnl_newlink(struct net_device *dev, { struct nlattr **data = params->data; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); - struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); struct ip_tunnel_encap ipencap; + struct ip6_tnl_net *ip6n; struct ip6_tnl *nt, *t; + struct net *net; int err; + net = params->link_net ? : dev_net(dev); + ip6n = net_generic(net, ip6_tnl_net_id); nt = netdev_priv(dev); nt->net = net; diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 16e0d74f99dd..83c055996fbb 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -177,8 +177,7 @@ vti6_tnl_unlink(struct vti6_net *ip6n, struct ip6_tnl *t) static int vti6_tnl_create2(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct net *net = dev_net(dev); - struct vti6_net *ip6n = net_generic(net, vti6_net_id); + struct vti6_net *ip6n = net_generic(t->net, vti6_net_id); int err; dev->rtnl_link_ops = &vti6_link_ops; @@ -1002,9 +1001,10 @@ static int vti6_newlink(struct net_device *dev, struct netlink_ext_ack *extack) { struct nlattr **data = params->data; - struct net *net = dev_net(dev); struct ip6_tnl *nt; + struct net *net; + net = params->link_net ? : dev_net(dev); nt = netdev_priv(dev); vti6_netlink_parms(data, &nt->parms); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 20453671ac50..f7b59bc957d3 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -201,8 +201,7 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) static int ipip6_tunnel_create(struct net_device *dev) { struct ip_tunnel *t = netdev_priv(dev); - struct net *net = dev_net(dev); - struct sit_net *sitn = net_generic(net, sit_net_id); + struct sit_net *sitn = net_generic(t->net, sit_net_id); int err; __dev_addr_set(dev, &t->parms.iph.saddr, 4); @@ -1556,14 +1555,15 @@ static int ipip6_newlink(struct net_device *dev, { struct nlattr **data = params->data; struct nlattr **tb = params->tb; - struct net *net = dev_net(dev); struct ip_tunnel *nt; struct ip_tunnel_encap ipencap; #ifdef CONFIG_IPV6_SIT_6RD struct ip_tunnel_6rd ip6rd; #endif + struct net *net; int err; + net = params->link_net ? : dev_net(dev); nt = netdev_priv(dev); nt->net = net; -- 2.48.1 From ismael at bouya.org Sun Feb 2 23:47:16 2025 From: ismael at bouya.org (Ismael Bouya) Date: Sun, 02 Feb 2025 23:47:16 -0000 Subject: Incorrect computation of the MTU in wg-quick Message-ID: Hi, I would like to report a behavior that seems to be incorrect in the way wg-quick computes the MTU to assign to a wireguard interface: https://git.zx2c4.com/wireguard-tools/tree/src/wg-quick/linux.bash#n125 In this block, wg-quick goes through every endpoint it knows about, gets the mtu of the route to reach the endpoint, and takes the highest value among all the computed values. However it appears to me that the chosen value should instead be the lowest among all endpoints rather than the highest. As an example, if I declare myself (localhost) as an endpoint (it may or may not be supported, but that?s how I found about this issue), then the mtu will be set to 65456 (65536-80) which is higher than what the other endpoints are able to manage, and I?ll only be able to contact myself properly. I can provide a (trivial) patch, but I would like confirmation that my report is correct? Kind regards, -- Ismael -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From wangyuli at uniontech.com Fri Feb 7 03:33:05 2025 From: wangyuli at uniontech.com (WangYuli) Date: Fri, 07 Feb 2025 03:33:05 -0000 Subject: [PATCH v2] wireguard: selftests: Cleanup CONFIG_UBSAN_SANITIZE_ALL Message-ID: <2CCC5056FBF7DD72+20250207033131.20046-1-wangyuli@uniontech.com> Commit 918327e9b7ff ("ubsan: Remove CONFIG_UBSAN_SANITIZE_ALL") removed the CONFIG_UBSAN_SANITIZE_ALL configuration option. Eliminate invalid configurations to improve code readability. Reviewed-by: Simon Horman Signed-off-by: WangYuli --- Changelog: *v1->v2: Add Simon Horman's "Reviewed-by" tag. --- tools/testing/selftests/wireguard/qemu/debug.config | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/testing/selftests/wireguard/qemu/debug.config b/tools/testing/selftests/wireguard/qemu/debug.config index 139fd9aa8b12..828f14300d0a 100644 --- a/tools/testing/selftests/wireguard/qemu/debug.config +++ b/tools/testing/selftests/wireguard/qemu/debug.config @@ -22,7 +22,6 @@ CONFIG_HAVE_ARCH_KASAN=y CONFIG_KASAN=y CONFIG_KASAN_INLINE=y CONFIG_UBSAN=y -CONFIG_UBSAN_SANITIZE_ALL=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_STACK_USAGE=y CONFIG_DEBUG_SHIRQ=y -- 2.47.2 From kuniyu at amazon.com Thu Feb 13 05:49:18 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Thu, 13 Feb 2025 05:49:18 -0000 Subject: [PATCH net-next v9 04/11] ieee802154: 6lowpan: Validate link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-5-shaw.leon@gmail.com> References: <20250210133002.883422-5-shaw.leon@gmail.com> Message-ID: <20250213054853.285-1-kuniyu@amazon.com> From: Xiao Liang Date: Mon, 10 Feb 2025 21:29:55 +0800 > Device denoted by IFLA_LINK is in link_net (IFLA_LINK_NETNSID) or > source netns by design, but 6lowpan uses dev_net. > > Note dev->netns_local is set to true and currently link_net is > implemented via a netns change. These together effectively reject > IFLA_LINK_NETNSID. > > This patch adds a validation to ensure link_net is either NULL or > identical to dev_net. Thus it would be fine to continue using dev_net > when rtnetlink core begins to create devices directly in target netns. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Thu Feb 13 06:20:52 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Thu, 13 Feb 2025 06:20:52 -0000 Subject: [PATCH net-next v9 05/11] net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-6-shaw.leon@gmail.com> References: <20250210133002.883422-6-shaw.leon@gmail.com> Message-ID: <20250213062031.4547-1-kuniyu@amazon.com> From: Xiao Liang Date: Mon, 10 Feb 2025 21:29:56 +0800 > When link_net is set, use it as link netns instead of dev_net(). This > prepares for rtnetlink core to create device in target netns directly, > in which case the two namespaces may be different. > > Convert common ip_tunnel_newlink() to accept an extra link netns > argument. Don't overwrite ip_tunnel.net in ip_tunnel_init(). Why... ? see a comment below. [...] > diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c > index 1fe9b13d351c..26d15f907551 100644 > --- a/net/ipv4/ip_gre.c > +++ b/net/ipv4/ip_gre.c > @@ -1413,7 +1413,8 @@ static int ipgre_newlink(struct net_device *dev, > err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); > if (err < 0) > return err; > - return ip_tunnel_newlink(dev, tb, &p, fwmark); > + return ip_tunnel_newlink(params->link_net ? : dev_net(dev), dev, tb, &p, This is duplicate at all call sites, let's move it into ip_tunnel_newlink() by passing params. > + fwmark); > } > > static int erspan_newlink(struct net_device *dev, > > > diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c > index 09b73acf037a..618a50d5c0c2 100644 > --- a/net/ipv4/ip_tunnel.c > +++ b/net/ipv4/ip_tunnel.c > @@ -1213,11 +1213,11 @@ void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id, > } > EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets); > > -int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], > - struct ip_tunnel_parm_kern *p, __u32 fwmark) > +int ip_tunnel_newlink(struct net *net, struct net_device *dev, > + struct nlattr *tb[], struct ip_tunnel_parm_kern *p, > + __u32 fwmark) > { > struct ip_tunnel *nt; > - struct net *net = dev_net(dev); > struct ip_tunnel_net *itn; > int mtu; > int err; > @@ -1326,7 +1326,9 @@ int ip_tunnel_init(struct net_device *dev) > } > > tunnel->dev = dev; > - tunnel->net = dev_net(dev); > + if (!tunnel->net) > + tunnel->net = dev_net(dev); Isn't tunnel->net always non-NULL ? ip_tunnel_newlink -> netdev_priv(dev)->net = net -> register_netdevice(dev) -> dev->netdev_ops->ndo_init(dev) -> ip_tunnel_init(dev) -> netdev_priv(dev)->net = dev_net(dev) From kuniyu at amazon.com Thu Feb 13 06:54:20 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Thu, 13 Feb 2025 06:54:20 -0000 Subject: [PATCH net-next v9 02/11] rtnetlink: Pack newlink() params into struct In-Reply-To: <20250210133002.883422-3-shaw.leon@gmail.com> References: <20250210133002.883422-3-shaw.leon@gmail.com> Message-ID: <20250213065348.8507-1-kuniyu@amazon.com> From: Xiao Liang Date: Mon, 10 Feb 2025 21:29:53 +0800 > There are 4 net namespaces involved when creating links: > > - source netns - where the netlink socket resides, > - target netns - where to put the device being created, > - link netns - netns associated with the device (backend), > - peer netns - netns of peer device. > > Currently, two nets are passed to newlink() callback - "src_net" > parameter and "dev_net" (implicitly in net_device). They are set as > follows, depending on netlink attributes in the request. > > +------------+-------------------+---------+---------+ > | peer netns | IFLA_LINK_NETNSID | src_net | dev_net | > +------------+-------------------+---------+---------+ > | | absent | source | target | > | absent +-------------------+---------+---------+ > | | present | link | link | > +------------+-------------------+---------+---------+ > | | absent | peer | target | > | present +-------------------+---------+---------+ > | | present | peer | link | > +------------+-------------------+---------+---------+ > > When IFLA_LINK_NETNSID is present, the device is created in link netns > first and then moved to target netns. This has some side effects, > including extra ifindex allocation, ifname validation and link events. > These could be avoided if we create it in target netns from > the beginning. > > On the other hand, the meaning of src_net parameter is ambiguous. It > varies depending on how parameters are passed. It is the effective > link (or peer netns) by design, but some drivers ignore it and use > dev_net instead. > > This patch packs existing newlink() parameters, along with the source > netns, link netns and peer netns, into a struct. The old "src_net" > is renamed to "net" to avoid confusion with real source netns, and > will be deprecated later. The use of src_net are converted to > params->net trivially. > > To make the semantics more clear, two helper functions - > rtnl_newlink_link_net() and rtnl_newlink_peer_net() - are provided > for netns fallback logic. Peer netns falls back to link netns, and > link netns falls back to source netns. > > In following patches, to prepare for creating link in target netns > directly: > > - For device drivers that are aware of the old "src_net", the use of > it are replace with one of the two helper functions. > - And for those that takes dev_net() as link netns, we try > params->link_net and then dev_net(), in order to maintain > compatibility with the old behavior. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima I left small comments below. [...] > diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h > index 523025106a64..0f7281e3e448 100644 > --- a/include/linux/if_macvlan.h > +++ b/include/linux/if_macvlan.h > @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, > > extern void macvlan_common_setup(struct net_device *dev); > > -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, > - struct nlattr *tb[], struct nlattr *data[], > +struct rtnl_newlink_params; You can just include and remove it from .c files, then this forward declaration will be unnecessary. > + > +extern int macvlan_common_newlink(struct net_device *dev, > + struct rtnl_newlink_params *params, > struct netlink_ext_ack *extack); > > extern void macvlan_dellink(struct net_device *dev, struct list_head *head); [...] > diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h > index bc0069a8b6ea..00c086ca0c11 100644 > --- a/include/net/rtnetlink.h > +++ b/include/net/rtnetlink.h > @@ -69,6 +69,42 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) > return AF_UNSPEC; > } > > +/** > + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() The '\t' after '*' should be single '\s'. Same for lines below. > + * > + * @net: Netns of interest > + * @src_net: Source netns of rtnetlink socket > + * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified > + * @peer_net: Peer netns > + * @tb: IFLA_* attributes > + * @data: IFLA_INFO_DATA attributes > + */ > +struct rtnl_newlink_params { [...] > +/* Get effective link netns from newlink params. Generally, this is link_net > + * and falls back to src_net. But for compatibility, a driver may * choose to > + * use dev_net(dev) instead. > + */ > +static inline struct net *rtnl_newlink_link_net(struct rtnl_newlink_params *p) > +{ > + return p->link_net ? : p->src_net; > +} > + > +/* Get peer netns from newlink params. Fallback to link netns if peer netns is > + * not specified explicitly. > + */ > +static inline struct net *rtnl_newlink_peer_net(struct rtnl_newlink_params *p) > +{ > + return p->peer_net ? : rtnl_newlink_link_net(p); > +} These helpers should belong to patch 2 ? From kuniyu at amazon.com Thu Feb 13 06:55:31 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Thu, 13 Feb 2025 06:55:31 -0000 Subject: [PATCH net-next v9 03/11] net: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-4-shaw.leon@gmail.com> References: <20250210133002.883422-4-shaw.leon@gmail.com> Message-ID: <20250213065506.8720-1-kuniyu@amazon.com> From: Xiao Liang Date: Mon, 10 Feb 2025 21:29:54 +0800 > These netdevice drivers already uses netns parameter in newlink() > callback. Convert them to use rtnl_newlink_link_net() or > rtnl_newlink_peer_net() for clarity and deprecate params->net. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima > diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c > index 8151e91395e2..ab7e5b6649b2 100644 > --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c > +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c > @@ -122,8 +122,8 @@ static int rmnet_newlink(struct net_device *dev, > struct netlink_ext_ack *extack) > { > u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION; > + struct net *link_net = rtnl_newlink_link_net(params); nit: reverse xmas tree > struct nlattr **data = params->data; > - struct net *src_net = params->net; > struct nlattr **tb = params->tb; > struct net_device *real_dev; > int mode = RMNET_EPMODE_VND; From kuniyu at amazon.com Thu Feb 13 07:05:56 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Thu, 13 Feb 2025 07:05:56 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250210133002.883422-7-shaw.leon@gmail.com> References: <20250210133002.883422-7-shaw.leon@gmail.com> Message-ID: <20250213070533.9926-1-kuniyu@amazon.com> From: Xiao Liang Date: Mon, 10 Feb 2025 21:29:57 +0800 > When link_net is set, use it as link netns instead of dev_net(). This > prepares for rtnetlink core to create device in target netns directly, > in which case the two namespaces may be different. > > Set correct netns in priv before registering device, and avoid > overwriting it in ndo_init() path. > > Signed-off-by: Xiao Liang > --- > net/ipv6/ip6_gre.c | 20 ++++++++++---------- > net/ipv6/ip6_tunnel.c | 13 ++++++++----- > net/ipv6/ip6_vti.c | 10 ++++++---- > net/ipv6/sit.c | 11 +++++++---- > 4 files changed, 31 insertions(+), 23 deletions(-) > > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c > index 863852abe8ea..108600dc716f 100644 > --- a/net/ipv6/ip6_gre.c > +++ b/net/ipv6/ip6_gre.c > @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) > tunnel = netdev_priv(dev); > > tunnel->dev = dev; > - tunnel->net = dev_net(dev); > + if (!tunnel->net) > + tunnel->net = dev_net(dev); Same question as patch 5 for here and other parts. Do we need this check and assignment ? ip6gre_newlink_common -> nt->net = dev_net(dev) -> register_netdevice -> ndo_init / ip6gre_tunnel_init() -> ip6gre_tunnel_init_common -> tunnel->net = dev_net(dev) From kuniyu at amazon.com Thu Feb 13 11:00:30 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Thu, 13 Feb 2025 11:00:30 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: References: Message-ID: <20250213110004.38415-1-kuniyu@amazon.com> From: Xiao Liang Date: Thu, 13 Feb 2025 17:55:32 +0800 > On Thu, Feb 13, 2025 at 4:37?PM Xiao Liang wrote: > > > > On Thu, Feb 13, 2025 at 3:05?PM Kuniyuki Iwashima wrote: > > > > > [...] > > > > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c > > > > index 863852abe8ea..108600dc716f 100644 > > > > --- a/net/ipv6/ip6_gre.c > > > > +++ b/net/ipv6/ip6_gre.c > > > > @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) > > > > tunnel = netdev_priv(dev); > > > > > > > > tunnel->dev = dev; > > > > - tunnel->net = dev_net(dev); > > > > + if (!tunnel->net) > > > > + tunnel->net = dev_net(dev); > > > > > > Same question as patch 5 for here and other parts. > > > Do we need this check and assignment ? > > > > > > ip6gre_newlink_common > > > -> nt->net = dev_net(dev) > > > -> register_netdevice > > > -> ndo_init / ip6gre_tunnel_init() > > > -> ip6gre_tunnel_init_common > > > -> tunnel->net = dev_net(dev) > > > > Will remove this line. > > However, fb tunnel of ip6_tunnel, ip6_vti and sit can have > tunnel->net == NULL here. Take ip6_tunnel for example: > > ip6_tnl_init_net() > -> ip6_fb_tnl_dev_init() > -> register_netdev() > -> register_netdevice() > -> ip6_tnl_dev_init() > > This code path (including ip6_fb_tnl_dev_init()) doesn't set > tunnel->net. But for ip6_gre, ip6gre_fb_tunnel_init() does. Ah, okay. Then, let's set net in a single place, which would be better than spreading net assignment and adding null check in ->ndo_init(), and maybe apply the same to IPv4 tunnels ? From kuniyu at amazon.com Fri Feb 14 10:52:21 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 14 Feb 2025 10:52:21 -0000 Subject: [PATCH net-next v9 06/11] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: References: Message-ID: <20250214105148.1920-1-kuniyu@amazon.com> From: Xiao Liang Date: Fri, 14 Feb 2025 17:22:28 +0800 > On Thu, Feb 13, 2025 at 7:00?PM Kuniyuki Iwashima wrote: > > > > From: Xiao Liang > > Date: Thu, 13 Feb 2025 17:55:32 +0800 > > > On Thu, Feb 13, 2025 at 4:37?PM Xiao Liang wrote: > > > > > > > > On Thu, Feb 13, 2025 at 3:05?PM Kuniyuki Iwashima wrote: > > > > > > > > > [...] > > > > > > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c > > > > > > index 863852abe8ea..108600dc716f 100644 > > > > > > --- a/net/ipv6/ip6_gre.c > > > > > > +++ b/net/ipv6/ip6_gre.c > > > > > > @@ -1498,7 +1498,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) > > > > > > tunnel = netdev_priv(dev); > > > > > > > > > > > > tunnel->dev = dev; > > > > > > - tunnel->net = dev_net(dev); > > > > > > + if (!tunnel->net) > > > > > > + tunnel->net = dev_net(dev); > > > > > > > > > > Same question as patch 5 for here and other parts. > > > > > Do we need this check and assignment ? > > > > > > > > > > ip6gre_newlink_common > > > > > -> nt->net = dev_net(dev) > > > > > -> register_netdevice > > > > > -> ndo_init / ip6gre_tunnel_init() > > > > > -> ip6gre_tunnel_init_common > > > > > -> tunnel->net = dev_net(dev) > > > > > > > > Will remove this line. > > > > > > However, fb tunnel of ip6_tunnel, ip6_vti and sit can have > > > tunnel->net == NULL here. Take ip6_tunnel for example: > > > > > > ip6_tnl_init_net() > > > -> ip6_fb_tnl_dev_init() > > > -> register_netdev() > > > -> register_netdevice() > > > -> ip6_tnl_dev_init() > > > > > > This code path (including ip6_fb_tnl_dev_init()) doesn't set > > > tunnel->net. But for ip6_gre, ip6gre_fb_tunnel_init() does. > > > > Ah, okay. Then, let's set net in a single place, which would > > be better than spreading net assignment and adding null check > > in ->ndo_init(), and maybe apply the same to IPv4 tunnels ? > > Tunnels are created in three ways: a) rtnetlink newlink, > b) ioctl SIOCADDTUNNEL and c) during per netns init (fb). > The code paths don't have much in common, and refactoring > to set net in a single place is somewhat beyond the scope > of this series. But for now I think we could put a general rule: > net should be set prior to register_netdevice(). > > For IPv4 tunnels, tunnel->net of a) is set in ip_tunnel_newlink(). > b) and c) are set in __ip_tunnel_create(): > ip_tunnel_init_net() -> __ip_tunnel_create() > ip_tunnel_ctl() -> ip_tunnel_create() -> __ip_tunnel_create() > So net has already been initialized when register_netdevice() > is called. > > But it varies for IPv6 tunnels. Some set net for a) or c) while > some don't. This patch has "fixed" for a). As for c) we can > adopt the way of ip6_gre - setting net in *_fb_tunnel_init(), > then remove the check in ndo_init(). > > Is it reasonable? Yes, fair enough. From thomas at eizinger.io Sun Feb 16 22:51:11 2025 From: thomas at eizinger.io (Thomas Eizinger) Date: Sun, 16 Feb 2025 22:51:11 -0000 Subject: Race-condition when removing instance of WinTUN adapter? Message-ID: <3026a6c9-ee83-43b4-97a1-0904d85b8ad7@app.fastmail.com> Hello! We are receiving variations of the following errors on multiple Windows machines from customers. The UUID is what we are setting as the tunnel adapter ID. ``` Spawning native process to remove instance Error executing worker process: "SWD\WINTUN\{E9245BC1-B8C1-44CA-AB1D-C6AAD4F13B9C}": The system cannot find the path specified. (Code 0x00000003) ``` and ``` Spawning native process to remove instance Failed to create process: rundll32 "C:\Windows\Temp\ab11b60bba2fb3bcc9a355e9e3a89003522ede647bc6c00704e734a8447c1ce5\setupapihost.dll",RemoveInstance "SWD\WINTUN\{E9245BC1-B8C1-44CA-AB1D-C6AAD4F13B9C}": Het systeem kan het opgegeven pad niet vinden. (Code 0x00000003) ``` (Error message here is Dutch because that particular customer is in the Netherlands. It means "The system cannot find the path specified") >From reading the source code at [0], I suspect that this is "only" a race condition where the adapter is simply no longer present at the time we want to remove it? I am not very well versed at C code which is why I figured I'd ask here before attempting to patch the code. Would it make sense to add a check for this particular error code and not fail as a result, making the function idempotent? Any insight is much appreciated. Kind regards, Thomas Eizinger [0]: https://git.zx2c4.com/wintun/tree/api/rundll32.c#n160 From kuniyu at amazon.com Fri Feb 21 03:25:14 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 03:25:14 -0000 Subject: [PATCH net-next v10 02/13] rtnetlink: Pack newlink() params into struct In-Reply-To: <20250219125039.18024-3-shaw.leon@gmail.com> References: <20250219125039.18024-3-shaw.leon@gmail.com> Message-ID: <20250221032449.73597-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:28 +0800 > There are 4 net namespaces involved when creating links: > > - source netns - where the netlink socket resides, > - target netns - where to put the device being created, > - link netns - netns associated with the device (backend), > - peer netns - netns of peer device. > > Currently, two nets are passed to newlink() callback - "src_net" > parameter and "dev_net" (implicitly in net_device). They are set as > follows, depending on netlink attributes in the request. > > +------------+-------------------+---------+---------+ > | peer netns | IFLA_LINK_NETNSID | src_net | dev_net | > +------------+-------------------+---------+---------+ > | | absent | source | target | > | absent +-------------------+---------+---------+ > | | present | link | link | > +------------+-------------------+---------+---------+ > | | absent | peer | target | > | present +-------------------+---------+---------+ > | | present | peer | link | > +------------+-------------------+---------+---------+ > > When IFLA_LINK_NETNSID is present, the device is created in link netns > first and then moved to target netns. This has some side effects, > including extra ifindex allocation, ifname validation and link events. > These could be avoided if we create it in target netns from > the beginning. > > On the other hand, the meaning of src_net parameter is ambiguous. It > varies depending on how parameters are passed. It is the effective > link (or peer netns) by design, but some drivers ignore it and use > dev_net instead. > > To provide more netns context for drivers, this patch packs existing > newlink() parameters, along with the source netns, link netns and peer > netns, into a struct. The old "src_net" is renamed to "net" to avoid > confusion with real source netns, and will be deprecated later. The use > of src_net are converted to params->net trivially. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Fri Feb 21 03:26:53 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 03:26:53 -0000 Subject: [PATCH net-next v10 05/13] net: ip_tunnel: Don't set tunnel->net in ip_tunnel_init() In-Reply-To: <20250219125039.18024-6-shaw.leon@gmail.com> References: <20250219125039.18024-6-shaw.leon@gmail.com> Message-ID: <20250221032629.73823-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:31 +0800 > ip_tunnel_init() is called from register_netdevice(). In all code paths > reaching here, tunnel->net should already have been set (either in > ip_tunnel_newlink() or __ip_tunnel_create()). So don't set it again. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Fri Feb 21 03:36:14 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 03:36:14 -0000 Subject: [PATCH net-next v10 06/13] net: ip_tunnel: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-7-shaw.leon@gmail.com> References: <20250219125039.18024-7-shaw.leon@gmail.com> Message-ID: <20250221033544.74835-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:32 +0800 > When link_net is set, use it as link netns instead of dev_net(). This > prepares for rtnetlink core to create device in target netns directly, > in which case the two namespaces may be different. > > Convert common ip_tunnel_newlink() to accept an extra link netns > argument. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Fri Feb 21 04:07:11 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 04:07:11 -0000 Subject: [PATCH net-next v10 07/13] net: ipv6: Init tunnel link-netns before registering dev In-Reply-To: <20250219125039.18024-8-shaw.leon@gmail.com> References: <20250219125039.18024-8-shaw.leon@gmail.com> Message-ID: <20250221040641.77646-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:33 +0800 > Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in > ndo_init(), which is called in register_netdevice(). However, it lacks > the context of link-netns when we enable cross-net tunnels at device > registration time. > > Let's move the init of tunnel link-netns before register_netdevice(). > > ip6_gre has already initialized netns, so just remove the redundant > assignment. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima left a small comment, but not a blocker. > @@ -1565,6 +1565,7 @@ static int ipip6_newlink(struct net_device *dev, > int err; > > nt = netdev_priv(dev); > + nt->net = net; This hunk is not necessary as we'll call ipip6_tunnel_locate(), but it's harmless and not worth reposting the whole series given we are alredy in v10. You can just post a follow-up patch after the series is applied. Thanks! From kuniyu at amazon.com Fri Feb 21 04:09:23 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 04:09:23 -0000 Subject: [PATCH net-next v10 08/13] net: ipv6: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-9-shaw.leon@gmail.com> References: <20250219125039.18024-9-shaw.leon@gmail.com> Message-ID: <20250221040858.78214-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:34 +0800 > When link_net is set, use it as link netns instead of dev_net(). This > prepares for rtnetlink core to create device in target netns directly, > in which case the two namespaces may be different. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Fri Feb 21 04:10:48 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 04:10:48 -0000 Subject: [PATCH net-next v10 09/13] net: xfrm: Use link netns in newlink() of rtnl_link_ops In-Reply-To: <20250219125039.18024-10-shaw.leon@gmail.com> References: <20250219125039.18024-10-shaw.leon@gmail.com> Message-ID: <20250221041030.78359-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:35 +0800 > When link_net is set, use it as link netns instead of dev_net(). This > prepares for rtnetlink core to create device in target netns directly, > in which case the two namespaces may be different. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Fri Feb 21 04:12:25 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 04:12:25 -0000 Subject: [PATCH net-next v10 10/13] rtnetlink: Remove "net" from newlink params In-Reply-To: <20250219125039.18024-11-shaw.leon@gmail.com> References: <20250219125039.18024-11-shaw.leon@gmail.com> Message-ID: <20250221041155.78502-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:36 +0800 > Now that devices have been converted to use the specific netns instead > of ambiguous "net", let's remove it from newlink parameters. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From kuniyu at amazon.com Fri Feb 21 04:17:02 2025 From: kuniyu at amazon.com (Kuniyuki Iwashima) Date: Fri, 21 Feb 2025 04:17:02 -0000 Subject: [PATCH net-next v10 11/13] rtnetlink: Create link directly in target net namespace In-Reply-To: <20250219125039.18024-12-shaw.leon@gmail.com> References: <20250219125039.18024-12-shaw.leon@gmail.com> Message-ID: <20250221041641.79788-1-kuniyu@amazon.com> From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:37 +0800 > Make rtnl_newlink_create() create device in target namespace directly. > Avoid extra netns change when link netns is provided. > > Device drivers has been converted to be aware of link netns, that is not > assuming device netns is and link netns is the same when ops->newlink() > is called. > > Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima From wangyuli at uniontech.com Mon Feb 24 04:14:21 2025 From: wangyuli at uniontech.com (WangYuli) Date: Mon, 24 Feb 2025 04:14:21 -0000 Subject: [RESEND PATCH v2] wireguard: selftests: Cleanup CONFIG_UBSAN_SANITIZE_ALL Message-ID: <6945896DD80A71BD+20250224041238.45039-1-wangyuli@uniontech.com> Commit 918327e9b7ff ("ubsan: Remove CONFIG_UBSAN_SANITIZE_ALL") removed the CONFIG_UBSAN_SANITIZE_ALL configuration option. Eliminate invalid configurations to improve code readability. Link: https://lore.kernel.org/all/20250123105743.GO395043 at kernel.org/ Reviewed-by: Simon Horman Signed-off-by: WangYuli --- Changelog: *v1->v2: Add Simon Horman's "Reviewed-by" tag. Signed-off-by: WangYuli --- tools/testing/selftests/wireguard/qemu/debug.config | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/testing/selftests/wireguard/qemu/debug.config b/tools/testing/selftests/wireguard/qemu/debug.config index 139fd9aa8b12..828f14300d0a 100644 --- a/tools/testing/selftests/wireguard/qemu/debug.config +++ b/tools/testing/selftests/wireguard/qemu/debug.config @@ -22,7 +22,6 @@ CONFIG_HAVE_ARCH_KASAN=y CONFIG_KASAN=y CONFIG_KASAN_INLINE=y CONFIG_UBSAN=y -CONFIG_UBSAN_SANITIZE_ALL=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_STACK_USAGE=y CONFIG_DEBUG_SHIRQ=y -- 2.47.2