Many commonly used functions like getifaddrs() invoke RTM_GETLINK to dump the interface information, and do not need the the AF_INET6 statististics that are always returned by default from rtnl_fill_ifinfo(). Computing the statistics can be an expensive operation that impacts scaling, so it is desirable to avoid this if the information is not needed. This patch adds a the RTEXT_FILTER_SKIP_STATS extended info flag that can be passed with netlink_request() to avoid statistics computation for the ifinfo path.
Unified · Split
| @@ -122,7 +122,8 @@ struct rtnl_af_ops { · 121 unmodified lines | ||
| 122 | 122 | int family; |
| 123 | 123 | |
| 124 | 124 | int (*fill_link_af)(struct sk_buff *skb, |
| 125 | − const struct net_device *dev); | |
| 125 | + const struct net_device *dev, | |
| 126 | + u32 ext_filter_mask); | |
| 126 | 127 | size_t (*get_link_af_size)(const struct net_device *dev); |
| 127 | 128 | |
| 128 | 129 | int (*validate_link_af)(const struct net_device *dev, |
| @@ -667,6 +667,7 @@ struct tcamsg { · 666 unmodified lines | ||
| 667 | 667 | #define RTEXT_FILTER_VF (1 << 0) |
| 668 | 668 | #define RTEXT_FILTER_BRVLAN (1 << 1) |
| 669 | 669 | #define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) |
| 670 | +#define RTEXT_FILTER_SKIP_STATS (1 << 3) | |
| 670 | 671 | |
| 671 | 672 | /* End of information exported to user level */ |
| 672 | 673 | |
| @@ -1272,7 +1272,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, · 1271 unmodified lines | ||
| 1272 | 1272 | if (!(af = nla_nest_start(skb, af_ops->family))) |
| 1273 | 1273 | goto nla_put_failure; |
| 1274 | 1274 | |
| 1275 | − err = af_ops->fill_link_af(skb, dev); | |
| 1275 | + err = af_ops->fill_link_af(skb, dev, ext_filter_mask); | |
| 1276 | 1276 | |
| 1277 | 1277 | /* |
| 1278 | 1278 | * Caller may return ENODATA to indicate that there |
| @@ -1654,7 +1654,8 @@ static size_t inet_get_link_af_size(const struct net_device *dev) · 1653 unmodified lines | ||
| 1654 | 1654 | return nla_total_size(IPV4_DEVCONF_MAX * 4); /* IFLA_INET_CONF */ |
| 1655 | 1655 | } |
| 1656 | 1656 | |
| 1657 | −static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev) | |
| 1657 | +static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev, | |
| 1658 | + u32 ext_filter_mask) | |
| 1658 | 1659 | { |
| 1659 | 1660 | struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
| 1660 | 1661 | struct nlattr *nla; |
| @@ -4729,7 +4729,8 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, · 4728 unmodified lines | ||
| 4729 | 4729 | } |
| 4730 | 4730 | } |
| 4731 | 4731 | |
| 4732 | −static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) | |
| 4732 | +static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev, | |
| 4733 | + u32 ext_filter_mask) | |
| 4733 | 4734 | { |
| 4734 | 4735 | struct nlattr *nla; |
| 4735 | 4736 | struct ifla_cacheinfo ci; |
| @@ -4749,6 +4750,9 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) · 13 unmodified lines | ||
| 4749 | 4750 | |
| 4750 | 4751 | /* XXX - MC not implemented */ |
| 4751 | 4752 | |
| 4753 | + if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS) | |
| 4754 | + return 0; | |
| 4755 | + | |
| 4752 | 4756 | nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); |
| 4753 | 4757 | if (!nla) |
| 4754 | 4758 | goto nla_put_failure; |
| @@ -4784,14 +4788,15 @@ static size_t inet6_get_link_af_size(const struct net_device *dev) · 29 unmodified lines | ||
| 4784 | 4788 | return inet6_ifla6_size(); |
| 4785 | 4789 | } |
| 4786 | 4790 | |
| 4787 | −static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev) | |
| 4791 | +static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev, | |
| 4792 | + u32 ext_filter_mask) | |
| 4788 | 4793 | { |
| 4789 | 4794 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 4790 | 4795 | |
| 4791 | 4796 | if (!idev) |
| 4792 | 4797 | return -ENODATA; |
| 4793 | 4798 | |
| 4794 | − if (inet6_fill_ifla6_attrs(skb, idev) < 0) | |
| 4799 | + if (inet6_fill_ifla6_attrs(skb, idev, ext_filter_mask) < 0) | |
| 4795 | 4800 | return -EMSGSIZE; |
| 4796 | 4801 | |
| 4797 | 4802 | return 0; |
| @@ -4946,7 +4951,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, · 148 unmodified lines | ||
| 4946 | 4951 | if (!protoinfo) |
| 4947 | 4952 | goto nla_put_failure; |
| 4948 | 4953 | |
| 4949 | − if (inet6_fill_ifla6_attrs(skb, idev) < 0) | |
| 4954 | + if (inet6_fill_ifla6_attrs(skb, idev, 0) < 0) | |
| 4950 | 4955 | goto nla_put_failure; |
| 4951 | 4956 | |
| 4952 | 4957 | nla_nest_end(skb, protoinfo); |