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: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: John Hurley <john.hurley@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
890d8d23ec
commit
e49efd5288
2 changed files with 55 additions and 0 deletions
|
@ -871,6 +871,7 @@ struct tc_red_qopt_offload {
|
||||||
enum tc_gred_command {
|
enum tc_gred_command {
|
||||||
TC_GRED_REPLACE,
|
TC_GRED_REPLACE,
|
||||||
TC_GRED_DESTROY,
|
TC_GRED_DESTROY,
|
||||||
|
TC_GRED_STATS,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tc_gred_vq_qopt_offload_params {
|
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_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 {
|
struct tc_gred_qopt_offload {
|
||||||
enum tc_gred_command command;
|
enum tc_gred_command command;
|
||||||
u32 handle;
|
u32 handle;
|
||||||
u32 parent;
|
u32 parent;
|
||||||
union {
|
union {
|
||||||
struct tc_gred_qopt_offload_params set;
|
struct tc_gred_qopt_offload_params set;
|
||||||
|
struct tc_gred_qopt_offload_stats stats;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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)
|
static inline void gred_destroy_vq(struct gred_sched_data *q)
|
||||||
{
|
{
|
||||||
kfree(q);
|
kfree(q);
|
||||||
|
@ -725,6 +769,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||||
.flags = table->red_flags,
|
.flags = table->red_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (gred_offload_dump_stats(sch))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
opts = nla_nest_start(skb, TCA_OPTIONS);
|
opts = nla_nest_start(skb, TCA_OPTIONS);
|
||||||
if (opts == NULL)
|
if (opts == NULL)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
Loading…
Add table
Reference in a new issue