Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libbpf: Support creating and destroying qdisc

Extend struct bpf_tc_hook with handle, qdisc name and a new attach type,
BPF_TC_QDISC, to allow users to add or remove any qdisc specified in
addition to clsact.

Signed-off-by: Amery Hung <amery.hung@bytedance.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://patch.msgid.link/20250409214606.2000194-8-ameryhung@gmail.com

authored by

Amery Hung and committed by
Martin KaFai Lau
4b15121d e582778f

+21 -4
+4 -1
tools/lib/bpf/libbpf.h
··· 1283 1283 BPF_TC_INGRESS = 1 << 0, 1284 1284 BPF_TC_EGRESS = 1 << 1, 1285 1285 BPF_TC_CUSTOM = 1 << 2, 1286 + BPF_TC_QDISC = 1 << 3, 1286 1287 }; 1287 1288 1288 1289 #define BPF_TC_PARENT(a, b) \ ··· 1298 1297 int ifindex; 1299 1298 enum bpf_tc_attach_point attach_point; 1300 1299 __u32 parent; 1300 + __u32 handle; 1301 + const char *qdisc; 1301 1302 size_t :0; 1302 1303 }; 1303 - #define bpf_tc_hook__last_field parent 1304 + #define bpf_tc_hook__last_field qdisc 1304 1305 1305 1306 struct bpf_tc_opts { 1306 1307 size_t sz;
+17 -3
tools/lib/bpf/netlink.c
··· 529 529 } 530 530 531 531 532 - typedef int (*qdisc_config_t)(struct libbpf_nla_req *req); 532 + typedef int (*qdisc_config_t)(struct libbpf_nla_req *req, const struct bpf_tc_hook *hook); 533 533 534 - static int clsact_config(struct libbpf_nla_req *req) 534 + static int clsact_config(struct libbpf_nla_req *req, const struct bpf_tc_hook *hook) 535 535 { 536 536 req->tc.tcm_parent = TC_H_CLSACT; 537 537 req->tc.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0); 538 538 539 539 return nlattr_add(req, TCA_KIND, "clsact", sizeof("clsact")); 540 + } 541 + 542 + static int qdisc_config(struct libbpf_nla_req *req, const struct bpf_tc_hook *hook) 543 + { 544 + const char *qdisc = OPTS_GET(hook, qdisc, NULL); 545 + 546 + req->tc.tcm_parent = OPTS_GET(hook, parent, TC_H_ROOT); 547 + req->tc.tcm_handle = OPTS_GET(hook, handle, 0); 548 + 549 + return nlattr_add(req, TCA_KIND, qdisc, strlen(qdisc) + 1); 540 550 } 541 551 542 552 static int attach_point_to_config(struct bpf_tc_hook *hook, ··· 562 552 return 0; 563 553 case BPF_TC_CUSTOM: 564 554 return -EOPNOTSUPP; 555 + case BPF_TC_QDISC: 556 + *config = &qdisc_config; 557 + return 0; 565 558 default: 566 559 return -EINVAL; 567 560 } ··· 609 596 req.tc.tcm_family = AF_UNSPEC; 610 597 req.tc.tcm_ifindex = OPTS_GET(hook, ifindex, 0); 611 598 612 - ret = config(&req); 599 + ret = config(&req, hook); 613 600 if (ret < 0) 614 601 return ret; 615 602 ··· 652 639 case BPF_TC_INGRESS: 653 640 case BPF_TC_EGRESS: 654 641 return libbpf_err(__bpf_tc_detach(hook, NULL, true)); 642 + case BPF_TC_QDISC: 655 643 case BPF_TC_INGRESS | BPF_TC_EGRESS: 656 644 return libbpf_err(tc_qdisc_delete(hook)); 657 645 case BPF_TC_CUSTOM: