nfp: bpf: drop support for cls_bpf with legacy actions
authorJakub Kicinski <jakub.kicinski@netronome.com>
Fri, 3 Nov 2017 20:56:22 +0000 (13:56 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 5 Nov 2017 13:26:19 +0000 (22:26 +0900)
Only support BPF_PROG_TYPE_SCHED_CLS programs in direct
action mode.  This simplifies preparing the offload since
there will now be only one mode of operation for that type
of program.  We need to know the attachment mode type of
cls_bpf programs, because exit codes are interpreted
differently for legacy vs DA mode.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/bpf/jit.c
drivers/net/ethernet/netronome/nfp/bpf/main.c
drivers/net/ethernet/netronome/nfp/bpf/main.h
drivers/net/ethernet/netronome/nfp/bpf/offload.c
drivers/net/ethernet/netronome/nfp/bpf/verifier.c

index 2609a2487100855d0b7a82f029e4a2cf4d813765..e1907a1d269e54ace5f979261b2da0c8600c8ddb 100644 (file)
@@ -201,47 +201,6 @@ emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, u16 addr, u8 defer)
                  BR_CSS_NONE, addr, defer);
 }
 
-static void
-__emit_br_byte(struct nfp_prog *nfp_prog, u8 areg, u8 breg, bool imm8,
-              u8 byte, bool equal, u16 addr, u8 defer, bool src_lmextn)
-{
-       u16 addr_lo, addr_hi;
-       u64 insn;
-
-       addr_lo = addr & (OP_BB_ADDR_LO >> __bf_shf(OP_BB_ADDR_LO));
-       addr_hi = addr != addr_lo;
-
-       insn = OP_BBYTE_BASE |
-               FIELD_PREP(OP_BB_A_SRC, areg) |
-               FIELD_PREP(OP_BB_BYTE, byte) |
-               FIELD_PREP(OP_BB_B_SRC, breg) |
-               FIELD_PREP(OP_BB_I8, imm8) |
-               FIELD_PREP(OP_BB_EQ, equal) |
-               FIELD_PREP(OP_BB_DEFBR, defer) |
-               FIELD_PREP(OP_BB_ADDR_LO, addr_lo) |
-               FIELD_PREP(OP_BB_ADDR_HI, addr_hi) |
-               FIELD_PREP(OP_BB_SRC_LMEXTN, src_lmextn);
-
-       nfp_prog_push(nfp_prog, insn);
-}
-
-static void
-emit_br_byte_neq(struct nfp_prog *nfp_prog,
-                swreg src, u8 imm, u8 byte, u16 addr, u8 defer)
-{
-       struct nfp_insn_re_regs reg;
-       int err;
-
-       err = swreg_to_restricted(reg_none(), src, reg_imm(imm), &reg, true);
-       if (err) {
-               nfp_prog->error = err;
-               return;
-       }
-
-       __emit_br_byte(nfp_prog, reg.areg, reg.breg, reg.i8, byte, false, addr,
-                      defer, reg.src_lmextn);
-}
-
 static void
 __emit_immed(struct nfp_prog *nfp_prog, u16 areg, u16 breg, u16 imm_hi,
             enum immed_width width, bool invert,
@@ -1547,7 +1506,7 @@ mem_ldx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
        unsigned int size)
 {
        if (meta->ptr.type == PTR_TO_CTX) {
-               if (nfp_prog->act == NN_ACT_XDP)
+               if (nfp_prog->type == BPF_PROG_TYPE_XDP)
                        return mem_ldx_xdp(nfp_prog, meta, size);
                else
                        return mem_ldx_skb(nfp_prog, meta, size);
@@ -2022,34 +1981,6 @@ static void nfp_intro(struct nfp_prog *nfp_prog)
                 plen_reg(nfp_prog), ALU_OP_AND, pv_len(nfp_prog));
 }
 
