Merge branch 'tc-qevent-block' into next
Petr Machata says:
====================
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:
# ip link add up type dummy
# tc qdisc add dev dummy1 root handle 1: \
red min 30000 max 60000 avpkt 1000 qevent early_drop block 100
# tc filter add block 100 pref 1234 handle 102 matchall action drop
# tc filter show block 100
Cannot find block "100"
This patchset fixes this issue:
# tc filter show block 100
filter protocol all pref 1234 matchall chain 0
filter protocol all pref 1234 matchall chain 0 handle 0x66
not_in_hw
action order 1: gact action drop
random type none pass val 0
index 2 ref 1 bind 1
In patch #1, the helpers and necessary infrastructure is introduced,
including a new qdisc_util callback that implements sniffing out bound
blocks in a given qdisc.
In patch #2, RED implements the new callback.
v3:
- Patch #1:
- Do not pass &ctx->found directly to has_block. Do it through a
helper variable, so that the callee does not overwrite the result
already stored in ctx->found.
v2:
- Patch #1:
- In tc_qdisc_block_exists_cb(), do not initialize 'q'.
- Propagate upwards errors from q->has_block.
====================
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
commit
7b6361bf61
17
tc/q_red.c
17
tc/q_red.c
|
|
@ -264,10 +264,27 @@ static int red_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int red_has_block(struct qdisc_util *qu, struct rtattr *opt, __u32 block_idx, bool *p_has)
|
||||
{
|
||||
struct rtattr *tb[TCA_RED_MAX + 1];
|
||||
|
||||
if (opt == NULL)
|
||||
return 0;
|
||||
|
||||
parse_rtattr_nested(tb, TCA_RED_MAX, opt);
|
||||
|
||||
qevents_init(qevents);
|
||||
if (qevents_read(qevents, tb))
|
||||
return -1;
|
||||
|
||||
*p_has = qevents_have_block(qevents, block_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct qdisc_util red_qdisc_util = {
|
||||
.id = "red",
|
||||
.parse_qopt = red_parse_opt,
|
||||
.print_qopt = red_print_opt,
|
||||
.print_xstats = red_print_xstats,
|
||||
.has_block = red_has_block,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue