Blob Blame History Raw
From 2e2ac620670997b59d65a73b0af3e77431be3c18 Mon Sep 17 00:00:00 2001
From: Andrea Claudi <aclaudi@redhat.com>
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 <jiri@mellanox.com>
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 <jiri@mellanox.com>
    Signed-off-by: David Ahern <dsahern@gmail.com>
---
 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.21.0