-static void nfp_outro_tc_legacy(struct nfp_prog *nfp_prog)
-{
-       const u8 act2code[] = {
-               [NN_ACT_TC_DROP]  = 0x22,
-               [NN_ACT_TC_REDIR] = 0x24
-       };
-       /* Target for aborts */
-       nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog);
-       wrp_immed(nfp_prog, reg_both(0), 0);
-
-       /* Target for normal exits */
-       nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog);
-       /* Legacy TC mode:
-        *   0        0x11 -> pass,  count as stat0
-        *  -1  drop  0x22 -> drop,  count as stat1
-        *     redir  0x24 -> redir, count as stat1
-        *  ife mark  0x21 -> pass,  count as stat1
-        *  ife + tx  0x24 -> redir, count as stat1
-        */
-       emit_br_byte_neq(nfp_prog, reg_b(0), 0xff, 0, nfp_prog->tgt_done, 2);
-       wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS);
-       emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16);
-
-       emit_br(nfp_prog, BR_UNC, nfp_prog->tgt_done, 1);
-       emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(act2code[nfp_prog->act]),
-                     SHF_SC_L_SHF, 16);
-}
-
 static void nfp_outro_tc_da(struct nfp_prog *nfp_prog)
 {
        /* TC direct-action mode:
@@ -2142,17 +2073,15 @@ static void nfp_outro_xdp(struct nfp_prog *nfp_prog)
 
 static void nfp_outro(struct nfp_prog *nfp_prog)
 {
-       switch (nfp_prog->act) {
-       case NN_ACT_DIRECT:
+       switch (nfp_prog->type) {
+       case BPF_PROG_TYPE_SCHED_CLS:
                nfp_outro_tc_da(nfp_prog);
                break;
-       case NN_ACT_TC_DROP:
-       case NN_ACT_TC_REDIR:
-               nfp_outro_tc_legacy(nfp_prog);
-               break;
-       case NN_ACT_XDP:
+       case BPF_PROG_TYPE_XDP:
                nfp_outro_xdp(nfp_prog);
                break;
+       default:
+               WARN_ON(1);
        }
 }
 
@@ -2351,7 +2280,6 @@ static int nfp_bpf_ustore_calc(struct nfp_prog *nfp_prog, __le64 *ustore)
  * nfp_bpf_jit() - translate BPF code into NFP assembly
  * @filter:    kernel BPF filter struct
  * @prog_mem:  memory to store assembler instructions
- * @act:       action attached to this eBPF program
  * @prog_start:        offset of the first instruction when loaded
  * @prog_done: where to jump on exit
  * @prog_sz:   size of @prog_mem in instructions
@@ -2359,7 +2287,6 @@ static int nfp_bpf_ustore_calc(struct nfp_prog *nfp_prog, __le64 *ustore)
  */
 int
 nfp_bpf_jit(struct bpf_prog *filter, void *prog_mem,
-           enum nfp_bpf_action_type act,
            unsigned int prog_start, unsigned int prog_done,
            unsigned int prog_sz, struct nfp_bpf_result *res)
 {
@@ -2371,7 +2298,7 @@ nfp_bpf_jit(struct bpf_prog *filter, void *prog_mem,
                return -ENOMEM;
 
        INIT_LIST_HEAD(&nfp_prog->insns);
-       nfp_prog->act = act;
+       nfp_prog->type = filter->type;
        nfp_prog->start_off = prog_start;
        nfp_prog->tgt_done = prog_done;
 
index 8e3e89cace8dff56948bc99c1e43145d7302b6fd..2ff97f12c160e869f00c1eb9c491cb8443ee3d78 100644 (file)
@@ -85,34 +85,10 @@ static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn)
        return nfp_net_ebpf_capable(nn) ? "BPF" : "";
 }
 
-static int
-nfp_bpf_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
-{
-       struct nfp_net_bpf_priv *priv;
-       int ret;
-
-       priv = kmalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       nn->app_priv = priv;
-       spin_lock_init(&priv->rx_filter_lock);
-       priv->nn = nn;
-       timer_setup(&priv->rx_filter_stats_timer,
-                   nfp_net_filter_stats_timer, 0);
-
-       ret = nfp_app_nic_vnic_alloc(app, nn, id);
-       if (ret)
-               kfree(priv);
-
-       return ret;
-}
-
 static void nfp_bpf_vnic_free(struct nfp_app *app, struct nfp_net *nn)
 {
        if (nn->dp.bpf_offload_xdp)
                nfp_bpf_xdp_offload(app, nn, NULL);
-       kfree(nn->app_priv);
 }
 
 static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
@@ -133,6 +109,13 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
                if (nn->dp.bpf_offload_xdp)
                        return -EBUSY;
 
+               /* Only support TC direct action */
+               if (!cls_bpf->exts_integrated ||
+                   tcf_exts_has_actions(cls_bpf->exts)) {
+                       nn_err(nn, "only direct action with no legacy actions supported\n");
+                       return -EOPNOTSUPP;
+               }
+
                return nfp_net_bpf_offload(nn, cls_bpf);
        default:
                return -EOPNOTSUPP;
@@ -184,7 +167,7 @@ const struct nfp_app_type app_bpf = {
 
        .extra_cap      = nfp_bpf_extra_cap,
 
-       .vnic_alloc     = nfp_bpf_vnic_alloc,
+       .vnic_alloc     = nfp_app_nic_vnic_alloc,
        .vnic_free      = nfp_bpf_vnic_free,
 
        .setup_tc       = nfp_bpf_setup_tc,
index bc604030ff6cbac3adacd46c124dcbf63390aa64..c5280de2ab14c0011f3c908a94c3fdcff170d672 100644 (file)
@@ -65,13 +65,6 @@ enum pkt_vec {
        PKT_VEC_PKT_PTR         = 2,
 };
 
-enum nfp_bpf_action_type {
-       NN_ACT_TC_DROP,
-       NN_ACT_TC_REDIR,
-       NN_ACT_DIRECT,
-       NN_ACT_XDP,
-};
-
 #define pv_len(np)     reg_lm(1, PKT_VEC_PKT_LEN)
 #define pv_ctm_ptr(np) reg_lm(1, PKT_VEC_PKT_PTR)
 
@@ -147,7 +140,7 @@ static inline u8 mbpf_mode(const struct nfp_insn_meta *meta)
  * @prog: machine code
  * @prog_len: number of valid instructions in @prog array
  * @__prog_alloc_len: alloc size of @prog array
- * @act: BPF program/action type (TC DA, TC with action, XDP etc.)
+ * @type: BPF program type
  * @num_regs: number of registers used by this program
  * @regs_per_thread: number of basic registers allocated per thread
  * @start_off: address of the first instruction in the memory
@@ -164,7 +157,7 @@ struct nfp_prog {
        unsigned int prog_len;
        unsigned int __prog_alloc_len;
 
-       enum nfp_bpf_action_type act;
+       enum bpf_prog_type type;
 
        unsigned int num_regs;
        unsigned int regs_per_thread;
@@ -188,7 +181,7 @@ struct nfp_bpf_result {
 };
 
 int
-nfp_bpf_jit(struct bpf_prog *filter, void *prog, enum nfp_bpf_action_type act,
+nfp_bpf_jit(struct bpf_prog *filter, void *prog,
            unsigned int prog_start, unsigned int prog_done,
            unsigned int prog_sz, struct nfp_bpf_result *res);
 
@@ -197,23 +190,6 @@ int nfp_prog_verify(struct nfp_prog *nfp_prog, struct bpf_prog *prog);
 struct nfp_net;
 struct tc_cls_bpf_offload;
 
-/**
- * struct nfp_net_bpf_priv - per-vNIC BPF private data
- * @rx_filter:         Filter offload statistics - dropped packets/bytes
- * @rx_filter_prev:    Filter offload statistics - values from previous update
- * @rx_filter_change:  Jiffies when statistics last changed
- * @rx_filter_stats_timer:  Timer for polling filter offload statistics
- * @rx_filter_lock:    Lock protecting timer state changes (teardown)
- */
-struct nfp_net_bpf_priv {
-       struct nfp_stat_pair rx_filter, rx_filter_prev;
-       unsigned long rx_filter_change;
-       struct timer_list rx_filter_stats_timer;
-       struct nfp_net *nn;
-       spinlock_t rx_filter_lock;
-};
-
 int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf);
-void nfp_net_filter_stats_timer(struct timer_list *t);
 
 #endif
index 6d576f63139208a4cee0992175ad89424ca9e131..b9b5d675c4d380b7069af9e466e5cc835af787c1 100644 (file)
 #include "../nfp_net_ctrl.h"
 #include "../nfp_net.h"
 
-void nfp_net_filter_stats_timer(struct timer_list *t)
-{
-       struct nfp_net_bpf_priv *priv = from_timer(priv, t,
-                                                  rx_filter_stats_timer);
-       struct nfp_net *nn = priv->nn;
-       struct nfp_stat_pair latest;
-
-       spin_lock_bh(&priv->rx_filter_lock);
-
-       if (nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF)
-               mod_timer(&priv->rx_filter_stats_timer,
-                         jiffies + NFP_NET_STAT_POLL_IVL);
-
-       spin_unlock_bh(&priv->rx_filter_lock);
-
-       latest.pkts = nn_readq(nn, NFP_NET_CFG_STATS_APP1_FRAMES);
-       latest.bytes = nn_readq(nn, NFP_NET_CFG_STATS_APP1_BYTES);
-
-       if (latest.pkts != priv->rx_filter.pkts)
-               priv->rx_filter_change = jiffies;
-
-       priv->rx_filter = latest;
-}
-
-static void nfp_net_bpf_stats_reset(struct nfp_net *nn)
-{
-       struct nfp_net_bpf_priv *priv = nn->app_priv;
-
-       priv->rx_filter.pkts = nn_readq(nn, NFP_NET_CFG_STATS_APP1_FRAMES);
-       priv->rx_filter.bytes = nn_readq(nn, NFP_NET_CFG_STATS_APP1_BYTES);
-       priv->rx_filter_prev = priv->rx_filter;
-       priv->rx_filter_change = jiffies;
-}
-
-static int
-nfp_net_bpf_stats_update(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
-{
-       struct nfp_net_bpf_priv *priv = nn->app_priv;
-       u64 bytes, pkts;
-
-       pkts = priv->rx_filter.pkts - priv->rx_filter_prev.pkts;
-       bytes = priv->rx_filter.bytes - priv->rx_filter_prev.bytes;
-       bytes -= pkts * ETH_HLEN;
-
-       priv->rx_filter_prev = priv->rx_filter;
-
-       tcf_exts_stats_update(cls_bpf->exts,
-                             bytes, pkts, priv->rx_filter_change);
-
-       return 0;
-}
-
-static int
-nfp_net_bpf_get_act(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
-{
-       const struct tc_action *a;
-       LIST_HEAD(actions);
-
-       if (!cls_bpf->exts)
-               return NN_ACT_XDP;
-
-       /* TC direct action */
-       if (cls_bpf->exts_integrated) {
-               if (!tcf_exts_has_actions(cls_bpf->exts))
-                       return NN_ACT_DIRECT;
-
-               return -EOPNOTSUPP;
-       }
-
-       /* TC legacy mode */
-       if (!tcf_exts_has_one_action(cls_bpf->exts))
-               return -EOPNOTSUPP;
-
-       tcf_exts_to_list(cls_bpf->exts, &actions);
-       list_for_each_entry(a, &actions, list) {
-               if (is_tcf_gact_shot(a))
-                       return NN_ACT_TC_DROP;
-
-               if (is_tcf_mirred_egress_redirect(a) &&
-                   tcf_mirred_ifindex(a) == nn->dp.netdev->ifindex)
-                       return NN_ACT_TC_REDIR;
-       }
-
-       return -EOPNOTSUPP;
-}
-
 static int
 nfp_net_bpf_offload_prepare(struct nfp_net *nn,
                            struct tc_cls_bpf_offload *cls_bpf,
@@ -144,17 +58,11 @@ nfp_net_bpf_offload_prepare(struct nfp_net *nn,
                            void **code, dma_addr_t *dma_addr, u16 max_instr)
 {
        unsigned int code_sz = max_instr * sizeof(u64);
-       enum nfp_bpf_action_type act;
        unsigned int stack_size;
        u16 start_off, done_off;
        unsigned int max_mtu;
        int ret;
 
-       ret = nfp_net_bpf_get_act(nn, cls_bpf);
-       if (ret < 0)
-               return ret;
-       act = ret;
-
        max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
        if (max_mtu < nn->dp.netdev->mtu) {
                nn_info(nn, "BPF offload not supported with MTU larger than HW packet split boundary\n");
@@ -175,7 +83,7 @@ nfp_net_bpf_offload_prepare(struct nfp_net *nn,
        if (!*code)
                return -ENOMEM;
 
-       ret = nfp_bpf_jit(cls_bpf->prog, *code, act, start_off, done_off,
+       ret = nfp_bpf_jit(cls_bpf->prog, *code, start_off, done_off,
                          max_instr, res);
        if (ret)
                goto out;
@@ -193,7 +101,6 @@ nfp_net_bpf_load_and_start(struct nfp_net *nn, u32 tc_flags,
                           unsigned int code_sz, unsigned int n_instr,
                           bool dense_mode)
 {
-       struct nfp_net_bpf_priv *priv = nn->app_priv;
        u64 bpf_addr = dma_addr;
        int err;
 
@@ -218,25 +125,15 @@ nfp_net_bpf_load_and_start(struct nfp_net *nn, u32 tc_flags,
                nn_err(nn, "FW command error while enabling BPF: %d\n", err);
 
        dma_free_coherent(nn->dp.dev, code_sz, code, dma_addr);
-
-       nfp_net_bpf_stats_reset(nn);
-       mod_timer(&priv->rx_filter_stats_timer,
-                 jiffies + NFP_NET_STAT_POLL_IVL);
 }
 
 static int nfp_net_bpf_stop(struct nfp_net *nn)
 {
-       struct nfp_net_bpf_priv *priv = nn->app_priv;
-
        if (!(nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF))
                return 0;
 
-       spin_lock_bh(&priv->rx_filter_lock);
        nn->dp.ctrl &= ~NFP_NET_CFG_CTRL_BPF;
-       spin_unlock_bh(&priv->rx_filter_lock);
        nn_writel(nn, NFP_NET_CFG_CTRL, nn->dp.ctrl);
-
-       del_timer_sync(&priv->rx_filter_stats_timer);
        nn->dp.bpf_offload_skip_sw = 0;
 
        return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN);
@@ -292,9 +189,6 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
        case TC_CLSBPF_DESTROY:
                return nfp_net_bpf_stop(nn);
 
-       case TC_CLSBPF_STATS:
-               return nfp_net_bpf_stats_update(nn, cls_bpf);
-
        default:
                return -EOPNOTSUPP;
        }
index a8c7615546a9733811a37146121f97bc0a14cda7..4f31bdefd331ef3f44b28da2b7b56885fade3c95 100644 (file)
@@ -81,7 +81,7 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog,
        const struct bpf_reg_state *reg0 = cur_regs(env) + BPF_REG_0;
        u64 imm;
 
-       if (nfp_prog->act == NN_ACT_XDP)
+       if (nfp_prog->type == BPF_PROG_TYPE_XDP)
                return 0;
 
        if (!(reg0->type == SCALAR_VALUE && tnum_is_const(reg0->var_off))) {
@@ -94,13 +94,8 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog,
        }
 
        imm = reg0->var_off.value;
-       if (nfp_prog->act != NN_ACT_DIRECT && imm != 0 && (imm & ~0U) != ~0U) {
-               pr_info("unsupported exit state: %d, imm: %llx\n",
-                       reg0->type, imm);
-               return -EINVAL;
-       }
-
-       if (nfp_prog->act == NN_ACT_DIRECT && imm <= TC_ACT_REDIRECT &&
+       if (nfp_prog->type == BPF_PROG_TYPE_SCHED_CLS &&
+           imm <= TC_ACT_REDIRECT &&
            imm != TC_ACT_SHOT && imm != TC_ACT_STOLEN &&
            imm != TC_ACT_QUEUED) {
                pr_info("unsupported exit state: %d, imm: %llx\n",