]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtnetlink: Pack newlink() params into struct
authorXiao Liang <shaw.leon@gmail.com>
Wed, 19 Feb 2025 12:50:28 +0000 (20:50 +0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 21 Feb 2025 23:28:02 +0000 (15: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 <shaw.leon@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250219125039.18024-3-shaw.leon@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
42 files changed:
drivers/infiniband/ulp/ipoib/ipoib_netlink.c
drivers/net/amt.c
drivers/net/bareudp.c
drivers/net/bonding/bond_netlink.c
drivers/net/can/dev/netlink.c
drivers/net/can/vxcan.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/ipvlan/ipvlan.h
drivers/net/ipvlan/ipvlan_main.c
drivers/net/ipvlan/ipvtap.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/netkit.c
drivers/net/pfcp.c
drivers/net/ppp/ppp_generic.c
drivers/net/team/team_core.c
drivers/net/veth.c
drivers/net/vrf.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wireguard/device.c
drivers/net/wireless/virtual/virt_wifi.c
drivers/net/wwan/wwan_core.c
include/linux/if_macvlan.h
include/net/rtnetlink.h
net/8021q/vlan_netlink.c
net/batman-adv/soft-interface.c
net/bridge/br_netlink.c
net/caif/chnl_net.c
net/core/rtnetlink.c
net/hsr/hsr_netlink.c
net/ieee802154/6lowpan/core.c
net/ipv4/ip_gre.c
net/ipv4/ip_vti.c
net/ipv4/ipip.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/sit.c
net/xfrm/xfrm_interface_core.c

index 9ad8d985627524118150ddcdbcd583d4d576257e..16cb8ced9f35ceebc7179d0149361906610ba796 100644 (file)
@@ -97,10 +97,13 @@ out_err:
        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;
index 98c6205ed19f157a2c42b65e509f960e6eceb065..96b7ec9a2c13eb60a02c2e739382205b58153841 100644 (file)
@@ -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;
index 70814303aab86079b8c86e7ed928bf1f1b0dfff2..fc21dcfb4848db400ed480aa7df701b0ced68e11 100644 (file)
@@ -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;
 
index 2a6a424806aa603ad8a00ca797e9e22d38bd0435..ac5e402c34bc6cdc5e449c96f9a33db0304f8dd1 100644 (file)
@@ -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);
index 01aacdcda26066e0679337a4342dc2ff817f2071..f1db9b7ffd4d0ee492d33de468f2385e49604e5b 100644 (file)
@@ -624,8 +624,8 @@ nla_put_failure:
        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;
index ca88119410852f7869cf32cbc31e47a3e17c21e6..6f8ebb1cfd7b2cd57a9283df405912364a875470 100644 (file)
@@ -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;
 
index f3bea196a8f9d59fc8f70d6b8bcbbf0e0aeca7c3..8151e91395e2ec334c2457c84679887cedaecf44 100644 (file)
@@ -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;
index dbb3960126ee7c32719fd9c475ff4cb86e3a7a33..d6e8b2521052314f767ed749b5f3488cf9b786ea 100644 (file)
@@ -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,
index b7b46c5e6399a5f3d520a3420f679f75e3689f1c..762514af8b3051a14c4017121147f9c84d895f19 100644 (file)
@@ -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;
index 025e0c19ec255295fb904d1bbba9b15e0ad8924e..50de3ee204dbc9bf63076b48e0f80222f8c10333 100644 (file)
@@ -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);
index da3a97a655070ef918ef9b6c866df400d1736a25..19ce19ca7e3249e17cfb031fa2bd124c3183531b 100644 (file)
@@ -532,11 +532,13 @@ err:
        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;
index 1afc4c47be73f906f58721aa227dd35fd30eff73..edd13916831a7c8fe90bfaece5a696e3e2803b17 100644 (file)
@@ -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;
index 1bc1e5993f56e08cf4fe2996743068d777d15723..1869b0513f57c0b1fcccb4bfead2bd0f83a1291f 100644 (file)
@@ -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;
index fed4fe2a4748f8f6b69a094dbe0362752da4699b..f903b414eaeb2ffda2483e9e92c74d9f99f2228e 100644 (file)
@@ -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 @@ destroy_macvlan_port:
 }
 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)
index 29a5929d48e55f52fd577d62a07b549a62a92086..b391a0f740a3f3a8b45c5adc7ca378ac8cc310cf 100644 (file)
@@ -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;
index 1e1b00756be7d974623bf1062725dac589a73b84..640a2dbbbd28c1a60b2154f699fea07afc870d06 100644 (file)
@@ -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]);
index 68d0d9e92a22093dcc7f17fd0ac6995897e78f05..7b0575940e1d6ea27335ee3997ab14b206f56cba 100644 (file)
@@ -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;
 
