History

net: rtnetlink: add linkxstats callbacks and attribute

Add callbacks to calculate the size and fill link extended statistics which can be split into multiple messages and are dumped via the new rtnl stats API (RTM_GETSTATS) with the IFLA_STATS_LINK_XSTATS attribute. Also add that attribute to the idx mask check since it is expected to be able to save state and resume dumping (e.g. future bridge per-vlan stats will be dumped via this attribute and callbacks). Each link type should nest its private attributes under the per-link type attribute. This allows to have any number of separated private attributes and to avoid one call to get the dev link type.

Nikolay Aleksandrov committed 10 years ago

Commit 97a47fa1 parent e8872a23 files · +49 −0Browse files

Unified · Split

3 files
  1. include/net/rtnetlink.h +7 −0
  2. include/uapi/linux/if_link.h +12 −0
  3. net/core/rtnetlink.c +30 −0
include/net/rtnetlink.h+7−0
@@ -47,6 +47,9 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) · 46 unmodified lines
47 * @get_num_rx_queues: Function to determine number of receive queues47 * @get_num_rx_queues: Function to determine number of receive queues
48 * to create when creating a new device.48 * to create when creating a new device.
49 * @get_link_net: Function to get the i/o netns of the device49 * @get_link_net: Function to get the i/o netns of the device
50 * @get_linkxstats_size: Function to calculate the required room for
51 * dumping device-specific extended link stats
52 * @fill_linkxstats: Function to dump device-specific extended link stats
50 */53 */
51struct rtnl_link_ops {54struct rtnl_link_ops {
52 struct list_head list;55 struct list_head list;
@@ -95,6 +98,10 @@ struct rtnl_link_ops { · 42 unmodified lines
95 const struct net_device *dev,98 const struct net_device *dev,
96 const struct net_device *slave_dev);99 const struct net_device *slave_dev);
97 struct net *(*get_link_net)(const struct net_device *dev);100 struct net *(*get_link_net)(const struct net_device *dev);
101 size_t (*get_linkxstats_size)(const struct net_device *dev);
102 int (*fill_linkxstats)(struct sk_buff *skb,
103 const struct net_device *dev,
104 int *prividx);
98};105};
99 106
100int __rtnl_link_register(struct rtnl_link_ops *ops);107int __rtnl_link_register(struct rtnl_link_ops *ops);
include/uapi/linux/if_link.h+12−0
@@ -810,6 +810,7 @@ struct if_stats_msg { · 809 unmodified lines
810enum {810enum {
811 IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */811 IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */
812 IFLA_STATS_LINK_64,812 IFLA_STATS_LINK_64,
813 IFLA_STATS_LINK_XSTATS,
813 __IFLA_STATS_MAX,814 __IFLA_STATS_MAX,
814};815};
815 816
@@ -817,4 +818,15 @@ enum { · 1 unmodified line
817 818
818#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1))819#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1))
819 820
821/* These are embedded into IFLA_STATS_LINK_XSTATS:
822 * [IFLA_STATS_LINK_XSTATS]
823 * -> [LINK_XSTATS_TYPE_xxx]
824 * -> [rtnl link type specific attributes]
825 */
826enum {
827 LINK_XSTATS_TYPE_UNSPEC,
828 __LINK_XSTATS_TYPE_MAX
829};
830#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
831
820#endif /* _UAPI_LINUX_IF_LINK_H */832#endif /* _UAPI_LINUX_IF_LINK_H */
net/core/rtnetlink.c+30−0
@@ -3483,6 +3483,26 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev, · 3482 unmodified lines
3483 dev_get_stats(dev, sp);3483 dev_get_stats(dev, sp);
3484 }3484 }
3485 3485
3486 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_XSTATS, *idxattr)) {
3487 const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
3488
3489 if (ops && ops->fill_linkxstats) {
3490 int err;
3491
3492 *idxattr = IFLA_STATS_LINK_XSTATS;
3493 attr = nla_nest_start(skb,
3494 IFLA_STATS_LINK_XSTATS);
3495 if (!attr)
3496 goto nla_put_failure;
3497
3498 err = ops->fill_linkxstats(skb, dev, prividx);
3499 nla_nest_end(skb, attr);
3500 if (err)
3501 goto nla_put_failure;
3502 *idxattr = 0;
3503 }
3504 }
3505
3486 nlmsg_end(skb, nlh);3506 nlmsg_end(skb, nlh);
3487 3507
3488 return 0;3508 return 0;
@@ -3509,6 +3529,16 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev, · 20 unmodified lines
3509 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_64, 0))3529 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_64, 0))
3510 size += nla_total_size_64bit(sizeof(struct rtnl_link_stats64));3530 size += nla_total_size_64bit(sizeof(struct rtnl_link_stats64));
3511 3531
3532 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_XSTATS, 0)) {
3533 const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
3534
3535 if (ops && ops->get_linkxstats_size) {
3536 size += nla_total_size(ops->get_linkxstats_size(dev));
3537 /* for IFLA_STATS_LINK_XSTATS */
3538 size += nla_total_size(0);
3539 }
3540 }
3541
3512 return size;3542 return size;
3513}3543}
3514 3544