Skip to content

Commit

Permalink
datapath: reliable interface indentification in port dumps
Browse files Browse the repository at this point in the history
Upstream commit:
    commit 9354d452034273a50a4fd703bea31e5d6b1fc20b
    Author: Jiri Benc <[email protected]>
    Date:   Thu Nov 2 17:04:37 2017 -0200

    openvswitch: reliable interface indentification in port dumps

    This patch allows reliable identification of netdevice interfaces connected
    to openvswitch bridges. In particular, user space queries the netdev
    interfaces belonging to the ports for statistics, up/down state, etc.
    Datapath dump needs to provide enough information for the user space to be
    able to do that.

    Currently, only interface names are returned. This is not sufficient, as
    openvswitch allows its ports to be in different name spaces and the
    interface name is valid only in its name space. What is needed and generally
    used in other netlink APIs, is the pair ifindex+netnsid.

    The solution is addition of the ifindex+netnsid pair (or only ifindex if in
    the same name space) to vport get/dump operation.

    On request side, ideally the ifindex+netnsid pair could be used to
    get/set/del the corresponding vport. This is not implemented by this patch
    and can be added later if needed.

    Signed-off-by: Jiri Benc <[email protected]>
    Signed-off-by: David S. Miller <[email protected]>

Added compat fixup for peernet2id.

Cc: Jiri Benc <[email protected]>
Signed-off-by: Greg Rose <[email protected]>
Acked-by: Pravin B Shelar <[email protected]>
  • Loading branch information
Jiri Benc authored and pshelar committed Feb 13, 2018
1 parent b68abe0 commit b147f2e
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 16 deletions.
3 changes: 3 additions & 0 deletions acinclude.m4
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/linux/timekeeping.h],
[ktime_get_ts64],
[OVS_DEFINE([HAVE_KTIME_GET_TS64])])
OVS_GREP_IFELSE([$KSRC/include/net/net_namespace.h],
[EXPORT_SYMBOL_GPL(peernet2id_alloc)],
[OVS_DEFINE([HAVE_PEERNET2ID_ALLOC])])
if cmp -s datapath/linux/kcompat.h.new \
datapath/linux/kcompat.h >/dev/null 2>&1; then
Expand Down
49 changes: 36 additions & 13 deletions datapath/datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -1864,9 +1865,19 @@ 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;

#ifdef HAVE_PEERNET2ID_ALLOC
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;
}

#endif
ovs_vport_get_stats(vport, &vport_stats);
if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
sizeof(struct ovs_vport_stats), &vport_stats,
Expand Down Expand Up @@ -1896,8 +1907,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;
Expand All @@ -1906,7 +1917,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;
Expand All @@ -1920,6 +1931,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)
Expand All @@ -1944,6 +1957,7 @@ static struct vport *lookup_vport(struct net *net,
return vport;
} else
return ERR_PTR(-EINVAL);

}

/* Called with ovs_mutex */
Expand Down Expand Up @@ -1983,6 +1997,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;
Expand Down Expand Up @@ -2032,8 +2048,9 @@ static int ovs_vport_cmd_new(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);

if (netdev_get_fwd_headroom(vport->dev) > dp->max_headroom)
Expand Down Expand Up @@ -2089,8 +2106,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();

Expand Down Expand Up @@ -2127,8 +2145,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 */
Expand Down Expand Up @@ -2169,8 +2188,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();

Expand Down Expand Up @@ -2202,6 +2222,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,
Expand All @@ -2228,6 +2249,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 struct genl_ops dp_vport_genl_ops[] = {
Expand Down
4 changes: 2 additions & 2 deletions datapath/datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ int ovs_dp_upcall(struct datapath *, struct sk_buff *,
uint32_t cutlen);

const char *ovs_dp_name(const struct datapath *dp);
struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 pid, u32 seq,
u8 cmd);
struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, struct net *net,
u32 portid, u32 seq, u8 cmd);

int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
const struct sw_flow_actions *, struct sw_flow_key *);
Expand Down
3 changes: 2 additions & 1 deletion datapath/dp_notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ static void dp_detach_port_notify(struct vport *vport)
struct datapath *dp;

dp = vport->dp;
notify = ovs_vport_cmd_build_info(vport, 0, 0, OVS_VPORT_CMD_DEL);
notify = ovs_vport_cmd_build_info(vport, ovs_dp_get_net(dp),
0, 0, OVS_VPORT_CMD_DEL);
ovs_dp_detach_port(vport);
if (IS_ERR(notify)) {
genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
Expand Down
2 changes: 2 additions & 0 deletions datapath/linux/compat/include/linux/openvswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ enum ovs_vport_attr {
/* receiving upcalls */
OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */
OVS_VPORT_ATTR_PAD,
OVS_VPORT_ATTR_IFINDEX,
OVS_VPORT_ATTR_NETNSID,
__OVS_VPORT_ATTR_MAX
};

Expand Down

0 comments on commit b147f2e

Please sign in to comment.