Skip to content

Commit

Permalink
nfp: bpf: add offload of TC direct action mode
Browse files Browse the repository at this point in the history
Add offload of TC in direct action mode.  We just need
to provide appropriate checks in the verifier and
a new outro block to translate the exit codes to what
data path expects

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jakub Kicinski authored and David S. Miller committed Sep 21, 2016
1 parent 2d18421 commit e3b8baf
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ enum static_regs {
enum nfp_bpf_action_type {
NN_ACT_TC_DROP,
NN_ACT_TC_REDIR,
NN_ACT_DIRECT,
};

/* Software register representation, hardware encoding in asm.h */
Expand Down
66 changes: 66 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,16 @@ __emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, enum br_ev_pip ev_pip,
nfp_prog_push(nfp_prog, insn);
}

static void emit_br_def(struct nfp_prog *nfp_prog, u16 addr, u8 defer)
{
if (defer > 2) {
pr_err("BUG: branch defer out of bounds %d\n", defer);
nfp_prog->error = -EFAULT;
return;
}
__emit_br(nfp_prog, BR_UNC, BR_EV_PIP_UNCOND, BR_CSS_NONE, addr, defer);
}

static void
emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, u16 addr, u8 defer)
{
Expand Down Expand Up @@ -1465,9 +1475,65 @@ static void nfp_outro_tc_legacy(struct nfp_prog *nfp_prog)
SHF_SC_L_SHF, 16);
}

static void nfp_outro_tc_da(struct nfp_prog *nfp_prog)
{
/* TC direct-action mode:
* 0,1 ok NOT SUPPORTED[1]
* 2 drop 0x22 -> drop, count as stat1
* 4,5 nuke 0x02 -> drop
* 7 redir 0x44 -> redir, count as stat2
* * unspec 0x11 -> pass, count as stat0
*
* [1] We can't support OK and RECLASSIFY because we can't tell TC
* the exact decision made. We are forced to support UNSPEC
* to handle aborts so that's the only one we handle for passing
* packets up the stack.
*/
/* Target for aborts */
nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog);

emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);

emit_alu(nfp_prog, reg_a(0),
reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16);

/* Target for normal exits */
nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog);

/* if R0 > 7 jump to abort */
emit_alu(nfp_prog, reg_none(), reg_imm(7), ALU_OP_SUB, reg_b(0));
emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0);
emit_alu(nfp_prog, reg_a(0),
reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);

wrp_immed(nfp_prog, reg_b(2), 0x41221211);
wrp_immed(nfp_prog, reg_b(3), 0x41001211);

emit_shf(nfp_prog, reg_a(1),
reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 2);

emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0));
emit_shf(nfp_prog, reg_a(2),
reg_imm(0xf), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0);

emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0));
emit_shf(nfp_prog, reg_b(2),
reg_imm(0xf), SHF_OP_AND, reg_b(3), SHF_SC_R_SHF, 0);

emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);

emit_shf(nfp_prog, reg_b(2),
reg_a(2), SHF_OP_OR, reg_b(2), SHF_SC_L_SHF, 4);
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16);
}

static void nfp_outro(struct nfp_prog *nfp_prog)
{
switch (nfp_prog->act) {
case NN_ACT_DIRECT:
nfp_outro_tc_da(nfp_prog);
break;
case NN_ACT_TC_DROP:
case NN_ACT_TC_REDIR:
nfp_outro_tc_legacy(nfp_prog);
Expand Down
11 changes: 10 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfp_bpf_verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,16 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog,
return -EINVAL;
}

if (reg0->imm != 0 && (reg0->imm & ~0U) != ~0U) {
if (nfp_prog->act != NN_ACT_DIRECT &&
reg0->imm != 0 && (reg0->imm & ~0U) != ~0U) {
pr_info("unsupported exit state: %d, imm: %llx\n",
reg0->type, reg0->imm);
return -EINVAL;
}

if (nfp_prog->act == NN_ACT_DIRECT && reg0->imm <= TC_ACT_REDIRECT &&
reg0->imm != TC_ACT_SHOT && reg0->imm != TC_ACT_STOLEN &&
reg0->imm != TC_ACT_QUEUED) {
pr_info("unsupported exit state: %d, imm: %llx\n",
reg0->type, reg0->imm);
return -EINVAL;
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfp_net_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@ nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
LIST_HEAD(actions);

/* TC direct action */
if (cls_bpf->exts_integrated)
if (cls_bpf->exts_integrated) {
if (tc_no_actions(cls_bpf->exts))
return NN_ACT_DIRECT;

return -ENOTSUPP;
}

/* TC legacy mode */
if (!tc_single_action(cls_bpf->exts))
Expand Down

0 comments on commit e3b8baf

Please sign in to comment.