net/ipv4/udp.c

Source file repositories/reference/linux-study-clean/net/ipv4/udp.c

File Facts

System
Linux kernel
Corpus path
net/ipv4/udp.c
Extension
.c
Size
99370 bytes
Lines
3893
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct bpf_iter__udp {
	__bpf_md_ptr(struct bpf_iter_meta *, meta);
	__bpf_md_ptr(struct udp_sock *, udp_sk);
	uid_t uid __aligned(8);
	int bucket __aligned(8);
};

union bpf_udp_iter_batch_item {
	struct sock *sk;
	__u64 cookie;
};

struct bpf_udp_iter_state {
	struct udp_iter_state state;
	unsigned int cur_sk;
	unsigned int end_sk;
	unsigned int max_sk;
	union bpf_udp_iter_batch_item *batch;
};

static int bpf_iter_udp_realloc_batch(struct bpf_udp_iter_state *iter,
				      unsigned int new_batch_sz, gfp_t flags);
static struct sock *bpf_iter_udp_resume(struct sock *first_sk,
					union bpf_udp_iter_batch_item *cookies,
					int n_cookies)
{
	struct sock *sk = NULL;
	int i;

	for (i = 0; i < n_cookies; i++) {
		sk = first_sk;
		udp_portaddr_for_each_entry_from(sk)
			if (cookies[i].cookie == atomic64_read(&sk->sk_cookie))
				goto done;
	}
done:
	return sk;
}

static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
{
	struct bpf_udp_iter_state *iter = seq->private;
	struct udp_iter_state *state = &iter->state;
	unsigned int find_cookie, end_cookie;
	struct net *net = seq_file_net(seq);
	struct udp_table *udptable;
	unsigned int batch_sks = 0;
	int resume_bucket;
	int resizes = 0;
	struct sock *sk;
	int err = 0;

	resume_bucket = state->bucket;

	/* The current batch is done, so advance the bucket. */
	if (iter->cur_sk == iter->end_sk)
		state->bucket++;

	udptable = net->ipv4.udp_table;

again:
	/* New batch for the next bucket.
	 * Iterate over the hash table to find a bucket with sockets matching
	 * the iterator attributes, and return the first matching socket from
	 * the bucket. The remaining matched sockets from the bucket are batched
	 * before releasing the bucket lock. This allows BPF programs that are
	 * called in seq_show to acquire the bucket lock if needed.
	 */
	find_cookie = iter->cur_sk;
	end_cookie = iter->end_sk;
	iter->cur_sk = 0;
	iter->end_sk = 0;
	batch_sks = 0;

	for (; state->bucket <= udptable->mask; state->bucket++) {
		struct udp_hslot *hslot2 = &udptable->hash2[state->bucket].hslot;

		if (hlist_empty(&hslot2->head))
			goto next_bucket;

		spin_lock_bh(&hslot2->lock);
		sk = hlist_entry_safe(hslot2->head.first, struct sock,
				      __sk_common.skc_portaddr_node);
		/* Resume from the first (in iteration order) unseen socket from
		 * the last batch that still exists in resume_bucket. Most of
		 * the time this will just be where the last iteration left off
		 * in resume_bucket unless that socket disappeared between
		 * reads.
		 */
		if (state->bucket == resume_bucket)

Annotation

Implementation Notes