]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: netfilter: Make ct zone opts configurable for bpf ct helpers
authorBrad Cowie <brad@faucet.nz>
Wed, 22 May 2024 05:07:11 +0000 (17:07 +1200)
committerMartin KaFai Lau <martin.lau@kernel.org>
Wed, 22 May 2024 22:00:56 +0000 (15:00 -0700)
Add ct zone id and direction to bpf_ct_opts so that arbitrary ct zones
can be used for xdp/tc bpf ct helper functions bpf_{xdp,skb}_ct_alloc
and bpf_{xdp,skb}_ct_lookup.

Signed-off-by: Brad Cowie <brad@faucet.nz>
Link: https://lore.kernel.org/r/20240522050712.732558-1-brad@faucet.nz
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
net/netfilter/nf_conntrack_bpf.c

index d2492d050fe601fbb1ce8e3cb598603914712a83..4a136fc3a9c0f57b63bb751cae64833b427345ad 100644 (file)
@@ -32,7 +32,9 @@
  *                -EINVAL - Passed NULL for bpf_tuple pointer
  *                -EINVAL - opts->reserved is not 0
  *                -EINVAL - netns_id is less than -1
- *                -EINVAL - opts__sz isn't NF_BPF_CT_OPTS_SZ (12)
+ *                -EINVAL - opts__sz isn't NF_BPF_CT_OPTS_SZ (16) or 12
+ *                -EINVAL - opts->ct_zone_id set when
+                            opts__sz isn't NF_BPF_CT_OPTS_SZ (16)
  *                -EPROTO - l4proto isn't one of IPPROTO_TCP or IPPROTO_UDP
  *                -ENONET - No network namespace found for netns_id
  *                -ENOENT - Conntrack lookup could not find entry for tuple
@@ -42,6 +44,8 @@
  *              Values:
  *                IPPROTO_TCP, IPPROTO_UDP
  * @dir:       - connection tracking tuple direction.
+ * @ct_zone_id - connection tracking zone id.
+ * @ct_zone_dir - connection tracking zone direction.
  * @reserved   - Reserved member, will be reused for more options in future
  *              Values:
  *                0
@@ -51,11 +55,13 @@ struct bpf_ct_opts {
        s32 error;
        u8 l4proto;
        u8 dir;
-       u8 reserved[2];
+       u16 ct_zone_id;
+       u8 ct_zone_dir;
+       u8 reserved[3];
 };
 
 enum {
-       NF_BPF_CT_OPTS_SZ = 12,
+       NF_BPF_CT_OPTS_SZ = 16,
 };
 
 static int bpf_nf_ct_tuple_parse(struct bpf_sock_tuple *bpf_tuple,
@@ -104,12 +110,21 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
                        u32 timeout)
 {
        struct nf_conntrack_tuple otuple, rtuple;
+       struct nf_conntrack_zone ct_zone;
        struct nf_conn *ct;
        int err;
 
-       if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] ||
-           opts_len != NF_BPF_CT_OPTS_SZ)
+       if (!opts || !bpf_tuple)
                return ERR_PTR(-EINVAL);
+       if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12))
+               return ERR_PTR(-EINVAL);
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+               if (opts->reserved[0] || opts->reserved[1] || opts->reserved[2])
+                       return ERR_PTR(-EINVAL);
+       } else {
+               if (opts->ct_zone_id)
+                       return ERR_PTR(-EINVAL);
+       }
 
        if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
                return ERR_PTR(-EINVAL);
@@ -130,7 +145,16 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple,
                        return ERR_PTR(-ENONET);
        }
 
-       ct = nf_conntrack_alloc(net, &nf_ct_zone_dflt, &otuple, &rtuple,
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+               if (opts->ct_zone_dir == 0)
+                       opts->ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR;
+               nf_ct_zone_init(&ct_zone,
+                               opts->ct_zone_id, opts->ct_zone_dir, 0);
+       } else {
+               ct_zone = nf_ct_zone_dflt;
+       }
+
+       ct = nf_conntrack_alloc(net, &ct_zone, &otuple, &rtuple,
                                GFP_ATOMIC);
        if (IS_ERR(ct))
                goto out;
@@ -152,12 +176,21 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
 {
        struct nf_conntrack_tuple_hash *hash;
        struct nf_conntrack_tuple tuple;
+       struct nf_conntrack_zone ct_zone;
        struct nf_conn *ct;
        int err;
 
-       if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] ||
-           opts_len != NF_BPF_CT_OPTS_SZ)
+       if (!opts || !bpf_tuple)
                return ERR_PTR(-EINVAL);
+       if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12))
+               return ERR_PTR(-EINVAL);
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+               if (opts->reserved[0] || opts->reserved[1] || opts->reserved[2])
+                       return ERR_PTR(-EINVAL);
+       } else {
+               if (opts->ct_zone_id)
+                       return ERR_PTR(-EINVAL);
+       }
        if (unlikely(opts->l4proto != IPPROTO_TCP && opts->l4proto != IPPROTO_UDP))
                return ERR_PTR(-EPROTO);
        if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
@@ -174,7 +207,16 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net,
                        return ERR_PTR(-ENONET);
        }
 
-       hash = nf_conntrack_find_get(net, &nf_ct_zone_dflt, &tuple);
+       if (opts_len == NF_BPF_CT_OPTS_SZ) {
+               if (opts->ct_zone_dir == 0)
+                       opts->ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR;
+               nf_ct_zone_init(&ct_zone,
+                               opts->ct_zone_id, opts->ct_zone_dir, 0);
+       } else {
+               ct_zone = nf_ct_zone_dflt;
+       }
+
+       hash = nf_conntrack_find_get(net, &ct_zone, &tuple);
        if (opts->netns_id >= 0)
                put_net(net);
        if (!hash)
@@ -245,7 +287,7 @@ __bpf_kfunc_start_defs();
  * @opts       - Additional options for allocation (documented above)
  *                 Cannot be NULL
  * @opts__sz   - Length of the bpf_ct_opts structure
- *                 Must be NF_BPF_CT_OPTS_SZ (12)
+ *                 Must be NF_BPF_CT_OPTS_SZ (16) or 12
  */
 __bpf_kfunc struct nf_conn___init *
 bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
@@ -279,7 +321,7 @@ bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
  * @opts       - Additional options for lookup (documented above)
  *                 Cannot be NULL
  * @opts__sz   - Length of the bpf_ct_opts structure
- *                 Must be NF_BPF_CT_OPTS_SZ (12)
+ *                 Must be NF_BPF_CT_OPTS_SZ (16) or 12
  */
 __bpf_kfunc struct nf_conn *
 bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
@@ -312,7 +354,7 @@ bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
  * @opts       - Additional options for allocation (documented above)
  *                 Cannot be NULL
  * @opts__sz   - Length of the bpf_ct_opts structure
- *                 Must be NF_BPF_CT_OPTS_SZ (12)
+ *                 Must be NF_BPF_CT_OPTS_SZ (16) or 12
  */
 __bpf_kfunc struct nf_conn___init *
 bpf_skb_ct_alloc(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,
@@ -347,7 +389,7 @@ bpf_skb_ct_alloc(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,
  * @opts       - Additional options for lookup (documented above)
  *                 Cannot be NULL
  * @opts__sz   - Length of the bpf_ct_opts structure
- *                 Must be NF_BPF_CT_OPTS_SZ (12)
+ *                 Must be NF_BPF_CT_OPTS_SZ (16) or 12
  */
 __bpf_kfunc struct nf_conn *
 bpf_skb_ct_lookup(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,