diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2016-03-15 22:41:22 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-10 10:26:18 +0200 |
commit | 832b5b7237f95564b3eb463cf47a79951b412a40 (patch) | |
tree | 71ccc8920b2d67dab57521cdd5556defa71caf44 /net/sched | |
parent | 7ac882670f8fa981943ac499c5d43a3378b0eb8b (diff) |
cls_bpf: reset class and reuse major in da
commit 3a461da1d03e7a857edfa6a002040d07e118c639 upstream.
There are two issues with the current code. First one is that we need
to set res->class to 0 in case we use non-default classid matching.
This is important for the case where cls_bpf was initially set up with
an optional binding to a default class with tcf_bind_filter(), where
the underlying qdisc implements bind_tcf() that fills res->class and
tests for it later on when doing the classification. Convention for
these cases is that after tc_classify() was called, such qdiscs (atm,
drr, qfq, cbq, hfsc, htb) first test class, and if 0, then they lookup
based on classid.
Second, there's a bug with da mode, where res->classid is only assigned
a 16 bit minor, but it needs to expand to the full 32 bit major/minor
combination instead, therefore we need to expand with the bound major.
This is fine as classes belonging to a classful qdisc must share the
same major.
Fixes: 045efa82ff56 ("cls_bpf: introduce integrated actions")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_bpf.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 3eef0215e53f..cdfb8d33bcba 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -107,8 +107,9 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, } if (prog->exts_integrated) { - res->class = prog->res.class; - res->classid = qdisc_skb_cb(skb)->tc_classid; + res->class = 0; + res->classid = TC_H_MAJ(prog->res.classid) | + qdisc_skb_cb(skb)->tc_classid; ret = cls_bpf_exec_opcode(filter_res); if (ret == TC_ACT_UNSPEC) @@ -118,10 +119,12 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, if (filter_res == 0) continue; - - *res = prog->res; - if (filter_res != -1) + if (filter_res != -1) { + res->class = 0; res->classid = filter_res; + } else { + *res = prog->res; + } ret = tcf_exts_exec(skb, &prog->exts, res); if (ret < 0) |