Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5566fd7 authored by Sowmini Varadhan's avatar Sowmini Varadhan Committed by David S. Miller
Browse files

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: default avatarSowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ad1e7b97
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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 */

+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −1
Original line number Diff line number Diff line
@@ -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;
+9 −4
Original line number Diff line number Diff line
@@ -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);