Commit 0d01d45f authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

net: cls_bpf: limit hardware offload by software-only flag

Add cls_bpf support for the TCA_CLS_FLAGS_SKIP_HW flag.
Unlike U32 and flower cls_bpf already has some netlink
flags defined.  Create a new attribute to be able to use
the same flag values as the above.

Unlike U32 and flower reject unknown flags.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 332ae8e2
...@@ -498,6 +498,7 @@ struct tc_cls_bpf_offload { ...@@ -498,6 +498,7 @@ struct tc_cls_bpf_offload {
struct bpf_prog *prog; struct bpf_prog *prog;
const char *name; const char *name;
bool exts_integrated; bool exts_integrated;
u32 gen_flags;
}; };
#endif #endif
...@@ -396,6 +396,7 @@ enum { ...@@ -396,6 +396,7 @@ enum {
TCA_BPF_FD, TCA_BPF_FD,
TCA_BPF_NAME, TCA_BPF_NAME,
TCA_BPF_FLAGS, TCA_BPF_FLAGS,
TCA_BPF_FLAGS_GEN,
__TCA_BPF_MAX, __TCA_BPF_MAX,
}; };
......
...@@ -27,6 +27,8 @@ MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>"); ...@@ -27,6 +27,8 @@ MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
MODULE_DESCRIPTION("TC BPF based classifier"); MODULE_DESCRIPTION("TC BPF based classifier");
#define CLS_BPF_NAME_LEN 256 #define CLS_BPF_NAME_LEN 256
#define CLS_BPF_SUPPORTED_GEN_FLAGS \
TCA_CLS_FLAGS_SKIP_HW
struct cls_bpf_head { struct cls_bpf_head {
struct list_head plist; struct list_head plist;
...@@ -40,6 +42,7 @@ struct cls_bpf_prog { ...@@ -40,6 +42,7 @@ struct cls_bpf_prog {
struct tcf_result res; struct tcf_result res;
bool exts_integrated; bool exts_integrated;
bool offloaded; bool offloaded;
u32 gen_flags;
struct tcf_exts exts; struct tcf_exts exts;
u32 handle; u32 handle;
union { union {
...@@ -55,6 +58,7 @@ struct cls_bpf_prog { ...@@ -55,6 +58,7 @@ struct cls_bpf_prog {
static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = { static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = {
[TCA_BPF_CLASSID] = { .type = NLA_U32 }, [TCA_BPF_CLASSID] = { .type = NLA_U32 },
[TCA_BPF_FLAGS] = { .type = NLA_U32 }, [TCA_BPF_FLAGS] = { .type = NLA_U32 },
[TCA_BPF_FLAGS_GEN] = { .type = NLA_U32 },
[TCA_BPF_FD] = { .type = NLA_U32 }, [TCA_BPF_FD] = { .type = NLA_U32 },
[TCA_BPF_NAME] = { .type = NLA_NUL_STRING, [TCA_BPF_NAME] = { .type = NLA_NUL_STRING,
.len = CLS_BPF_NAME_LEN }, .len = CLS_BPF_NAME_LEN },
...@@ -154,6 +158,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, ...@@ -154,6 +158,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
bpf_offload.prog = prog->filter; bpf_offload.prog = prog->filter;
bpf_offload.name = prog->bpf_name; bpf_offload.name = prog->bpf_name;
bpf_offload.exts_integrated = prog->exts_integrated; bpf_offload.exts_integrated = prog->exts_integrated;
bpf_offload.gen_flags = prog->gen_flags;
return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
tp->protocol, &offload); tp->protocol, &offload);
...@@ -167,14 +172,14 @@ static void cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, ...@@ -167,14 +172,14 @@ static void cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
enum tc_clsbpf_command cmd; enum tc_clsbpf_command cmd;
if (oldprog && oldprog->offloaded) { if (oldprog && oldprog->offloaded) {
if (tc_should_offload(dev, tp, 0)) { if (tc_should_offload(dev, tp, prog->gen_flags)) {
cmd = TC_CLSBPF_REPLACE; cmd = TC_CLSBPF_REPLACE;
} else { } else {
obj = oldprog; obj = oldprog;
cmd = TC_CLSBPF_DESTROY; cmd = TC_CLSBPF_DESTROY;
} }
} else { } else {
if (!tc_should_offload(dev, tp, 0)) if (!tc_should_offload(dev, tp, prog->gen_flags))
return; return;
cmd = TC_CLSBPF_ADD; cmd = TC_CLSBPF_ADD;
} }
...@@ -370,6 +375,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, ...@@ -370,6 +375,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
{ {
bool is_bpf, is_ebpf, have_exts = false; bool is_bpf, is_ebpf, have_exts = false;
struct tcf_exts exts; struct tcf_exts exts;
u32 gen_flags = 0;
int ret; int ret;
is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS]; is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
...@@ -394,8 +400,17 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, ...@@ -394,8 +400,17 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT; have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
} }
if (tb[TCA_BPF_FLAGS_GEN]) {
gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
!tc_flags_valid(gen_flags)) {
ret = -EINVAL;
goto errout;
}
}
prog->exts_integrated = have_exts; prog->exts_integrated = have_exts;
prog->gen_flags = gen_flags;
ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) : ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
cls_bpf_prog_from_efd(tb, prog, tp); cls_bpf_prog_from_efd(tb, prog, tp);
...@@ -568,6 +583,9 @@ static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, ...@@ -568,6 +583,9 @@ static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
bpf_flags |= TCA_BPF_FLAG_ACT_DIRECT; bpf_flags |= TCA_BPF_FLAG_ACT_DIRECT;
if (bpf_flags && nla_put_u32(skb, TCA_BPF_FLAGS, bpf_flags)) if (bpf_flags && nla_put_u32(skb, TCA_BPF_FLAGS, bpf_flags))
goto nla_put_failure; goto nla_put_failure;
if (prog->gen_flags &&
nla_put_u32(skb, TCA_BPF_FLAGS_GEN, prog->gen_flags))
goto nla_put_failure;
nla_nest_end(skb, nest); nla_nest_end(skb, nest);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment