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

bpf: Add ingress_ifindex to bpf_sk_lookup

It may be helpful to have access to the ifindex during bpf socket
lookup. An example may be to scope certain socket lookup logic to
specific interfaces, i.e. an interface may be made exempt from custom
lookup code.

Add the ifindex of the arriving connection to the bpf_sk_lookup API.

Signed-off-by: Mark Pashmfouroush <markpash@cloudflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211110111016.5670-2-markpash@cloudflare.com

authored by

Mark Pashmfouroush and committed by
Alexei Starovoitov
f8931565 1a8b597d

+30 -18
+5 -2
include/linux/filter.h
··· 1374 1374 const struct in6_addr *daddr; 1375 1375 } v6; 1376 1376 struct sock *selected_sk; 1377 + u32 ingress_ifindex; 1377 1378 bool no_reuseport; 1378 1379 }; 1379 1380 ··· 1437 1436 static inline bool bpf_sk_lookup_run_v4(struct net *net, int protocol, 1438 1437 const __be32 saddr, const __be16 sport, 1439 1438 const __be32 daddr, const u16 dport, 1440 - struct sock **psk) 1439 + const int ifindex, struct sock **psk) 1441 1440 { 1442 1441 struct bpf_prog_array *run_array; 1443 1442 struct sock *selected_sk = NULL; ··· 1453 1452 .v4.daddr = daddr, 1454 1453 .sport = sport, 1455 1454 .dport = dport, 1455 + .ingress_ifindex = ifindex, 1456 1456 }; 1457 1457 u32 act; 1458 1458 ··· 1476 1474 const __be16 sport, 1477 1475 const struct in6_addr *daddr, 1478 1476 const u16 dport, 1479 - struct sock **psk) 1477 + const int ifindex, struct sock **psk) 1480 1478 { 1481 1479 struct bpf_prog_array *run_array; 1482 1480 struct sock *selected_sk = NULL; ··· 1492 1490 .v6.daddr = daddr, 1493 1491 .sport = sport, 1494 1492 .dport = dport, 1493 + .ingress_ifindex = ifindex, 1495 1494 }; 1496 1495 u32 act; 1497 1496
+1
include/uapi/linux/bpf.h
··· 6316 6316 __u32 local_ip4; /* Network byte order */ 6317 6317 __u32 local_ip6[4]; /* Network byte order */ 6318 6318 __u32 local_port; /* Host byte order */ 6319 + __u32 ingress_ifindex; /* The arriving interface. Determined by inet_iif. */ 6319 6320 }; 6320 6321 6321 6322 /*
+7
net/core/filter.c
··· 10491 10491 case bpf_ctx_range_till(struct bpf_sk_lookup, local_ip6[0], local_ip6[3]): 10492 10492 case bpf_ctx_range(struct bpf_sk_lookup, remote_port): 10493 10493 case bpf_ctx_range(struct bpf_sk_lookup, local_port): 10494 + case bpf_ctx_range(struct bpf_sk_lookup, ingress_ifindex): 10494 10495 bpf_ctx_record_field_size(info, sizeof(__u32)); 10495 10496 return bpf_ctx_narrow_access_ok(off, size, sizeof(__u32)); 10496 10497 ··· 10580 10579 *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg, 10581 10580 bpf_target_off(struct bpf_sk_lookup_kern, 10582 10581 dport, 2, target_size)); 10582 + break; 10583 + 10584 + case offsetof(struct bpf_sk_lookup, ingress_ifindex): 10585 + *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg, 10586 + bpf_target_off(struct bpf_sk_lookup_kern, 10587 + ingress_ifindex, 4, target_size)); 10583 10588 break; 10584 10589 } 10585 10590
+4 -4
net/ipv4/inet_hashtables.c
··· 307 307 struct inet_hashinfo *hashinfo, 308 308 struct sk_buff *skb, int doff, 309 309 __be32 saddr, __be16 sport, 310 - __be32 daddr, u16 hnum) 310 + __be32 daddr, u16 hnum, const int dif) 311 311 { 312 312 struct sock *sk, *reuse_sk; 313 313 bool no_reuseport; ··· 315 315 if (hashinfo != &tcp_hashinfo) 316 316 return NULL; /* only TCP is supported */ 317 317 318 - no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_TCP, 319 - saddr, sport, daddr, hnum, &sk); 318 + no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_TCP, saddr, sport, 319 + daddr, hnum, dif, &sk); 320 320 if (no_reuseport || IS_ERR_OR_NULL(sk)) 321 321 return sk; 322 322 ··· 340 340 /* Lookup redirect from BPF */ 341 341 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) { 342 342 result = inet_lookup_run_bpf(net, hashinfo, skb, doff, 343 - saddr, sport, daddr, hnum); 343 + saddr, sport, daddr, hnum, dif); 344 344 if (result) 345 345 goto done; 346 346 }
+4 -4
net/ipv4/udp.c
··· 460 460 struct udp_table *udptable, 461 461 struct sk_buff *skb, 462 462 __be32 saddr, __be16 sport, 463 - __be32 daddr, u16 hnum) 463 + __be32 daddr, u16 hnum, const int dif) 464 464 { 465 465 struct sock *sk, *reuse_sk; 466 466 bool no_reuseport; ··· 468 468 if (udptable != &udp_table) 469 469 return NULL; /* only UDP is supported */ 470 470 471 - no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_UDP, 472 - saddr, sport, daddr, hnum, &sk); 471 + no_reuseport = bpf_sk_lookup_run_v4(net, IPPROTO_UDP, saddr, sport, 472 + daddr, hnum, dif, &sk); 473 473 if (no_reuseport || IS_ERR_OR_NULL(sk)) 474 474 return sk; 475 475 ··· 505 505 /* Lookup redirect from BPF */ 506 506 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) { 507 507 sk = udp4_lookup_run_bpf(net, udptable, skb, 508 - saddr, sport, daddr, hnum); 508 + saddr, sport, daddr, hnum, dif); 509 509 if (sk) { 510 510 result = sk; 511 511 goto done;
+4 -4
net/ipv6/inet6_hashtables.c
··· 165 165 const struct in6_addr *saddr, 166 166 const __be16 sport, 167 167 const struct in6_addr *daddr, 168 - const u16 hnum) 168 + const u16 hnum, const int dif) 169 169 { 170 170 struct sock *sk, *reuse_sk; 171 171 bool no_reuseport; ··· 173 173 if (hashinfo != &tcp_hashinfo) 174 174 return NULL; /* only TCP is supported */ 175 175 176 - no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP, 177 - saddr, sport, daddr, hnum, &sk); 176 + no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP, saddr, sport, 177 + daddr, hnum, dif, &sk); 178 178 if (no_reuseport || IS_ERR_OR_NULL(sk)) 179 179 return sk; 180 180 ··· 198 198 /* Lookup redirect from BPF */ 199 199 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) { 200 200 result = inet6_lookup_run_bpf(net, hashinfo, skb, doff, 201 - saddr, sport, daddr, hnum); 201 + saddr, sport, daddr, hnum, dif); 202 202 if (result) 203 203 goto done; 204 204 }
+4 -4
net/ipv6/udp.c
··· 195 195 const struct in6_addr *saddr, 196 196 __be16 sport, 197 197 const struct in6_addr *daddr, 198 - u16 hnum) 198 + u16 hnum, const int dif) 199 199 { 200 200 struct sock *sk, *reuse_sk; 201 201 bool no_reuseport; ··· 203 203 if (udptable != &udp_table) 204 204 return NULL; /* only UDP is supported */ 205 205 206 - no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP, 207 - saddr, sport, daddr, hnum, &sk); 206 + no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP, saddr, sport, 207 + daddr, hnum, dif, &sk); 208 208 if (no_reuseport || IS_ERR_OR_NULL(sk)) 209 209 return sk; 210 210 ··· 240 240 /* Lookup redirect from BPF */ 241 241 if (static_branch_unlikely(&bpf_sk_lookup_enabled)) { 242 242 sk = udp6_lookup_run_bpf(net, udptable, skb, 243 - saddr, sport, daddr, hnum); 243 + saddr, sport, daddr, hnum, dif); 244 244 if (sk) { 245 245 result = sk; 246 246 goto done;
+1
tools/include/uapi/linux/bpf.h
··· 6316 6316 __u32 local_ip4; /* Network byte order */ 6317 6317 __u32 local_ip6[4]; /* Network byte order */ 6318 6318 __u32 local_port; /* Host byte order */ 6319 + __u32 ingress_ifindex; /* The arriving interface. Determined by inet_iif. */ 6319 6320 }; 6320 6321 6321 6322 /*