[PATCH] tc: fix build failure with Linux >= 6.8 kernel headers (CBQ removal)

Muhammad Bilal via busybox <[email protected]>
Newsgroups gmane.linux.busybox
Message-ID <[email protected]>
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).

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);
-- 
2.55.0
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.