Skip to content

Commit

Permalink
cls_bpf: fix offload assumptions after callback conversion
Browse files Browse the repository at this point in the history
cls_bpf used to take care of tracking what offload state a filter
is in, i.e. it would track if offload request succeeded or not.
This information would then be used to issue correct requests to
the driver, e.g. requests for statistics only on offloaded filters,
removing only filters which were offloaded, using add instead of
replace if previous filter was not added etc.

This tracking of offload state no longer functions with the new
callback infrastructure.  There could be multiple entities trying
to offload the same filter.

Throw out all the tracking and corresponding commands and simply
pass to the drivers both old and new bpf program.  Drivers will
have to deal with offload state tracking by themselves.

Fixes: 3f7889c ("net: sched: cls_bpf: call block callbacks for offload")
Signed-off-by: Jakub Kicinski <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Jakub Kicinski authored and davem330 committed Dec 20, 2017
1 parent 21b5944 commit 102740b
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 67 deletions.
12 changes: 3 additions & 9 deletions drivers/net/ethernet/netronome/nfp/bpf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,10 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
return -EOPNOTSUPP;
}

switch (cls_bpf->command) {
case TC_CLSBPF_REPLACE:
return nfp_net_bpf_offload(nn, cls_bpf->prog, true);
case TC_CLSBPF_ADD:
return nfp_net_bpf_offload(nn, cls_bpf->prog, false);
case TC_CLSBPF_DESTROY:
return nfp_net_bpf_offload(nn, NULL, true);
default:
if (cls_bpf->command != TC_CLSBPF_OFFLOAD)
return -EOPNOTSUPP;
}

return nfp_net_bpf_offload(nn, cls_bpf->prog, cls_bpf->oldprog);
}

static int nfp_bpf_setup_tc_block(struct net_device *netdev,
Expand Down
5 changes: 2 additions & 3 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,9 +694,7 @@ struct tc_cls_matchall_offload {
};

enum tc_clsbpf_command {
TC_CLSBPF_ADD,
TC_CLSBPF_REPLACE,
TC_CLSBPF_DESTROY,
TC_CLSBPF_OFFLOAD,
TC_CLSBPF_STATS,
};

Expand All @@ -705,6 +703,7 @@ struct tc_cls_bpf_offload {
enum tc_clsbpf_command command;
struct tcf_exts *exts;
struct bpf_prog *prog;
struct bpf_prog *oldprog;
const char *name;
bool exts_integrated;
u32 gen_flags;
Expand Down
93 changes: 38 additions & 55 deletions net/sched/cls_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ struct cls_bpf_prog {
struct list_head link;
struct tcf_result res;
bool exts_integrated;
bool offloaded;
u32 gen_flags;
struct tcf_exts exts;
u32 handle;
Expand Down Expand Up @@ -148,33 +147,37 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
}

static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
enum tc_clsbpf_command cmd)
struct cls_bpf_prog *oldprog)
{
bool addorrep = cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE;
struct tcf_block *block = tp->chain->block;
bool skip_sw = tc_skip_sw(prog->gen_flags);
struct tc_cls_bpf_offload cls_bpf = {};
struct cls_bpf_prog *obj;
bool skip_sw;
int err;

skip_sw = prog && tc_skip_sw(prog->gen_flags);
obj = prog ?: oldprog;

tc_cls_common_offload_init(&cls_bpf.common, tp);
cls_bpf.command = cmd;
cls_bpf.exts = &prog->exts;
cls_bpf.prog = prog->filter;
cls_bpf.name = prog->bpf_name;
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_flags;
cls_bpf.command = TC_CLSBPF_OFFLOAD;
cls_bpf.exts = &obj->exts;
cls_bpf.prog = prog ? prog->filter : NULL;
cls_bpf.oldprog = oldprog ? oldprog->filter : NULL;
cls_bpf.name = obj->bpf_name;
cls_bpf.exts_integrated = obj->exts_integrated;
cls_bpf.gen_flags = obj->gen_flags;

err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw);
if (addorrep) {
if (prog) {
if (err < 0) {
cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_DESTROY);
cls_bpf_offload_cmd(tp, oldprog, prog);
return err;
} else if (err > 0) {
prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
}
}

if (addorrep && skip_sw && !(prog->gen_flags & TCA_CLS_FLAGS_IN_HW))
if (prog && skip_sw && !(prog->gen_flags & TCA_CLS_FLAGS_IN_HW))
return -EINVAL;

return 0;
Expand All @@ -183,64 +186,44 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
struct cls_bpf_prog *oldprog)
{
struct cls_bpf_prog *obj = prog;
enum tc_clsbpf_command cmd;
bool skip_sw;
int ret;

skip_sw = tc_skip_sw(prog->gen_flags) ||
(oldprog && tc_skip_sw(oldprog->gen_flags));

if (oldprog && oldprog->offloaded) {
if (!tc_skip_hw(prog->gen_flags)) {
cmd = TC_CLSBPF_REPLACE;
} else if (!tc_skip_sw(prog->gen_flags)) {
obj = oldprog;
cmd = TC_CLSBPF_DESTROY;
} else {
return -EINVAL;
}
} else {
if (tc_skip_hw(prog->gen_flags))
return skip_sw ? -EINVAL : 0;
cmd = TC_CLSBPF_ADD;
}

ret = cls_bpf_offload_cmd(tp, obj, cmd);
if (ret)
return ret;
if (prog && oldprog && prog->gen_flags != oldprog->gen_flags)
return -EINVAL;

obj->offloaded = true;
if (oldprog)
oldprog->offloaded = false;
if (prog && tc_skip_hw(prog->gen_flags))
prog = NULL;
if (oldprog && tc_skip_hw(oldprog->gen_flags))
oldprog = NULL;
if (!prog && !oldprog)
return 0;

return 0;
return cls_bpf_offload_cmd(tp, prog, oldprog);
}

static void cls_bpf_stop_offload(struct tcf_proto *tp,
struct cls_bpf_prog *prog)
{
int err;

if (!prog->offloaded)
return;

err = cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_DESTROY);
if (err) {
err = cls_bpf_offload_cmd(tp, NULL, prog);
if (err)
pr_err("Stopping hardware offload failed: %d\n", err);
return;
}

prog->offloaded = false;
}

static void cls_bpf_offload_update_stats(struct tcf_proto *tp,
struct cls_bpf_prog *prog)
{
if (!prog->offloaded)
return;
struct tcf_block *block = tp->chain->block;
struct tc_cls_bpf_offload cls_bpf = {};

tc_cls_common_offload_init(&cls_bpf.common, tp);
cls_bpf.command = TC_CLSBPF_STATS;
cls_bpf.exts = &prog->exts;
cls_bpf.prog = prog->filter;
cls_bpf.name = prog->bpf_name;
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_flags;

cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_STATS);
tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, false);
}

static int cls_bpf_init(struct tcf_proto *tp)
Expand Down

0 comments on commit 102740b

Please sign in to comment.