AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/06/19 15:30 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": [
    "NET_SCH_DUALPI2"
  ],
  "FocusSymbols": [
    "dualpi2_qdisc_enqueue"
  ],
  "Reasoning": "The patch fixes a bug in the backlog accounting of the `dualpi2` network scheduler when handling GSO packets. It modifies the `dualpi2_qdisc_enqueue` function to correctly calculate and reduce the backlog using `qdisc_tree_reduce_backlog`. This is a functional change in reachable core network scheduling logic, and should be fuzzed to ensure the accounting is correct and doesn't lead to underflows or other issues.",
  "WorthFuzzing": true
}

1/1 2026/06/19 15:30 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 10997b74fc3e8d14b9ee0e873f3946c7b4bd4be9\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Fri Jun 19 15:30:51 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c\nindex d7c3254ef800f8..5434df6ca8efe6 100644\n--- a/net/sched/sch_dualpi2.c\n+++ b/net/sched/sch_dualpi2.c\n@@ -461,7 +461,7 @@ static int dualpi2_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,\n \t\tif (IS_ERR_OR_NULL(nskb))\n \t\t\treturn qdisc_drop(skb, sch, to_free);\n \n-\t\tcnt = 1;\n+\t\tcnt = 0;\n \t\tbyte_len = 0;\n \t\torig_len = qdisc_pkt_len(skb);\n \t\tskb_list_walk_safe(nskb, nskb, next) {\n@@ -488,16 +488,15 @@ static int dualpi2_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,\n \t\t\t\tbyte_len += nskb-\u003elen;\n \t\t\t}\n \t\t}\n-\t\tif (cnt \u003e 1) {\n+\t\tif (cnt \u003e 0) {\n \t\t\t/* The caller will add the original skb stats to its\n \t\t\t * backlog, compensate this if any nskb is enqueued.\n \t\t\t */\n-\t\t\t--cnt;\n-\t\t\tbyte_len -= orig_len;\n+\t\t\tqdisc_tree_reduce_backlog(sch, 1 - cnt,\n+\t\t\t\t\t\t  orig_len - byte_len);\n \t\t}\n-\t\tqdisc_tree_reduce_backlog(sch, -cnt, -byte_len);\n \t\tconsume_skb(skb);\n-\t\treturn err;\n+\t\treturn cnt \u003e 0 ? NET_XMIT_SUCCESS : err;\n \t}\n \treturn dualpi2_enqueue_skb(skb, sch, to_free);\n }\ndiff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json\nindex cd1f2ee8f354d6..ed6a900bb568f4 100644\n--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json\n+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json\n@@ -250,5 +250,49 @@\n         \"teardown\": [\n             \"$TC qdisc del dev $DUMMY handle 1: root\"\n         ]\n+    },\n+    {\n+        \"id\": \"891f\",\n+        \"name\": \"Verify DualPI2 GSO backlog accounting with QFQ parent\",\n+        \"category\": [\n+            \"qdisc\",\n+            \"dualpi2\",\n+            \"qfq\",\n+            \"gso\"\n+        ],\n+        \"plugins\": {\n+            \"requires\": \"nsPlugin\"\n+        },\n+        \"setup\": [\n+            \"$IP link set dev $DUMMY up || true\",\n+            \"$IP addr add 10.10.10.10/24 dev $DUMMY || true\",\n+            \"$TC qdisc add dev $DUMMY root handle 1: qfq\",\n+            \"$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 1 maxpkt 4096\",\n+            \"$TC qdisc add dev $DUMMY parent 1:1 handle 2: dualpi2\",\n+            \"$TC filter add dev $DUMMY parent 1: matchall classid 1:1\"\n+        ],\n+        \"cmdUnderTest\": \"./tdc_gso.py 10.10.10.10 10.10.10.1 9000 1200 2400\",\n+        \"expExitCode\": \"0\",\n+        \"verifyCmd\": \"$TC -j -s qdisc ls dev $DUMMY\",\n+        \"matchJSON\": [\n+            {\n+                \"kind\": \"qfq\",\n+                \"handle\": \"1:\",\n+                \"packets\": 2,\n+                \"backlog\": 0,\n+                \"qlen\": 0\n+            },\n+            {\n+                \"kind\": \"dualpi2\",\n+                \"handle\": \"2:\",\n+                \"packets\": 2,\n+                \"backlog\": 0,\n+                \"qlen\": 0\n+            }\n+        ],\n+        \"teardown\": [\n+            \"$TC qdisc del dev $DUMMY root\",\n+            \"$IP addr del 10.10.10.10/24 dev $DUMMY || true\"\n+        ]\n     }\n ]\ndiff --git a/tools/testing/selftests/tc-testing/tdc_gso.py b/tools/testing/selftests/tc-testing/tdc_gso.py\nnew file mode 100755\nindex 00000000000000..b66528ea4b680a\n--- /dev/null\n+++ b/tools/testing/selftests/tc-testing/tdc_gso.py\n@@ -0,0 +1,43 @@\n+#!/usr/bin/env python3\n+# SPDX-License-Identifier: GPL-2.0\n+\n+\"\"\"\n+tdc_gso.py - send a UDP GSO datagram\n+\n+Copyright (C) 2026 Xingquan Liu \u003cb1n@b1n.io\u003e\n+\"\"\"\n+\n+import argparse\n+import socket\n+import struct\n+import sys\n+\n+UDP_MAX_SEGMENTS = 1 \u003c\u003c 7\n+\n+\n+parser = argparse.ArgumentParser(description=\"UDP GSO datagram sender\")\n+parser.add_argument(\"src\", help=\"source IPv4 address\")\n+parser.add_argument(\"dst\", help=\"destination IPv4 address\")\n+parser.add_argument(\"port\", type=int, help=\"destination UDP port\")\n+parser.add_argument(\"gso_size\", type=int, help=\"UDP GSO segment payload size\")\n+parser.add_argument(\"payload_len\", type=int, help=\"total UDP payload length\")\n+args = parser.parse_args()\n+\n+if args.gso_size \u003c= 0 or args.gso_size \u003e 0xFFFF:\n+    parser.error(\"gso_size must fit in an unsigned 16-bit integer\")\n+if args.payload_len \u003c= args.gso_size:\n+    parser.error(\"payload_len must be larger than gso_size\")\n+if args.payload_len \u003e args.gso_size * UDP_MAX_SEGMENTS:\n+    parser.error(\"payload_len exceeds UDP_MAX_SEGMENTS\")\n+\n+SOL_UDP = getattr(socket, \"SOL_UDP\", socket.IPPROTO_UDP)\n+UDP_SEGMENT = getattr(socket, \"UDP_SEGMENT\", 103)\n+\n+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n+sock.bind((args.src, 0))\n+\n+payload = b\"b\" * args.payload_len\n+cmsg = [(SOL_UDP, UDP_SEGMENT, struct.pack(\"=H\", args.gso_size))]\n+\n+sent = sock.sendmsg([payload], cmsg, 0, (args.dst, args.port))\n+sys.exit(sent != len(payload))\n"
}

