net/ipv4/tcp.c

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

File Facts

System
Linux kernel
Corpus path
net/ipv4/tcp.c
Extension
.c
Size
149832 bytes
Lines
5383
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 tcp_xa_pool {
	u8		max; /* max <= MAX_SKB_FRAGS */
	u8		idx; /* idx <= max */
	__u32		tokens[MAX_SKB_FRAGS];
	netmem_ref	netmems[MAX_SKB_FRAGS];
};

static void tcp_xa_pool_commit_locked(struct sock *sk, struct tcp_xa_pool *p)
{
	int i;

	/* Commit part that has been copied to user space. */
	for (i = 0; i < p->idx; i++)
		__xa_cmpxchg(&sk->sk_user_frags, p->tokens[i], XA_ZERO_ENTRY,
			     (__force void *)p->netmems[i], GFP_KERNEL);
	/* Rollback what has been pre-allocated and is no longer needed. */
	for (; i < p->max; i++)
		__xa_erase(&sk->sk_user_frags, p->tokens[i]);

	p->max = 0;
	p->idx = 0;
}

static void tcp_xa_pool_commit(struct sock *sk, struct tcp_xa_pool *p)
{
	if (!p->max)
		return;

	xa_lock_bh(&sk->sk_user_frags);

	tcp_xa_pool_commit_locked(sk, p);

	xa_unlock_bh(&sk->sk_user_frags);
}

static int tcp_xa_pool_refill(struct sock *sk, struct tcp_xa_pool *p,
			      unsigned int max_frags)
{
	int err, k;

	if (p->idx < p->max)
		return 0;

	xa_lock_bh(&sk->sk_user_frags);

	tcp_xa_pool_commit_locked(sk, p);

	for (k = 0; k < max_frags; k++) {
		err = __xa_alloc(&sk->sk_user_frags, &p->tokens[k],
				 XA_ZERO_ENTRY, xa_limit_31b, GFP_KERNEL);
		if (err)
			break;
	}

	xa_unlock_bh(&sk->sk_user_frags);

	p->max = k;
	p->idx = 0;
	return k ? 0 : err;
}

/* On error, returns the -errno. On success, returns number of bytes sent to the
 * user. May not consume all of @remaining_len.
 */
static int tcp_recvmsg_dmabuf(struct sock *sk, const struct sk_buff *skb,
			      unsigned int offset, struct msghdr *msg,
			      int remaining_len)
{
	struct dmabuf_cmsg dmabuf_cmsg = { 0 };
	struct tcp_xa_pool tcp_xa_pool;
	unsigned int start;
	int i, copy, n;
	int sent = 0;
	int err = 0;

	tcp_xa_pool.max = 0;
	tcp_xa_pool.idx = 0;
	do {
		start = skb_headlen(skb);

		if (skb_frags_readable(skb)) {
			err = -ENODEV;
			goto out;
		}

		/* Copy header. */
		copy = start - offset;
		if (copy > 0) {
			copy = min(copy, remaining_len);

Annotation

Implementation Notes