rtnetlink: RTEXT_FILTER_SKIP_STATS support to avoid dumping inet/inet6 stats
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. Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ad1e7b97b3
commit
d5566fd72e
|
@ -122,7 +122,8 @@ struct rtnl_af_ops {
|
|||
int family;
|
||||
|
||||
int (*fill_link_af)(struct sk_buff *skb,
|
||||
const struct net_device *dev);
|
||||
const struct net_device *dev,
|
||||
u32 ext_filter_mask);
|
||||
size_t (*get_link_af_size)(const struct net_device *dev);
|
||||
|
||||
int (*validate_link_af)(const struct net_device *dev,
|
||||
|
|
|
@ -667,6 +667,7 @@ struct tcamsg {
|
|||
#define RTEXT_FILTER_VF (1 << 0)
|
||||
#define RTEXT_FILTER_BRVLAN (1 << 1)
|
||||
#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
|
||||
#define RTEXT_FILTER_SKIP_STATS (1 << 3)
|
||||
|
||||
/* End of information exported to user level */
|
||||
|
||||
|
|
|
@ -1272,7 +1272,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
|||
if (!(af = nla_nest_start(skb, af_ops->family)))
|
||||
goto nla_put_failure;
|
||||
|
||||
err = af_ops->fill_link_af(skb, dev);
|
||||
err = af_ops->fill_link_af(skb, dev, ext_filter_mask);
|
||||
|
||||
/*
|
||||
* 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)
|
|||
return nla_total_size(IPV4_DEVCONF_MAX * 4); /* IFLA_INET_CONF */
|
||||
}
|
||||
|
||||
static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
|
||||
static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev,
|
||||
u32 ext_filter_mask)
|
||||
{
|
||||
struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr);
|
||||
struct nlattr *nla;
|
||||
|
|
|
@ -4729,7 +4729,8 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
|
|||
}
|
||||
}
|
||||
|
||||
static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
|
||||
static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
|
||||
u32 ext_filter_mask)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
struct ifla_cacheinfo ci;
|
||||
|
@ -4749,6 +4750,9 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
|
|||
|
||||
/* XXX - MC not implemented */
|
||||
|
||||
if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS)
|
||||
return 0;
|
||||
|
||||
nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
|
||||
if (!nla)
|
||||
goto nla_put_failure;
|
||||
|
@ -4784,14 +4788,15 @@ static size_t inet6_get_link_af_size(const struct net_device *dev)
|
|||
return inet6_ifla6_size();
|
||||
}
|
||||
|
||||
static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
|
||||
static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev,
|
||||
u32 ext_filter_mask)
|
||||
{
|
||||
struct inet6_dev *idev = __in6_dev_get(dev);
|
||||
|
||||
if (!idev)
|
||||
return -ENODATA;
|
||||
|
||||
if (inet6_fill_ifla6_attrs(skb, idev) < 0)
|
||||
if (inet6_fill_ifla6_attrs(skb, idev, ext_filter_mask) < 0)
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
|
@ -4946,7 +4951,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
|
|||
if (!protoinfo)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (inet6_fill_ifla6_attrs(skb, idev) < 0)
|
||||
if (inet6_fill_ifla6_attrs(skb, idev, 0) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(skb, protoinfo);
|
||||
|
|
Loading…
Reference in New Issue