2/1 2026/06/19 15:30 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "NET_SCH_DUALPI2"
  ],
  "FocusSymbols": [
    "dualpi2_qdisc_enqueue"
  ],
  "Reasoning": "The patch fixes a bug in the backlog accounting of the `dualpi2` network scheduler when handling GSO packets. It modifies the `dualpi2_qdisc_enqueue` function to correctly calculate and reduce the backlog using `qdisc_tree_reduce_backlog`. This is a functional change in reachable core network scheduling logic, and should be fuzzed to ensure the accounting is correct and doesn't lead to underflows or other issues.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 10997b74fc3e8d14b9ee0e873f3946c7b4bd4be9
Author: syz-cluster <triage@syzkaller.com>
Date:   Fri Jun 19 15:30:51 2026 +0000

    syz-cluster: applied patch under review

diff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c
index d7c3254ef800f8..5434df6ca8efe6 100644
--- a/net/sched/sch_dualpi2.c
+++ b/net/sched/sch_dualpi2.c
@@ -461,7 +461,7 @@ static int dualpi2_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 		if (IS_ERR_OR_NULL(nskb))
 			return qdisc_drop(skb, sch, to_free);
 
-		cnt = 1;
+		cnt = 0;
 		byte_len = 0;
 		orig_len = qdisc_pkt_len(skb);
 		skb_list_walk_safe(nskb, nskb, next) {
@@ -488,16 +488,15 @@ static int dualpi2_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 				byte_len += nskb->len;
 			}
 		}
-		if (cnt > 1) {
+		if (cnt > 0) {
 			/* The caller will add the original skb stats to its
 			 * backlog, compensate this if any nskb is enqueued.
 			 */
-			--cnt;
-			byte_len -= orig_len;
+			qdisc_tree_reduce_backlog(sch, 1 - cnt,
+						  orig_len - byte_len);
 		}
-		qdisc_tree_reduce_backlog(sch, -cnt, -byte_len);
 		consume_skb(skb);
-		return err;
+		return cnt > 0 ? NET_XMIT_SUCCESS : err;
 	}
 	return dualpi2_enqueue_skb(skb, sch, to_free);
 }
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json
index cd1f2ee8f354d6..ed6a900bb568f4 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/dualpi2.json
@@ -250,5 +250,49 @@
         "teardown": [
             "$TC qdisc del dev $DUMMY handle 1: root"
         ]
+    },
+    {
+        "id": "891f",
+        "name": "Verify DualPI2 GSO backlog accounting with QFQ parent",
+        "category": [
+            "qdisc",
+            "dualpi2",
+            "qfq",
+            "gso"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link set dev $DUMMY up || true",
+            "$IP addr add 10.10.10.10/24 dev $DUMMY || true",
+            "$TC qdisc add dev $DUMMY root handle 1: qfq",
+            "$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 1 maxpkt 4096",
+            "$TC qdisc add dev $DUMMY parent 1:1 handle 2: dualpi2",
+            "$TC filter add dev $DUMMY parent 1: matchall classid 1:1"
+        ],
+        "cmdUnderTest": "./tdc_gso.py 10.10.10.10 10.10.10.1 9000 1200 2400",
+        "expExitCode": "0",
+        "verifyCmd": "$TC -j -s qdisc ls dev $DUMMY",
+        "matchJSON": [
+            {
+                "kind": "qfq",
+                "handle": "1:",
+                "packets": 2,
+                "backlog": 0,
+                "qlen": 0
+            },
+            {
+                "kind": "dualpi2",
+                "handle": "2:",
+                "packets": 2,
+                "backlog": 0,
+                "qlen": 0
+            }
+        ],
+        "teardown": [
+            "$TC qdisc del dev $DUMMY root",
+            "$IP addr del 10.10.10.10/24 dev $DUMMY || true"
+        ]
     }
 ]
