Commit e49efd52 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

net: sched: gred: support reporting stats from offloads



Allow drivers which offload GRED to report back statistics.  Since
A lot of GRED stats is fairly ad hoc in nature pass to drivers the
standard struct gnet_stats_basic/gnet_stats_queue pairs, and
untangle the values in the core.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarJohn Hurley <john.hurley@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 890d8d23
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -871,6 +871,7 @@ struct tc_red_qopt_offload {
enum tc_gred_command {
	TC_GRED_REPLACE,
	TC_GRED_DESTROY,
	TC_GRED_STATS,
};

struct tc_gred_vq_qopt_offload_params {
@@ -895,12 +896,19 @@ struct tc_gred_qopt_offload_params {
	struct tc_gred_vq_qopt_offload_params tab[MAX_DPs];
};

struct tc_gred_qopt_offload_stats {
	struct gnet_stats_basic_packed bstats[MAX_DPs];
	struct gnet_stats_queue qstats[MAX_DPs];
	struct red_stats *xstats[MAX_DPs];
};

struct tc_gred_qopt_offload {
	enum tc_gred_command command;
	u32 handle;
	u32 parent;
	union {
		struct tc_gred_qopt_offload_params set;
		struct tc_gred_qopt_offload_stats stats;
	};
};

+47 −0
Original line number Diff line number Diff line
@@ -354,6 +354,50 @@ static void gred_offload(struct Qdisc *sch, enum tc_gred_command command)
	dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_GRED, &opt);
}

static int gred_offload_dump_stats(struct Qdisc *sch)
{
	struct gred_sched *table = qdisc_priv(sch);
	struct tc_gred_qopt_offload *hw_stats;
	unsigned int i;
	int ret;

	hw_stats = kzalloc(sizeof(*hw_stats), GFP_KERNEL);
	if (!hw_stats)
		return -ENOMEM;

	hw_stats->command = TC_GRED_STATS;
	hw_stats->handle = sch->handle;
	hw_stats->parent = sch->parent;

	for (i = 0; i < MAX_DPs; i++)
		if (table->tab[i])
			hw_stats->stats.xstats[i] = &table->tab[i]->stats;

	ret = qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_GRED, hw_stats);
	/* Even if driver returns failure adjust the stats - in case offload
	 * ended but driver still wants to adjust the values.
	 */
	for (i = 0; i < MAX_DPs; i++) {
		if (!table->tab[i])
			continue;
		table->tab[i]->packetsin += hw_stats->stats.bstats[i].packets;
		table->tab[i]->bytesin += hw_stats->stats.bstats[i].bytes;
		table->tab[i]->backlog += hw_stats->stats.qstats[i].backlog;

		_bstats_update(&sch->bstats,
			       hw_stats->stats.bstats[i].bytes,
			       hw_stats->stats.bstats[i].packets);
		sch->qstats.qlen += hw_stats->stats.qstats[i].qlen;
		sch->qstats.backlog += hw_stats->stats.qstats[i].backlog;
		sch->qstats.drops += hw_stats->stats.qstats[i].drops;
		sch->qstats.requeues += hw_stats->stats.qstats[i].requeues;
		sch->qstats.overlimits += hw_stats->stats.qstats[i].overlimits;
	}

	kfree(hw_stats);
	return ret;
}

static inline void gred_destroy_vq(struct gred_sched_data *q)
{
	kfree(q);
@@ -725,6 +769,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
		.flags	= table->red_flags,
	};

	if (gred_offload_dump_stats(sch))
		goto nla_put_failure;

	opts = nla_nest_start(skb, TCA_OPTIONS);
	if (opts == NULL)
		goto nla_put_failure;