Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Brad Cowie and committed by
Martin KaFai Lau
ece4b296 6c8d7598

+55 -13
+55 -13
net/netfilter/nf_conntrack_bpf.c
··· 32 32 * -EINVAL - Passed NULL for bpf_tuple pointer 33 33 * -EINVAL - opts->reserved is not 0 34 34 * -EINVAL - netns_id is less than -1 35 - * -EINVAL - opts__sz isn't NF_BPF_CT_OPTS_SZ (12) 35 + * -EINVAL - opts__sz isn't NF_BPF_CT_OPTS_SZ (16) or 12 36 + * -EINVAL - opts->ct_zone_id set when 37 + opts__sz isn't NF_BPF_CT_OPTS_SZ (16) 36 38 * -EPROTO - l4proto isn't one of IPPROTO_TCP or IPPROTO_UDP 37 39 * -ENONET - No network namespace found for netns_id 38 40 * -ENOENT - Conntrack lookup could not find entry for tuple ··· 44 42 * Values: 45 43 * IPPROTO_TCP, IPPROTO_UDP 46 44 * @dir: - connection tracking tuple direction. 45 + * @ct_zone_id - connection tracking zone id. 46 + * @ct_zone_dir - connection tracking zone direction. 47 47 * @reserved - Reserved member, will be reused for more options in future 48 48 * Values: 49 49 * 0 ··· 55 51 s32 error; 56 52 u8 l4proto; 57 53 u8 dir; 58 - u8 reserved[2]; 54 + u16 ct_zone_id; 55 + u8 ct_zone_dir; 56 + u8 reserved[3]; 59 57 }; 60 58 61 59 enum { 62 - NF_BPF_CT_OPTS_SZ = 12, 60 + NF_BPF_CT_OPTS_SZ = 16, 63 61 }; 64 62 65 63 static int bpf_nf_ct_tuple_parse(struct bpf_sock_tuple *bpf_tuple, ··· 110 104 u32 timeout) 111 105 { 112 106 struct nf_conntrack_tuple otuple, rtuple; 107 + struct nf_conntrack_zone ct_zone; 113 108 struct nf_conn *ct; 114 109 int err; 115 110 116 - if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] || 117 - opts_len != NF_BPF_CT_OPTS_SZ) 111 + if (!opts || !bpf_tuple) 118 112 return ERR_PTR(-EINVAL); 113 + if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12)) 114 + return ERR_PTR(-EINVAL); 115 + if (opts_len == NF_BPF_CT_OPTS_SZ) { 116 + if (opts->reserved[0] || opts->reserved[1] || opts->reserved[2]) 117 + return ERR_PTR(-EINVAL); 118 + } else { 119 + if (opts->ct_zone_id) 120 + return ERR_PTR(-EINVAL); 121 + } 119 122 120 123 if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) 121 124 return ERR_PTR(-EINVAL); ··· 145 130 return ERR_PTR(-ENONET); 146 131 } 147 132 148 - ct = nf_conntrack_alloc(net, &nf_ct_zone_dflt, &otuple, &rtuple, 133 + if (opts_len == NF_BPF_CT_OPTS_SZ) { 134 + if (opts->ct_zone_dir == 0) 135 + opts->ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR; 136 + nf_ct_zone_init(&ct_zone, 137 + opts->ct_zone_id, opts->ct_zone_dir, 0); 138 + } else { 139 + ct_zone = nf_ct_zone_dflt; 140 + } 141 + 142 + ct = nf_conntrack_alloc(net, &ct_zone, &otuple, &rtuple, 149 143 GFP_ATOMIC); 150 144 if (IS_ERR(ct)) 151 145 goto out; ··· 176 152 { 177 153 struct nf_conntrack_tuple_hash *hash; 178 154 struct nf_conntrack_tuple tuple; 155 + struct nf_conntrack_zone ct_zone; 179 156 struct nf_conn *ct; 180 157 int err; 181 158 182 - if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] || 183 - opts_len != NF_BPF_CT_OPTS_SZ) 159 + if (!opts || !bpf_tuple) 184 160 return ERR_PTR(-EINVAL); 161 + if (!(opts_len == NF_BPF_CT_OPTS_SZ || opts_len == 12)) 162 + return ERR_PTR(-EINVAL); 163 + if (opts_len == NF_BPF_CT_OPTS_SZ) { 164 + if (opts->reserved[0] || opts->reserved[1] || opts->reserved[2]) 165 + return ERR_PTR(-EINVAL); 166 + } else { 167 + if (opts->ct_zone_id) 168 + return ERR_PTR(-EINVAL); 169 + } 185 170 if (unlikely(opts->l4proto != IPPROTO_TCP && opts->l4proto != IPPROTO_UDP)) 186 171 return ERR_PTR(-EPROTO); 187 172 if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) ··· 207 174 return ERR_PTR(-ENONET); 208 175 } 209 176 210 - hash = nf_conntrack_find_get(net, &nf_ct_zone_dflt, &tuple); 177 + if (opts_len == NF_BPF_CT_OPTS_SZ) { 178 + if (opts->ct_zone_dir == 0) 179 + opts->ct_zone_dir = NF_CT_DEFAULT_ZONE_DIR; 180 + nf_ct_zone_init(&ct_zone, 181 + opts->ct_zone_id, opts->ct_zone_dir, 0); 182 + } else { 183 + ct_zone = nf_ct_zone_dflt; 184 + } 185 + 186 + hash = nf_conntrack_find_get(net, &ct_zone, &tuple); 211 187 if (opts->netns_id >= 0) 212 188 put_net(net); 213 189 if (!hash) ··· 287 245 * @opts - Additional options for allocation (documented above) 288 246 * Cannot be NULL 289 247 * @opts__sz - Length of the bpf_ct_opts structure 290 - * Must be NF_BPF_CT_OPTS_SZ (12) 248 + * Must be NF_BPF_CT_OPTS_SZ (16) or 12 291 249 */ 292 250 __bpf_kfunc struct nf_conn___init * 293 251 bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple, ··· 321 279 * @opts - Additional options for lookup (documented above) 322 280 * Cannot be NULL 323 281 * @opts__sz - Length of the bpf_ct_opts structure 324 - * Must be NF_BPF_CT_OPTS_SZ (12) 282 + * Must be NF_BPF_CT_OPTS_SZ (16) or 12 325 283 */ 326 284 __bpf_kfunc struct nf_conn * 327 285 bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple, ··· 354 312 * @opts - Additional options for allocation (documented above) 355 313 * Cannot be NULL 356 314 * @opts__sz - Length of the bpf_ct_opts structure 357 - * Must be NF_BPF_CT_OPTS_SZ (12) 315 + * Must be NF_BPF_CT_OPTS_SZ (16) or 12 358 316 */ 359 317 __bpf_kfunc struct nf_conn___init * 360 318 bpf_skb_ct_alloc(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple, ··· 389 347 * @opts - Additional options for lookup (documented above) 390 348 * Cannot be NULL 391 349 * @opts__sz - Length of the bpf_ct_opts structure 392 - * Must be NF_BPF_CT_OPTS_SZ (12) 350 + * Must be NF_BPF_CT_OPTS_SZ (16) or 12 393 351 */ 394 352 __bpf_kfunc struct nf_conn * 395 353 bpf_skb_ct_lookup(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,