net/mptcp/protocol.c

Source file repositories/reference/linux-study-clean/net/mptcp/protocol.c

File Facts

System
Linux kernel
Corpus path
net/mptcp/protocol.c
Extension
.c
Size
122778 bytes
Lines
4736
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern 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

static const struct proto_ops *mptcp_fallback_tcp_ops(const struct sock *sk)
{
	unsigned short family = READ_ONCE(sk->sk_family);

#if IS_ENABLED(CONFIG_MPTCP_IPV6)
	if (family == AF_INET6)
		return &inet6_stream_ops;
#endif
	WARN_ON_ONCE(family != AF_INET);
	return &inet_stream_ops;
}

bool __mptcp_try_fallback(struct mptcp_sock *msk, int fb_mib)
{
	struct net *net = sock_net((struct sock *)msk);

	if (__mptcp_check_fallback(msk))
		return true;

	/* The caller possibly is not holding the msk socket lock, but
	 * in the fallback case only the current subflow is touching
	 * the OoO queue.
	 */
	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
		return false;

	spin_lock_bh(&msk->fallback_lock);
	if (!msk->allow_infinite_fallback) {
		spin_unlock_bh(&msk->fallback_lock);
		return false;
	}

	msk->allow_subflows = false;
	set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
	__MPTCP_INC_STATS(net, fb_mib);
	spin_unlock_bh(&msk->fallback_lock);
	return true;
}

static int __mptcp_socket_create(struct mptcp_sock *msk)
{
	struct mptcp_subflow_context *subflow;
	struct sock *sk = (struct sock *)msk;
	struct socket *ssock;
	int err;

	err = mptcp_subflow_create_socket(sk, sk->sk_family, &ssock);
	if (err)
		return err;

	msk->scaling_ratio = tcp_sk(ssock->sk)->scaling_ratio;
	WRITE_ONCE(msk->first, ssock->sk);
	subflow = mptcp_subflow_ctx(ssock->sk);
	list_add(&subflow->node, &msk->conn_list);
	sock_hold(ssock->sk);
	subflow->request_mptcp = 1;
	subflow->subflow_id = msk->subflow_id++;

	/* This is the first subflow, always with id 0 */
	WRITE_ONCE(subflow->local_id, 0);
	mptcp_sock_graft(msk->first, sk->sk_socket);
	iput(SOCK_INODE(ssock));

	return 0;
}

/* If the MPC handshake is not started, returns the first subflow,
 * eventually allocating it.
 */
struct sock *__mptcp_nmpc_sk(struct mptcp_sock *msk)
{
	struct sock *sk = (struct sock *)msk;
	int ret;

	if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
		return ERR_PTR(-EINVAL);

	if (!msk->first) {
		ret = __mptcp_socket_create(msk);
		if (ret)
			return ERR_PTR(ret);
	}

	return msk->first;
}

static void mptcp_drop(struct sock *sk, struct sk_buff *skb)
{
	sk_drops_skbadd(sk, skb);
	__kfree_skb(skb);

Annotation

Implementation Notes