]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
tc: Look for blocks in qevents
authorPetr Machata <petrm@mellanox.com>
Thu, 16 Jul 2020 16:47:07 +0000 (19:47 +0300)
committerDavid Ahern <dsahern@kernel.org>
Mon, 20 Jul 2020 16:34:02 +0000 (16:34 +0000)
When a list of filters at a given block is requested, tc first validates
that the block exists before doing the filter query. Currently the
validation routine checks ingress and egress blocks. But now that blocks
can be bound to qevents as well, qevent blocks should be looked for as
well.

In order to support that, extend struct qdisc_util with a new callback,
has_block. That should report whether, give the attributes in TCA_OPTIONS,
a blocks with a given number is bound to a qevent. In
tc_qdisc_block_exists_cb(), invoke that callback when set.

Add a helper to the tc_qevent module that walks the list of qevents and
looks for a given block. This is meant to be used by the individual qdiscs.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
tc/tc_qdisc.c
tc/tc_qevent.c
tc/tc_qevent.h
tc/tc_util.h

index 8eb08c342113d96d8f08b2a1aa1735ff104eb548..b79029d96202b2a4897ce4a11eae83ecdef516a2 100644 (file)
@@ -478,6 +478,9 @@ static int tc_qdisc_block_exists_cb(struct nlmsghdr *n, void *arg)
        struct tcmsg *t = NLMSG_DATA(n);
        struct rtattr *tb[TCA_MAX+1];
        int len = n->nlmsg_len;
+       struct qdisc_util *q;
+       const char *kind;
+       int err;
 
        if (n->nlmsg_type != RTM_NEWQDISC)
                return 0;
@@ -506,6 +509,21 @@ static int tc_qdisc_block_exists_cb(struct nlmsghdr *n, void *arg)
                if (block == ctx->block_index)
                        ctx->found = true;
        }
+
+       kind = rta_getattr_str(tb[TCA_KIND]);
+       q = get_qdisc_kind(kind);
+       if (!q)
+               return -1;
+       if (q->has_block) {
+               bool found = false;
+
+               err = q->has_block(q, tb[TCA_OPTIONS], ctx->block_index, &found);
+               if (err)
+                       return err;
+               if (found)
+                       ctx->found = true;
+       }
+
        return 0;
 }
 
index 1f8e6506e3a3a1767fa9f3355e597281a416606c..2c010fcf752f0545ab6dca7e2e178f981d1e106e 100644 (file)
@@ -92,6 +92,21 @@ void qevents_print(struct qevent_util *qevents, FILE *f)
                close_json_array(PRINT_ANY, "");
 }
 
+bool qevents_have_block(struct qevent_util *qevents, __u32 block_idx)
+{
+       if (!qevents)
+               return false;
+
+       for (; qevents->id; qevents++) {
+               struct qevent_base *qeb = qevents->data;
+
+               if (qeb->block_idx == block_idx)
+                       return true;
+       }
+
+       return false;
+}
+
 int qevents_dump(struct qevent_util *qevents, struct nlmsghdr *n)
 {
        int err;
index 574e7cff5907114abc60d0f5bab1311df0c483eb..d60c3f75b987c646cc58e6e9e2822cd987eb438d 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _TC_QEVENT_H_
 #define _TC_QEVENT_H_
 
+#include <stdbool.h>
 #include <linux/types.h>
 #include <libnetlink.h>
 
@@ -37,6 +38,7 @@ int qevent_parse(struct qevent_util *qevents, int *p_argc, char ***p_argv);
 int qevents_read(struct qevent_util *qevents, struct rtattr **tb);
 int qevents_dump(struct qevent_util *qevents, struct nlmsghdr *n);
 void qevents_print(struct qevent_util *qevents, FILE *f);
+bool qevents_have_block(struct qevent_util *qevents, __u32 block_idx);
 
 struct qevent_plain {
        struct qevent_base base;
index edc3913889b9a9326ee67ed53b5ba6de881a58f6..c8af4e952109c27b9a69f3ac9fd7ded82e40da4f 100644 (file)
@@ -5,6 +5,7 @@
 #define MAX_MSG 16384
 #include <limits.h>
 #include <linux/if.h>
+#include <stdbool.h>
 
 #include <linux/pkt_sched.h>
 #include <linux/pkt_cls.h>
@@ -40,6 +41,7 @@ struct qdisc_util {
        int (*parse_copt)(struct qdisc_util *qu, int argc,
                          char **argv, struct nlmsghdr *n, const char *dev);
        int (*print_copt)(struct qdisc_util *qu, FILE *f, struct rtattr *opt);
+       int (*has_block)(struct qdisc_util *qu, struct rtattr *opt, __u32 block_idx, bool *p_has);
 };
 
 extern __u16 f_proto;