forked from mirrors/linux
		
	mptcp: send out ADD_ADDR with echo flag
When the ADD_ADDR suboption has been received, we need to send out the same ADD_ADDR suboption with echo-flag=1, and no HMAC. Suggested-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: Geliang Tang <geliangtang@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									d0876b2284
								
							
						
					
					
						commit
						6a6c05a8b0
					
				
					 4 changed files with 32 additions and 23 deletions
				
			
		|  | @ -242,7 +242,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, | ||||||
| 		mp_opt->add_addr = 1; | 		mp_opt->add_addr = 1; | ||||||
| 		mp_opt->port = 0; | 		mp_opt->port = 0; | ||||||
| 		mp_opt->addr_id = *ptr++; | 		mp_opt->addr_id = *ptr++; | ||||||
| 		pr_debug("ADD_ADDR: id=%d", mp_opt->addr_id); | 		pr_debug("ADD_ADDR: id=%d, echo=%d", mp_opt->addr_id, mp_opt->echo); | ||||||
| 		if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) { | 		if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) { | ||||||
| 			memcpy((u8 *)&mp_opt->addr.s_addr, (u8 *)ptr, 4); | 			memcpy((u8 *)&mp_opt->addr.s_addr, (u8 *)ptr, 4); | ||||||
| 			ptr += 4; | 			ptr += 4; | ||||||
|  | @ -579,10 +579,11 @@ static bool mptcp_established_options_add_addr(struct sock *sk, | ||||||
| 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | ||||||
| 	struct mptcp_sock *msk = mptcp_sk(subflow->conn); | 	struct mptcp_sock *msk = mptcp_sk(subflow->conn); | ||||||
| 	struct mptcp_addr_info saddr; | 	struct mptcp_addr_info saddr; | ||||||
|  | 	bool echo; | ||||||
| 	int len; | 	int len; | ||||||
| 
 | 
 | ||||||
| 	if (!mptcp_pm_should_add_signal(msk) || | 	if (!mptcp_pm_should_add_signal(msk) || | ||||||
| 	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr))) | 	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr, &echo))) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	len = mptcp_add_addr_len(saddr.family); | 	len = mptcp_add_addr_len(saddr.family); | ||||||
|  | @ -594,22 +595,26 @@ static bool mptcp_established_options_add_addr(struct sock *sk, | ||||||
| 	if (saddr.family == AF_INET) { | 	if (saddr.family == AF_INET) { | ||||||
| 		opts->suboptions |= OPTION_MPTCP_ADD_ADDR; | 		opts->suboptions |= OPTION_MPTCP_ADD_ADDR; | ||||||
| 		opts->addr = saddr.addr; | 		opts->addr = saddr.addr; | ||||||
|  | 		if (!echo) { | ||||||
| 			opts->ahmac = add_addr_generate_hmac(msk->local_key, | 			opts->ahmac = add_addr_generate_hmac(msk->local_key, | ||||||
| 							     msk->remote_key, | 							     msk->remote_key, | ||||||
| 							     opts->addr_id, | 							     opts->addr_id, | ||||||
| 							     &opts->addr); | 							     &opts->addr); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| #if IS_ENABLED(CONFIG_MPTCP_IPV6) | #if IS_ENABLED(CONFIG_MPTCP_IPV6) | ||||||
| 	else if (saddr.family == AF_INET6) { | 	else if (saddr.family == AF_INET6) { | ||||||
| 		opts->suboptions |= OPTION_MPTCP_ADD_ADDR6; | 		opts->suboptions |= OPTION_MPTCP_ADD_ADDR6; | ||||||
| 		opts->addr6 = saddr.addr6; | 		opts->addr6 = saddr.addr6; | ||||||
|  | 		if (!echo) { | ||||||
| 			opts->ahmac = add_addr6_generate_hmac(msk->local_key, | 			opts->ahmac = add_addr6_generate_hmac(msk->local_key, | ||||||
| 							      msk->remote_key, | 							      msk->remote_key, | ||||||
| 							      opts->addr_id, | 							      opts->addr_id, | ||||||
| 							      &opts->addr6); | 							      &opts->addr6); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| #endif | #endif | ||||||
| 	pr_debug("addr_id=%d, ahmac=%llu", opts->addr_id, opts->ahmac); | 	pr_debug("addr_id=%d, ahmac=%llu, echo=%d", opts->addr_id, opts->ahmac, echo); | ||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,11 +13,13 @@ | ||||||
| /* path manager command handlers */ | /* path manager command handlers */ | ||||||
| 
 | 
 | ||||||
| int mptcp_pm_announce_addr(struct mptcp_sock *msk, | int mptcp_pm_announce_addr(struct mptcp_sock *msk, | ||||||
| 			   const struct mptcp_addr_info *addr) | 			   const struct mptcp_addr_info *addr, | ||||||
|  | 			   bool echo) | ||||||
| { | { | ||||||
| 	pr_debug("msk=%p, local_id=%d", msk, addr->id); | 	pr_debug("msk=%p, local_id=%d", msk, addr->id); | ||||||
| 
 | 
 | ||||||
| 	msk->pm.local = *addr; | 	msk->pm.local = *addr; | ||||||
|  | 	WRITE_ONCE(msk->pm.add_addr_echo, echo); | ||||||
| 	WRITE_ONCE(msk->pm.add_addr_signal, true); | 	WRITE_ONCE(msk->pm.add_addr_signal, true); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -135,15 +137,11 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk, | ||||||
| 	pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id, | 	pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id, | ||||||
| 		 READ_ONCE(pm->accept_addr)); | 		 READ_ONCE(pm->accept_addr)); | ||||||
| 
 | 
 | ||||||
| 	/* avoid acquiring the lock if there is no room for fouther addresses */ |  | ||||||
| 	if (!READ_ONCE(pm->accept_addr)) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	spin_lock_bh(&pm->lock); | 	spin_lock_bh(&pm->lock); | ||||||
| 
 | 
 | ||||||
| 	/* be sure there is something to signal re-checking under PM lock */ | 	if (!READ_ONCE(pm->accept_addr)) | ||||||
| 	if (READ_ONCE(pm->accept_addr) && | 		mptcp_pm_announce_addr(msk, addr, true); | ||||||
| 	    mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) | 	else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) | ||||||
| 		pm->remote = *addr; | 		pm->remote = *addr; | ||||||
| 
 | 
 | ||||||
| 	spin_unlock_bh(&pm->lock); | 	spin_unlock_bh(&pm->lock); | ||||||
|  | @ -164,7 +162,7 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id) | ||||||
| /* path manager helpers */ | /* path manager helpers */ | ||||||
| 
 | 
 | ||||||
| bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | ||||||
| 			      struct mptcp_addr_info *saddr) | 			      struct mptcp_addr_info *saddr, bool *echo) | ||||||
| { | { | ||||||
| 	int ret = false; | 	int ret = false; | ||||||
| 
 | 
 | ||||||
|  | @ -178,6 +176,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | ||||||
| 		goto out_unlock; | 		goto out_unlock; | ||||||
| 
 | 
 | ||||||
| 	*saddr = msk->pm.local; | 	*saddr = msk->pm.local; | ||||||
|  | 	*echo = READ_ONCE(msk->pm.add_addr_echo); | ||||||
| 	WRITE_ONCE(msk->pm.add_addr_signal, false); | 	WRITE_ONCE(msk->pm.add_addr_signal, false); | ||||||
| 	ret = true; | 	ret = true; | ||||||
| 
 | 
 | ||||||
|  | @ -226,6 +225,7 @@ void mptcp_pm_data_init(struct mptcp_sock *msk) | ||||||
| 	WRITE_ONCE(msk->pm.rm_addr_signal, false); | 	WRITE_ONCE(msk->pm.rm_addr_signal, false); | ||||||
| 	WRITE_ONCE(msk->pm.accept_addr, false); | 	WRITE_ONCE(msk->pm.accept_addr, false); | ||||||
| 	WRITE_ONCE(msk->pm.accept_subflow, false); | 	WRITE_ONCE(msk->pm.accept_subflow, false); | ||||||
|  | 	WRITE_ONCE(msk->pm.add_addr_echo, false); | ||||||
| 	msk->pm.status = 0; | 	msk->pm.status = 0; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_init(&msk->pm.lock); | 	spin_lock_init(&msk->pm.lock); | ||||||
|  |  | ||||||
|  | @ -198,7 +198,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) | ||||||
| 
 | 
 | ||||||
| 		if (local) { | 		if (local) { | ||||||
| 			msk->pm.add_addr_signaled++; | 			msk->pm.add_addr_signaled++; | ||||||
| 			mptcp_pm_announce_addr(msk, &local->addr); | 			mptcp_pm_announce_addr(msk, &local->addr, false); | ||||||
| 		} else { | 		} else { | ||||||
| 			/* pick failed, avoid fourther attempts later */ | 			/* pick failed, avoid fourther attempts later */ | ||||||
| 			msk->pm.local_addr_used = msk->pm.add_addr_signal_max; | 			msk->pm.local_addr_used = msk->pm.add_addr_signal_max; | ||||||
|  | @ -266,6 +266,8 @@ void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk) | ||||||
| 	spin_unlock_bh(&msk->pm.lock); | 	spin_unlock_bh(&msk->pm.lock); | ||||||
| 	__mptcp_subflow_connect((struct sock *)msk, &local, &remote); | 	__mptcp_subflow_connect((struct sock *)msk, &local, &remote); | ||||||
| 	spin_lock_bh(&msk->pm.lock); | 	spin_lock_bh(&msk->pm.lock); | ||||||
|  | 
 | ||||||
|  | 	mptcp_pm_announce_addr(msk, &remote, true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk) | void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk) | ||||||
|  |  | ||||||
|  | @ -169,6 +169,7 @@ struct mptcp_pm_data { | ||||||
| 	bool		work_pending; | 	bool		work_pending; | ||||||
| 	bool		accept_addr; | 	bool		accept_addr; | ||||||
| 	bool		accept_subflow; | 	bool		accept_subflow; | ||||||
|  | 	bool		add_addr_echo; | ||||||
| 	u8		add_addr_signaled; | 	u8		add_addr_signaled; | ||||||
| 	u8		add_addr_accepted; | 	u8		add_addr_accepted; | ||||||
| 	u8		local_addr_used; | 	u8		local_addr_used; | ||||||
|  | @ -442,7 +443,8 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk, | ||||||
| void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id); | void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id); | ||||||
| 
 | 
 | ||||||
| int mptcp_pm_announce_addr(struct mptcp_sock *msk, | int mptcp_pm_announce_addr(struct mptcp_sock *msk, | ||||||
| 			   const struct mptcp_addr_info *addr); | 			   const struct mptcp_addr_info *addr, | ||||||
|  | 			   bool echo); | ||||||
| int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id); | int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id); | ||||||
| int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id); | int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id); | ||||||
| 
 | 
 | ||||||
|  | @ -464,7 +466,7 @@ static inline unsigned int mptcp_add_addr_len(int family) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | ||||||
| 			      struct mptcp_addr_info *saddr); | 			      struct mptcp_addr_info *saddr, bool *echo); | ||||||
| bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, | ||||||
| 			     u8 *rm_id); | 			     u8 *rm_id); | ||||||
| int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); | int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Geliang Tang
						Geliang Tang