1

net: netfilter: Make ct zone opts configurable for bpf ct helpers

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>
This commit is contained in:
Brad Cowie 2024-05-22 17:07:11 +12:00 committed by Martin KaFai Lau
parent 6c8d7598df
commit ece4b29690

View File

@ -32,7 +32,9 @@
* -EINVAL - Passed NULL for bpf_tuple pointer * -EINVAL - Passed NULL for bpf_tuple pointer
* -EINVAL - opts->reserved is not 0 * -EINVAL - opts->reserved is not 0
* -EINVAL - netns_id is less than -1 * -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 * -EPROTO - l4proto isn't one of IPPROTO_TCP or IPPROTO_UDP
* -ENONET - No network namespace found for netns_id * -ENONET - No network namespace found for netns_id
* -ENOENT - Conntrack lookup could not find entry for tuple * -ENOENT - Conntrack lookup could not find entry for tuple
@ -42,6 +44,8 @@
* Values: * Values:
* IPPROTO_TCP, IPPROTO_UDP * IPPROTO_TCP, IPPROTO_UDP
* @dir: - connection tracking tuple direction. * @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 * @reserved - Reserved member, will be reused for more options in future
* Values: * Values:
* 0 * 0
@ -51,11 +55,13 @@ struct bpf_ct_opts {
s32 error; s32 error;
u8 l4proto; u8 l4proto;
u8 dir; u8 dir;
u8 reserved[2]; u16 ct_zone_id;
u8 ct_zone_dir;
u8 reserved[3];
}; };
enum { 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, 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) u32 timeout)
{ {
struct nf_conntrack_tuple otuple, rtuple; struct nf_conntrack_tuple otuple, rtuple;
struct nf_conntrack_zone ct_zone;
struct nf_conn *ct; struct nf_conn *ct;
int err; int err;
if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] || if (!opts || !bpf_tuple)
opts_len != NF_BPF_CT_OPTS_SZ)
return ERR_PTR(-EINVAL); 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)) if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS))
return ERR_PTR(-EINVAL); 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); 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); GFP_ATOMIC);
if (IS_ERR(ct)) if (IS_ERR(ct))
goto out; 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_hash *hash;
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
struct nf_conntrack_zone ct_zone;
struct nf_conn *ct; struct nf_conn *ct;
int err; int err;
if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] || if (!opts || !bpf_tuple)
opts_len != NF_BPF_CT_OPTS_SZ)
return ERR_PTR(-EINVAL); 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)) if (unlikely(opts->l4proto != IPPROTO_TCP && opts->l4proto != IPPROTO_UDP))
return ERR_PTR(-EPROTO); return ERR_PTR(-EPROTO);
if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) 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); 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) if (opts->netns_id >= 0)
put_net(net); put_net(net);
if (!hash) if (!hash)
@ -245,7 +287,7 @@ __bpf_kfunc_start_defs();
* @opts - Additional options for allocation (documented above) * @opts - Additional options for allocation (documented above)
* Cannot be NULL * Cannot be NULL
* @opts__sz - Length of the bpf_ct_opts structure * @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_kfunc struct nf_conn___init *
bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple, 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) * @opts - Additional options for lookup (documented above)
* Cannot be NULL * Cannot be NULL
* @opts__sz - Length of the bpf_ct_opts structure * @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_kfunc struct nf_conn *
bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple, 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) * @opts - Additional options for allocation (documented above)
* Cannot be NULL * Cannot be NULL
* @opts__sz - Length of the bpf_ct_opts structure * @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_kfunc struct nf_conn___init *
bpf_skb_ct_alloc(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple, 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) * @opts - Additional options for lookup (documented above)
* Cannot be NULL * Cannot be NULL
* @opts__sz - Length of the bpf_ct_opts structure * @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_kfunc struct nf_conn *
bpf_skb_ct_lookup(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple, bpf_skb_ct_lookup(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,