@@ -1200,12 +1200,20 @@ int print_linkinfo(struct nlmsghdr *n, void *arg)
if ((do_link || show_details) && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
- int rem = RTA_PAYLOAD(vflist), count = 0;
+ struct rtattr *j, *vfstats = tb[IFLA_VFSTATS_LIST];
+ int rem_stats, rem = RTA_PAYLOAD(vflist), count = 0;
+ j = vfstats ? RTA_DATA(vfstats) : NULL;
+ rem_stats = vfstats ? RTA_PAYLOAD(vfstats) : 0;
open_json_array(PRINT_JSON, "vfinfo_list");
for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
open_json_object(NULL);
print_vfinfo(fp, ifi, i);
+ if (show_stats && j) {
+ print_vf_stats64(fp, j);
+ j = RTA_OK(j, rem_stats) ?
+ RTA_NEXT(j, rem_stats) : NULL;
+ }
close_json_object();
count++;
}
@@ -1885,7 +1893,7 @@ static int iplink_filter_req(struct nlmsghdr *nlh, int reqlen)
__u32 filt_mask;
int err;
- filt_mask = RTEXT_FILTER_VF;
+ filt_mask = RTEXT_FILTER_VF | RTEXT_FILTER_VF_SEPARATE_STATS;
if (!show_stats)
filt_mask |= RTEXT_FILTER_SKIP_STATS;
err = addattr32(nlh, reqlen, IFLA_EXT_MASK, filt_mask);
@@ -1923,7 +1931,7 @@ static int ipaddr_link_get(int index, struct nlmsg_chain *linfo)
.i.ifi_family = filter.family,
.i.ifi_index = index,
};
- __u32 filt_mask = RTEXT_FILTER_VF;
+ __u32 filt_mask = RTEXT_FILTER_VF | RTEXT_FILTER_VF_SEPARATE_STATS;
struct nlmsghdr *answer;
if (!show_stats)
@@ -1117,6 +1117,7 @@ int iplink_get(char *name, __u32 filt_mask)
name, strlen(name) + 1);
}
+ filt_mask |= RTEXT_FILTER_VF_SEPARATE_STATS;
if (!show_stats)
filt_mask |= RTEXT_FILTER_SKIP_STATS;
addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
@@ -486,7 +486,8 @@ static int __rtnl_linkdump_req(struct rtnl_handle *rth, int family)
int rtnl_linkdump_req(struct rtnl_handle *rth, int family)
{
if (family == AF_UNSPEC)
- return rtnl_linkdump_req_filter(rth, family, RTEXT_FILTER_VF);
+ return rtnl_linkdump_req_filter(rth, family, RTEXT_FILTER_VF |
+ RTEXT_FILTER_VF_SEPARATE_STATS);
return __rtnl_linkdump_req(rth, family);
}
The maximum possible length of a netlink attribute is 64KB, but the IFLA_VFINFO_LIST exceeds this when stats are included and more than about 220 VFs are present (each VF consumes approximately 300 bytes, depending on alignment and optional fields). Exceeding the limit will cause the list to be truncated by the kernel's nla_nest_end(). A recent ABI fix moves the VF stats into an independent list when requested, thus avoiding the problem. Send requests using the new RTEXT_FILTER_VF_SEPARATE_STATS filter and render the stats from the alternate list instead. Signed-off-by: Edwin Peer <edwin.peer@broadcom.com> --- ip/ipaddress.c | 14 +++++++++++--- ip/iplink.c | 1 + lib/libnetlink.c | 3 ++- 3 files changed, 14 insertions(+), 4 deletions(-)