From 2e2ac620670997b59d65a73b0af3e77431be3c18 Mon Sep 17 00:00:00 2001 From: Andrea Claudi Date: Tue, 18 Jun 2019 20:01:45 +0200 Subject: [PATCH] tc: introduce tc_qdisc_block_exists helper Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1721291 Upstream Status: iproute2.git commit d0bcedd549566 Conflicts: context change due to missing commit 6f7df6b2a1fef ("tc: Optimize gact action lookup") commit d0bcedd549566a87354aa804df3be6be80681ee9 Author: Jiri Pirko Date: Sat Jan 20 11:00:27 2018 +0100 tc: introduce tc_qdisc_block_exists helper This hepler used qdisc dump to list all qdisc and find if block index in question is used by any of them. That means the block with specified index exists. Signed-off-by: Jiri Pirko Signed-off-by: David Ahern --- tc/tc_qdisc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ tc/tc_util.h | 2 ++ 2 files changed, 63 insertions(+) diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c index 8b0c5c72dbad1..f8e06ccf205a0 100644 --- a/tc/tc_qdisc.c +++ b/tc/tc_qdisc.c @@ -366,3 +366,64 @@ int do_qdisc(int argc, char **argv) fprintf(stderr, "Command \"%s\" is unknown, try \"tc qdisc help\".\n", *argv); return -1; } + +struct tc_qdisc_block_exists_ctx { + __u32 block_index; + bool found; +}; + +static int tc_qdisc_block_exists_cb(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg) +{ + struct tc_qdisc_block_exists_ctx *ctx = arg; + struct tcmsg *t = NLMSG_DATA(n); + struct rtattr *tb[TCA_MAX+1]; + int len = n->nlmsg_len; + + if (n->nlmsg_type != RTM_NEWQDISC) + return 0; + + len -= NLMSG_LENGTH(sizeof(*t)); + if (len < 0) + return -1; + + parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len); + + if (tb[TCA_KIND] == NULL) + return -1; + + if (tb[TCA_INGRESS_BLOCK] && + RTA_PAYLOAD(tb[TCA_INGRESS_BLOCK]) >= sizeof(__u32)) { + __u32 block = rta_getattr_u32(tb[TCA_INGRESS_BLOCK]); + + if (block == ctx->block_index) + ctx->found = true; + } + + if (tb[TCA_EGRESS_BLOCK] && + RTA_PAYLOAD(tb[TCA_EGRESS_BLOCK]) >= sizeof(__u32)) { + __u32 block = rta_getattr_u32(tb[TCA_EGRESS_BLOCK]); + + if (block == ctx->block_index) + ctx->found = true; + } + return 0; +} + +bool tc_qdisc_block_exists(__u32 block_index) +{ + struct tc_qdisc_block_exists_ctx ctx = { .block_index = block_index }; + struct tcmsg t = { .tcm_family = AF_UNSPEC }; + + if (rtnl_dump_request(&rth, RTM_GETQDISC, &t, sizeof(t)) < 0) { + perror("Cannot send dump request"); + return false; + } + + if (rtnl_dump_filter(&rth, tc_qdisc_block_exists_cb, &ctx) < 0) { + perror("Dump terminated\n"); + return false; + } + + return ctx.found; +} diff --git a/tc/tc_util.h b/tc/tc_util.h index 5c54ad384eae6..8344c11833ee8 100644 --- a/tc/tc_util.h +++ b/tc/tc_util.h @@ -122,4 +122,6 @@ int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt); int cls_names_init(char *path); void cls_names_uninit(void); +bool tc_qdisc_block_exists(__u32 block_index); + #endif -- 2.20.1