[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1572462854-26188-2-git-send-email-lariel@mellanox.com>
Date: Wed, 30 Oct 2019 19:14:47 +0000
From: Ariel Levkovich <lariel@...lanox.com>
To: "netdev@...r.kernel.org" <netdev@...r.kernel.org>
CC: Saeed Mahameed <saeedm@...lanox.com>,
Ariel Levkovich <lariel@...lanox.com>
Subject: [PATCH 1/3] net: Support querying specific VF properties
Querying the link with its VFs information involves putting a
vfinfo struct per VF in the netlink message under the
IFLA_VFINFO_LIST attribute.
Since the attribute's length is limited by it's definition to u16,
this introduces a problem when we want to add new fields to the
vfinfo attribute.
With increasing the vfinfo attribute and running in an environment
with a large number of VFs, we may overflow the IFLA_VFINFO_LIST
attribute length.
To avoid that, this patch introduces a single VF query.
With single VF query, the kernel may include extended VF information
and fields, such that take up a significant amount of memory, in the
vfinfo attribute.
This information may not be included with VF list
query and prevent attribute length overflow.
The admin will be able to query the link and get extended VF info
using iptool and following command:
ip link show dev <ifname> vf <vf_num>
Issue: 989268
Change-Id: Ifec312583f4996c8108629394e94f302282d3ae0
Signed-off-by: Ariel Levkovich <lariel@...lanox.com>
---
include/uapi/linux/if_link.h | 1 +
include/uapi/linux/rtnetlink.h | 1 +
net/core/rtnetlink.c | 49 ++++++++++++++++++++++++++++++++----------
3 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 8aec876..797e214 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -169,6 +169,7 @@ enum {
IFLA_MAX_MTU,
IFLA_PROP_LIST,
IFLA_ALT_IFNAME, /* Alternative ifname */
+ IFLA_VF_NUM, /* Get extended information for specific VF */
__IFLA_MAX
};
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 1418a83..09df2f4 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -760,6 +760,7 @@ enum {
#define RTEXT_FILTER_BRVLAN (1 << 1)
#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
#define RTEXT_FILTER_SKIP_STATS (1 << 3)
+#define RTEXT_FILTER_VF_EXT (1 << 4)
/* End of information exported to user level */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 49fa910..31fa0af 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -906,9 +906,14 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
static inline int rtnl_vfinfo_size(const struct net_device *dev,
u32 ext_filter_mask)
{
- if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) {
+ if (dev->dev.parent &&
+ (ext_filter_mask & (RTEXT_FILTER_VF | RTEXT_FILTER_VF_EXT))) {
int num_vfs = dev_num_vf(dev->dev.parent);
size_t size = nla_total_size(0);
+
+ if (num_vfs && (ext_filter_mask & RTEXT_FILTER_VF_EXT))
+ num_vfs = 1;
+
size += num_vfs *
(nla_total_size(0) +
nla_total_size(sizeof(struct ifla_vf_mac)) +
@@ -1022,7 +1027,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
+ nla_total_size(4) /* IFLA_LINK_NETNSID */
+ nla_total_size(4) /* IFLA_GROUP */
+ nla_total_size(ext_filter_mask
- & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
+ & (RTEXT_FILTER_VF | RTEXT_FILTER_VF_EXT) ?
+ 4 : 0) /* IFLA_NUM_VF */
+ rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
+ rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
+ rtnl_link_get_size(dev) /* IFLA_LINKINFO */
@@ -1203,7 +1209,8 @@ static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb,
static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
struct net_device *dev,
int vfs_num,
- struct nlattr *vfinfo)
+ struct nlattr *vfinfo,
+ int vf_ext)
{
struct ifla_vf_rss_query_en vf_rss_query_en;
struct nlattr *vf, *vfstats, *vfvlanlist;
@@ -1332,15 +1339,21 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
struct net_device *dev,
- u32 ext_filter_mask)
+ u32 ext_filter_mask,
+ int vf)
{
+ int vf_ext = (ext_filter_mask & RTEXT_FILTER_VF_EXT) && (vf >= 0);
struct nlattr *vfinfo;
int i, num_vfs;
- if (!dev->dev.parent || ((ext_filter_mask & RTEXT_FILTER_VF) == 0))
+ if (!dev->dev.parent ||
+ ((ext_filter_mask & (RTEXT_FILTER_VF | RTEXT_FILTER_VF_EXT)) == 0))
return 0;
num_vfs = dev_num_vf(dev->dev.parent);
+ if (vf_ext && num_vfs)
+ num_vfs = 1;
+
if (nla_put_u32(skb, IFLA_NUM_VF, num_vfs))
return -EMSGSIZE;
@@ -1352,7 +1365,7 @@ static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
return -EMSGSIZE;
for (i = 0; i < num_vfs; i++) {
- if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
+ if (rtnl_fill_vfinfo(skb, dev, vf_ext ? vf : i, vfinfo, vf_ext))
return -EMSGSIZE;
}
@@ -1639,7 +1652,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
int type, u32 pid, u32 seq, u32 change,
unsigned int flags, u32 ext_filter_mask,
u32 event, int *new_nsid, int new_ifindex,
- int tgt_netnsid)
+ int tgt_netnsid, int vf)
{
struct ifinfomsg *ifm;
struct nlmsghdr *nlh;
@@ -1717,7 +1730,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
if (rtnl_fill_stats(skb, dev))
goto nla_put_failure;
- if (rtnl_fill_vf(skb, dev, ext_filter_mask))
+ if (rtnl_fill_vf(skb, dev, ext_filter_mask, vf))
goto nla_put_failure;
if (rtnl_port_fill(skb, dev, ext_filter_mask))
@@ -1806,6 +1819,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
[IFLA_PROP_LIST] = { .type = NLA_NESTED },
[IFLA_ALT_IFNAME] = { .type = NLA_STRING,
.len = ALTIFNAMSIZ - 1 },
+ [IFLA_VF_NUM] = { .type = NLA_U32 },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -2057,7 +2071,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
NETLINK_CB(cb->skb).portid,
nlh->nlmsg_seq, 0, flags,
ext_filter_mask, 0, NULL, 0,
- netnsid);
+ netnsid, -1);
if (err < 0) {
if (likely(skb->len))
@@ -3365,6 +3379,7 @@ static int rtnl_valid_getlink_req(struct sk_buff *skb,
case IFLA_ALT_IFNAME:
case IFLA_EXT_MASK:
case IFLA_TARGET_NETNSID:
+ case IFLA_VF_NUM:
break;
default:
NL_SET_ERR_MSG(extack, "Unsupported attribute in get link request");
@@ -3385,6 +3400,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
struct net_device *dev = NULL;
struct sk_buff *nskb;
int netnsid = -1;
+ int vf = -1;
int err;
u32 ext_filter_mask = 0;
@@ -3407,6 +3423,17 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
err = -EINVAL;
+ if ((ext_filter_mask & RTEXT_FILTER_VF) &&
+ (ext_filter_mask & RTEXT_FILTER_VF_EXT))
+ goto out;
+
+ if (ext_filter_mask & RTEXT_FILTER_VF_EXT) {
+ if (tb[IFLA_VF_NUM])
+ vf = nla_get_u32(tb[IFLA_VF_NUM]);
+ else
+ goto out;
+ }
+
ifm = nlmsg_data(nlh);
if (ifm->ifi_index > 0)
dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
@@ -3428,7 +3455,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
err = rtnl_fill_ifinfo(nskb, dev, net,
RTM_NEWLINK, NETLINK_CB(skb).portid,
nlh->nlmsg_seq, 0, 0, ext_filter_mask,
- 0, NULL, 0, netnsid);
+ 0, NULL, 0, netnsid, vf);
if (err < 0) {
/* -EMSGSIZE implies BUG in if_nlmsg_size */
WARN_ON(err == -EMSGSIZE);
@@ -3634,7 +3661,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
type, 0, 0, change, 0, 0, event,
- new_nsid, new_ifindex, -1);
+ new_nsid, new_ifindex, -1, -1);
if (err < 0) {
/* -EMSGSIZE implies BUG in if_nlmsg_size() */
WARN_ON(err == -EMSGSIZE);
--
1.8.3.1
Powered by blists - more mailing lists