index 4583e15ad03a0b0ae219d9d07a4cdb5462e28748..b3340f8a6149a0a7839cfca4da0c5f0511d37b54 100644 (file)
@@ -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,
index f4019815f473617708b4e0662b355c7738c64731..78edb8186b6d0fac00aa8b57c4526228e29969c3 100644 (file)
@@ -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);
 
index 01251868a9c27592f0dfbcdc32c0afbd7e9baafc..7dfda89f072fea855f0ed61c07ca26c26f3a3937 100644 (file)
@@ -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;
index 5f21ce1013c426b373a857d5000a0daabcc1b898..849c3ced2690ece4501bd7e7f0d6044675103a4d 100644 (file)
@@ -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;
index e2354c02def0e76b13f87f879ab49bffa3f75104..1a1d03abb6b99a9f0e7788dff11842d689bd9e95 100644 (file)
@@ -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;
 
index 6cf173a008e782c8254d45bbd250202fc215da5a..404cf05bd72bf649903c2debddf74c97a0557c86 100644 (file)
@@ -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);
index 4ee3740804667b5a1cf846a4cbd7ae0406b98cdc..26905b2b3ba3761641ef304c9abf57017aa932e1 100644 (file)
@@ -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])
index a51e2755991af993f0c4570b1daeec8c411d9c6c..a05c49b4e7f80b1b1678c93bcb72579d4b80c70d 100644 (file)
@@ -967,15 +967,18 @@ out:
        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, &params, NULL))) {
                free_netdev(dev);
                goto unlock;
        }
index 523025106a643eebc2d3f948f8fe380bce376bbd..0f7281e3e448891a78c24b096862a2de790b7687 100644 (file)
@@ -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);
index bc0069a8b6ea12263a34b333ef2946c9db036059..563a6a27436c2eb2fb90bb34cb54dfe93750a679 100644 (file)
@@ -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[],
index 134419667d59e9906b47b171d8c16d0dd00cdb8a..91df0f96e32aedfc376884bf27d3c6f6c8bcb447 100644 (file)
@@ -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;
index 822d788a5f86bb8f034d0bdedebf18ec5f044ade..d893c80132616aa03c00dfe8de89b89607cd5228 100644 (file)
@@ -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;
 
index 3e0f47203f2a1a74a253b4d5cb7a11939145160d..6e337937d0d7b53200d2fc70c20f9f5ccd77fee1 100644 (file)
@@ -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);
index 94ad09e36df2ade0b1e0b6274a7dcefc5c8f2b28..fa6a3c2634a8cb4803e3511e6cbf96821bfa6338 100644 (file)
@@ -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();
index 0f3e2c6021de0792e587aebb56102705d0d60e74..9ebbde0d131cea4d053785da519c0185fceab6b6 100644 (file)
@@ -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, &params, extack);
        else
                err = register_netdevice(dev);
        if (err < 0) {
index b68f2f71d0e1f3ce06276b0b99b3afb0bbe13e88..39add538ba9987c52494c5b084414400afea4380 100644 (file)
@@ -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;
index 175efd860f7b4adaa49dfbb42bf05a55784e8e9b..704bf9e3f097534961d90eb4586faae2068f1efd 100644 (file)
@@ -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;
 
index c9f11a046c263005dadad9276e2f1abe82fa23cc..1fe9b13d351c1d6b93cc104dcdaaa25c19e39bd5 100644 (file)
@@ -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, &params, NULL);
        if (err < 0) {
                free_netdev(dev);
                return ERR_PTR(err);
index f0b4419cef349329bf9ecad8d581111979786029..b901bee03e6d68d8f3fc9885048d4b622c5dfe26 100644 (file)
@@ -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);
index dc0db5895e0e0668c28bc6ae2937181bc784ea06..a8b844bcfc64535c53e22f463536948317bc3d33 100644 (file)
@@ -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;
index 235808cfec705032b545d6f396f8e58f4693e8d8..863852abe8eacf8abbe2f17b204d3bb97030cbae 100644 (file)
@@ -2005,11 +2005,14 @@ out:
        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;
index 48fd53b9897265338086136e96ea8e8c6ec3cac8..54b843d2087089de40ec328d8ad70c7bcd0231fc 100644 (file)
@@ -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;
index 590737c275379851f7bbd8c44e08c2d75ce7c375..993f85aeb88239964fbefdf210bb33e2e4e845b7 100644 (file)
@@ -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;
 
index 39bd8951bfca18e570154dc298f7f8ebdf6208d7..e2bd52cabdee596e2e4ed050d13b8021456cec4b 100644 (file)
@@ -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;
index c397eb99d867918516401bf2e158b9c438b8eb3f..5659a6cadd5193c1f69371232b962f17b109faea 100644 (file)
@@ -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;