Add missing ABI defines and eBPF instructions to allow
mark to be passed on and extend prepend parsing on the
RX path to pick it up from packet metadata.

Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_bpf.h       |  2 ++
 drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c   | 19 +++++++++++
 .../net/ethernet/netronome/nfp/nfp_net_common.c    | 38 ++++++++++++++++++----
 drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h  |  8 +++++
 4 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf.h 
b/drivers/net/ethernet/netronome/nfp/nfp_bpf.h
index f4265f88db23..85b258a70b18 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_bpf.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf.h
@@ -91,6 +91,8 @@ enum nfp_bpf_reg_type {
 #define imm_both(np)   reg_both((np)->regs_per_thread - STATIC_REG_IMM)
 
 #define NFP_BPF_ABI_FLAGS      reg_nnr(0)
+#define   NFP_BPF_ABI_FLAG_MARK        1
+#define NFP_BPF_ABI_MARK       reg_nnr(1)
 #define NFP_BPF_ABI_PKT                reg_nnr(2)
 #define NFP_BPF_ABI_LEN                reg_nnr(3)
 
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c 
b/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
index 09ed1627ae20..ca73be6fcc3d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_bpf_jit.c
@@ -674,6 +674,16 @@ static int construct_data_ld(struct nfp_prog *nfp_prog, 
u16 offset, u8 size)
        return construct_data_ind_ld(nfp_prog, offset, 0, false, size);
 }
 
+static int wrp_set_mark(struct nfp_prog *nfp_prog, u8 src)
+{
+       emit_alu(nfp_prog, NFP_BPF_ABI_MARK,
+                reg_none(), ALU_OP_NONE, reg_b(src));
+       emit_alu(nfp_prog, NFP_BPF_ABI_FLAGS,
+                NFP_BPF_ABI_FLAGS, ALU_OP_OR, reg_imm(NFP_BPF_ABI_FLAG_MARK));
+
+       return 0;
+}
+
 static void
 wrp_alu_imm(struct nfp_prog *nfp_prog, u8 dst, enum alu_op alu_op, u32 imm)
 {
@@ -1117,6 +1127,14 @@ static int mem_ldx4(struct nfp_prog *nfp_prog, struct 
nfp_insn_meta *meta)
        return 0;
 }
 
+static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
+{
+       if (meta->insn.off == offsetof(struct sk_buff, mark))
+               return wrp_set_mark(nfp_prog, meta->insn.src_reg * 2);
+
+       return -ENOTSUPP;
+}
+
 static int jump(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
        if (meta->insn.off < 0) /* TODO */
@@ -1306,6 +1324,7 @@ static const instr_cb_t instr_cb[256] = {
        [BPF_LD | BPF_IND | BPF_H] =    data_ind_ld2,
        [BPF_LD | BPF_IND | BPF_W] =    data_ind_ld4,
        [BPF_LDX | BPF_MEM | BPF_W] =   mem_ldx4,
+       [BPF_STX | BPF_MEM | BPF_W] =   mem_stx4,
        [BPF_JMP | BPF_JA | BPF_K] =    jump,
        [BPF_JMP | BPF_JEQ | BPF_K] =   jeq_imm,
        [BPF_JMP | BPF_JGT | BPF_K] =   jgt_imm,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c 
b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 053bda8a0fbd..739dd13dc18e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1298,23 +1298,20 @@ static void nfp_net_rx_csum(struct nfp_net *nn, struct 
nfp_net_r_vector *r_vec,
  * nfp_net_set_hash() - Set SKB hash data
  * @netdev: adapter's net_device structure
  * @skb:   SKB to set the hash data on
- * @rxd:   RX descriptor
  *
  * The RSS hash and hash-type are pre-pended to the packet data.
  * Extract and decode it and set the skb fields.
  */
-static void nfp_net_set_hash(struct net_device *netdev, struct sk_buff *skb,
-                            struct nfp_net_rx_desc *rxd)
+static void nfp_net_set_hash(struct net_device *netdev, struct sk_buff *skb)
 {
        struct nfp_net_rx_hash *rx_hash;
 
-       if (!(rxd->rxd.flags & PCIE_DESC_RX_RSS) ||
-           !(netdev->features & NETIF_F_RXHASH))
+       if (!(netdev->features & NETIF_F_RXHASH))
                return;
 
        rx_hash = (struct nfp_net_rx_hash *)(skb->data - sizeof(*rx_hash));
 
-       switch (be32_to_cpu(rx_hash->hash_type)) {
+       switch (be32_to_cpu(rx_hash->hash_type) & NPF_NET_META_FIELD_HASH) {
        case NFP_NET_RSS_IPV4:
        case NFP_NET_RSS_IPV6:
        case NFP_NET_RSS_IPV6_EX:
@@ -1326,6 +1323,33 @@ static void nfp_net_set_hash(struct net_device *netdev, 
struct sk_buff *skb,
        }
 }
 
+static void
+nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb,
+                  struct nfp_net_rx_desc *rxd, int meta_len)
+{
+       u32 meta_info;
+       u8 *data = skb->data - 4;
+
+       if (rxd->rxd.flags & PCIE_DESC_RX_RSS) {
+               data -= 4;
+               nfp_net_set_hash(netdev, skb);
+       }
+
+       meta_info = get_unaligned_be32(data) >> 8;
+       data -= 4;
+
+       while (meta_info) {
+               switch (meta_info & GENMASK(NFP_NET_META_FIELD_SIZE, 0)) {
+               case NFP_NET_META_MARK:
+                       skb->mark = get_unaligned_be32(data);
+                       data -= 4;
+                       break;
+               }
+
+               meta_info >>= NFP_NET_META_FIELD_SIZE;
+       }
+}
+
 /**
  * nfp_net_rx() - receive up to @budget packets on @rx_ring
  * @rx_ring:   RX ring to receive from
@@ -1440,7 +1464,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, 
int budget)
                        skb_reserve(skb, nn->rx_offset);
                skb_put(skb, data_len - meta_len);
 
-               nfp_net_set_hash(nn->netdev, skb, rxd);
+               nfp_net_parse_meta(nn->netdev, skb, rxd, meta_len);
 
                /* Pad small frames to minimum */
                if (skb_put_padto(skb, 60))
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h 
b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index a4b0ef11a09c..4c30439d3fcb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -80,6 +80,14 @@
 #define NFP_NET_RSS_IPV6_EX_UDP         9
 
 /**
+ * Prepend field types
+ */
+#define NPF_NET_META_FIELD_HASH                0xff
+
+#define NFP_NET_META_FIELD_SIZE                4
+#define NFP_NET_META_MARK              1
+
+/**
  * @NFP_NET_TXR_MAX:         Maximum number of TX rings
  * @NFP_NET_RXR_MAX:         Maximum number of RX rings
  */
-- 
1.9.1

Reply via email to