File Index
Files and directories
Sign in
FILE

sock_iter_batch.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/sock_iter_batch.c 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.