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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.