diff options
author | Eric Dumazet <edumazet@google.com> | 2023-12-04 09:19:09 +0000 |
---|---|---|
committer | David Ahern <dsahern@kernel.org> | 2023-12-06 16:51:41 +0000 |
commit | 73a31c94548138f3448408b207caf08d8ed2c9c2 (patch) | |
tree | a728bc68172ecfe446d97587057c3316da202772 | |
parent | 467879b418ff73d7afc60fab85c8cc766aca7553 (diff) | |
download | iproute2-73a31c94548138f3448408b207caf08d8ed2c9c2.tar.gz |
tc: fq: add TCA_FQ_PRIOMAP handling
linux-6.7 FQ packet scheduler gets 3-bands, and the ability
to report or program the associated priomap.
$ tc qdisc show dev eth0
...
qdisc fq ... bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
$ tc qdisc change dev eth0 ... qdisc fq ... bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r-- | tc/q_fq.c | 59 |
1 files changed, 59 insertions, 0 deletions
@@ -25,6 +25,7 @@ static void explain(void) " [ quantum BYTES ] [ initial_quantum BYTES ]\n" " [ maxrate RATE ] [ buckets NUMBER ]\n" " [ [no]pacing ] [ refill_delay TIME ]\n" + " [ bands 3 priomap P0 P1 ... P14 P15 ]\n" " [ low_rate_threshold RATE ]\n" " [ orphan_mask MASK]\n" " [ timer_slack TIME]\n" @@ -48,6 +49,7 @@ static unsigned int ilog2(unsigned int val) static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { + struct tc_prio_qopt prio2band; unsigned int plimit; unsigned int flow_plimit; unsigned int quantum; @@ -74,6 +76,7 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, bool set_ce_threshold = false; bool set_timer_slack = false; bool set_horizon = false; + bool set_priomap = false; int pacing = -1; struct rtattr *tail; @@ -193,6 +196,48 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, pacing = 1; } else if (strcmp(*argv, "nopacing") == 0) { pacing = 0; + } else if (strcmp(*argv, "bands") == 0) { + int idx; + + if (set_priomap) { + fprintf(stderr, "Duplicate \"bands\"\n"); + return -1; + } + memset(&prio2band, 0, sizeof(prio2band)); + NEXT_ARG(); + if (get_integer(&prio2band.bands, *argv, 10)) { + fprintf(stderr, "Illegal \"bands\"\n"); + return -1; + } + if (prio2band.bands != 3) { + fprintf(stderr, "\"bands\" must be 3\n"); + return -1; + } + NEXT_ARG(); + if (strcmp(*argv, "priomap") != 0) { + fprintf(stderr, "\"priomap\" expected\n"); + return -1; + } + for (idx = 0; idx <= TC_PRIO_MAX; ++idx) { + unsigned band; + + if (!NEXT_ARG_OK()) { + fprintf(stderr, "Not enough elements in priomap\n"); + return -1; + } + NEXT_ARG(); + if (get_unsigned(&band, *argv, 10)) { + fprintf(stderr, "Illegal \"priomap\" element, number in [0..%u] expected\n", + prio2band.bands - 1); + return -1; + } + if (band >= prio2band.bands) { + fprintf(stderr, "\"priomap\" element %u too big\n", band); + return -1; + } + prio2band.priomap[idx] = band; + } + set_priomap = true; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; @@ -252,6 +297,9 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, if (horizon_drop != 255) addattr_l(n, 1024, TCA_FQ_HORIZON_DROP, &horizon_drop, sizeof(horizon_drop)); + if (set_priomap) + addattr_l(n, 1024, TCA_FQ_PRIOMAP, + &prio2band, sizeof(prio2band)); addattr_nest_end(n, tail); return 0; } @@ -306,6 +354,17 @@ static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) if (pacing == 0) print_bool(PRINT_ANY, "pacing", "nopacing ", false); } + if (tb[TCA_FQ_PRIOMAP] && + RTA_PAYLOAD(tb[TCA_FQ_PRIOMAP]) >= sizeof(struct tc_prio_qopt)) { + struct tc_prio_qopt *prio2band = RTA_DATA(tb[TCA_FQ_PRIOMAP]); + int i; + + print_uint(PRINT_ANY, "bands", "bands %u ", prio2band->bands); + open_json_array(PRINT_ANY, "priomap "); + for (i = 0; i <= TC_PRIO_MAX; i++) + print_uint(PRINT_ANY, NULL, "%d ", prio2band->priomap[i]); + close_json_array(PRINT_ANY, ""); + } if (tb[TCA_FQ_QUANTUM] && RTA_PAYLOAD(tb[TCA_FQ_QUANTUM]) >= sizeof(__u32)) { quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]); |