162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Multipath TCP
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2019, Intel Corporation.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#define pr_fmt(fmt) "MPTCP: " fmt
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include <net/tcp.h>
1062306a36Sopenharmony_ci#include <net/mptcp.h>
1162306a36Sopenharmony_ci#include "protocol.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "mib.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* path manager command handlers */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ciint mptcp_pm_announce_addr(struct mptcp_sock *msk,
1862306a36Sopenharmony_ci			   const struct mptcp_addr_info *addr,
1962306a36Sopenharmony_ci			   bool echo)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	u8 add_addr = READ_ONCE(msk->pm.addr_signal);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	pr_debug("msk=%p, local_id=%d, echo=%d", msk, addr->id, echo);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	lockdep_assert_held(&msk->pm.lock);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	if (add_addr &
2862306a36Sopenharmony_ci	    (echo ? BIT(MPTCP_ADD_ADDR_ECHO) : BIT(MPTCP_ADD_ADDR_SIGNAL))) {
2962306a36Sopenharmony_ci		MPTCP_INC_STATS(sock_net((struct sock *)msk),
3062306a36Sopenharmony_ci				echo ? MPTCP_MIB_ECHOADDTXDROP : MPTCP_MIB_ADDADDRTXDROP);
3162306a36Sopenharmony_ci		return -EINVAL;
3262306a36Sopenharmony_ci	}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	if (echo) {
3562306a36Sopenharmony_ci		msk->pm.remote = *addr;
3662306a36Sopenharmony_ci		add_addr |= BIT(MPTCP_ADD_ADDR_ECHO);
3762306a36Sopenharmony_ci	} else {
3862306a36Sopenharmony_ci		msk->pm.local = *addr;
3962306a36Sopenharmony_ci		add_addr |= BIT(MPTCP_ADD_ADDR_SIGNAL);
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci	WRITE_ONCE(msk->pm.addr_signal, add_addr);
4262306a36Sopenharmony_ci	return 0;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ciint mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	u8 rm_addr = READ_ONCE(msk->pm.addr_signal);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	if (rm_addr) {
5262306a36Sopenharmony_ci		MPTCP_ADD_STATS(sock_net((struct sock *)msk),
5362306a36Sopenharmony_ci				MPTCP_MIB_RMADDRTXDROP, rm_list->nr);
5462306a36Sopenharmony_ci		return -EINVAL;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	msk->pm.rm_list_tx = *rm_list;
5862306a36Sopenharmony_ci	rm_addr |= BIT(MPTCP_RM_ADDR_SIGNAL);
5962306a36Sopenharmony_ci	WRITE_ONCE(msk->pm.addr_signal, rm_addr);
6062306a36Sopenharmony_ci	mptcp_pm_nl_addr_send_ack(msk);
6162306a36Sopenharmony_ci	return 0;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciint mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	spin_lock_bh(&msk->pm.lock);
6962306a36Sopenharmony_ci	mptcp_pm_nl_rm_subflow_received(msk, rm_list);
7062306a36Sopenharmony_ci	spin_unlock_bh(&msk->pm.lock);
7162306a36Sopenharmony_ci	return 0;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/* path manager event handlers */
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_civoid mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	pr_debug("msk=%p, token=%u side=%d", msk, msk->token, server_side);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	WRITE_ONCE(pm->server_side, server_side);
8362306a36Sopenharmony_ci	mptcp_event(MPTCP_EVENT_CREATED, msk, ssk, GFP_ATOMIC);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cibool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
8962306a36Sopenharmony_ci	unsigned int subflows_max;
9062306a36Sopenharmony_ci	int ret = 0;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	if (mptcp_pm_is_userspace(msk)) {
9362306a36Sopenharmony_ci		if (mptcp_userspace_pm_active(msk)) {
9462306a36Sopenharmony_ci			spin_lock_bh(&pm->lock);
9562306a36Sopenharmony_ci			pm->subflows++;
9662306a36Sopenharmony_ci			spin_unlock_bh(&pm->lock);
9762306a36Sopenharmony_ci			return true;
9862306a36Sopenharmony_ci		}
9962306a36Sopenharmony_ci		return false;
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	subflows_max = mptcp_pm_get_subflows_max(msk);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows,
10562306a36Sopenharmony_ci		 subflows_max, READ_ONCE(pm->accept_subflow));
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* try to avoid acquiring the lock below */
10862306a36Sopenharmony_ci	if (!READ_ONCE(pm->accept_subflow))
10962306a36Sopenharmony_ci		return false;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
11262306a36Sopenharmony_ci	if (READ_ONCE(pm->accept_subflow)) {
11362306a36Sopenharmony_ci		ret = pm->subflows < subflows_max;
11462306a36Sopenharmony_ci		if (ret && ++pm->subflows == subflows_max)
11562306a36Sopenharmony_ci			WRITE_ONCE(pm->accept_subflow, false);
11662306a36Sopenharmony_ci	}
11762306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return ret;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/* return true if the new status bit is currently cleared, that is, this event
12362306a36Sopenharmony_ci * can be server, eventually by an already scheduled work
12462306a36Sopenharmony_ci */
12562306a36Sopenharmony_cistatic bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
12662306a36Sopenharmony_ci				   enum mptcp_pm_status new_status)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	pr_debug("msk=%p status=%x new=%lx", msk, msk->pm.status,
12962306a36Sopenharmony_ci		 BIT(new_status));
13062306a36Sopenharmony_ci	if (msk->pm.status & BIT(new_status))
13162306a36Sopenharmony_ci		return false;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	msk->pm.status |= BIT(new_status);
13462306a36Sopenharmony_ci	mptcp_schedule_work((struct sock *)msk);
13562306a36Sopenharmony_ci	return true;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_civoid mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
14162306a36Sopenharmony_ci	bool announce = false;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	pr_debug("msk=%p", msk);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* mptcp_pm_fully_established() can be invoked by multiple
14862306a36Sopenharmony_ci	 * racing paths - accept() and check_fully_established()
14962306a36Sopenharmony_ci	 * be sure to serve this event only once.
15062306a36Sopenharmony_ci	 */
15162306a36Sopenharmony_ci	if (READ_ONCE(pm->work_pending) &&
15262306a36Sopenharmony_ci	    !(msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)))
15362306a36Sopenharmony_ci		mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if ((msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)) == 0)
15662306a36Sopenharmony_ci		announce = true;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	msk->pm.status |= BIT(MPTCP_PM_ALREADY_ESTABLISHED);
15962306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (announce)
16262306a36Sopenharmony_ci		mptcp_event(MPTCP_EVENT_ESTABLISHED, msk, ssk, GFP_ATOMIC);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_civoid mptcp_pm_connection_closed(struct mptcp_sock *msk)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	pr_debug("msk=%p", msk);
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_civoid mptcp_pm_subflow_established(struct mptcp_sock *msk)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	pr_debug("msk=%p", msk);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (!READ_ONCE(pm->work_pending))
17762306a36Sopenharmony_ci		return;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (READ_ONCE(pm->work_pending))
18262306a36Sopenharmony_ci		mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_civoid mptcp_pm_subflow_check_next(struct mptcp_sock *msk, const struct sock *ssk,
18862306a36Sopenharmony_ci				 const struct mptcp_subflow_context *subflow)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
19162306a36Sopenharmony_ci	bool update_subflows;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	update_subflows = subflow->request_join || subflow->mp_join;
19462306a36Sopenharmony_ci	if (mptcp_pm_is_userspace(msk)) {
19562306a36Sopenharmony_ci		if (update_subflows) {
19662306a36Sopenharmony_ci			spin_lock_bh(&pm->lock);
19762306a36Sopenharmony_ci			pm->subflows--;
19862306a36Sopenharmony_ci			spin_unlock_bh(&pm->lock);
19962306a36Sopenharmony_ci		}
20062306a36Sopenharmony_ci		return;
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	if (!READ_ONCE(pm->work_pending) && !update_subflows)
20462306a36Sopenharmony_ci		return;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
20762306a36Sopenharmony_ci	if (update_subflows)
20862306a36Sopenharmony_ci		__mptcp_pm_close_subflow(msk);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/* Even if this subflow is not really established, tell the PM to try
21162306a36Sopenharmony_ci	 * to pick the next ones, if possible.
21262306a36Sopenharmony_ci	 */
21362306a36Sopenharmony_ci	if (mptcp_pm_nl_check_work_pending(msk))
21462306a36Sopenharmony_ci		mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_civoid mptcp_pm_add_addr_received(const struct sock *ssk,
22062306a36Sopenharmony_ci				const struct mptcp_addr_info *addr)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
22362306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
22462306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id,
22762306a36Sopenharmony_ci		 READ_ONCE(pm->accept_addr));
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	mptcp_event_addr_announced(ssk, addr);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (mptcp_pm_is_userspace(msk)) {
23462306a36Sopenharmony_ci		if (mptcp_userspace_pm_active(msk)) {
23562306a36Sopenharmony_ci			mptcp_pm_announce_addr(msk, addr, true);
23662306a36Sopenharmony_ci			mptcp_pm_add_addr_send_ack(msk);
23762306a36Sopenharmony_ci		} else {
23862306a36Sopenharmony_ci			__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
23962306a36Sopenharmony_ci		}
24062306a36Sopenharmony_ci	} else if (!READ_ONCE(pm->accept_addr)) {
24162306a36Sopenharmony_ci		mptcp_pm_announce_addr(msk, addr, true);
24262306a36Sopenharmony_ci		mptcp_pm_add_addr_send_ack(msk);
24362306a36Sopenharmony_ci	} else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
24462306a36Sopenharmony_ci		pm->remote = *addr;
24562306a36Sopenharmony_ci	} else {
24662306a36Sopenharmony_ci		__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_civoid mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
25362306a36Sopenharmony_ci			      const struct mptcp_addr_info *addr)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	pr_debug("msk=%p", msk);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (mptcp_lookup_anno_list_by_saddr(msk, addr) && READ_ONCE(pm->work_pending))
26262306a36Sopenharmony_ci		mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_civoid mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	if (!mptcp_pm_should_add_signal(msk))
27062306a36Sopenharmony_ci		return;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_SEND_ACK);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_civoid mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
27662306a36Sopenharmony_ci			       const struct mptcp_rm_list *rm_list)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
27962306a36Sopenharmony_ci	u8 i;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	pr_debug("msk=%p remote_ids_nr=%d", msk, rm_list->nr);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	for (i = 0; i < rm_list->nr; i++)
28462306a36Sopenharmony_ci		mptcp_event_addr_removed(msk, rm_list->ids[i]);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	spin_lock_bh(&pm->lock);
28762306a36Sopenharmony_ci	if (mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED))
28862306a36Sopenharmony_ci		pm->rm_list_rx = *rm_list;
28962306a36Sopenharmony_ci	else
29062306a36Sopenharmony_ci		__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_RMADDRDROP);
29162306a36Sopenharmony_ci	spin_unlock_bh(&pm->lock);
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_civoid mptcp_pm_mp_prio_received(struct sock *ssk, u8 bkup)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
29762306a36Sopenharmony_ci	struct sock *sk = subflow->conn;
29862306a36Sopenharmony_ci	struct mptcp_sock *msk;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	pr_debug("subflow->backup=%d, bkup=%d\n", subflow->backup, bkup);
30162306a36Sopenharmony_ci	msk = mptcp_sk(sk);
30262306a36Sopenharmony_ci	if (subflow->backup != bkup)
30362306a36Sopenharmony_ci		subflow->backup = bkup;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	mptcp_event(MPTCP_EVENT_SUB_PRIORITY, msk, ssk, GFP_ATOMIC);
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_civoid mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
31162306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	pr_debug("fail_seq=%llu", fail_seq);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (!READ_ONCE(msk->allow_infinite_fallback))
31662306a36Sopenharmony_ci		return;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	if (!subflow->fail_tout) {
31962306a36Sopenharmony_ci		pr_debug("send MP_FAIL response and infinite map");
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci		subflow->send_mp_fail = 1;
32262306a36Sopenharmony_ci		subflow->send_infinite_map = 1;
32362306a36Sopenharmony_ci		tcp_send_ack(sk);
32462306a36Sopenharmony_ci	} else {
32562306a36Sopenharmony_ci		pr_debug("MP_FAIL response received");
32662306a36Sopenharmony_ci		WRITE_ONCE(subflow->fail_tout, 0);
32762306a36Sopenharmony_ci	}
32862306a36Sopenharmony_ci}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci/* path manager helpers */
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cibool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, const struct sk_buff *skb,
33362306a36Sopenharmony_ci			      unsigned int opt_size, unsigned int remaining,
33462306a36Sopenharmony_ci			      struct mptcp_addr_info *addr, bool *echo,
33562306a36Sopenharmony_ci			      bool *drop_other_suboptions)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	int ret = false;
33862306a36Sopenharmony_ci	u8 add_addr;
33962306a36Sopenharmony_ci	u8 family;
34062306a36Sopenharmony_ci	bool port;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	spin_lock_bh(&msk->pm.lock);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	/* double check after the lock is acquired */
34562306a36Sopenharmony_ci	if (!mptcp_pm_should_add_signal(msk))
34662306a36Sopenharmony_ci		goto out_unlock;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	/* always drop every other options for pure ack ADD_ADDR; this is a
34962306a36Sopenharmony_ci	 * plain dup-ack from TCP perspective. The other MPTCP-relevant info,
35062306a36Sopenharmony_ci	 * if any, will be carried by the 'original' TCP ack
35162306a36Sopenharmony_ci	 */
35262306a36Sopenharmony_ci	if (skb && skb_is_tcp_pure_ack(skb)) {
35362306a36Sopenharmony_ci		remaining += opt_size;
35462306a36Sopenharmony_ci		*drop_other_suboptions = true;
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	*echo = mptcp_pm_should_add_signal_echo(msk);
35862306a36Sopenharmony_ci	port = !!(*echo ? msk->pm.remote.port : msk->pm.local.port);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	family = *echo ? msk->pm.remote.family : msk->pm.local.family;
36162306a36Sopenharmony_ci	if (remaining < mptcp_add_addr_len(family, *echo, port))
36262306a36Sopenharmony_ci		goto out_unlock;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (*echo) {
36562306a36Sopenharmony_ci		*addr = msk->pm.remote;
36662306a36Sopenharmony_ci		add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_ECHO);
36762306a36Sopenharmony_ci	} else {
36862306a36Sopenharmony_ci		*addr = msk->pm.local;
36962306a36Sopenharmony_ci		add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_SIGNAL);
37062306a36Sopenharmony_ci	}
37162306a36Sopenharmony_ci	WRITE_ONCE(msk->pm.addr_signal, add_addr);
37262306a36Sopenharmony_ci	ret = true;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ciout_unlock:
37562306a36Sopenharmony_ci	spin_unlock_bh(&msk->pm.lock);
37662306a36Sopenharmony_ci	return ret;
37762306a36Sopenharmony_ci}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cibool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
38062306a36Sopenharmony_ci			     struct mptcp_rm_list *rm_list)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	int ret = false, len;
38362306a36Sopenharmony_ci	u8 rm_addr;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	spin_lock_bh(&msk->pm.lock);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	/* double check after the lock is acquired */
38862306a36Sopenharmony_ci	if (!mptcp_pm_should_rm_signal(msk))
38962306a36Sopenharmony_ci		goto out_unlock;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	rm_addr = msk->pm.addr_signal & ~BIT(MPTCP_RM_ADDR_SIGNAL);
39262306a36Sopenharmony_ci	len = mptcp_rm_addr_len(&msk->pm.rm_list_tx);
39362306a36Sopenharmony_ci	if (len < 0) {
39462306a36Sopenharmony_ci		WRITE_ONCE(msk->pm.addr_signal, rm_addr);
39562306a36Sopenharmony_ci		goto out_unlock;
39662306a36Sopenharmony_ci	}
39762306a36Sopenharmony_ci	if (remaining < len)
39862306a36Sopenharmony_ci		goto out_unlock;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	*rm_list = msk->pm.rm_list_tx;
40162306a36Sopenharmony_ci	WRITE_ONCE(msk->pm.addr_signal, rm_addr);
40262306a36Sopenharmony_ci	ret = true;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ciout_unlock:
40562306a36Sopenharmony_ci	spin_unlock_bh(&msk->pm.lock);
40662306a36Sopenharmony_ci	return ret;
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ciint mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	struct mptcp_addr_info skc_local;
41262306a36Sopenharmony_ci	struct mptcp_addr_info msk_local;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	if (WARN_ON_ONCE(!msk))
41562306a36Sopenharmony_ci		return -1;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	/* The 0 ID mapping is defined by the first subflow, copied into the msk
41862306a36Sopenharmony_ci	 * addr
41962306a36Sopenharmony_ci	 */
42062306a36Sopenharmony_ci	mptcp_local_address((struct sock_common *)msk, &msk_local);
42162306a36Sopenharmony_ci	mptcp_local_address((struct sock_common *)skc, &skc_local);
42262306a36Sopenharmony_ci	if (mptcp_addresses_equal(&msk_local, &skc_local, false))
42362306a36Sopenharmony_ci		return 0;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	if (mptcp_pm_is_userspace(msk))
42662306a36Sopenharmony_ci		return mptcp_userspace_pm_get_local_id(msk, &skc_local);
42762306a36Sopenharmony_ci	return mptcp_pm_nl_get_local_id(msk, &skc_local);
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ciint mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id,
43162306a36Sopenharmony_ci					 u8 *flags, int *ifindex)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	*flags = 0;
43462306a36Sopenharmony_ci	*ifindex = 0;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	if (!id)
43762306a36Sopenharmony_ci		return 0;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	if (mptcp_pm_is_userspace(msk))
44062306a36Sopenharmony_ci		return mptcp_userspace_pm_get_flags_and_ifindex_by_id(msk, id, flags, ifindex);
44162306a36Sopenharmony_ci	return mptcp_pm_nl_get_flags_and_ifindex_by_id(msk, id, flags, ifindex);
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ciint mptcp_pm_set_flags(struct net *net, struct nlattr *token,
44562306a36Sopenharmony_ci		       struct mptcp_pm_addr_entry *loc,
44662306a36Sopenharmony_ci		       struct mptcp_pm_addr_entry *rem, u8 bkup)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	if (token)
44962306a36Sopenharmony_ci		return mptcp_userspace_pm_set_flags(net, token, loc, rem, bkup);
45062306a36Sopenharmony_ci	return mptcp_pm_nl_set_flags(net, loc, bkup);
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_civoid mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
45662306a36Sopenharmony_ci	u32 rcv_tstamp = READ_ONCE(tcp_sk(ssk)->rcv_tstamp);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	/* keep track of rtx periods with no progress */
45962306a36Sopenharmony_ci	if (!subflow->stale_count) {
46062306a36Sopenharmony_ci		subflow->stale_rcv_tstamp = rcv_tstamp;
46162306a36Sopenharmony_ci		subflow->stale_count++;
46262306a36Sopenharmony_ci	} else if (subflow->stale_rcv_tstamp == rcv_tstamp) {
46362306a36Sopenharmony_ci		if (subflow->stale_count < U8_MAX)
46462306a36Sopenharmony_ci			subflow->stale_count++;
46562306a36Sopenharmony_ci		mptcp_pm_nl_subflow_chk_stale(msk, ssk);
46662306a36Sopenharmony_ci	} else {
46762306a36Sopenharmony_ci		subflow->stale_count = 0;
46862306a36Sopenharmony_ci		mptcp_subflow_set_active(subflow);
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci/* if sk is ipv4 or ipv6_only allows only same-family local and remote addresses,
47362306a36Sopenharmony_ci * otherwise allow any matching local/remote pair
47462306a36Sopenharmony_ci */
47562306a36Sopenharmony_cibool mptcp_pm_addr_families_match(const struct sock *sk,
47662306a36Sopenharmony_ci				  const struct mptcp_addr_info *loc,
47762306a36Sopenharmony_ci				  const struct mptcp_addr_info *rem)
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	bool mptcp_is_v4 = sk->sk_family == AF_INET;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
48262306a36Sopenharmony_ci	bool loc_is_v4 = loc->family == AF_INET || ipv6_addr_v4mapped(&loc->addr6);
48362306a36Sopenharmony_ci	bool rem_is_v4 = rem->family == AF_INET || ipv6_addr_v4mapped(&rem->addr6);
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	if (mptcp_is_v4)
48662306a36Sopenharmony_ci		return loc_is_v4 && rem_is_v4;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	if (ipv6_only_sock(sk))
48962306a36Sopenharmony_ci		return !loc_is_v4 && !rem_is_v4;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	return loc_is_v4 == rem_is_v4;
49262306a36Sopenharmony_ci#else
49362306a36Sopenharmony_ci	return mptcp_is_v4 && loc->family == AF_INET && rem->family == AF_INET;
49462306a36Sopenharmony_ci#endif
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_civoid mptcp_pm_data_reset(struct mptcp_sock *msk)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	u8 pm_type = mptcp_get_pm_type(sock_net((struct sock *)msk));
50062306a36Sopenharmony_ci	struct mptcp_pm_data *pm = &msk->pm;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	pm->add_addr_signaled = 0;
50362306a36Sopenharmony_ci	pm->add_addr_accepted = 0;
50462306a36Sopenharmony_ci	pm->local_addr_used = 0;
50562306a36Sopenharmony_ci	pm->subflows = 0;
50662306a36Sopenharmony_ci	pm->rm_list_tx.nr = 0;
50762306a36Sopenharmony_ci	pm->rm_list_rx.nr = 0;
50862306a36Sopenharmony_ci	WRITE_ONCE(pm->pm_type, pm_type);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	if (pm_type == MPTCP_PM_TYPE_KERNEL) {
51162306a36Sopenharmony_ci		bool subflows_allowed = !!mptcp_pm_get_subflows_max(msk);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci		/* pm->work_pending must be only be set to 'true' when
51462306a36Sopenharmony_ci		 * pm->pm_type is set to MPTCP_PM_TYPE_KERNEL
51562306a36Sopenharmony_ci		 */
51662306a36Sopenharmony_ci		WRITE_ONCE(pm->work_pending,
51762306a36Sopenharmony_ci			   (!!mptcp_pm_get_local_addr_max(msk) &&
51862306a36Sopenharmony_ci			    subflows_allowed) ||
51962306a36Sopenharmony_ci			   !!mptcp_pm_get_add_addr_signal_max(msk));
52062306a36Sopenharmony_ci		WRITE_ONCE(pm->accept_addr,
52162306a36Sopenharmony_ci			   !!mptcp_pm_get_add_addr_accept_max(msk) &&
52262306a36Sopenharmony_ci			   subflows_allowed);
52362306a36Sopenharmony_ci		WRITE_ONCE(pm->accept_subflow, subflows_allowed);
52462306a36Sopenharmony_ci	} else {
52562306a36Sopenharmony_ci		WRITE_ONCE(pm->work_pending, 0);
52662306a36Sopenharmony_ci		WRITE_ONCE(pm->accept_addr, 0);
52762306a36Sopenharmony_ci		WRITE_ONCE(pm->accept_subflow, 0);
52862306a36Sopenharmony_ci	}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	WRITE_ONCE(pm->addr_signal, 0);
53162306a36Sopenharmony_ci	WRITE_ONCE(pm->remote_deny_join_id0, false);
53262306a36Sopenharmony_ci	pm->status = 0;
53362306a36Sopenharmony_ci	bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
53462306a36Sopenharmony_ci}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_civoid mptcp_pm_data_init(struct mptcp_sock *msk)
53762306a36Sopenharmony_ci{
53862306a36Sopenharmony_ci	spin_lock_init(&msk->pm.lock);
53962306a36Sopenharmony_ci	INIT_LIST_HEAD(&msk->pm.anno_list);
54062306a36Sopenharmony_ci	INIT_LIST_HEAD(&msk->pm.userspace_pm_local_addr_list);
54162306a36Sopenharmony_ci	mptcp_pm_data_reset(msk);
54262306a36Sopenharmony_ci}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_civoid __init mptcp_pm_init(void)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	mptcp_pm_nl_init();
54762306a36Sopenharmony_ci}
548