net: sched: gred: provide a better structured dump and expose stats

Currently all GRED's virtual queue data is dumped in a single
array in a single attribute.  This makes it pretty much impossible
to add new fields.  In order to expose more detailed stats add a
new set of attributes.  We can now expose the 64 bit value of bytesin
and all the mark stats which were not part of the original design.

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:
Jakub Kicinski 2018-11-14 22:23:49 -08:00 committed by David S. Miller
parent 9f5cd0c806
commit 80e22e961d
2 changed files with 78 additions and 1 deletions

View File

@ -291,11 +291,37 @@ enum {
TCA_GRED_DPS,
TCA_GRED_MAX_P,
TCA_GRED_LIMIT,
TCA_GRED_VQ_LIST, /* nested TCA_GRED_VQ_ENTRY */
__TCA_GRED_MAX,
};
#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
enum {
TCA_GRED_VQ_ENTRY_UNSPEC,
TCA_GRED_VQ_ENTRY, /* nested TCA_GRED_VQ_* */
__TCA_GRED_VQ_ENTRY_MAX,
};
#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1)
enum {
TCA_GRED_VQ_UNSPEC,
TCA_GRED_VQ_PAD,
TCA_GRED_VQ_DP, /* u32 */
TCA_GRED_VQ_STAT_BYTES, /* u64 */
TCA_GRED_VQ_STAT_PACKETS, /* u32 */
TCA_GRED_VQ_STAT_BACKLOG, /* u32 */
TCA_GRED_VQ_STAT_PROB_DROP, /* u32 */
TCA_GRED_VQ_STAT_PROB_MARK, /* u32 */
TCA_GRED_VQ_STAT_FORCED_DROP, /* u32 */
TCA_GRED_VQ_STAT_FORCED_MARK, /* u32 */
TCA_GRED_VQ_STAT_PDROP, /* u32 */
TCA_GRED_VQ_STAT_OTHER, /* u32 */
__TCA_GRED_VQ_MAX
};
#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1)
struct tc_gred_qopt {
__u32 limit; /* HARD maximal queue length (bytes) */
__u32 qth_min; /* Min average length threshold (bytes) */

View File

@ -404,6 +404,7 @@ static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
[TCA_GRED_DPS] = { .len = sizeof(struct tc_gred_sopt) },
[TCA_GRED_MAX_P] = { .type = NLA_U32 },
[TCA_GRED_LIMIT] = { .type = NLA_U32 },
[TCA_GRED_VQ_LIST] = { .type = NLA_REJECT },
};
static int gred_change(struct Qdisc *sch, struct nlattr *opt,
@ -517,7 +518,7 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt,
static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct gred_sched *table = qdisc_priv(sch);
struct nlattr *parms, *opts = NULL;
struct nlattr *parms, *vqs, *opts = NULL;
int i;
u32 max_p[MAX_DPs];
struct tc_gred_sopt sopt = {
@ -544,6 +545,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
if (nla_put_u32(skb, TCA_GRED_LIMIT, sch->limit))
goto nla_put_failure;
/* Old style all-in-one dump of VQs */
parms = nla_nest_start(skb, TCA_GRED_PARMS);
if (parms == NULL)
goto nla_put_failure;
@ -594,6 +596,55 @@ append_opt:
nla_nest_end(skb, parms);
/* Dump the VQs again, in more structured way */
vqs = nla_nest_start(skb, TCA_GRED_VQ_LIST);
if (!vqs)
goto nla_put_failure;
for (i = 0; i < MAX_DPs; i++) {
struct gred_sched_data *q = table->tab[i];
struct nlattr *vq;
if (!q)
continue;
vq = nla_nest_start(skb, TCA_GRED_VQ_ENTRY);
if (!vq)
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_DP, q->DP))
goto nla_put_failure;
/* Stats */
if (nla_put_u64_64bit(skb, TCA_GRED_VQ_STAT_BYTES, q->bytesin,
TCA_GRED_VQ_PAD))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PACKETS, q->packetsin))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_BACKLOG,
gred_backlog(table, q, sch)))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PROB_DROP,
q->stats.prob_drop))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PROB_MARK,
q->stats.prob_mark))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_FORCED_DROP,
q->stats.forced_drop))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_FORCED_MARK,
q->stats.forced_mark))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PDROP, q->stats.pdrop))
goto nla_put_failure;
if (nla_put_u32(skb, TCA_GRED_VQ_STAT_OTHER, q->stats.other))
goto nla_put_failure;
nla_nest_end(skb, vq);
}
nla_nest_end(skb, vqs);
return nla_nest_end(skb, opts);
nla_put_failure: