mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10.git
synced 2026-09-09 00:07:04 +08:00
Merge: net: Fix deadlock on netns change.
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/2576 JIRA: https://redhat.atlassian.net/browse/RHEL-144808 Upstream Status: linux.git Backport upstream commit 7ca486d08a30 ("rtnetlink: Create link directly in target net namespace") and its dependencies, plus selftests. Signed-off-by: Guillaume Nault <gnault@redhat.com> Approved-by: Antoine Tenart <atenart@redhat.com> Approved-by: José Ignacio Tornos Martínez <jtornosm@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct net_device *pdev;
|
||||
struct ipoib_dev_priv *ppriv;
|
||||
u16 child_pkey;
|
||||
@@ -109,7 +112,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
|
||||
if (!tb[IFLA_LINK])
|
||||
return -EINVAL;
|
||||
|
||||
pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
|
||||
pdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK]));
|
||||
if (!pdev || pdev->type != ARPHRD_INFINIBAND)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
+7
-4
@@ -3161,14 +3161,17 @@ static int amt_validate(struct nlattr *tb[], struct nlattr *data[],
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amt_newlink(struct net *net, struct net_device *dev,
|
||||
struct nlattr *tb[], struct nlattr *data[],
|
||||
static int amt_newlink(struct net_device *dev,
|
||||
struct rtnl_newlink_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct net *link_net = rtnl_newlink_link_net(params);
|
||||
struct amt_dev *amt = netdev_priv(dev);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
int err = -EINVAL;
|
||||
|
||||
amt->net = net;
|
||||
amt->net = link_net;
|
||||
amt->mode = nla_get_u32(data[IFLA_AMT_MODE]);
|
||||
|
||||
if (data[IFLA_AMT_MAX_TUNNELS] &&
|
||||
@@ -3183,7 +3186,7 @@ static int amt_newlink(struct net *net, struct net_device *dev,
|
||||
amt->hash_buckets = AMT_HSIZE;
|
||||
amt->nr_tunnels = 0;
|
||||
get_random_bytes(&amt->hash_seed, sizeof(amt->hash_seed));
|
||||
amt->stream_dev = dev_get_by_index(net,
|
||||
amt->stream_dev = dev_get_by_index(link_net,
|
||||
nla_get_u32(data[IFLA_AMT_LINK]));
|
||||
if (!amt->stream_dev) {
|
||||
NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_AMT_LINK],
|
||||
|
||||
@@ -698,10 +698,13 @@ static void bareudp_dellink(struct net_device *dev, struct list_head *head)
|
||||
unregister_netdevice_queue(dev, head);
|
||||
}
|
||||
|
||||
static int bareudp_newlink(struct net *net, struct net_device *dev,
|
||||
struct nlattr *tb[], struct nlattr *data[],
|
||||
static int bareudp_newlink(struct net_device *dev,
|
||||
struct rtnl_newlink_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct net *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct bareudp_conf conf;
|
||||
int err;
|
||||
|
||||
@@ -709,7 +712,7 @@ static int bareudp_newlink(struct net *net, struct net_device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = bareudp_configure(net, dev, &conf, extack);
|
||||
err = bareudp_configure(link_net, dev, &conf, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -591,10 +591,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 net *peer_net = rtnl_newlink_peer_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct vxcan_priv *priv;
|
||||
struct net_device *peer;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
struct net *link_net = rtnl_newlink_link_net(params);
|
||||
u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION;
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct net_device *real_dev;
|
||||
int mode = RMNET_EPMODE_VND;
|
||||
struct rmnet_endpoint *ep;
|
||||
@@ -134,7 +137,7 @@ 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(link_net, nla_get_u32(tb[IFLA_LINK]));
|
||||
if (!real_dev) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "link does not exist");
|
||||
return -ENODEV;
|
||||
|
||||
@@ -2132,10 +2132,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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct geneve_config cfg = {
|
||||
.df = GENEVE_DF_UNSET,
|
||||
.use_udp6_rx_checksums = false,
|
||||
@@ -2151,7 +2154,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(link_net, dev, extack, &cfg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
+6
-4
@@ -1460,10 +1460,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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
unsigned int role = GTP_ROLE_GGSN;
|
||||
struct gtp_dev *gtp;
|
||||
struct gtp_net *gn;
|
||||
@@ -1496,7 +1498,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
|
||||
else
|
||||
gtp->restart_count = nla_get_u8(data[IFLA_GTP_RESTART_COUNT]);
|
||||
|
||||
gtp->net = src_net;
|
||||
gtp->net = link_net;
|
||||
|
||||
err = gtp_hashtable_new(gtp, hashsize);
|
||||
if (err < 0)
|
||||
@@ -1526,7 +1528,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
|
||||
goto out_encap;
|
||||
}
|
||||
|
||||
gn = net_generic(dev_net(dev), gtp_net_id);
|
||||
gn = net_generic(link_net, gtp_net_id);
|
||||
list_add_rcu(>p->list, &gn->gtp_dev_list);
|
||||
dev->priv_destructor = gtp_destructor;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -533,11 +533,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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct ipvl_dev *ipvlan = netdev_priv(dev);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct ipvl_port *port;
|
||||
struct net_device *phy_dev;
|
||||
int err;
|
||||
@@ -546,7 +548,7 @@ 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(link_net, nla_get_u32(tb[IFLA_LINK]));
|
||||
if (!phy_dev)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -4170,11 +4170,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 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;
|
||||
rx_handler_func_t *rx_handler;
|
||||
u8 icv_len = MACSEC_DEFAULT_ICV_LEN;
|
||||
struct net_device *real_dev;
|
||||
@@ -4183,7 +4186,7 @@ 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(link_net, nla_get_u32(tb[IFLA_LINK]));
|
||||
if (!real_dev)
|
||||
return -ENODEV;
|
||||
if (real_dev->type != ARPHRD_ETHER)
|
||||
|
||||
+12
-9
@@ -1447,21 +1447,24 @@ 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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
struct macvlan_port *port;
|
||||
struct nlattr **data = params->data;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
@@ -1578,11 +1581,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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -328,21 +328,25 @@ 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;
|
||||
struct net *peer_net = rtnl_newlink_peer_net(params);
|
||||
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp, *attr;
|
||||
enum netkit_action default_prim = NETKIT_PASS;
|
||||
enum netkit_action default_peer = NETKIT_PASS;
|
||||
struct nlattr **data = params->data;
|
||||
enum netkit_mode mode = NETKIT_L3;
|
||||
unsigned char ifname_assign_type;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct ifinfomsg *ifmp = NULL;
|
||||
struct net_device *peer;
|
||||
char ifname[IFNAMSIZ];
|
||||
struct netkit *nk;
|
||||
int err;
|
||||
|
||||
tbp = tb;
|
||||
if (data) {
|
||||
if (data[IFLA_NETKIT_MODE]) {
|
||||
attr = data[IFLA_NETKIT_MODE];
|
||||
|
||||
+5
-4
@@ -184,15 +184,16 @@ 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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct pfcp_dev *pfcp = netdev_priv(dev);
|
||||
struct pfcp_net *pn;
|
||||
int err;
|
||||
|
||||
pfcp->net = net;
|
||||
pfcp->net = link_net;
|
||||
|
||||
err = pfcp_add_sock(pfcp);
|
||||
if (err) {
|
||||
@@ -206,7 +207,7 @@ static int pfcp_newlink(struct net *net, struct net_device *dev,
|
||||
goto exit_del_pfcp_sock;
|
||||
}
|
||||
|
||||
pn = net_generic(dev_net(dev), pfcp_net_id);
|
||||
pn = net_generic(link_net, pfcp_net_id);
|
||||
list_add_rcu(&pfcp->list, &pn->pfcp_dev_list);
|
||||
|
||||
netdev_dbg(dev, "registered new PFCP interface\n");
|
||||
|
||||
@@ -1316,10 +1316,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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct ppp_config conf = {
|
||||
.unit = -1,
|
||||
.ifname_is_set = true,
|
||||
@@ -1356,7 +1359,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(link_net, dev, &conf);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&ppp_mutex);
|
||||
|
||||
@@ -2189,10 +2189,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);
|
||||
|
||||
|
||||
+5
-2
@@ -1766,10 +1766,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 net *peer_net = rtnl_newlink_peer_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
int err;
|
||||
struct net_device *peer;
|
||||
struct veth_priv *priv;
|
||||
|
||||
+3
-2
@@ -1699,11 +1699,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;
|
||||
|
||||
@@ -4390,10 +4390,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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct vxlan_config conf;
|
||||
int err;
|
||||
|
||||
@@ -4401,7 +4404,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(link_net, dev, &conf, extack);
|
||||
}
|
||||
|
||||
static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
|
||||
@@ -307,14 +307,15 @@ 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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct wg_device *wg = netdev_priv(dev);
|
||||
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);
|
||||
|
||||
@@ -523,11 +523,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 *link_net = rtnl_newlink_link_net(params);
|
||||
struct nlattr **tb = params->tb;
|
||||
int err;
|
||||
|
||||
if (!tb[IFLA_LINK])
|
||||
@@ -536,7 +538,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(link_net,
|
||||
nla_get_u32(tb[IFLA_LINK]));
|
||||
|
||||
if (!priv->lowerdev)
|
||||
|
||||
@@ -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 = {
|
||||
.src_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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -417,8 +417,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[],
|
||||
|
||||
+36
-4
@@ -69,6 +69,40 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink()
|
||||
*
|
||||
* @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 *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 +159,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[],
|
||||
|
||||
@@ -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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct net_device *real_dev;
|
||||
unsigned int max_mtu;
|
||||
__be16 proto;
|
||||
@@ -155,7 +158,7 @@ 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(link_net, nla_get_u32(tb[IFLA_LINK]));
|
||||
if (!real_dev) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "link does not exist");
|
||||
return -ENODEV;
|
||||
|
||||
@@ -1063,19 +1063,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;
|
||||
|
||||
|
||||
@@ -1573,11 +1573,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);
|
||||
|
||||
+3
-2
@@ -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();
|
||||
|
||||
+18
-16
@@ -3803,7 +3803,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];
|
||||
@@ -3819,8 +3825,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;
|
||||
@@ -3828,13 +3834,8 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
|
||||
|
||||
dev->ifindex = ifm->ifi_index;
|
||||
|
||||
if (link_net)
|
||||
net = link_net;
|
||||
if (peer_net)
|
||||
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) {
|
||||
@@ -3847,11 +3848,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)
|
||||
@@ -3922,20 +3918,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;
|
||||
|
||||
@@ -29,16 +29,18 @@ 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 net *link_net = rtnl_newlink_link_net(params);
|
||||
struct net_device *link[2], *interlink = NULL;
|
||||
struct nlattr **data = params->data;
|
||||
enum hsr_version proto_version;
|
||||
unsigned char multicast_spec;
|
||||
u8 proto = HSR_PROTOCOL_HSR;
|
||||
|
||||
if (!net_eq(src_net, dev_net(dev))) {
|
||||
if (!net_eq(link_net, dev_net(dev))) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"HSR slaves/interlink must be on the same net namespace than HSR link");
|
||||
return -EINVAL;
|
||||
@@ -52,7 +54,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(link_net,
|
||||
nla_get_u32(data[IFLA_HSR_SLAVE1]));
|
||||
if (!link[0]) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Slave1 does not exist");
|
||||
@@ -62,7 +64,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(link_net,
|
||||
nla_get_u32(data[IFLA_HSR_SLAVE2]));
|
||||
if (!link[1]) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Slave2 does not exist");
|
||||
@@ -75,7 +77,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(link_net,
|
||||
nla_get_u32(data[IFLA_HSR_INTERLINK]));
|
||||
|
||||
if (interlink && interlink == link[0]) {
|
||||
|
||||
@@ -130,10 +130,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;
|
||||
|
||||
@@ -143,6 +144,8 @@ static int lowpan_newlink(struct net *src_net, 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)
|
||||
|
||||
+15
-7
@@ -1397,10 +1397,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;
|
||||
@@ -1412,13 +1414,16 @@ 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(params->link_net ? : dev_net(dev), 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;
|
||||
@@ -1430,7 +1435,8 @@ 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(params->link_net ? : dev_net(dev), dev, tb, &p,
|
||||
fwmark);
|
||||
}
|
||||
|
||||
static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
@@ -1698,6 +1704,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 = { .src_net = net };
|
||||
struct nlattr *tb[IFLA_MAX + 1];
|
||||
struct net_device *dev;
|
||||
LIST_HEAD(list_kill);
|
||||
@@ -1705,6 +1712,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);
|
||||
@@ -1715,7 +1723,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);
|
||||
|
||||
@@ -1189,11 +1189,11 @@ void ip_tunnel_delete_net(struct net *net, unsigned int id,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_tunnel_delete_net);
|
||||
|
||||
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;
|
||||
@@ -1302,7 +1302,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;
|
||||
|
||||
+6
-3
@@ -574,15 +574,18 @@ 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);
|
||||
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[],
|
||||
|
||||
+6
-3
@@ -461,11 +461,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;
|
||||
@@ -478,7 +480,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(params->link_net ? : dev_net(dev), dev, tb, &p,
|
||||
fwmark);
|
||||
}
|
||||
|
||||
static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
|
||||
+14
-12
@@ -1510,7 +1510,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);
|
||||
@@ -1884,7 +1883,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);
|
||||
@@ -1973,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)
|
||||
{
|
||||
@@ -1994,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)
|
||||
@@ -2007,12 +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 net *net = params->link_net ? : dev_net(dev);
|
||||
struct ip6_tnl *nt = netdev_priv(dev);
|
||||
struct net *net = dev_net(dev);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct ip6gre_net *ign;
|
||||
int err;
|
||||
|
||||
@@ -2027,7 +2027,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);
|
||||
@@ -2243,12 +2243,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 net *net = params->link_net ? : dev_net(dev);
|
||||
struct ip6_tnl *nt = netdev_priv(dev);
|
||||
struct net *net = dev_net(dev);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
struct ip6gre_net *ign;
|
||||
int err;
|
||||
|
||||
@@ -2264,7 +2266,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);
|
||||
|
||||
+11
-7
@@ -254,8 +254,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;
|
||||
@@ -1921,7 +1920,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)
|
||||
@@ -1983,6 +1981,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);
|
||||
@@ -2045,17 +2044,22 @@ 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 net *net = dev_net(dev);
|
||||
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
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);
|
||||
|
||||
+8
-6
@@ -178,8 +178,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;
|
||||
@@ -926,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;
|
||||
@@ -959,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);
|
||||
@@ -998,17 +997,20 @@ 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 net *net = dev_net(dev);
|
||||
struct nlattr **data = params->data;
|
||||
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;
|
||||
|
||||
+12
-8
@@ -202,8 +202,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->net = net;
|
||||
nt->parms = *parms;
|
||||
if (ipip6_tunnel_create(dev) < 0)
|
||||
goto failed_free;
|
||||
@@ -1450,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);
|
||||
@@ -1551,19 +1550,23 @@ 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 net *net = dev_net(dev);
|
||||
struct nlattr **data = params->data;
|
||||
struct nlattr **tb = params->tb;
|
||||
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);
|
||||
@@ -1858,6 +1861,9 @@ static int __net_init sit_init_net(struct net *net)
|
||||
*/
|
||||
sitn->fb_tunnel_dev->netns_immutable = true;
|
||||
|
||||
t = netdev_priv(sitn->fb_tunnel_dev);
|
||||
t->net = net;
|
||||
|
||||
err = register_netdev(sitn->fb_tunnel_dev);
|
||||
if (err)
|
||||
goto err_reg_dev;
|
||||
@@ -1865,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;
|
||||
|
||||
|
||||
@@ -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,15 +813,17 @@ 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 net *net = dev_net(dev);
|
||||
struct nlattr **data = params->data;
|
||||
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);
|
||||
@@ -851,7 +852,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ TEST_PROGS := \
|
||||
ipv6_route_update_soft_lockup.sh \
|
||||
l2_tos_ttl_inherit.sh \
|
||||
l2tp.sh \
|
||||
link_netns.py \
|
||||
msg_zerocopy.sh \
|
||||
nat6to4.sh \
|
||||
ndisc_unsolicited_na_test.sh \
|
||||
|
||||
@@ -110,3 +110,8 @@ CONFIG_VLAN_8021Q=y
|
||||
CONFIG_VXLAN=m
|
||||
CONFIG_XFRM_INTERFACE=m
|
||||
CONFIG_XFRM_USER=m
|
||||
CONFIG_IPVLAN=m
|
||||
CONFIG_CAN=m
|
||||
CONFIG_CAN_DEV=m
|
||||
CONFIG_CAN_VXCAN=m
|
||||
CONFIG_NETKIT=y
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Executable
+141
@@ -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()
|
||||
@@ -83,6 +83,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 ]"
|
||||
|
||||
Reference in New Issue
Block a user