forked from mirrors/linux
		
	mptcp: add the incoming RM_ADDR support
This patch added the RM_ADDR option parsing logic: We parsed the incoming options to find if the rm_addr option is received, and called mptcp_pm_rm_addr_received to schedule PM work to a new status, named MPTCP_PM_RM_ADDR_RECEIVED. PM work got this status, and called mptcp_pm_nl_rm_addr_received to handle it. In mptcp_pm_nl_rm_addr_received, we closed the subflow matching the rm_id, and updated PM counter. Suggested-by: Matthieu Baerts <matthieu.baerts@tessares.net> Suggested-by: Paolo Abeni <pabeni@redhat.com> Suggested-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: Geliang Tang <geliangtang@gmail.com> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5cb104ae55
								
							
						
					
					
						commit
						d0876b2284
					
				
					 5 changed files with 66 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -888,6 +888,11 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
 | 
			
		|||
		mp_opt.add_addr = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mp_opt.rm_addr) {
 | 
			
		||||
		mptcp_pm_rm_addr_received(msk, mp_opt.rm_id);
 | 
			
		||||
		mp_opt.rm_addr = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!mp_opt.dss)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,6 +149,18 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 | 
			
		|||
	spin_unlock_bh(&pm->lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id)
 | 
			
		||||
{
 | 
			
		||||
	struct mptcp_pm_data *pm = &msk->pm;
 | 
			
		||||
 | 
			
		||||
	pr_debug("msk=%p remote_id=%d", msk, rm_id);
 | 
			
		||||
 | 
			
		||||
	spin_lock_bh(&pm->lock);
 | 
			
		||||
	mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED);
 | 
			
		||||
	pm->rm_id = rm_id;
 | 
			
		||||
	spin_unlock_bh(&pm->lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* path manager helpers */
 | 
			
		||||
 | 
			
		||||
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -268,6 +268,40 @@ void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
 | 
			
		|||
	spin_lock_bh(&msk->pm.lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
 | 
			
		||||
{
 | 
			
		||||
	struct mptcp_subflow_context *subflow, *tmp;
 | 
			
		||||
	struct sock *sk = (struct sock *)msk;
 | 
			
		||||
 | 
			
		||||
	pr_debug("address rm_id %d", msk->pm.rm_id);
 | 
			
		||||
 | 
			
		||||
	if (!msk->pm.rm_id)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (list_empty(&msk->conn_list))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
 | 
			
		||||
		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 | 
			
		||||
		int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
 | 
			
		||||
		long timeout = 0;
 | 
			
		||||
 | 
			
		||||
		if (msk->pm.rm_id != subflow->remote_id)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		spin_unlock_bh(&msk->pm.lock);
 | 
			
		||||
		mptcp_subflow_shutdown(sk, ssk, how);
 | 
			
		||||
		__mptcp_close_ssk(sk, ssk, subflow, timeout);
 | 
			
		||||
		spin_lock_bh(&msk->pm.lock);
 | 
			
		||||
 | 
			
		||||
		msk->pm.add_addr_accepted--;
 | 
			
		||||
		msk->pm.subflows--;
 | 
			
		||||
		WRITE_ONCE(msk->pm.accept_addr, true);
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool address_use_port(struct mptcp_pm_addr_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	return (entry->addr.flags &
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1652,7 +1652,7 @@ static struct sock *mptcp_subflow_get_retrans(const struct mptcp_sock *msk)
 | 
			
		|||
 * so we need to use tcp_close() after detaching them from the mptcp
 | 
			
		||||
 * parent socket.
 | 
			
		||||
 */
 | 
			
		||||
static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
 | 
			
		||||
void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
 | 
			
		||||
		       struct mptcp_subflow_context *subflow,
 | 
			
		||||
		       long timeout)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1685,6 +1685,10 @@ static void pm_work(struct mptcp_sock *msk)
 | 
			
		|||
		pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_RECEIVED);
 | 
			
		||||
		mptcp_pm_nl_add_addr_received(msk);
 | 
			
		||||
	}
 | 
			
		||||
	if (pm->status & BIT(MPTCP_PM_RM_ADDR_RECEIVED)) {
 | 
			
		||||
		pm->status &= ~BIT(MPTCP_PM_RM_ADDR_RECEIVED);
 | 
			
		||||
		mptcp_pm_nl_rm_addr_received(msk);
 | 
			
		||||
	}
 | 
			
		||||
	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
 | 
			
		||||
		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
 | 
			
		||||
		mptcp_pm_nl_fully_established(msk);
 | 
			
		||||
| 
						 | 
				
			
			@ -1846,7 +1850,7 @@ static void mptcp_cancel_work(struct sock *sk)
 | 
			
		|||
		sock_put(sk);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
 | 
			
		||||
void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
 | 
			
		||||
{
 | 
			
		||||
	lock_sock(ssk);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -152,6 +152,7 @@ struct mptcp_addr_info {
 | 
			
		|||
 | 
			
		||||
enum mptcp_pm_status {
 | 
			
		||||
	MPTCP_PM_ADD_ADDR_RECEIVED,
 | 
			
		||||
	MPTCP_PM_RM_ADDR_RECEIVED,
 | 
			
		||||
	MPTCP_PM_ESTABLISHED,
 | 
			
		||||
	MPTCP_PM_SUBFLOW_ESTABLISHED,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -362,6 +363,10 @@ void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
 | 
			
		|||
				     struct mptcp_options_received *mp_opt);
 | 
			
		||||
bool mptcp_subflow_data_available(struct sock *sk);
 | 
			
		||||
void __init mptcp_subflow_init(void);
 | 
			
		||||
void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how);
 | 
			
		||||
void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
 | 
			
		||||
		       struct mptcp_subflow_context *subflow,
 | 
			
		||||
		       long timeout);
 | 
			
		||||
 | 
			
		||||
/* called with sk socket lock held */
 | 
			
		||||
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
 | 
			
		||||
| 
						 | 
				
			
			@ -434,6 +439,7 @@ void mptcp_pm_subflow_established(struct mptcp_sock *msk,
 | 
			
		|||
void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
 | 
			
		||||
void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
 | 
			
		||||
				const struct mptcp_addr_info *addr);
 | 
			
		||||
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id);
 | 
			
		||||
 | 
			
		||||
int mptcp_pm_announce_addr(struct mptcp_sock *msk,
 | 
			
		||||
			   const struct mptcp_addr_info *addr);
 | 
			
		||||
| 
						 | 
				
			
			@ -468,6 +474,7 @@ void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
 | 
			
		|||
void mptcp_pm_nl_fully_established(struct mptcp_sock *msk);
 | 
			
		||||
void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk);
 | 
			
		||||
void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk);
 | 
			
		||||
void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk);
 | 
			
		||||
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 | 
			
		||||
 | 
			
		||||
static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue