forked from mirrors/linux
		
	mptcp: netlink: issue MP_PRIO signals from userspace PMs
This change updates MPTCP_PM_CMD_SET_FLAGS to allow userspace PMs
to issue MP_PRIO signals over a specific subflow selected by
the connection token, local and remote address+port.
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/286
Fixes: 702c2f646d ("mptcp: netlink: allow userspace-driven subflow establishment")
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									a657430260
								
							
						
					
					
						commit
						892f396c8e
					
				
					 3 changed files with 62 additions and 6 deletions
				
			
		| 
						 | 
					@ -717,8 +717,9 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
 | 
					int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
 | 
				
			||||||
				 struct mptcp_addr_info *addr,
 | 
									 struct mptcp_addr_info *addr,
 | 
				
			||||||
 | 
									 struct mptcp_addr_info *rem,
 | 
				
			||||||
				 u8 bkup)
 | 
									 u8 bkup)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mptcp_subflow_context *subflow;
 | 
						struct mptcp_subflow_context *subflow;
 | 
				
			||||||
| 
						 | 
					@ -727,13 +728,19 @@ static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mptcp_for_each_subflow(msk, subflow) {
 | 
						mptcp_for_each_subflow(msk, subflow) {
 | 
				
			||||||
		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 | 
							struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 | 
				
			||||||
		struct mptcp_addr_info local;
 | 
							struct mptcp_addr_info local, remote;
 | 
				
			||||||
		bool slow;
 | 
							bool slow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local_address((struct sock_common *)ssk, &local);
 | 
							local_address((struct sock_common *)ssk, &local);
 | 
				
			||||||
		if (!mptcp_addresses_equal(&local, addr, addr->port))
 | 
							if (!mptcp_addresses_equal(&local, addr, addr->port))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (rem && rem->family != AF_UNSPEC) {
 | 
				
			||||||
 | 
								remote_address((struct sock_common *)ssk, &remote);
 | 
				
			||||||
 | 
								if (!mptcp_addresses_equal(&remote, rem, rem->port))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		slow = lock_sock_fast(ssk);
 | 
							slow = lock_sock_fast(ssk);
 | 
				
			||||||
		if (subflow->backup != bkup)
 | 
							if (subflow->backup != bkup)
 | 
				
			||||||
			msk->last_snd = NULL;
 | 
								msk->last_snd = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1837,7 +1844,7 @@ static int mptcp_nl_set_flags(struct net *net,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lock_sock(sk);
 | 
							lock_sock(sk);
 | 
				
			||||||
		if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
 | 
							if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
 | 
				
			||||||
			ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup);
 | 
								ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
 | 
				
			||||||
		if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
 | 
							if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
 | 
				
			||||||
			mptcp_pm_nl_fullmesh(msk, addr);
 | 
								mptcp_pm_nl_fullmesh(msk, addr);
 | 
				
			||||||
		release_sock(sk);
 | 
							release_sock(sk);
 | 
				
			||||||
| 
						 | 
					@ -1853,6 +1860,9 @@ static int mptcp_nl_set_flags(struct net *net,
 | 
				
			||||||
static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
 | 
					static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry;
 | 
						struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry;
 | 
				
			||||||
 | 
						struct mptcp_pm_addr_entry remote = { .addr = { .family = AF_UNSPEC }, };
 | 
				
			||||||
 | 
						struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
 | 
				
			||||||
 | 
						struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
 | 
				
			||||||
	struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
 | 
						struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
 | 
				
			||||||
	struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
 | 
						struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
 | 
				
			||||||
	u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP |
 | 
						u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP |
 | 
				
			||||||
| 
						 | 
					@ -1865,6 +1875,12 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (attr_rem) {
 | 
				
			||||||
 | 
							ret = mptcp_pm_parse_entry(attr_rem, info, false, &remote);
 | 
				
			||||||
 | 
							if (ret < 0)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP)
 | 
						if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP)
 | 
				
			||||||
		bkup = 1;
 | 
							bkup = 1;
 | 
				
			||||||
	if (addr.addr.family == AF_UNSPEC) {
 | 
						if (addr.addr.family == AF_UNSPEC) {
 | 
				
			||||||
| 
						 | 
					@ -1873,6 +1889,10 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
			return -EOPNOTSUPP;
 | 
								return -EOPNOTSUPP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (token)
 | 
				
			||||||
 | 
							return mptcp_userspace_pm_set_flags(sock_net(skb->sk),
 | 
				
			||||||
 | 
											    token, &addr, &remote, bkup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&pernet->lock);
 | 
						spin_lock_bh(&pernet->lock);
 | 
				
			||||||
	entry = __lookup_addr(pernet, &addr.addr, lookup_by_id);
 | 
						entry = __lookup_addr(pernet, &addr.addr, lookup_by_id);
 | 
				
			||||||
	if (!entry) {
 | 
						if (!entry) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -420,3 +420,33 @@ int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	sock_put((struct sock *)msk);
 | 
						sock_put((struct sock *)msk);
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
 | 
				
			||||||
 | 
									 struct mptcp_pm_addr_entry *loc,
 | 
				
			||||||
 | 
									 struct mptcp_pm_addr_entry *rem, u8 bkup)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mptcp_sock *msk;
 | 
				
			||||||
 | 
						int ret = -EINVAL;
 | 
				
			||||||
 | 
						u32 token_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						token_val = nla_get_u32(token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msk = mptcp_token_get_sock(net, token_val);
 | 
				
			||||||
 | 
						if (!msk)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mptcp_pm_is_userspace(msk))
 | 
				
			||||||
 | 
							goto set_flags_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (loc->addr.family == AF_UNSPEC ||
 | 
				
			||||||
 | 
						    rem->addr.family == AF_UNSPEC)
 | 
				
			||||||
 | 
							goto set_flags_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lock_sock((struct sock *)msk);
 | 
				
			||||||
 | 
						ret = mptcp_pm_nl_mp_prio_send_ack(msk, &loc->addr, &rem->addr, bkup);
 | 
				
			||||||
 | 
						release_sock((struct sock *)msk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_flags_err:
 | 
				
			||||||
 | 
						sock_put((struct sock *)msk);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -772,6 +772,10 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
 | 
				
			||||||
			       const struct mptcp_rm_list *rm_list);
 | 
								       const struct mptcp_rm_list *rm_list);
 | 
				
			||||||
void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup);
 | 
					void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup);
 | 
				
			||||||
void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq);
 | 
					void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq);
 | 
				
			||||||
 | 
					int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
 | 
				
			||||||
 | 
									 struct mptcp_addr_info *addr,
 | 
				
			||||||
 | 
									 struct mptcp_addr_info *rem,
 | 
				
			||||||
 | 
									 u8 bkup);
 | 
				
			||||||
bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
 | 
					bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
 | 
				
			||||||
			      const struct mptcp_pm_addr_entry *entry);
 | 
								      const struct mptcp_pm_addr_entry *entry);
 | 
				
			||||||
void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
 | 
					void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
 | 
				
			||||||
| 
						 | 
					@ -788,7 +792,9 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
 | 
				
			||||||
int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
 | 
					int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
 | 
				
			||||||
						   unsigned int id,
 | 
											   unsigned int id,
 | 
				
			||||||
						   u8 *flags, int *ifindex);
 | 
											   u8 *flags, int *ifindex);
 | 
				
			||||||
 | 
					int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
 | 
				
			||||||
 | 
									 struct mptcp_pm_addr_entry *loc,
 | 
				
			||||||
 | 
									 struct mptcp_pm_addr_entry *rem, u8 bkup);
 | 
				
			||||||
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);
 | 
								   bool echo);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue