Skip to content

Commit

Permalink
cls_bpf: reset class and reuse major in da
Browse files Browse the repository at this point in the history
commit 3a461da 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: 045efa8 ("cls_bpf: introduce integrated actions")
Signed-off-by: Daniel Borkmann <[email protected]>
Acked-by: Alexei Starovoitov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
borkmann authored and gregkh committed May 10, 2020
1 parent 7ac8826 commit 832b5b7
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions net/sched/cls_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down

0 comments on commit 832b5b7

Please sign in to comment.