diff --git a/tools/testing/selftests/tc-testing/tdc_gso.py b/tools/testing/selftests/tc-testing/tdc_gso.py
new file mode 100755
index 00000000000000..b66528ea4b680a
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tdc_gso.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""
+tdc_gso.py - send a UDP GSO datagram
+
+Copyright (C) 2026 Xingquan Liu <b1n@b1n.io>
+"""
+
+import argparse
+import socket
+import struct
+import sys
+
+UDP_MAX_SEGMENTS = 1 << 7
+
+
+parser = argparse.ArgumentParser(description="UDP GSO datagram sender")
+parser.add_argument("src", help="source IPv4 address")
+parser.add_argument("dst", help="destination IPv4 address")
+parser.add_argument("port", type=int, help="destination UDP port")
+parser.add_argument("gso_size", type=int, help="UDP GSO segment payload size")
+parser.add_argument("payload_len", type=int, help="total UDP payload length")
+args = parser.parse_args()
+
+if args.gso_size <= 0 or args.gso_size > 0xFFFF:
+    parser.error("gso_size must fit in an unsigned 16-bit integer")
+if args.payload_len <= args.gso_size:
+    parser.error("payload_len must be larger than gso_size")
+if args.payload_len > args.gso_size * UDP_MAX_SEGMENTS:
+    parser.error("payload_len exceeds UDP_MAX_SEGMENTS")
+
+SOL_UDP = getattr(socket, "SOL_UDP", socket.IPPROTO_UDP)
+UDP_SEGMENT = getattr(socket, "UDP_SEGMENT", 103)
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.bind((args.src, 0))
+
+payload = b"b" * args.payload_len
+cmsg = [(SOL_UDP, UDP_SEGMENT, struct.pack("=H", args.gso_size))]
+
+sent = sock.sendmsg([payload], cmsg, 0, (args.dst, args.port))
+sys.exit(sent != len(payload))

3/2 2026/06/19 15:30 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 3515
							output: 27
							thoughts: 599
						

Thoughts:
**Analyzing a Patch for `sch_dualpi2` Backlog Accounting**

Okay, so I've got a patch here that's touching `net/sched/sch_dualpi2.c` and adding a test for it in `tools/testing/selftests/tc-testing/`. That tells me this is likely a bug fix and a corresponding test case, which is good practice. The core of the change is in `dualpi2_qdisc_enqueue`, and the description mentions backlog accounting for Generic Segmentation Offload (GSO) packets. That's immediately interesting because GSO often has some subtle interactions with traffic control.

Let me take a closer look at the diff.  Ah, it seems we have a reduction in `cnt` and a corresponding adjustment to `qdisc_tree_reduce_backlog`. Specifically, it appears the patch is correcting an issue where GSO packets weren't being accounted for correctly when their internal segments are processed. We're now correctly decrementing the backlog. Previously, the original `skb` statistics were being incorrectly adjusted. This looks like a functional correction, the comment makes this abundantly clear.

The key change is around lines 461 to 488. I can see the adjustment to backlog reduction based on the length of each segmented packet and the original packet. So it's about correcting how the backlog is adjusted for the original packet after its GSO segments have been handled.  It appears to fix an accounting error for GSO packets, preventing inflated or deflated backlog values in the `sch_dualpi2` qdisc. The addition of the conditional `cnt > 0 ? NET_XMIT_SUCCESS : err` makes sense in this context.

Now, to understand the context a bit better, I'd like to look at the relevant Kconfig options for the `sch_dualpi2` Qdisc. I'm going to quickly search for them in `net/sched/Kconfig` or `net/sched/Makefile` using `grepper` just to get a good overview of how this is enabled, and any possible dependencies.



4/2 2026/06/19 15:31 tool grepper
0m Args:
{
  "Expression": "dualpi2",
  "PathPrefix": "net/sched/"
}

Results:
{
  "Output": "net/sched/Kconfig=418=config NET_SCH_DUALPI2\n--\nnet/sched/Kconfig-425-\t  To compile this driver as a module, choose M here: the module\nnet/sched/Kconfig:426:\t  will be called sch_dualpi2.\nnet/sched/Kconfig-427-\n--\nnet/sched/Makefile=65=obj-$(CONFIG_NET_SCH_BPF)\t+= bpf_qdisc.o\nnet/sched/Makefile:66:obj-$(CONFIG_NET_SCH_DUALPI2)\t+= sch_dualpi2.o\nnet/sched/Makefile-67-\n--\nnet/sched/sch_dualpi2.c-9- *\nnet/sched/sch_dualpi2.c:10: * DualPI Improved with a Square (dualpi2):\nnet/sched/sch_dualpi2.c-11- * - Supports congestion controls that comply with the Prague requirements\n--\nnet/sched/sch_dualpi2.c-42- * i.e., twice the maximal snd_cwnd.\nnet/sched/sch_dualpi2.c:43: * MAX_PROB must be consistent with the RNG in dualpi2_roll().\nnet/sched/sch_dualpi2.c-44- */\n--\nnet/sched/sch_dualpi2.c-50-/* Scaled values of alpha/beta must fit in 32b to avoid overflow in later\nnet/sched/sch_dualpi2.c:51: * computations. Consequently (see and dualpi2_scale_alpha_beta()), their\nnet/sched/sch_dualpi2.c-52- * netlink-provided values can use at most 31b, i.e. be at most (2^23)-1\n--\nnet/sched/sch_dualpi2.c-69-\nnet/sched/sch_dualpi2.c:70:struct dualpi2_sched_data {\nnet/sched/sch_dualpi2.c-71-\tstruct Qdisc *l_queue;\t/* The L4S Low latency queue (L-queue) */\n--\nnet/sched/sch_dualpi2.c-121-\nnet/sched/sch_dualpi2.c:122:struct dualpi2_skb_cb {\nnet/sched/sch_dualpi2.c-123-\tu64 ts;\t\t\t/* Timestamp at enqueue */\n--\nnet/sched/sch_dualpi2.c-128-\nnet/sched/sch_dualpi2.c:129:enum dualpi2_classification_results {\nnet/sched/sch_dualpi2.c-130-\tDUALPI2_C_CLASSIC\t= 0,\t/* C-queue */\n--\nnet/sched/sch_dualpi2.c-135-\nnet/sched/sch_dualpi2.c:136:static struct dualpi2_skb_cb *dualpi2_skb_cb(struct sk_buff *skb)\nnet/sched/sch_dualpi2.c-137-{\nnet/sched/sch_dualpi2.c:138:\tqdisc_cb_private_validate(skb, sizeof(struct dualpi2_skb_cb));\nnet/sched/sch_dualpi2.c:139:\treturn (struct dualpi2_skb_cb *)qdisc_skb_cb(skb)-\u003edata;\nnet/sched/sch_dualpi2.c-140-}\nnet/sched/sch_dualpi2.c-141-\nnet/sched/sch_dualpi2.c:142:static u64 dualpi2_sojourn_time(struct sk_buff *skb, u64 reference)\nnet/sched/sch_dualpi2.c-143-{\nnet/sched/sch_dualpi2.c:144:\treturn reference - dualpi2_skb_cb(skb)-\u003ets;\nnet/sched/sch_dualpi2.c-145-}\n--\nnet/sched/sch_dualpi2.c=147=static u64 head_enqueue_time(struct Qdisc *q)\n--\nnet/sched/sch_dualpi2.c-150-\nnet/sched/sch_dualpi2.c:151:\treturn skb ? dualpi2_skb_cb(skb)-\u003ets : 0;\nnet/sched/sch_dualpi2.c-152-}\nnet/sched/sch_dualpi2.c-153-\nnet/sched/sch_dualpi2.c:154:static u32 dualpi2_scale_alpha_beta(u32 param)\nnet/sched/sch_dualpi2.c-155-{\n--\nnet/sched/sch_dualpi2.c-161-\nnet/sched/sch_dualpi2.c:162:static u32 dualpi2_unscale_alpha_beta(u32 param)\nnet/sched/sch_dualpi2.c-163-{\n--\nnet/sched/sch_dualpi2.c-169-\nnet/sched/sch_dualpi2.c:170:static ktime_t next_pi2_timeout(struct dualpi2_sched_data *q)\nnet/sched/sch_dualpi2.c-171-{\n--\nnet/sched/sch_dualpi2.c=175=static bool skb_is_l4s(struct sk_buff *skb)\nnet/sched/sch_dualpi2.c-176-{\nnet/sched/sch_dualpi2.c:177:\treturn dualpi2_skb_cb(skb)-\u003eclassified == DUALPI2_C_L4S;\nnet/sched/sch_dualpi2.c-178-}\n--\nnet/sched/sch_dualpi2.c=180=static bool skb_in_l_queue(struct sk_buff *skb)\nnet/sched/sch_dualpi2.c-181-{\nnet/sched/sch_dualpi2.c:182:\treturn dualpi2_skb_cb(skb)-\u003eclassified != DUALPI2_C_CLASSIC;\nnet/sched/sch_dualpi2.c-183-}\nnet/sched/sch_dualpi2.c-184-\nnet/sched/sch_dualpi2.c:185:static bool skb_apply_step(struct sk_buff *skb, struct dualpi2_sched_data *q)\nnet/sched/sch_dualpi2.c-186-{\n--\nnet/sched/sch_dualpi2.c-189-\nnet/sched/sch_dualpi2.c:190:static bool dualpi2_mark(struct dualpi2_sched_data *q, struct sk_buff *skb)\nnet/sched/sch_dualpi2.c-191-{\n--\nnet/sched/sch_dualpi2.c-198-\nnet/sched/sch_dualpi2.c:199:static void dualpi2_reset_c_protection(struct dualpi2_sched_data *q)\nnet/sched/sch_dualpi2.c-200-{\n--\nnet/sched/sch_dualpi2.c-207- */\nnet/sched/sch_dualpi2.c:208:static void dualpi2_calculate_c_protection(struct Qdisc *sch,\nnet/sched/sch_dualpi2.c:209:\t\t\t\t\t   struct dualpi2_sched_data *q, u32 wc)\nnet/sched/sch_dualpi2.c-210-{\n--\nnet/sched/sch_dualpi2.c-214-\t\t((int)q-\u003ec_protection_wc - (int)q-\u003ec_protection_wl);\nnet/sched/sch_dualpi2.c:215:\tdualpi2_reset_c_protection(q);\nnet/sched/sch_dualpi2.c-216-}\nnet/sched/sch_dualpi2.c-217-\nnet/sched/sch_dualpi2.c:218:static bool dualpi2_roll(u32 prob)\nnet/sched/sch_dualpi2.c-219-{\n--\nnet/sched/sch_dualpi2.c-229- */\nnet/sched/sch_dualpi2.c:230:static bool dualpi2_classic_marking(struct dualpi2_sched_data *q,\nnet/sched/sch_dualpi2.c-231-\t\t\t\t    struct sk_buff *skb, u32 prob,\n--\nnet/sched/sch_dualpi2.c-233-{\nnet/sched/sch_dualpi2.c:234:\tif (dualpi2_roll(prob) \u0026\u0026 dualpi2_roll(prob)) {\nnet/sched/sch_dualpi2.c:235:\t\tif (overload || dualpi2_skb_cb(skb)-\u003eect == INET_ECN_NOT_ECT)\nnet/sched/sch_dualpi2.c-236-\t\t\treturn true;\nnet/sched/sch_dualpi2.c:237:\t\tdualpi2_mark(q, skb);\nnet/sched/sch_dualpi2.c-238-\t}\n--\nnet/sched/sch_dualpi2.c-252- */\nnet/sched/sch_dualpi2.c:253:static bool dualpi2_scalable_marking(struct dualpi2_sched_data *q,\nnet/sched/sch_dualpi2.c-254-\t\t\t\t     struct sk_buff *skb,\n--\nnet/sched/sch_dualpi2.c-260-\t\tif (!q-\u003edrop_overload ||\nnet/sched/sch_dualpi2.c:261:\t\t    !(dualpi2_roll(prob) \u0026\u0026 dualpi2_roll(prob)))\nnet/sched/sch_dualpi2.c-262-\t\t\tgoto mark;\n--\nnet/sched/sch_dualpi2.c-266-\t/* We can safely cut the upper 32b as overload==false */\nnet/sched/sch_dualpi2.c:267:\tif (dualpi2_roll(local_l_prob)) {\nnet/sched/sch_dualpi2.c-268-\t\t/* Non-ECT packets could have classified as L4S by filters. */\nnet/sched/sch_dualpi2.c:269:\t\tif (dualpi2_skb_cb(skb)-\u003eect == INET_ECN_NOT_ECT)\nnet/sched/sch_dualpi2.c-270-\t\t\treturn true;\nnet/sched/sch_dualpi2.c-271-mark:\nnet/sched/sch_dualpi2.c:272:\t\tdualpi2_mark(q, skb);\nnet/sched/sch_dualpi2.c-273-\t}\n--\nnet/sched/sch_dualpi2.c-281- */\nnet/sched/sch_dualpi2.c:282:static bool must_drop(struct Qdisc *sch, struct dualpi2_sched_data *q,\nnet/sched/sch_dualpi2.c-283-\t\t      struct sk_buff *skb)\n--\nnet/sched/sch_dualpi2.c-295-\nnet/sched/sch_dualpi2.c:296:\tswitch (dualpi2_skb_cb(skb)-\u003eclassified) {\nnet/sched/sch_dualpi2.c-297-\tcase DUALPI2_C_CLASSIC:\nnet/sched/sch_dualpi2.c:298:\t\treturn dualpi2_classic_marking(q, skb, prob, overload);\nnet/sched/sch_dualpi2.c-299-\tcase DUALPI2_C_L4S:\nnet/sched/sch_dualpi2.c:300:\t\treturn dualpi2_scalable_marking(q, skb, local_l_prob, prob,\nnet/sched/sch_dualpi2.c-301-\t\t\t\t\t\toverload);\n--\nnet/sched/sch_dualpi2.c-306-\nnet/sched/sch_dualpi2.c:307:static void dualpi2_read_ect(struct sk_buff *skb)\nnet/sched/sch_dualpi2.c-308-{\nnet/sched/sch_dualpi2.c:309:\tstruct dualpi2_skb_cb *cb = dualpi2_skb_cb(skb);\nnet/sched/sch_dualpi2.c-310-\tint wlen = skb_network_offset(skb);\n--\nnet/sched/sch_dualpi2.c-340-\nnet/sched/sch_dualpi2.c:341:static int dualpi2_skb_classify(struct dualpi2_sched_data *q,\nnet/sched/sch_dualpi2.c-342-\t\t\t\tstruct sk_buff *skb)\nnet/sched/sch_dualpi2.c-343-{\nnet/sched/sch_dualpi2.c:344:\tstruct dualpi2_skb_cb *cb = dualpi2_skb_cb(skb);\nnet/sched/sch_dualpi2.c-345-\tstruct tcf_result res;\n--\nnet/sched/sch_dualpi2.c-348-\nnet/sched/sch_dualpi2.c:349:\tdualpi2_read_ect(skb);\nnet/sched/sch_dualpi2.c-350-\tif (cb-\u003eect \u0026 q-\u003eecn_mask) {\n--\nnet/sched/sch_dualpi2.c-384-\nnet/sched/sch_dualpi2.c:385:static int dualpi2_enqueue_skb(struct sk_buff *skb, struct Qdisc *sch,\nnet/sched/sch_dualpi2.c-386-\t\t\t       struct sk_buff **to_free)\nnet/sched/sch_dualpi2.c-387-{\nnet/sched/sch_dualpi2.c:388:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c:389:\tstruct dualpi2_skb_cb *cb;\nnet/sched/sch_dualpi2.c-390-\n--\nnet/sched/sch_dualpi2.c-403-\nnet/sched/sch_dualpi2.c:404:\tcb = dualpi2_skb_cb(skb);\nnet/sched/sch_dualpi2.c-405-\tcb-\u003ets = ktime_get_ns();\n--\nnet/sched/sch_dualpi2.c-414-\t\t/* Apply step thresh if skb is L4S \u0026\u0026 L-queue len \u003e= min_qlen */\nnet/sched/sch_dualpi2.c:415:\t\tdualpi2_skb_cb(skb)-\u003eapply_step = skb_apply_step(skb, q);\nnet/sched/sch_dualpi2.c-416-\n--\nnet/sched/sch_dualpi2.c-430-\nnet/sched/sch_dualpi2.c:431:/* By default, dualpi2 will split GSO skbs into independent skbs and enqueue\nnet/sched/sch_dualpi2.c-432- * each of those individually. This yields the following benefits, at the\n--\nnet/sched/sch_dualpi2.c-438- */\nnet/sched/sch_dualpi2.c:439:static int dualpi2_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,\nnet/sched/sch_dualpi2.c-440-\t\t\t\t struct sk_buff **to_free)\nnet/sched/sch_dualpi2.c-441-{\nnet/sched/sch_dualpi2.c:442:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-443-\tint err;\nnet/sched/sch_dualpi2.c-444-\nnet/sched/sch_dualpi2.c:445:\terr = dualpi2_skb_classify(q, skb);\nnet/sched/sch_dualpi2.c-446-\tif (err != NET_XMIT_SUCCESS) {\n--\nnet/sched/sch_dualpi2.c-472-\t\t\t * (2) Copy classified and ect values of an skb\nnet/sched/sch_dualpi2.c:473:\t\t\t * (3) Enqueue fragment \u0026 set ts in dualpi2_enqueue_skb\nnet/sched/sch_dualpi2.c-474-\t\t\t */\n--\nnet/sched/sch_dualpi2.c-476-\t\t\tqdisc_skb_cb(nskb)-\u003epkt_segs = 1;\nnet/sched/sch_dualpi2.c:477:\t\t\tdualpi2_skb_cb(nskb)-\u003eclassified =\nnet/sched/sch_dualpi2.c:478:\t\t\t\tdualpi2_skb_cb(skb)-\u003eclassified;\nnet/sched/sch_dualpi2.c:479:\t\t\tdualpi2_skb_cb(nskb)-\u003eect = dualpi2_skb_cb(skb)-\u003eect;\nnet/sched/sch_dualpi2.c:480:\t\t\terr = dualpi2_enqueue_skb(nskb, sch, to_free);\nnet/sched/sch_dualpi2.c-481-\n--\nnet/sched/sch_dualpi2.c-500-\t}\nnet/sched/sch_dualpi2.c:501:\treturn dualpi2_enqueue_skb(skb, sch, to_free);\nnet/sched/sch_dualpi2.c-502-}\n--\nnet/sched/sch_dualpi2.c=514=static struct sk_buff *dequeue_packet(struct Qdisc *sch,\nnet/sched/sch_dualpi2.c:515:\t\t\t\t      struct dualpi2_sched_data *q,\nnet/sched/sch_dualpi2.c-516-\t\t\t\t      int *credit_change,\n--\nnet/sched/sch_dualpi2.c-538-\t} else {\nnet/sched/sch_dualpi2.c:539:\t\tdualpi2_reset_c_protection(q);\nnet/sched/sch_dualpi2.c-540-\t\treturn NULL;\n--\nnet/sched/sch_dualpi2.c-547-\nnet/sched/sch_dualpi2.c:548:static int do_step_aqm(struct dualpi2_sched_data *q, struct sk_buff *skb,\nnet/sched/sch_dualpi2.c-549-\t\t       u64 now)\n--\nnet/sched/sch_dualpi2.c-555-\telse\nnet/sched/sch_dualpi2.c:556:\t\tqdelay = dualpi2_sojourn_time(skb, now);\nnet/sched/sch_dualpi2.c-557-\nnet/sched/sch_dualpi2.c:558:\tif (dualpi2_skb_cb(skb)-\u003eapply_step \u0026\u0026 qdelay \u003e q-\u003estep_thresh) {\nnet/sched/sch_dualpi2.c:559:\t\tif (!dualpi2_skb_cb(skb)-\u003eect) {\nnet/sched/sch_dualpi2.c-560-\t\t\t/* Drop this non-ECT packet */\n--\nnet/sched/sch_dualpi2.c-563-\nnet/sched/sch_dualpi2.c:564:\t\tif (dualpi2_mark(q, skb))\nnet/sched/sch_dualpi2.c-565-\t\t\tWRITE_ONCE(q-\u003estep_marks, q-\u003estep_marks + 1);\n--\nnet/sched/sch_dualpi2.c-570-\nnet/sched/sch_dualpi2.c:571:static void drop_and_retry(struct dualpi2_sched_data *q, struct sk_buff *skb,\nnet/sched/sch_dualpi2.c-572-\t\t\t   struct Qdisc *sch, enum qdisc_drop_reason reason)\n--\nnet/sched/sch_dualpi2.c-579-\nnet/sched/sch_dualpi2.c:580:static struct sk_buff *__dualpi2_qdisc_dequeue(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-581-{\nnet/sched/sch_dualpi2.c:582:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-583-\tstruct sk_buff *skb;\n--\nnet/sched/sch_dualpi2.c-609-\nnet/sched/sch_dualpi2.c:610:static void dualpi2_dequeue_drop(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-611-{\nnet/sched/sch_dualpi2.c:612:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-613-\n--\nnet/sched/sch_dualpi2.c-621-\nnet/sched/sch_dualpi2.c:622:static struct sk_buff *dualpi2_qdisc_dequeue(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-623-{\n--\nnet/sched/sch_dualpi2.c-625-\nnet/sched/sch_dualpi2.c:626:\tskb = __dualpi2_qdisc_dequeue(sch);\nnet/sched/sch_dualpi2.c-627-\nnet/sched/sch_dualpi2.c:628:\tdualpi2_dequeue_drop(sch);\nnet/sched/sch_dualpi2.c-629-\n--\nnet/sched/sch_dualpi2.c-632-\nnet/sched/sch_dualpi2.c:633:static struct sk_buff *dualpi2_peek(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-634-{\n--\nnet/sched/sch_dualpi2.c-637-\tif (!skb) {\nnet/sched/sch_dualpi2.c:638:\t\tskb = __dualpi2_qdisc_dequeue(sch);\nnet/sched/sch_dualpi2.c-639-\n--\nnet/sched/sch_dualpi2.c-646-\nnet/sched/sch_dualpi2.c:647:\t\tdualpi2_dequeue_drop(sch);\nnet/sched/sch_dualpi2.c-648-\t}\n--\nnet/sched/sch_dualpi2.c=653=static s64 __scale_delta(u64 diff)\n--\nnet/sched/sch_dualpi2.c-658-\nnet/sched/sch_dualpi2.c:659:static void get_queue_delays(struct dualpi2_sched_data *q, u64 *qdelay_c,\nnet/sched/sch_dualpi2.c-660-\t\t\t     u64 *qdelay_l)\n--\nnet/sched/sch_dualpi2.c=672=static u32 calculate_probability(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-673-{\nnet/sched/sch_dualpi2.c:674:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-675-\tu32 new_prob;\n--\nnet/sched/sch_dualpi2.c=733=static u32 convert_ns_to_usec(u64 ns)\n--\nnet/sched/sch_dualpi2.c-741-\nnet/sched/sch_dualpi2.c:742:static enum hrtimer_restart dualpi2_timer(struct hrtimer *timer)\nnet/sched/sch_dualpi2.c-743-{\nnet/sched/sch_dualpi2.c:744:\tstruct dualpi2_sched_data *q = timer_container_of(q, timer, pi2_timer);\nnet/sched/sch_dualpi2.c-745-\tstruct Qdisc *sch = q-\u003esch;\n--\nnet/sched/sch_dualpi2.c-759-\nnet/sched/sch_dualpi2.c:760:static struct netlink_range_validation dualpi2_alpha_beta_range = {\nnet/sched/sch_dualpi2.c-761-\t.min = 1,\n--\nnet/sched/sch_dualpi2.c-764-\nnet/sched/sch_dualpi2.c:765:static const struct nla_policy dualpi2_policy[TCA_DUALPI2_MAX + 1] = {\nnet/sched/sch_dualpi2.c-766-\t[TCA_DUALPI2_LIMIT]\t\t= NLA_POLICY_MIN(NLA_U32, 1),\n--\nnet/sched/sch_dualpi2.c-770-\t[TCA_DUALPI2_ALPHA]\t\t=\nnet/sched/sch_dualpi2.c:771:\t\tNLA_POLICY_FULL_RANGE(NLA_U32, \u0026dualpi2_alpha_beta_range),\nnet/sched/sch_dualpi2.c-772-\t[TCA_DUALPI2_BETA]\t\t=\nnet/sched/sch_dualpi2.c:773:\t\tNLA_POLICY_FULL_RANGE(NLA_U32, \u0026dualpi2_alpha_beta_range),\nnet/sched/sch_dualpi2.c-774-\t[TCA_DUALPI2_STEP_THRESH_PKTS]\t= { .type = NLA_U32 },\n--\nnet/sched/sch_dualpi2.c-790-\nnet/sched/sch_dualpi2.c:791:static int dualpi2_change(struct Qdisc *sch, struct nlattr *opt,\nnet/sched/sch_dualpi2.c-792-\t\t\t  struct netlink_ext_ack *extack)\n--\nnet/sched/sch_dualpi2.c-794-\tstruct nlattr *tb[TCA_DUALPI2_MAX + 1];\nnet/sched/sch_dualpi2.c:795:\tstruct dualpi2_sched_data *q;\nnet/sched/sch_dualpi2.c-796-\tint old_backlog;\n--\nnet/sched/sch_dualpi2.c-803-\t}\nnet/sched/sch_dualpi2.c:804:\terr = nla_parse_nested(tb, TCA_DUALPI2_MAX, opt, dualpi2_policy,\nnet/sched/sch_dualpi2.c-805-\t\t\t       extack);\n--\nnet/sched/sch_dualpi2.c-841-\nnet/sched/sch_dualpi2.c:842:\t\tWRITE_ONCE(q-\u003epi2_alpha, dualpi2_scale_alpha_beta(alpha));\nnet/sched/sch_dualpi2.c-843-\t}\n--\nnet/sched/sch_dualpi2.c-847-\nnet/sched/sch_dualpi2.c:848:\t\tWRITE_ONCE(q-\u003epi2_beta, dualpi2_scale_alpha_beta(beta));\nnet/sched/sch_dualpi2.c-849-\t}\n--\nnet/sched/sch_dualpi2.c-887-\nnet/sched/sch_dualpi2.c:888:\t\tdualpi2_calculate_c_protection(sch, q, wc);\nnet/sched/sch_dualpi2.c-889-\t}\n--\nnet/sched/sch_dualpi2.c-944-/* Default alpha/beta values give a 10dB stability margin with max_rtt=100ms. */\nnet/sched/sch_dualpi2.c:945:static void dualpi2_reset_default(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-946-{\nnet/sched/sch_dualpi2.c:947:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-948-\n--\nnet/sched/sch_dualpi2.c-953-\tq-\u003epi2_tupdate = 16 * NSEC_PER_MSEC;\nnet/sched/sch_dualpi2.c:954:\tq-\u003epi2_alpha = dualpi2_scale_alpha_beta(41);\t/* ~0.16 Hz * 256 */\nnet/sched/sch_dualpi2.c:955:\tq-\u003epi2_beta = dualpi2_scale_alpha_beta(819);\t/* ~3.20 Hz * 256 */\nnet/sched/sch_dualpi2.c-956-\n--\nnet/sched/sch_dualpi2.c-959-\nnet/sched/sch_dualpi2.c:960:\tdualpi2_calculate_c_protection(q-\u003esch, q, 10);\t/* wc=10%, wl=90% */\nnet/sched/sch_dualpi2.c-961-\n--\nnet/sched/sch_dualpi2.c-969-\nnet/sched/sch_dualpi2.c:970:static int dualpi2_init(struct Qdisc *sch, struct nlattr *opt,\nnet/sched/sch_dualpi2.c-971-\t\t\tstruct netlink_ext_ack *extack)\nnet/sched/sch_dualpi2.c-972-{\nnet/sched/sch_dualpi2.c:973:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-974-\tint err;\n--\nnet/sched/sch_dualpi2.c-976-\tsch-\u003eflags |= TCQ_F_DEQUEUE_DROPS;\nnet/sched/sch_dualpi2.c:977:\thrtimer_setup(\u0026q-\u003epi2_timer, dualpi2_timer, CLOCK_MONOTONIC,\nnet/sched/sch_dualpi2.c-978-\t\t      HRTIMER_MODE_ABS_PINNED_SOFT);\n--\nnet/sched/sch_dualpi2.c-989-\tq-\u003esch = sch;\nnet/sched/sch_dualpi2.c:990:\tdualpi2_reset_default(sch);\nnet/sched/sch_dualpi2.c-991-\nnet/sched/sch_dualpi2.c-992-\tif (opt \u0026\u0026 nla_len(opt)) {\nnet/sched/sch_dualpi2.c:993:\t\terr = dualpi2_change(sch, opt, extack);\nnet/sched/sch_dualpi2.c-994-\n--\nnet/sched/sch_dualpi2.c-1003-\nnet/sched/sch_dualpi2.c:1004:static int dualpi2_dump(struct Qdisc *sch, struct sk_buff *skb)\nnet/sched/sch_dualpi2.c-1005-{\nnet/sched/sch_dualpi2.c:1006:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-1007-\tstruct nlattr *opts;\n--\nnet/sched/sch_dualpi2.c-1026-\t    nla_put_u32(skb, TCA_DUALPI2_ALPHA,\nnet/sched/sch_dualpi2.c:1027:\t\t\tdualpi2_unscale_alpha_beta(READ_ONCE(q-\u003epi2_alpha))) ||\nnet/sched/sch_dualpi2.c-1028-\t    nla_put_u32(skb, TCA_DUALPI2_BETA,\nnet/sched/sch_dualpi2.c:1029:\t\t\tdualpi2_unscale_alpha_beta(READ_ONCE(q-\u003epi2_beta))) ||\nnet/sched/sch_dualpi2.c-1030-\t    nla_put_u32(skb, TCA_DUALPI2_STEP_THRESH_PKTS, step_th) ||\n--\nnet/sched/sch_dualpi2.c-1053-\t    nla_put_u32(skb, TCA_DUALPI2_ALPHA,\nnet/sched/sch_dualpi2.c:1054:\t\t\tdualpi2_unscale_alpha_beta(READ_ONCE(q-\u003epi2_alpha))) ||\nnet/sched/sch_dualpi2.c-1055-\t    nla_put_u32(skb, TCA_DUALPI2_BETA,\nnet/sched/sch_dualpi2.c:1056:\t\t\tdualpi2_unscale_alpha_beta(READ_ONCE(q-\u003epi2_beta))) ||\nnet/sched/sch_dualpi2.c-1057-\t    nla_put_u32(skb, TCA_DUALPI2_STEP_THRESH_US,\n--\nnet/sched/sch_dualpi2.c-1079-\nnet/sched/sch_dualpi2.c:1080:static int dualpi2_dump_stats(struct Qdisc *sch, struct gnet_dump *d)\nnet/sched/sch_dualpi2.c-1081-{\nnet/sched/sch_dualpi2.c:1082:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c:1083:\tstruct tc_dualpi2_xstats st = {\nnet/sched/sch_dualpi2.c-1084-\t\t.prob\t\t\t= READ_ONCE(q-\u003epi2_prob),\n--\nnet/sched/sch_dualpi2.c-1106- */\nnet/sched/sch_dualpi2.c:1107:static void dualpi2_reset(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-1108-{\nnet/sched/sch_dualpi2.c:1109:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-1110-\n--\nnet/sched/sch_dualpi2.c-1122-\tWRITE_ONCE(q-\u003emax_memory_used, 0);\nnet/sched/sch_dualpi2.c:1123:\tdualpi2_reset_c_protection(q);\nnet/sched/sch_dualpi2.c-1124-}\nnet/sched/sch_dualpi2.c-1125-\nnet/sched/sch_dualpi2.c:1126:static void dualpi2_destroy(struct Qdisc *sch)\nnet/sched/sch_dualpi2.c-1127-{\nnet/sched/sch_dualpi2.c:1128:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-1129-\n--\nnet/sched/sch_dualpi2.c-1136-\nnet/sched/sch_dualpi2.c:1137:static struct Qdisc *dualpi2_leaf(struct Qdisc *sch, unsigned long arg)\nnet/sched/sch_dualpi2.c-1138-{\n--\nnet/sched/sch_dualpi2.c-1141-\nnet/sched/sch_dualpi2.c:1142:static unsigned long dualpi2_find(struct Qdisc *sch, u32 classid)\nnet/sched/sch_dualpi2.c-1143-{\n--\nnet/sched/sch_dualpi2.c-1146-\nnet/sched/sch_dualpi2.c:1147:static unsigned long dualpi2_bind(struct Qdisc *sch, unsigned long parent,\nnet/sched/sch_dualpi2.c-1148-\t\t\t\t  u32 classid)\n--\nnet/sched/sch_dualpi2.c-1152-\nnet/sched/sch_dualpi2.c:1153:static void dualpi2_unbind(struct Qdisc *q, unsigned long cl)\nnet/sched/sch_dualpi2.c-1154-{\n--\nnet/sched/sch_dualpi2.c-1156-\nnet/sched/sch_dualpi2.c:1157:static struct tcf_block *dualpi2_tcf_block(struct Qdisc *sch, unsigned long cl,\nnet/sched/sch_dualpi2.c-1158-\t\t\t\t\t   struct netlink_ext_ack *extack)\nnet/sched/sch_dualpi2.c-1159-{\nnet/sched/sch_dualpi2.c:1160:\tstruct dualpi2_sched_data *q = qdisc_priv(sch);\nnet/sched/sch_dualpi2.c-1161-\n--\nnet/sched/sch_dualpi2.c-1166-\nnet/sched/sch_dualpi2.c:1167:static void dualpi2_walk(struct Qdisc *sch, struct qdisc_walker *arg)\nnet/sched/sch_dualpi2.c-1168-{\n--\nnet/sched/sch_dualpi2.c-1188-/* Minimal class support to handle tc filters */\nnet/sched/sch_dualpi2.c:1189:static const struct Qdisc_class_ops dualpi2_class_ops = {\nnet/sched/sch_dualpi2.c:1190:\t.leaf\t\t= dualpi2_leaf,\nnet/sched/sch_dualpi2.c:1191:\t.find\t\t= dualpi2_find,\nnet/sched/sch_dualpi2.c:1192:\t.tcf_block\t= dualpi2_tcf_block,\nnet/sched/sch_dualpi2.c:1193:\t.bind_tcf\t= dualpi2_bind,\nnet/sched/sch_dualpi2.c:1194:\t.unbind_tcf\t= dualpi2_unbind,\nnet/sched/sch_dualpi2.c:1195:\t.walk\t\t= dualpi2_walk,\nnet/sched/sch_dualpi2.c-1196-};\nnet/sched/sch_dualpi2.c-1197-\nnet/sched/sch_dualpi2.c:1198:static struct Qdisc_ops dualpi2_qdisc_ops __read_mostly = {\nnet/sched/sch_dualpi2.c:1199:\t.id\t\t= \"dualpi2\",\nnet/sched/sch_dualpi2.c:1200:\t.cl_ops\t\t= \u0026dualpi2_class_ops,\nnet/sched/sch_dualpi2.c:1201:\t.priv_size\t= sizeof(struct dualpi2_sched_data),\nnet/sched/sch_dualpi2.c:1202:\t.enqueue\t= dualpi2_qdisc_enqueue,\nnet/sched/sch_dualpi2.c:1203:\t.dequeue\t= dualpi2_qdisc_dequeue,\nnet/sched/sch_dualpi2.c:1204:\t.peek\t\t= dualpi2_peek,\nnet/sched/sch_dualpi2.c:1205:\t.init\t\t= dualpi2_init,\nnet/sched/sch_dualpi2.c:1206:\t.destroy\t= dualpi2_destroy,\nnet/sched/sch_dualpi2.c:1207:\t.reset\t\t= dualpi2_reset,\nnet/sched/sch_dualpi2.c:1208:\t.change\t\t= dualpi2_change,\nnet/sched/sch_dualpi2.c:1209:\t.dump\t\t= dualpi2_dump,\nnet/sched/sch_dualpi2.c:1210:\t.dump_stats\t= dualpi2_dump_stats,\nnet/sched/sch_dualpi2.c-1211-\t.owner\t\t= THIS_MODULE,\nnet/sched/sch_dualpi2.c-1212-};\nnet/sched/sch_dualpi2.c:1213:MODULE_ALIAS_NET_SCH(\"dualpi2\");\nnet/sched/sch_dualpi2.c-1214-\nnet/sched/sch_dualpi2.c:1215:static int __init dualpi2_module_init(void)\nnet/sched/sch_dualpi2.c-1216-{\nnet/sched/sch_dualpi2.c:1217:\treturn register_qdisc(\u0026dualpi2_qdisc_ops);\nnet/sched/sch_dualpi2.c-1218-}\nnet/sched/sch_dualpi2.c-1219-\nnet/sched/sch_dualpi2.c:1220:static void __exit dualpi2_module_exit(void)\nnet/sched/sch_dualpi2.c-1221-{\nnet/sched/sch_dualpi2.c:1222:\tunregister_qdisc(\u0026dualpi2_qdisc_ops);\nnet/sched/sch_dualpi2.c-1223-}\nnet/sched/sch_dualpi2.c-1224-\nnet/sched/sch_dualpi2.c:1225:module_init(dualpi2_module_init);\nnet/sched/sch_dualpi2.c:1226:module_exit(dualpi2_module_exit);\nnet/sched/sch_dualpi2.c-1227-\nnet/sched/sch_dualpi2.c:1228:MODULE_DESCRIPTION(\"Dual Queue with Proportional Integral controller Improved with a Square (dualpi2) scheduler\");\nnet/sched/sch_dualpi2.c-1229-MODULE_AUTHOR(\"Koen De Schepper \u003ckoen.de_schepper@nokia-bell-labs.com\u003e\");\n"
}

5/2 2026/06/19 15:31 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15321
							output: 30
							thoughts: 189
						

Thoughts:
**Analyzing a Network Scheduler Change**

Okay, so I'm looking at this patch and the core of it seems to be a fix related to backlog accounting when GSO packets are enqueued in the `dualpi2` qdisc. The config option is `NET_SCH_DUALPI2`, and the function directly affected is `dualpi2_qdisc_enqueue`. That's a definite functional change in the network scheduler, and the path to this code is straightforward: `dualpi2_qdisc_enqueue` *is* the `.enqueue` callback for the `dualpi2` qdisc.

Given the potential for subtle issues in packet scheduling and accounting, this is *absolutely* something that warrants fuzzing to ensure robustness.

Now, I need to check for any dependencies. The test environment mentions the `qfq` qdisc as a parent. The associated config option there is `NET_SCH_QFQ`. Though the code changes are localized to `sch_dualpi2.c`, so `NET_SCH_DUALPI2` is the critical option. Let me just confirm that `NET_SCH_QFQ` isn't accidentally also required, even indirectly, to avoid missing any hidden configurations.



6/2 2026/06/19 15:31 tool grepper
0m Args:
{
  "Expression": "NET_SCH_QFQ",
  "PathPrefix": "net/sched/"
}

Results:
{
  "Output": "net/sched/Kconfig=244=config NET_SCH_CHOKE\n--\nnet/sched/Kconfig-254-\nnet/sched/Kconfig:255:config NET_SCH_QFQ\nnet/sched/Kconfig-256-\ttristate \"Quick Fair Queueing scheduler (QFQ)\"\n--\nnet/sched/Makefile=53=obj-$(CONFIG_NET_SCH_CHOKE)\t+= sch_choke.o\nnet/sched/Makefile:54:obj-$(CONFIG_NET_SCH_QFQ)\t+= sch_qfq.o\nnet/sched/Makefile-55-obj-$(CONFIG_NET_SCH_CODEL)\t+= sch_codel.o\n"
}

7/2 2026/06/19 15:31 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15980
							output: 144
							thoughts: 859
						

Thoughts:
**My Analysis of the DualPI2 Scheduler Bug Fix**

Okay, here's what I've got. I need to focus on this patch related to the `dualpi2` scheduler. My initial thought is to include `NET_SCH_DUALPI2` and `NET_SCH_QFQ` in `EnableConfigs`, as the test case uses them, but let's be precise. The main function being modified is `dualpi2_qdisc_enqueue`. I've verified that this is the *only* function directly touched by the patch.

Now, a closer look at `dualpi2_qdisc_enqueue`, specifically in `net/sched/sch_dualpi2.c`, reveals it calls several other functions: `dualpi2_skb_classify`, `skb_gso_segment`, `qdisc_tree_reduce_backlog`, `consume_skb`, and `dualpi2_enqueue_skb`. The key change centers around the arguments passed to `qdisc_tree_reduce_backlog`.

This is a very specific fix within the `dualpi2_qdisc_enqueue` function, dealing with GSO packet enqueueing. This means this is worth fuzzing, and I should set `WorthFuzzing=true`. I can also define `FocusSymbols` to `["dualpi2_qdisc_enqueue"]`.

Initially, I had thought to include `NET_SCH_QFQ`, as the test uses it. But the bug is in `dualpi2_qdisc_enqueue` and `qdisc_tree_reduce_backlog`, which is called when a qdisc is a child of another qdisc (classful qdisc). `dualpi2` itself is a classless qdisc, but it can be attached to a classful qdisc like `qfq`, `htb`, `hfsc`, etc. Any classful qdisc would trigger `qdisc_tree_reduce_backlog` correctly if it has a parent. So `NET_SCH_DUALPI2` is the main one. I can also add `NET_SCH_QFQ` since the test uses it, but I'll stick with only `NET_SCH_DUALPI2` to be as focused as possible.

Quick check confirms `dualpi2` depends on `NET_SCHED`, but that should be implicitly handled. I'm going to set `EnableConfigs` to just `["NET_SCH_DUALPI2"]`.

In summary, the patch fixes a bug in the backlog accounting for the `dualpi2` network scheduler when it deals with GSO packets. It specifically modifies `dualpi2_qdisc_enqueue` and the parameters passed to `qdisc_tree_reduce_backlog`. This is a functional change in the core network scheduling logic, so I need to fuzz it to make sure the accounting is correct and that it doesn't cause underflows or other related issues. It's a precise fix, worth paying close attention to. I'm ready to set-results.



8/2 2026/06/19 15:31 tool set-results
0m Args:
{
  "EnableConfigs": [
    "NET_SCH_DUALPI2"
  ],
  "FocusSymbols": [
    "dualpi2_qdisc_enqueue"
  ],
  "Reasoning": "The patch fixes a bug in the backlog accounting of the `dualpi2` network scheduler when handling GSO packets. It modifies the `dualpi2_qdisc_enqueue` function to correctly calculate and reduce the backlog using `qdisc_tree_reduce_backlog`. This is a functional change in reachable core network scheduling logic, and should be fuzzed to ensure the accounting is correct and doesn't lead to underflows or other issues.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "NET_SCH_DUALPI2"
  ],
  "FocusSymbols": [
    "dualpi2_qdisc_enqueue"
  ],
  "Reasoning": "The patch fixes a bug in the backlog accounting of the `dualpi2` network scheduler when handling GSO packets. It modifies the `dualpi2_qdisc_enqueue` function to correctly calculate and reduce the backlog using `qdisc_tree_reduce_backlog`. This is a functional change in reachable core network scheduling logic, and should be fuzzed to ensure the accounting is correct and doesn't lead to underflows or other issues.",
  "WorthFuzzing": true
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)