diff options
Diffstat (limited to 'net/core/rtnetlink.c')
| -rw-r--r-- | net/core/rtnetlink.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 18b5aae99bec..152744643074 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -837,8 +837,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
| 837 | static inline int rtnl_vfinfo_size(const struct net_device *dev, | 837 | static inline int rtnl_vfinfo_size(const struct net_device *dev, |
| 838 | u32 ext_filter_mask) | 838 | u32 ext_filter_mask) |
| 839 | { | 839 | { |
| 840 | if (dev->dev.parent && dev_is_pci(dev->dev.parent) && | 840 | if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) { |
| 841 | (ext_filter_mask & RTEXT_FILTER_VF)) { | ||
| 842 | int num_vfs = dev_num_vf(dev->dev.parent); | 841 | int num_vfs = dev_num_vf(dev->dev.parent); |
| 843 | size_t size = nla_total_size(0); | 842 | size_t size = nla_total_size(0); |
| 844 | size += num_vfs * | 843 | size += num_vfs * |
| @@ -3829,6 +3828,39 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev, | |||
| 3829 | *idxattr = 0; | 3828 | *idxattr = 0; |
| 3830 | } | 3829 | } |
| 3831 | 3830 | ||
| 3831 | if (stats_attr_valid(filter_mask, IFLA_STATS_AF_SPEC, *idxattr)) { | ||
| 3832 | struct rtnl_af_ops *af_ops; | ||
| 3833 | |||
| 3834 | *idxattr = IFLA_STATS_AF_SPEC; | ||
| 3835 | attr = nla_nest_start(skb, IFLA_STATS_AF_SPEC); | ||
| 3836 | if (!attr) | ||
| 3837 | goto nla_put_failure; | ||
| 3838 | |||
| 3839 | list_for_each_entry(af_ops, &rtnl_af_ops, list) { | ||
| 3840 | if (af_ops->fill_stats_af) { | ||
| 3841 | struct nlattr *af; | ||
| 3842 | int err; | ||
| 3843 | |||
| 3844 | af = nla_nest_start(skb, af_ops->family); | ||
| 3845 | if (!af) | ||
| 3846 | goto nla_put_failure; | ||
| 3847 | |||
| 3848 | err = af_ops->fill_stats_af(skb, dev); | ||
| 3849 | |||
| 3850 | if (err == -ENODATA) | ||
| 3851 | nla_nest_cancel(skb, af); | ||
| 3852 | else if (err < 0) | ||
| 3853 | goto nla_put_failure; | ||
| 3854 | |||
| 3855 | nla_nest_end(skb, af); | ||
| 3856 | } | ||
| 3857 | } | ||
| 3858 | |||
| 3859 | nla_nest_end(skb, attr); | ||
| 3860 | |||
| 3861 | *idxattr = 0; | ||
| 3862 | } | ||
| 3863 | |||
| 3832 | nlmsg_end(skb, nlh); | 3864 | nlmsg_end(skb, nlh); |
| 3833 | 3865 | ||
| 3834 | return 0; | 3866 | return 0; |
| @@ -3885,6 +3917,23 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev, | |||
| 3885 | if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0)) | 3917 | if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0)) |
| 3886 | size += rtnl_get_offload_stats_size(dev); | 3918 | size += rtnl_get_offload_stats_size(dev); |
| 3887 | 3919 | ||
| 3920 | if (stats_attr_valid(filter_mask, IFLA_STATS_AF_SPEC, 0)) { | ||
| 3921 | struct rtnl_af_ops *af_ops; | ||
| 3922 | |||
| 3923 | /* for IFLA_STATS_AF_SPEC */ | ||
| 3924 | size += nla_total_size(0); | ||
| 3925 | |||
| 3926 | list_for_each_entry(af_ops, &rtnl_af_ops, list) { | ||
| 3927 | if (af_ops->get_stats_af_size) { | ||
| 3928 | size += nla_total_size( | ||
| 3929 | af_ops->get_stats_af_size(dev)); | ||
| 3930 | |||
| 3931 | /* for AF_* */ | ||
| 3932 | size += nla_total_size(0); | ||
| 3933 | } | ||
| 3934 | } | ||
| 3935 | } | ||
| 3936 | |||
| 3888 | return size; | 3937 | return size; |
| 3889 | } | 3938 | } |
| 3890 | 3939 | ||
| @@ -3898,6 +3947,9 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 3898 | u32 filter_mask; | 3947 | u32 filter_mask; |
| 3899 | int err; | 3948 | int err; |
| 3900 | 3949 | ||
| 3950 | if (nlmsg_len(nlh) < sizeof(*ifsm)) | ||
| 3951 | return -EINVAL; | ||
| 3952 | |||
| 3901 | ifsm = nlmsg_data(nlh); | 3953 | ifsm = nlmsg_data(nlh); |
| 3902 | if (ifsm->ifindex > 0) | 3954 | if (ifsm->ifindex > 0) |
| 3903 | dev = __dev_get_by_index(net, ifsm->ifindex); | 3955 | dev = __dev_get_by_index(net, ifsm->ifindex); |
| @@ -3947,6 +3999,9 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 3947 | 3999 | ||
| 3948 | cb->seq = net->dev_base_seq; | 4000 | cb->seq = net->dev_base_seq; |
| 3949 | 4001 | ||
| 4002 | if (nlmsg_len(cb->nlh) < sizeof(*ifsm)) | ||
| 4003 | return -EINVAL; | ||
| 4004 | |||
| 3950 | ifsm = nlmsg_data(cb->nlh); | 4005 | ifsm = nlmsg_data(cb->nlh); |
| 3951 | filter_mask = ifsm->filter_mask; | 4006 | filter_mask = ifsm->filter_mask; |
| 3952 | if (!filter_mask) | 4007 | if (!filter_mask) |
