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.
Unified · Split
| @@ -291,11 +291,37 @@ enum { · 290 unmodified lines | ||
| 291 | 291 | TCA_GRED_DPS, |
| 292 | 292 | TCA_GRED_MAX_P, |
| 293 | 293 | TCA_GRED_LIMIT, |
| 294 | + TCA_GRED_VQ_LIST, /* nested TCA_GRED_VQ_ENTRY */ | |
| 294 | 295 | __TCA_GRED_MAX, |
| 295 | 296 | }; |
| 296 | 297 | |
| 297 | 298 | #define TCA_GRED_MAX (__TCA_GRED_MAX - 1) |
| 298 | 299 | |
| 300 | +enum { | |
| 301 | + TCA_GRED_VQ_ENTRY_UNSPEC, | |
| 302 | + TCA_GRED_VQ_ENTRY, /* nested TCA_GRED_VQ_* */ | |
| 303 | + __TCA_GRED_VQ_ENTRY_MAX, | |
| 304 | +}; | |
| 305 | +#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1) | |
| 306 | + | |
| 307 | +enum { | |
| 308 | + TCA_GRED_VQ_UNSPEC, | |
| 309 | + TCA_GRED_VQ_PAD, | |
| 310 | + TCA_GRED_VQ_DP, /* u32 */ | |
| 311 | + TCA_GRED_VQ_STAT_BYTES, /* u64 */ | |
| 312 | + TCA_GRED_VQ_STAT_PACKETS, /* u32 */ | |
| 313 | + TCA_GRED_VQ_STAT_BACKLOG, /* u32 */ | |
| 314 | + TCA_GRED_VQ_STAT_PROB_DROP, /* u32 */ | |
| 315 | + TCA_GRED_VQ_STAT_PROB_MARK, /* u32 */ | |
| 316 | + TCA_GRED_VQ_STAT_FORCED_DROP, /* u32 */ | |
| 317 | + TCA_GRED_VQ_STAT_FORCED_MARK, /* u32 */ | |
| 318 | + TCA_GRED_VQ_STAT_PDROP, /* u32 */ | |
| 319 | + TCA_GRED_VQ_STAT_OTHER, /* u32 */ | |
| 320 | + __TCA_GRED_VQ_MAX | |
| 321 | +}; | |
| 322 | + | |
| 323 | +#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1) | |
| 324 | + | |
| 299 | 325 | struct tc_gred_qopt { |
| 300 | 326 | __u32 limit; /* HARD maximal queue length (bytes) */ |
| 301 | 327 | __u32 qth_min; /* Min average length threshold (bytes) */ |
| @@ -404,6 +404,7 @@ static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = { · 403 unmodified lines | ||
| 404 | 404 | [TCA_GRED_DPS] = { .len = sizeof(struct tc_gred_sopt) }, |
| 405 | 405 | [TCA_GRED_MAX_P] = { .type = NLA_U32 }, |
| 406 | 406 | [TCA_GRED_LIMIT] = { .type = NLA_U32 }, |
| 407 | + [TCA_GRED_VQ_LIST] = { .type = NLA_REJECT }, | |
| 407 | 408 | }; |
| 408 | 409 | |
| 409 | 410 | static int gred_change(struct Qdisc *sch, struct nlattr *opt, |
| @@ -517,7 +518,7 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt, · 107 unmodified lines | ||
| 517 | 518 | static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) |
| 518 | 519 | { |
| 519 | 520 | struct gred_sched *table = qdisc_priv(sch); |
| 520 | − struct nlattr *parms, *opts = NULL; | |
| 521 | + struct nlattr *parms, *vqs, *opts = NULL; | |
| 521 | 522 | int i; |
| 522 | 523 | u32 max_p[MAX_DPs]; |
| 523 | 524 | struct tc_gred_sopt sopt = { |
| @@ -544,6 +545,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) · 20 unmodified lines | ||
| 544 | 545 | if (nla_put_u32(skb, TCA_GRED_LIMIT, sch->limit)) |
| 545 | 546 | goto nla_put_failure; |
| 546 | 547 | |
| 548 | + /* Old style all-in-one dump of VQs */ | |
| 547 | 549 | parms = nla_nest_start(skb, TCA_GRED_PARMS); |
| 548 | 550 | if (parms == NULL) |
| 549 | 551 | goto nla_put_failure; |
| @@ -594,6 +596,55 @@ append_opt: · 44 unmodified lines | ||
| 594 | 596 | |
| 595 | 597 | nla_nest_end(skb, parms); |
| 596 | 598 | |
| 599 | + /* Dump the VQs again, in more structured way */ | |
| 600 | + vqs = nla_nest_start(skb, TCA_GRED_VQ_LIST); | |
| 601 | + if (!vqs) | |
| 602 | + goto nla_put_failure; | |
| 603 | + | |
| 604 | + for (i = 0; i < MAX_DPs; i++) { | |
| 605 | + struct gred_sched_data *q = table->tab[i]; | |
| 606 | + struct nlattr *vq; | |
| 607 | + | |
| 608 | + if (!q) | |
| 609 | + continue; | |
| 610 | + | |
| 611 | + vq = nla_nest_start(skb, TCA_GRED_VQ_ENTRY); | |
| 612 | + if (!vq) | |
| 613 | + goto nla_put_failure; | |
| 614 | + | |
| 615 | + if (nla_put_u32(skb, TCA_GRED_VQ_DP, q->DP)) | |
| 616 | + goto nla_put_failure; | |
| 617 | + | |
| 618 | + /* Stats */ | |
| 619 | + if (nla_put_u64_64bit(skb, TCA_GRED_VQ_STAT_BYTES, q->bytesin, | |
| 620 | + TCA_GRED_VQ_PAD)) | |
| 621 | + goto nla_put_failure; | |
| 622 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PACKETS, q->packetsin)) | |
| 623 | + goto nla_put_failure; | |
| 624 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_BACKLOG, | |
| 625 | + gred_backlog(table, q, sch))) | |
| 626 | + goto nla_put_failure; | |
| 627 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PROB_DROP, | |
| 628 | + q->stats.prob_drop)) | |
| 629 | + goto nla_put_failure; | |
| 630 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PROB_MARK, | |
| 631 | + q->stats.prob_mark)) | |
| 632 | + goto nla_put_failure; | |
| 633 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_FORCED_DROP, | |
| 634 | + q->stats.forced_drop)) | |
| 635 | + goto nla_put_failure; | |
| 636 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_FORCED_MARK, | |
| 637 | + q->stats.forced_mark)) | |
| 638 | + goto nla_put_failure; | |
| 639 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PDROP, q->stats.pdrop)) | |
| 640 | + goto nla_put_failure; | |
| 641 | + if (nla_put_u32(skb, TCA_GRED_VQ_STAT_OTHER, q->stats.other)) | |
| 642 | + goto nla_put_failure; | |
| 643 | + | |
| 644 | + nla_nest_end(skb, vq); | |
| 645 | + } | |
| 646 | + nla_nest_end(skb, vqs); | |
| 647 | + | |
| 597 | 648 | return nla_nest_end(skb, opts); |
| 598 | 649 | |
| 599 | 650 | nla_put_failure: |