@@ -97,7 +97,8 @@ 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,
+static int ipoib_new_child_link(struct rtnl_link_nets *nets,
+ struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -109,7 +110,8 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
if (!tb[IFLA_LINK])
return -EINVAL;
- pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+ pdev = __dev_get_by_index(rtnl_link_netns(nets),
+ nla_get_u32(tb[IFLA_LINK]));
if (!pdev || pdev->type != ARPHRD_INFINIBAND)
return -ENODEV;
@@ -3161,14 +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,
+static int amt_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct amt_dev *amt = netdev_priv(dev);
int err = -EINVAL;
- amt->net = net;
+ amt->net = rtnl_link_netns(nets);
amt->mode = nla_get_u32(data[IFLA_AMT_MODE]);
if (data[IFLA_AMT_MAX_TUNNELS] &&
@@ -3183,7 +3183,7 @@ static int amt_newlink(struct net *net, struct net_device *dev,
amt->hash_buckets = AMT_HSIZE;
amt->nr_tunnels = 0;
get_random_bytes(&amt->hash_seed, sizeof(amt->hash_seed));
- amt->stream_dev = dev_get_by_index(net,
+ amt->stream_dev = dev_get_by_index(rtnl_link_netns(nets),
nla_get_u32(data[IFLA_AMT_LINK]));
if (!amt->stream_dev) {
NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_LINK],
@@ -698,7 +698,7 @@ 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,
+static int bareudp_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -709,7 +709,7 @@ static int bareudp_newlink(struct net *net, struct net_device *dev,
if (err)
return err;
- err = bareudp_configure(net, dev, &conf, extack);
+ err = bareudp_configure(rtnl_link_netns(nets), dev, &conf, extack);
if (err)
return err;
@@ -564,7 +564,8 @@ 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,
+static int bond_newlink(struct rtnl_link_nets *nets,
+ struct net_device *bond_dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -624,7 +624,7 @@ 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,
+static int can_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -172,7 +172,7 @@ 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 *net, struct net_device *dev,
+static int vxcan_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -203,7 +203,7 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
name_assign_type = NET_NAME_ENUM;
}
- peer_net = rtnl_link_get_net(net, tbp);
+ peer_net = rtnl_link_get_net(rtnl_link_netns(nets), tbp);
peer = rtnl_create_link(peer_net, ifname, name_assign_type,
&vxcan_link_ops, tbp, extack);
if (IS_ERR(peer)) {
@@ -117,7 +117,7 @@ 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,
+static int rmnet_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -134,7 +134,8 @@ static int rmnet_newlink(struct net *src_net, 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(rtnl_link_netns(nets),
+ nla_get_u32(tb[IFLA_LINK]));
if (!real_dev) {
NL_SET_ERR_MSG_MOD(extack, "link does not exist");
return -ENODEV;
@@ -1614,7 +1614,7 @@ 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,
+static int geneve_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1631,7 +1631,7 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
if (err)
return err;
- err = geneve_configure(net, dev, extack, &cfg);
+ err = geneve_configure(rtnl_link_netns(nets), dev, extack, &cfg);
if (err)
return err;
@@ -1460,7 +1460,7 @@ 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,
+static int gtp_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1494,7 +1494,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
gtp->restart_count = nla_get_u8_default(data[IFLA_GTP_RESTART_COUNT],
0);
- gtp->net = src_net;
+ gtp->net = rtnl_link_netns(nets);
err = gtp_hashtable_new(gtp, hashsize);
if (err < 0)
@@ -166,7 +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,
+int ipvlan_link_new(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack);
void ipvlan_link_delete(struct net_device *dev, struct list_head *head);
@@ -532,7 +532,7 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb,
return ret;
}
-int ipvlan_link_new(struct net *src_net, struct net_device *dev,
+int ipvlan_link_new(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -545,7 +545,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
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(rtnl_link_netns(nets),
+ nla_get_u32(tb[IFLA_LINK]));
if (!phy_dev)
return -ENODEV;
@@ -73,7 +73,7 @@ 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,
+static int ipvtap_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -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(nets, dev, tb, data, extack);
if (err) {
netdev_rx_handler_unregister(dev);
return err;
@@ -4141,7 +4141,7 @@ 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,
+static int macsec_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -4154,7 +4154,8 @@ static int macsec_newlink(struct net *net, 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(rtnl_link_netns(nets),
+ nla_get_u32(tb[IFLA_LINK]));
if (!real_dev)
return -ENODEV;
if (real_dev->type != ARPHRD_ETHER)
@@ -1565,11 +1565,12 @@ 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,
+static int macvlan_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
- return macvlan_common_newlink(src_net, dev, tb, data, extack);
+ return macvlan_common_newlink(rtnl_link_netns(nets), dev, tb, data,
+ extack);
}
void macvlan_dellink(struct net_device *dev, struct list_head *head)
@@ -77,7 +77,7 @@ 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,
+static int macvtap_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -105,7 +105,8 @@ 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(rtnl_link_netns(nets), dev, tb, data,
+ extack);
if (err) {
netdev_rx_handler_unregister(dev);
return err;
@@ -327,7 +327,7 @@ 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 *src_net, struct net_device *dev,
+static int netkit_new_link(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -385,7 +385,7 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
(tb[IFLA_ADDRESS] || tbp[IFLA_ADDRESS]))
return -EOPNOTSUPP;
- net = rtnl_link_get_net(src_net, tbp);
+ net = rtnl_link_get_net(rtnl_link_netns(nets), tbp);
peer = rtnl_create_link(net, ifname, ifname_assign_type,
&netkit_link_ops, tbp, extack);
if (IS_ERR(peer)) {
@@ -184,7 +184,7 @@ 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,
+static int pfcp_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -192,7 +192,7 @@ static int pfcp_newlink(struct net *net, struct net_device *dev,
struct pfcp_net *pn;
int err;
- pfcp->net = net;
+ pfcp->net = rtnl_link_netns(nets);
err = pfcp_add_sock(pfcp);
if (err) {
@@ -1303,7 +1303,7 @@ 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,
+static int ppp_nl_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1343,7 +1343,7 @@ static int ppp_nl_newlink(struct net *src_net, 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(rtnl_link_netns(nets), dev, &conf);
out_unlock:
mutex_unlock(&ppp_mutex);
@@ -2206,7 +2206,7 @@ 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,
+static int team_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1765,7 +1765,7 @@ static int veth_init_queues(struct net_device *dev, struct nlattr *tb[])
return 0;
}
-static int veth_newlink(struct net *src_net, struct net_device *dev,
+static int veth_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1800,7 +1800,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
name_assign_type = NET_NAME_ENUM;
}
- net = rtnl_link_get_net(src_net, tbp);
+ net = rtnl_link_get_net(rtnl_link_netns(nets), tbp);
peer = rtnl_create_link(net, ifname, name_assign_type,
&veth_link_ops, tbp, extack);
if (IS_ERR(peer)) {
@@ -1698,7 +1698,7 @@ 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,
+static int vrf_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -4345,7 +4345,7 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
return 0;
}
-static int vxlan_newlink(struct net *src_net, struct net_device *dev,
+static int vxlan_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -4356,7 +4356,7 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
if (err)
return err;
- return __vxlan_dev_create(src_net, dev, &conf, extack);
+ return __vxlan_dev_create(rtnl_link_netns(nets), dev, &conf, extack);
}
static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -306,14 +306,14 @@ static void wg_setup(struct net_device *dev)
wg->dev = dev;
}
-static int wg_newlink(struct net *src_net, struct net_device *dev,
+static int wg_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct wg_device *wg = netdev_priv(dev);
int ret = -ENOMEM;
- rcu_assign_pointer(wg->creating_net, src_net);
+ rcu_assign_pointer(wg->creating_net, rtnl_link_netns(nets));
init_rwsem(&wg->static_identity.lock);
mutex_init(&wg->socket_update_lock);
mutex_init(&wg->device_update_lock);
@@ -519,7 +519,8 @@ 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,
+static int virt_wifi_newlink(struct rtnl_link_nets *nets,
+ struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -532,7 +533,7 @@ static int virt_wifi_newlink(struct net *src_net, 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(rtnl_link_netns(nets),
nla_get_u32(tb[IFLA_LINK]));
if (!priv->lowerdev)
@@ -967,7 +967,8 @@ 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,
+static int wwan_rtnl_newlink(struct rtnl_link_nets *nets,
+ struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1064,6 +1065,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev,
struct net_device *dev;
struct nlmsghdr *nlh;
struct sk_buff *msg;
+ struct rtnl_link_nets nets = { .src_net = &init_net };
/* Forge attributes required to create a WWAN netdev. We first
* build a netlink message and then parse it. This looks
@@ -1105,7 +1107,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(&nets, dev, tb, data, NULL))) {
free_netdev(dev);
goto unlock;
}
@@ -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[],
@@ -69,6 +69,26 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
return AF_UNSPEC;
}
+/**
+ * struct rtnl_link_nets - net namespace context of newlink.
+ *
+ * @src_net: Source netns of rtnetlink socket
+ * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified.
+ */
+struct rtnl_link_nets {
+ struct net *src_net;
+ struct net *link_net;
+};
+
+/* Get effective link netns from struct rtnl_link_nets. 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_link_netns(struct rtnl_link_nets *nets)
+{
+ return nets->link_net ? : nets->src_net;
+}
+
/**
* struct rtnl_link_ops - rtnetlink link operations
*
@@ -125,7 +145,7 @@ struct rtnl_link_ops {
struct nlattr *data[],
struct netlink_ext_ack *extack);
- int (*newlink)(struct net *src_net,
+ int (*newlink)(struct rtnl_link_nets *nets,
struct net_device *dev,
struct nlattr *tb[],
struct nlattr *data[],
@@ -135,7 +135,7 @@ 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,
+static int vlan_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -155,7 +155,8 @@ static int vlan_newlink(struct net *src_net, 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(rtnl_link_netns(nets),
+ nla_get_u32(tb[IFLA_LINK]));
if (!real_dev) {
NL_SET_ERR_MSG_MOD(extack, "link does not exist");
return -ENODEV;
@@ -1063,7 +1063,7 @@ 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
+ * @nets: the applicable net namespaces
* @dev: network device to register
* @tb: IFLA_INFO_DATA netlink attributes
* @data: enum batadv_ifla_attrs attributes
@@ -1071,7 +1071,8 @@ static int batadv_softif_validate(struct nlattr *tb[], struct nlattr *data[],
*
* Return: 0 if successful or error otherwise.
*/
-static int batadv_softif_newlink(struct net *src_net, struct net_device *dev,
+static int batadv_softif_newlink(struct rtnl_link_nets *nets,
+ struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1553,7 +1553,7 @@ 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,
+static int br_dev_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -438,7 +438,7 @@ static void caif_netlink_parms(struct nlattr *data[],
}
}
-static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
+static int ipcaif_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -3750,6 +3750,10 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
struct net_device *dev;
char ifname[IFNAMSIZ];
int err;
+ struct rtnl_link_nets nets = {
+ .src_net = net,
+ .link_net = link_net,
+ };
if (!ops->alloc && !ops->setup)
return -EOPNOTSUPP;
@@ -3761,8 +3765,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;
@@ -3771,7 +3775,7 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
dev->ifindex = ifm->ifi_index;
if (ops->newlink)
- err = ops->newlink(link_net ? : net, dev, tb, data, extack);
+ err = ops->newlink(&nets, dev, tb, data, extack);
else
err = register_netdevice(dev);
if (err < 0) {
@@ -3782,11 +3786,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)
@@ -29,7 +29,7 @@ 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,
+static int hsr_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -46,7 +46,7 @@ static int hsr_newlink(struct net *src_net, 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(rtnl_link_netns(nets),
nla_get_u32(data[IFLA_HSR_SLAVE1]));
if (!link[0]) {
NL_SET_ERR_MSG_MOD(extack, "Slave1 does not exist");
@@ -56,7 +56,7 @@ static int hsr_newlink(struct net *src_net, 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(rtnl_link_netns(nets),
nla_get_u32(data[IFLA_HSR_SLAVE2]));
if (!link[1]) {
NL_SET_ERR_MSG_MOD(extack, "Slave2 does not exist");
@@ -69,7 +69,7 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
}
if (data[IFLA_HSR_INTERLINK])
- interlink = __dev_get_by_index(src_net,
+ interlink = __dev_get_by_index(rtnl_link_netns(nets),
nla_get_u32(data[IFLA_HSR_INTERLINK]));
if (interlink && interlink == link[0]) {
@@ -129,7 +129,7 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[],
return 0;
}
-static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
+static int lowpan_newlink(struct rtnl_link_nets *nets, struct net_device *ldev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -143,7 +143,8 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
if (!tb[IFLA_LINK])
return -EINVAL;
/* find and hold wpan device */
- wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK]));
+ wdev = dev_get_by_index(nets->link_net ? : dev_net(ldev),
+ nla_get_u32(tb[IFLA_LINK]));
if (!wdev)
return -ENODEV;
if (wdev->type != ARPHRD_IEEE802154) {
@@ -1389,10 +1389,11 @@ 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,
+static int ipgre_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip_tunnel_parm_kern p;
__u32 fwmark = 0;
int err;
@@ -1404,13 +1405,14 @@ static int ipgre_newlink(struct net *src_net, 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(net, dev, tb, &p, fwmark);
}
-static int erspan_newlink(struct net *src_net, struct net_device *dev,
+static int erspan_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip_tunnel_parm_kern p;
__u32 fwmark = 0;
int err;
@@ -1422,7 +1424,7 @@ static int erspan_newlink(struct net *src_net, 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(net, dev, tb, &p, fwmark);
}
static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -1695,6 +1697,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
LIST_HEAD(list_kill);
struct ip_tunnel *t;
int err;
+ struct rtnl_link_nets nets = { .src_net = net };
memset(&tb, 0, sizeof(tb));
@@ -1707,7 +1710,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(&nets, dev, tb, NULL, NULL);
if (err < 0) {
free_netdev(dev);
return ERR_PTR(err);
@@ -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;
@@ -575,7 +575,7 @@ 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,
+static int vti_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -583,7 +583,8 @@ static int vti_newlink(struct net *src_net, 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(nets->link_net ? : dev_net(dev), dev, tb,
+ &parms, fwmark);
}
static int vti_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -436,7 +436,7 @@ 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,
+static int ipip_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -453,7 +453,8 @@ static int ipip_newlink(struct net *src_net, 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(nets->link_net ? : dev_net(dev), dev, tb, &p,
+ fwmark);
}
static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -1971,7 +1971,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 +1992,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)
@@ -2005,12 +2005,12 @@ 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,
+static int ip6gre_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct ip6_tnl *nt = netdev_priv(dev);
- struct net *net = dev_net(dev);
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip6gre_net *ign;
int err;
@@ -2025,7 +2025,7 @@ static int ip6gre_newlink(struct net *src_net, 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);
@@ -2241,12 +2241,13 @@ 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,
+static int ip6erspan_newlink(struct rtnl_link_nets *nets,
+ struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct ip6_tnl *nt = netdev_priv(dev);
- struct net *net = dev_net(dev);
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip6gre_net *ign;
int err;
@@ -2262,7 +2263,7 @@ static int ip6erspan_newlink(struct net *src_net, 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);
@@ -250,10 +250,9 @@ static void ip6_dev_free(struct net_device *dev)
dst_cache_destroy(&t->dst_cache);
}
-static int ip6_tnl_create2(struct net_device *dev)
+static int ip6_tnl_create2(struct net *net, 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);
int err;
@@ -308,7 +307,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
t = netdev_priv(dev);
t->parms = *p;
t->net = dev_net(dev);
- err = ip6_tnl_create2(dev);
+ err = ip6_tnl_create2(net, dev);
if (err < 0)
goto failed_free;
@@ -2002,11 +2001,11 @@ 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,
+static int ip6_tnl_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
- struct net *net = dev_net(dev);
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
struct ip_tunnel_encap ipencap;
struct ip6_tnl *nt, *t;
@@ -2031,7 +2030,7 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
return -EEXIST;
}
- err = ip6_tnl_create2(dev);
+ err = ip6_tnl_create2(net, dev);
if (!err && tb[IFLA_MTU])
ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
@@ -174,10 +174,9 @@ vti6_tnl_unlink(struct vti6_net *ip6n, struct ip6_tnl *t)
}
}
-static int vti6_tnl_create2(struct net_device *dev)
+static int vti6_tnl_create2(struct net *net, 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);
int err;
@@ -221,7 +220,7 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p
t->parms = *p;
t->net = dev_net(dev);
- err = vti6_tnl_create2(dev);
+ err = vti6_tnl_create2(net, dev);
if (err < 0)
goto failed_free;
@@ -997,11 +996,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,
+static int vti6_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
- struct net *net = dev_net(dev);
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip6_tnl *nt;
nt = netdev_priv(dev);
@@ -1012,7 +1011,7 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev,
if (vti6_locate(net, &nt->parms, 0))
return -EEXIST;
- return vti6_tnl_create2(dev);
+ return vti6_tnl_create2(net, dev);
}
static void vti6_dellink(struct net_device *dev, struct list_head *head)
@@ -198,10 +198,9 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
#endif
}
-static int ipip6_tunnel_create(struct net_device *dev)
+static int ipip6_tunnel_create(struct net *net, 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);
int err;
@@ -270,7 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
nt = netdev_priv(dev);
nt->parms = *parms;
- if (ipip6_tunnel_create(dev) < 0)
+ if (ipip6_tunnel_create(net, dev) < 0)
goto failed_free;
if (!parms->name[0])
@@ -1550,11 +1549,11 @@ static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
}
#endif
-static int ipip6_newlink(struct net *src_net, struct net_device *dev,
+static int ipip6_newlink(struct rtnl_link_nets *nets, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
- struct net *net = dev_net(dev);
+ struct net *net = nets->link_net ? : dev_net(dev);
struct ip_tunnel *nt;
struct ip_tunnel_encap ipencap;
#ifdef CONFIG_IPV6_SIT_6RD
@@ -1575,7 +1574,7 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev,
if (ipip6_tunnel_locate(net, &nt->parms, 0))
return -EEXIST;
- err = ipip6_tunnel_create(dev);
+ err = ipip6_tunnel_create(net, dev);
if (err < 0)
return err;
@@ -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;
@@ -814,11 +813,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 rtnl_link_nets *nets, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
- struct net *net = dev_net(dev);
+ struct net *net = nets->link_net ? : dev_net(dev);
struct xfrm_if_parms p = {};
struct xfrm_if *xi;
int err;
@@ -851,7 +850,7 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
xi->net = net;
xi->dev = dev;
- err = xfrmi_create(dev);
+ err = xfrmi_create(net, dev);
return err;
}
There are three 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). 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 whether IFLA_LINK_NETNSID is present. +-------------------+---------+---------+ | IFLA_LINK_NETNSID | src_net | dev_net | +-------------------+---------+---------+ | absent | source | target | +-------------------+---------+---------+ | present | link | link | +-------------------+---------+---------+ When IFLA_LINK_NETNSID is present, the device is created in link netns first. This has some side effects, including extra ifindex allocation, ifname validation and link notifications. There's also an extra step to move the device to target netns. These could be avoided if we create it in target netns at the beginning. On the other hand, the meaning of src_net is ambiguous. It should be the effective link netns by design, but some drivers ignore it and use dev_net instead. This patch refactors netns handling. rtnl_newlink_create() now creates devices in target netns directly, so dev_net is always target netns. Source and link netns are passed to newlink() as src_net and link_net in a new struct consistently. When determining the effective link netns, in the absence link_net, drivers should look for src_net in general. But for compatibility, drivers that use dev_net will keep current behavior. Signed-off-by: Xiao Liang <shaw.leon@gmail.com> --- There're some issues found when coverting drivers. Please check if they work as intended: - In amt_newlink() drivers/net/amt.c: amt->net = net; ... amt->stream_dev = dev_get_by_index(net, ... Uses net (src_net actually), but amt_lookup_upper_dev() only searches in dev_net. - In gtp_newlink() in drivers/net/gtp.c: gtp->net = src_net; ... gn = net_generic(dev_net(dev), gtp_net_id); list_add_rcu(>p->list, &gn->gtp_dev_list); Uses src_net, but is linked to list in dev_net. - In pfcp_newlink() in drivers/net/pfcp.c: pfcp->net = net; ... pn = net_generic(dev_net(dev), pfcp_net_id); list_add_rcu(&pfcp->list, &pn->pfcp_dev_list); Same. - 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. --- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 6 +++-- drivers/net/amt.c | 6 ++--- drivers/net/bareudp.c | 4 ++-- drivers/net/bonding/bond_netlink.c | 3 ++- drivers/net/can/dev/netlink.c | 2 +- drivers/net/can/vxcan.c | 4 ++-- .../ethernet/qualcomm/rmnet/rmnet_config.c | 5 +++-- drivers/net/geneve.c | 4 ++-- drivers/net/gtp.c | 4 ++-- drivers/net/ipvlan/ipvlan.h | 2 +- drivers/net/ipvlan/ipvlan_main.c | 5 +++-- drivers/net/ipvlan/ipvtap.c | 4 ++-- drivers/net/macsec.c | 5 +++-- drivers/net/macvlan.c | 5 +++-- drivers/net/macvtap.c | 5 +++-- drivers/net/netkit.c | 4 ++-- drivers/net/pfcp.c | 4 ++-- drivers/net/ppp/ppp_generic.c | 4 ++-- drivers/net/team/team_core.c | 2 +- drivers/net/veth.c | 4 ++-- drivers/net/vrf.c | 2 +- drivers/net/vxlan/vxlan_core.c | 4 ++-- drivers/net/wireguard/device.c | 4 ++-- drivers/net/wireless/virtual/virt_wifi.c | 5 +++-- drivers/net/wwan/wwan_core.c | 6 +++-- include/net/ip_tunnels.h | 5 +++-- include/net/rtnetlink.h | 22 ++++++++++++++++++- net/8021q/vlan_netlink.c | 5 +++-- net/batman-adv/soft-interface.c | 5 +++-- net/bridge/br_netlink.c | 2 +- net/caif/chnl_net.c | 2 +- net/core/rtnetlink.c | 15 ++++++------- net/hsr/hsr_netlink.c | 8 +++---- net/ieee802154/6lowpan/core.c | 5 +++-- net/ipv4/ip_gre.c | 13 ++++++----- net/ipv4/ip_tunnel.c | 10 +++++---- net/ipv4/ip_vti.c | 5 +++-- net/ipv4/ipip.c | 5 +++-- net/ipv6/ip6_gre.c | 17 +++++++------- net/ipv6/ip6_tunnel.c | 11 +++++----- net/ipv6/ip6_vti.c | 11 +++++----- net/ipv6/sit.c | 11 +++++----- net/xfrm/xfrm_interface_core.c | 13 +++++------ 43 files changed, 153 insertions(+), 115 deletions(-)