From d0bcedd549566a87354aa804df3be6be80681ee9 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 20 Jan 2018 11:00:27 +0100 Subject: [PATCH] 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 70279b9d..54701c26 100644 --- a/tc/tc_qdisc.c +++ b/tc/tc_qdisc.c @@ -412,3 +412,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 e354765f..cd2ff596 100644 --- a/tc/tc_util.h +++ b/tc/tc_util.h @@ -134,4 +134,6 @@ void cls_names_uninit(void); int action_a2n(char *arg, int *result, bool allow_num); +bool tc_qdisc_block_exists(__u32 block_index); + #endif