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

Commit 519c818e authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

net: sched: add percpu stats to actions



Reuse existing percpu infrastructure John Fastabend added for qdisc.

This patch adds a new cpustats parameter to tcf_hash_create() and all
actions pass false, meaning this patch should have no effect yet.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 24ea591d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ struct tcf_common {
	struct gnet_stats_rate_est64	tcfc_rate_est;
	spinlock_t			tcfc_lock;
	struct rcu_head			tcfc_rcu;
	struct gnet_stats_basic_cpu __percpu *cpu_bstats;
	struct gnet_stats_queue __percpu *cpu_qstats;
};
#define tcf_head	common.tcfc_head
#define tcf_index	common.tcfc_index
@@ -103,7 +105,7 @@ int tcf_hash_release(struct tc_action *a, int bind);
u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo);
int tcf_hash_check(u32 index, struct tc_action *a, int bind);
int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
		    int size, int bind);
		    int size, int bind, bool cpustats);
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
void tcf_hash_insert(struct tc_action *a);

+34 −10
Original line number Diff line number Diff line
@@ -27,6 +27,15 @@
#include <net/act_api.h>
#include <net/netlink.h>

static void free_tcf(struct rcu_head *head)
{
	struct tcf_common *p = container_of(head, struct tcf_common, tcfc_rcu);

	free_percpu(p->cpu_bstats);
	free_percpu(p->cpu_qstats);
	kfree(p);
}

void tcf_hash_destroy(struct tc_action *a)
{
	struct tcf_common *p = a->priv;
@@ -41,7 +50,7 @@ void tcf_hash_destroy(struct tc_action *a)
	 * gen_estimator est_timer() might access p->tcfc_lock
	 * or bstats, wait a RCU grace period before freeing p
	 */
	kfree_rcu(p, tcfc_rcu);
	call_rcu(&p->tcfc_rcu, free_tcf);
}
EXPORT_SYMBOL(tcf_hash_destroy);

@@ -230,15 +239,16 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
	if (est)
		gen_kill_estimator(&pc->tcfc_bstats,
				   &pc->tcfc_rate_est);
	kfree_rcu(pc, tcfc_rcu);
	call_rcu(&pc->tcfc_rcu, free_tcf);
}
EXPORT_SYMBOL(tcf_hash_cleanup);

int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
		    int size, int bind)
		    int size, int bind, bool cpustats)
{
	struct tcf_hashinfo *hinfo = a->ops->hinfo;
	struct tcf_common *p = kzalloc(size, GFP_KERNEL);
	int err = -ENOMEM;

	if (unlikely(!p))
		return -ENOMEM;
@@ -246,18 +256,32 @@ int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
	if (bind)
		p->tcfc_bindcnt = 1;

	if (cpustats) {
		p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
		if (!p->cpu_bstats) {
err1:
			kfree(p);
			return err;
		}
		p->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
		if (!p->cpu_qstats) {
err2:
			free_percpu(p->cpu_bstats);
			goto err1;
		}
	}
	spin_lock_init(&p->tcfc_lock);
	INIT_HLIST_NODE(&p->tcfc_head);
	p->tcfc_index = index ? index : tcf_hash_new_index(hinfo);
	p->tcfc_tm.install = jiffies;
	p->tcfc_tm.lastuse = jiffies;
	if (est) {
		int err = gen_new_estimator(&p->tcfc_bstats, NULL,
		err = gen_new_estimator(&p->tcfc_bstats, p->cpu_bstats,
					&p->tcfc_rate_est,
					&p->tcfc_lock, est);
		if (err) {
			kfree(p);
			return err;
			free_percpu(p->cpu_qstats);
			goto err2;
		}
	}

@@ -615,10 +639,10 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
	if (err < 0)
		goto errout;

	if (gnet_stats_copy_basic(&d, NULL, &p->tcfc_bstats) < 0 ||
	if (gnet_stats_copy_basic(&d, p->cpu_bstats, &p->tcfc_bstats) < 0 ||
	    gnet_stats_copy_rate_est(&d, &p->tcfc_bstats,
				     &p->tcfc_rate_est) < 0 ||
	    gnet_stats_copy_queue(&d, NULL,
	    gnet_stats_copy_queue(&d, p->cpu_qstats,
				  &p->tcfc_qstats,
				  p->tcfc_qstats.qlen) < 0)
		goto errout;
+1 −1
Original line number Diff line number Diff line
@@ -281,7 +281,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,

	if (!tcf_hash_check(parm->index, act, bind)) {
		ret = tcf_hash_create(parm->index, est, act,
				      sizeof(*prog), bind);
				      sizeof(*prog), bind, false);
		if (ret < 0)
			goto destroy_fp;

+2 −1
Original line number Diff line number Diff line
@@ -108,7 +108,8 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
	parm = nla_data(tb[TCA_CONNMARK_PARMS]);

	if (!tcf_hash_check(parm->index, a, bind)) {
		ret = tcf_hash_create(parm->index, est, a, sizeof(*ci), bind);
		ret = tcf_hash_create(parm->index, est, a, sizeof(*ci),
				      bind, false);
		if (ret)
			return ret;

+2 −1
Original line number Diff line number Diff line
@@ -62,7 +62,8 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
	parm = nla_data(tb[TCA_CSUM_PARMS]);

	if (!tcf_hash_check(parm->index, a, bind)) {
		ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
		ret = tcf_hash_create(parm->index, est, a, sizeof(*p),
				      bind, false);
		if (ret)
			return ret;
		ret = ACT_P_CREATED;
Loading