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: Jakub Kicinski <jakub.kicinski@netronome.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
332ae8e2f6
commit
0d01d45f1b
|
@ -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 {
|
||||||
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>");
|
||||||
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 {
|
||||||
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 {
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue