|
@@ -1848,7 +1848,8 @@ static struct genl_family dp_datapath_genl_family __ro_after_init = {
|
|
|
|
|
|
/* Called with ovs_mutex or RCU read lock. */
|
|
|
static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
|
|
|
- u32 portid, u32 seq, u32 flags, u8 cmd)
|
|
|
+ struct net *net, u32 portid, u32 seq,
|
|
|
+ u32 flags, u8 cmd)
|
|
|
{
|
|
|
struct ovs_header *ovs_header;
|
|
|
struct ovs_vport_stats vport_stats;
|
|
@@ -1864,9 +1865,17 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
|
|
|
if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||
|
|
|
nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||
|
|
|
nla_put_string(skb, OVS_VPORT_ATTR_NAME,
|
|
|
- ovs_vport_name(vport)))
|
|
|
+ ovs_vport_name(vport)) ||
|
|
|
+ nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
+ if (!net_eq(net, dev_net(vport->dev))) {
|
|
|
+ int id = peernet2id_alloc(net, dev_net(vport->dev));
|
|
|
+
|
|
|
+ if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
|
|
|
+ goto nla_put_failure;
|
|
|
+ }
|
|
|
+
|
|
|
ovs_vport_get_stats(vport, &vport_stats);
|
|
|
if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
|
|
|
sizeof(struct ovs_vport_stats), &vport_stats,
|
|
@@ -1896,8 +1905,8 @@ static struct sk_buff *ovs_vport_cmd_alloc_info(void)
|
|
|
}
|
|
|
|
|
|
/* Called with ovs_mutex, only via ovs_dp_notify_wq(). */
|
|
|
-struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid,
|
|
|
- u32 seq, u8 cmd)
|
|
|
+struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, struct net *net,
|
|
|
+ u32 portid, u32 seq, u8 cmd)
|
|
|
{
|
|
|
struct sk_buff *skb;
|
|
|
int retval;
|
|
@@ -1906,7 +1915,7 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid,
|
|
|
if (!skb)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
- retval = ovs_vport_cmd_fill_info(vport, skb, portid, seq, 0, cmd);
|
|
|
+ retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd);
|
|
|
BUG_ON(retval < 0);
|
|
|
|
|
|
return skb;
|
|
@@ -1920,6 +1929,8 @@ static struct vport *lookup_vport(struct net *net,
|
|
|
struct datapath *dp;
|
|
|
struct vport *vport;
|
|
|
|
|
|
+ if (a[OVS_VPORT_ATTR_IFINDEX])
|
|
|
+ return ERR_PTR(-EOPNOTSUPP);
|
|
|
if (a[OVS_VPORT_ATTR_NAME]) {
|
|
|
vport = ovs_vport_locate(net, nla_data(a[OVS_VPORT_ATTR_NAME]));
|
|
|
if (!vport)
|
|
@@ -1944,6 +1955,7 @@ static struct vport *lookup_vport(struct net *net,
|
|
|
return vport;
|
|
|
} else
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/* Called with ovs_mutex */
|
|
@@ -1983,6 +1995,8 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|
|
if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] ||
|
|
|
!a[OVS_VPORT_ATTR_UPCALL_PID])
|
|
|
return -EINVAL;
|
|
|
+ if (a[OVS_VPORT_ATTR_IFINDEX])
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
|
|
port_no = a[OVS_VPORT_ATTR_PORT_NO]
|
|
|
? nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]) : 0;
|
|
@@ -2032,8 +2046,9 @@ restart:
|
|
|
goto exit_unlock_free;
|
|
|
}
|
|
|
|
|
|
- err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
|
|
|
- info->snd_seq, 0, OVS_VPORT_CMD_NEW);
|
|
|
+ err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
|
|
|
+ info->snd_portid, info->snd_seq, 0,
|
|
|
+ OVS_VPORT_CMD_NEW);
|
|
|
|
|
|
if (netdev_get_fwd_headroom(vport->dev) > dp->max_headroom)
|
|
|
update_headroom(dp);
|
|
@@ -2090,8 +2105,9 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto exit_unlock_free;
|
|
|
}
|
|
|
|
|
|
- err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
|
|
|
- info->snd_seq, 0, OVS_VPORT_CMD_NEW);
|
|
|
+ err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
|
|
|
+ info->snd_portid, info->snd_seq, 0,
|
|
|
+ OVS_VPORT_CMD_NEW);
|
|
|
BUG_ON(err < 0);
|
|
|
|
|
|
ovs_unlock();
|
|
@@ -2128,8 +2144,9 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
|
|
goto exit_unlock_free;
|
|
|
}
|
|
|
|
|
|
- err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
|
|
|
- info->snd_seq, 0, OVS_VPORT_CMD_DEL);
|
|
|
+ err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
|
|
|
+ info->snd_portid, info->snd_seq, 0,
|
|
|
+ OVS_VPORT_CMD_DEL);
|
|
|
BUG_ON(err < 0);
|
|
|
|
|
|
/* the vport deletion may trigger dp headroom update */
|
|
@@ -2169,8 +2186,9 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
|
|
err = PTR_ERR(vport);
|
|
|
if (IS_ERR(vport))
|
|
|
goto exit_unlock_free;
|
|
|
- err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
|
|
|
- info->snd_seq, 0, OVS_VPORT_CMD_NEW);
|
|
|
+ err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
|
|
|
+ info->snd_portid, info->snd_seq, 0,
|
|
|
+ OVS_VPORT_CMD_NEW);
|
|
|
BUG_ON(err < 0);
|
|
|
rcu_read_unlock();
|
|
|
|
|
@@ -2202,6 +2220,7 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
|
|
|
if (j >= skip &&
|
|
|
ovs_vport_cmd_fill_info(vport, skb,
|
|
|
+ sock_net(skb->sk),
|
|
|
NETLINK_CB(cb->skb).portid,
|
|
|
cb->nlh->nlmsg_seq,
|
|
|
NLM_F_MULTI,
|
|
@@ -2228,6 +2247,8 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
|
|
|
[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
|
|
|
[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
|
|
|
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
|
|
|
+ [OVS_VPORT_ATTR_IFINDEX] = { .type = NLA_U32 },
|
|
|
+ [OVS_VPORT_ATTR_NETNSID] = { .type = NLA_S32 },
|
|
|
};
|
|
|
|
|
|
static const struct genl_ops dp_vport_genl_ops[] = {
|