nfp: bpf: parse global BPF ABI version capability
authorJakub Kicinski <jakub.kicinski@netronome.com>
Tue, 2 Oct 2018 01:30:32 +0000 (18:30 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Tue, 2 Oct 2018 12:39:58 +0000 (14:39 +0200)
Up until now we only had per-vNIC BPF ABI version capabilities,
which are slightly awkward to use because bulk of the resources
and configuration does not relate to any particular vNIC.  Add
a new capability for global ABI version and check the per-vNIC
version are equal to it.  Assume the ABI version 2 if no explicit
version capability is present.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
drivers/net/ethernet/netronome/nfp/bpf/fw.h
drivers/net/ethernet/netronome/nfp/bpf/main.c
drivers/net/ethernet/netronome/nfp/bpf/main.h

index e4f9b7e..58bad86 100644 (file)
@@ -52,6 +52,7 @@ enum bpf_cap_tlv_type {
        NFP_BPF_CAP_TYPE_RANDOM         = 4,
        NFP_BPF_CAP_TYPE_QUEUE_SELECT   = 5,
        NFP_BPF_CAP_TYPE_ADJUST_TAIL    = 6,
+       NFP_BPF_CAP_TYPE_ABI_VERSION    = 7,
 };
 
 struct nfp_bpf_cap_tlv_func {
index 970af07..1f79246 100644 (file)
@@ -54,11 +54,14 @@ const struct rhashtable_params nfp_bpf_maps_neutral_params = {
 static bool nfp_net_ebpf_capable(struct nfp_net *nn)
 {
 #ifdef __LITTLE_ENDIAN
-       if (nn->cap & NFP_NET_CFG_CTRL_BPF &&
-           nn_readb(nn, NFP_NET_CFG_BPF_ABI) == NFP_NET_BPF_ABI)
-               return true;
-#endif
+       struct nfp_app_bpf *bpf = nn->app->priv;
+
+       return nn->cap & NFP_NET_CFG_CTRL_BPF &&
+              bpf->abi_version &&
+              nn_readb(nn, NFP_NET_CFG_BPF_ABI) == bpf->abi_version;
+#else
        return false;
+#endif
 }
 
 static int
@@ -342,6 +345,26 @@ nfp_bpf_parse_cap_adjust_tail(struct nfp_app_bpf *bpf, void __iomem *value,
        return 0;
 }
 
+static int
+nfp_bpf_parse_cap_abi_version(struct nfp_app_bpf *bpf, void __iomem *value,
+                             u32 length)
+{
+       if (length < 4) {
+               nfp_err(bpf->app->cpp, "truncated ABI version TLV: %d\n",
+                       length);
+               return -EINVAL;
+       }
+
+       bpf->abi_version = readl(value);
+       if (bpf->abi_version != 2) {
+               nfp_warn(bpf->app->cpp, "unsupported BPF ABI version: %d\n",
+                        bpf->abi_version);
+               bpf->abi_version = 0;
+       }
+
+       return 0;
+}
+
 static int nfp_bpf_parse_capabilities(struct nfp_app *app)
 {
        struct nfp_cpp *cpp = app->pf->cpp;
@@ -393,6 +416,11 @@ static int nfp_bpf_parse_capabilities(struct nfp_app *app)
                                                          length))
                                goto err_release_free;
                        break;
+               case NFP_BPF_CAP_TYPE_ABI_VERSION:
+                       if (nfp_bpf_parse_cap_abi_version(app->priv, value,
+                                                         length))
+                               goto err_release_free;
+                       break;
                default:
                        nfp_dbg(cpp, "unknown BPF capability: %d\n", type);
                        break;
@@ -414,6 +442,11 @@ err_release_free:
        return -EINVAL;
 }
 
+static void nfp_bpf_init_capabilities(struct nfp_app_bpf *bpf)
+{
+       bpf->abi_version = 2; /* Original BPF ABI version */
+}
+
 static int nfp_bpf_ndo_init(struct nfp_app *app, struct net_device *netdev)
 {
        struct nfp_app_bpf *bpf = app->priv;
@@ -447,6 +480,8 @@ static int nfp_bpf_init(struct nfp_app *app)
        if (err)
                goto err_free_bpf;
 
+       nfp_bpf_init_capabilities(bpf);
+
        err = nfp_bpf_parse_capabilities(app);
        if (err)
                goto err_free_neutral_maps;
index dbd0098..62cdb18 100644 (file)
@@ -127,6 +127,8 @@ enum pkt_vec {
  *
  * @maps_neutral:      hash table of offload-neutral maps (on pointer)
  *
+ * @abi_version:       global BPF ABI version
+ *
  * @adjust_head:       adjust head capability
  * @adjust_head.flags:         extra flags for adjust head
  * @adjust_head.off_min:       minimal packet offset within buffer required
@@ -170,6 +172,8 @@ struct nfp_app_bpf {
 
        struct rhashtable maps_neutral;
 
+       u32 abi_version;
+
        struct nfp_bpf_cap_adjust_head {
                u32 flags;
                int off_min;