Re: [PATCH] tc: fix build failure with Linux >= 6.8 kernel headers (CBQ removal)
tito via busybox <[email protected]>
| Newsgroups | gmane.linux.busybox |
|---|---|
| Message-ID | <20260816235506.114e2927@devuan> |
On Mon, 17 Aug 2026 02:15:16 +0500 Muhammad Bilal via busybox <[email protected]> wrote: > Linux commit 33241dca4862 ("net/sched: Remove uapi support for CBQ > qdisc"), first released in v6.8-rc1 (2024-01-02), dropped all CBQ > related definitions (TCA_CBQ_*, struct tc_cbq_*, TC_CBQ_MAXPRIO, ...) > from include/uapi/linux/pkt_sched.h. The CBQ qdisc itself had already > been retired from the kernel earlier, in v6.3 (commit 051d44209842, > "net/sched: Retire CBQ qdisc"). > > Building tc.c against >= 6.8 kernel headers fails with: > > networking/tc.c: In function 'cbq_print_opt': > networking/tc.c:236:27: error: 'TCA_CBQ_MAX' undeclared (first > use in this function); did you mean 'TCA_CBS_MAX'? > 236 | struct rtattr *tb[TCA_CBQ_MAX+1]; > | ^~~~~~~~~~~ > (and further errors for TCA_CBQ_RATE, struct tc_cbq_lssopt, etc.) > > Guard cbq_print_opt() with '#ifdef TCA_CBQ_MAX', the same pattern > already used a few lines above for the deprecated TCA_PRIO_MAX > multiqueue interface, and guard its two call sites in print_qdisc() > and print_class(). print_rate() is only ever called from > cbq_print_opt(), so move it under the same #ifdef too, to avoid a new > "defined but not used" warning once CBQ support is compiled out. > > This is essentially the same fix independently proposed by Uwe > Kleine-Koenig on the mailing list in March 2024, which was never > applied: > http://lists.busybox.net/pipermail/busybox/2024-March/090678.html > > Already reported twice, but never fixed: > https://bugs.busybox.net/show_bug.cgi?id=15931 > "CBQ support removed from Linux kernel" > https://bugs.busybox.net/show_bug.cgi?id=15934 > "Busybox fails to build with linux kernels >= 6.8" > https://lists.busybox.net/pipermail/busybox-cvs/2024-January/041752.html > > Root cause double-checked directly against a local clone of > torvalds/linux: commit 33241dca486264193ed68167c8eeae1fb197f3df > removes struct tc_cbq_*/TCA_CBQ_* from > include/uapi/linux/pkt_sched.h, and `git describe --contains` places > it at v6.8-rc1~131^2~60^2^2 (2024-01-02). > Hi, as far as I understand with the proposed fix the tc applet will only work with the kernel it is compiled with, if you use a busybox tc applet compiled with kernel 6.12.103 it will not work with 6.7.0 and cbq , this could be seen as a shortcoming. Please take a look at my proposed patch which fixes building busybox and allows use with all kernels at the expense of a little size increase. Ciao, Tito > Build tested on: > OS: Fedora Linux 44 (Forty Four), x86_64 > Kernel: Linux 7.1.8-200.fc44.x86_64 > Headers: kernel-headers-7.1.3-200.fc44.x86_64 > (/usr/include/linux/pkt_sched.h has no CBQ symbols) > gcc: gcc (GCC) 15.3.1 20260729 > > Before this patch, `make defconfig && make` failed while compiling > networking/tc.c on the above system. With this patch, the build > completes cleanly and "busybox tc" still builds and runs normally. > > Fixes: https://bugs.busybox.net/show_bug.cgi?id=15931 > Fixes: https://bugs.busybox.net/show_bug.cgi?id=15934 > > Signed-off-by: Muhammad Bilal <[email protected]> > --- > networking/tc.c | 55 ++++++++++++++++++++++++++++++------------------- > 1 file changed, 34 insertions(+), 21 deletions(-) > > diff --git a/networking/tc.c b/networking/tc.c > index 3a79fd2d9..337d499b4 100644 > --- a/networking/tc.c > +++ b/networking/tc.c > @@ -176,27 +176,6 @@ static int get_tc_classid(uint32_t *h, const char *str) > return 0; > } > > -static void print_rate(char *buf, int len, uint32_t rate) > -{ > - double tmp = (double)rate*8; > - > - if (use_iec) { > - if (tmp >= 1000*1024*1024) > - snprintf(buf, len, "%.0fMibit", tmp/(1024*1024)); > - else if (tmp >= 1000*1024) > - snprintf(buf, len, "%.0fKibit", tmp/1024); > - else > - snprintf(buf, len, "%.0fbit", tmp); > - } else { > - if (tmp >= 1000*1000000) > - snprintf(buf, len, "%.0fMbit", tmp/1000000); > - else if (tmp >= 1000*1000) > - snprintf(buf, len, "%.0fKbit", tmp/1000); > - else > - snprintf(buf, len, "%.0fbit", tmp); > - } > -} > - > #if 0 > /* This is "pfifo_fast". */ > static int prio_parse_opt(int argc, char **argv, struct nlmsghdr *n) > @@ -231,6 +210,35 @@ static int cbq_parse_opt(int argc, char **argv, struct nlmsghdr *n) > return 0; > } > #endif > + > +#ifndef TCA_CBQ_MAX > +/* > + * Linux v6.8-rc1~131^2~60^2^2 removed the uapi definitions for CBQ. > + * See https://git.kernel.org/linus/33241dca48626 > + */ > +#else > +/* Used only by CBQ; other qdiscs print rates without this helper. */ > +static void print_rate(char *buf, int len, uint32_t rate) > +{ > + double tmp = (double)rate*8; > + > + if (use_iec) { > + if (tmp >= 1000*1024*1024) > + snprintf(buf, len, "%.0fMibit", tmp/(1024*1024)); > + else if (tmp >= 1000*1024) > + snprintf(buf, len, "%.0fKibit", tmp/1024); > + else > + snprintf(buf, len, "%.0fbit", tmp); > + } else { > + if (tmp >= 1000*1000000) > + snprintf(buf, len, "%.0fMbit", tmp/1000000); > + else if (tmp >= 1000*1000) > + snprintf(buf, len, "%.0fKbit", tmp/1000); > + else > + snprintf(buf, len, "%.0fbit", tmp); > + } > +} > + > static int cbq_print_opt(struct rtattr *opt) > { > struct rtattr *tb[TCA_CBQ_MAX+1]; > @@ -322,6 +330,7 @@ static int cbq_print_opt(struct rtattr *opt) > done: > return 0; > } > +#endif > > static FAST_FUNC int print_qdisc( > const struct sockaddr_nl *who UNUSED_PARAM, > @@ -372,8 +381,10 @@ static FAST_FUNC int print_qdisc( > int qqq = index_in_strings(_q_, name); > if (qqq == 0) { /* pfifo_fast aka prio */ > prio_print_opt(tb[TCA_OPTIONS]); > +#ifdef TCA_CBQ_MAX > } else if (qqq == 1) { /* class based queuing */ > cbq_print_opt(tb[TCA_OPTIONS]); > +#endif > } else { > /* don't know how to print options for this qdisc */ > printf("(options for %s)", name); > @@ -442,9 +453,11 @@ static FAST_FUNC int print_class( > int qqq = index_in_strings(_q_, name); > if (qqq == 0) { /* pfifo_fast aka prio */ > /* nothing. */ /*prio_print_opt(tb[TCA_OPTIONS]);*/ > +#ifdef TCA_CBQ_MAX > } else if (qqq == 1) { /* class based queuing */ > /* cbq_print_copt() is identical to cbq_print_opt(). */ > cbq_print_opt(tb[TCA_OPTIONS]); > +#endif > } else { > /* don't know how to print options for this class */ > printf("(options for %s)", name);