FILE
sock_iter_batch.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/bpf/progs/sock_iter_batch.c
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (c) 2024 Meta 3 4#include "vmlinux.h" 5#include <bpf/bpf_helpers.h> 6#include <bpf/bpf_core_read.h> 7#include <bpf/bpf_endian.h> 8#include "bpf_tracing_net.h" 9#include "bpf_kfuncs.h" 10 11#define ATTR __always_inline 12#include "test_jhash.h" 13 14static bool ipv6_addr_loopback(const struct in6_addr *a) 15{ 16 return (a->s6_addr32[0] | a->s6_addr32[1] | 17 a->s6_addr32[2] | (a->s6_addr32[3] ^ bpf_htonl(1))) == 0; 18} 19 20static bool ipv4_addr_loopback(__be32 a) 21{ 22 return a == bpf_ntohl(0x7f000001); 23} 24 25volatile const unsigned int sf; 26volatile const unsigned int ss; 27volatile const __u16 ports[2]; 28unsigned int bucket[2]; 29 30SEC("iter/tcp") 31int iter_tcp_soreuse(struct bpf_iter__tcp *ctx) 32{ 33 struct sock *sk = (struct sock *)ctx->sk_common; 34 struct inet_hashinfo *hinfo; 35 unsigned int hash; 36 __u64 sock_cookie; 37 struct net *net; 38 int idx; 39 40 if (!sk) 41 return 0; 42 43 sock_cookie = bpf_get_socket_cookie(sk); 44 sk = bpf_core_cast(sk, struct sock); 45 if (sk->sk_family != sf || 46 (ss && sk->sk_state != ss) || 47 (sk->sk_family == AF_INET6 ? 48 !ipv6_addr_loopback(&sk->sk_v6_rcv_saddr) : 49 !ipv4_addr_loopback(sk->sk_rcv_saddr))) 50 return 0; 51 52 if (sk->sk_num == ports[0]) 53 idx = 0; 54 else if (sk->sk_num == ports[1]) 55 idx = 1; 56 else if (!ports[0] && !ports[1]) 57 idx = 0; 58 else 59 return 0; 60 61 /* bucket selection as in inet_lhash2_bucket_sk() */ 62 net = sk->sk_net.net; 63 hash = jhash2(sk->sk_v6_rcv_saddr.s6_addr32, 4, net->hash_mix); 64 hash ^= sk->sk_num; 65 hinfo = net->ipv4.tcp_death_row.hashinfo; 66 bucket[idx] = hash & hinfo->lhash2_mask; 67 bpf_seq_write(ctx->meta->seq, &idx, sizeof(idx)); 68 bpf_seq_write(ctx->meta->seq, &sock_cookie, sizeof(sock_cookie)); 69 70 return 0; 71} 72 73volatile const __u64 destroy_cookie; 74 75SEC("iter/tcp") 76int iter_tcp_destroy(struct bpf_iter__tcp *ctx) 77{ 78 struct sock_common *sk_common = (struct sock_common *)ctx->sk_common; 79 __u64 sock_cookie; 80 81 if (!sk_common) 82 return 0; 83 84 sock_cookie = bpf_get_socket_cookie(sk_common); 85 if (sock_cookie != destroy_cookie) 86 return 0; 87 88 bpf_sock_destroy(sk_common); 89 bpf_seq_write(ctx->meta->seq, &sock_cookie, sizeof(sock_cookie)); 90 91 return 0; 92} 93 94#define udp_sk(ptr) container_of(ptr, struct udp_sock, inet.sk) 95 96SEC("iter/udp") 97int iter_udp_soreuse(struct bpf_iter__udp *ctx) 98{ 99 struct sock *sk = (struct sock *)ctx->udp_sk; 100 struct udp_table *udptable; 101 __u64 sock_cookie; 102 int idx; 103 104 if (!sk) 105 return 0; 106 107 sock_cookie = bpf_get_socket_cookie(sk); 108 sk = bpf_core_cast(sk, struct sock); 109 if (sk->sk_family != sf || 110 (sk->sk_family == AF_INET6 ? 111 !ipv6_addr_loopback(&sk->sk_v6_rcv_saddr) : 112 !ipv4_addr_loopback(sk->sk_rcv_saddr))) 113 return 0; 114 115 if (sk->sk_num == ports[0]) 116 idx = 0; 117 else if (sk->sk_num == ports[1]) 118 idx = 1; 119 else if (!ports[0] && !ports[1]) 120 idx = 0; 121 else 122 return 0; 123 124 /* bucket selection as in udp_hashslot2() */ 125 udptable = sk->sk_net.net->ipv4.udp_table; 126 bucket[idx] = udp_sk(sk)->udp_portaddr_hash & udptable->mask; 127 bpf_seq_write(ctx->meta->seq, &idx, sizeof(idx)); 128 bpf_seq_write(ctx->meta->seq, &sock_cookie, sizeof(sock_cookie)); 129 130 return 0; 131} 132 133char _license[] SEC("license") = "GPL";
~/
Read-only file preview.