All of lore.kernel.org
 help / color / mirror / Atom feed
* [MPTCP] Re: [PATCH net-next] mptcp: add REMOVE_ADDR support v1
@ 2020-07-22  9:02 Geliang Tang
  0 siblings, 0 replies; 2+ messages in thread
From: Geliang Tang @ 2020-07-22  9:02 UTC (permalink / raw)
  To: mptcp 

[-- Attachment #1: Type: text/plain, Size: 18358 bytes --]

On Thu, Jul 16, 2020 at 04:41:52PM +0200, Paolo Abeni wrote:
> Hi,
> 
> On Thu, 2020-07-16 at 16:45 +0800, Geliang Tang wrote:
> > Add REMOVE_ADDR support.
> > 
> > Signed-off-by: Geliang Tang <geliangtang(a)gmail.com>
> > ---
> >  This is the first version of REMOVE_ADDR support. It's not finished yet but
> >  it works. I'll add selftest case and patch commit description later. Please
> >  give me some advice on how to improve it. Thanks.
> 
> I think this code could be split in a few patches:
> 
> * one renaming the existing add_addr related functions
> * one doing the rm_addr option parsing/writing
> * one implementing the rm addr logic
> 
> This latter part is the least clear to me. If I read the code
> correctly, the idea is having each msk checking in the data path if any
> address has been removed via the PM netlink APIs. Is the above correct?
> 
> I think it would be better triggering the remove addr in the reverse
> way: when the PM netlink removes an address it should traverse all the
> existing msk sockets - using the recently introduced
> mptcp_token_iter_next() helper - and set 'rm_addr_signal' on the
> relevant sockets - the ones that already announced it.
> 
> This latter condition is possibly a bit hard to track. As far as I read
> the RFC, we could use a simpler one: send the RM_ADDR on the msk with a
> subflows using the relevant addr.
> 
> The idea behind the above is that servers should not usually send
> RM_ADDR, while clients should have a limited number of open MPTCP
> connections, so traversing all the token table should not be a
> problem. 
> 
> Not sure if the above is somewhat readable - we can discuss it in the
> mtg soon!
> 
> Please see also:
> 
> https://github.com/multipath-tcp/mptcp_net-next/issues/19
> 
> which is somewhat related.
> 
> Cheers,
> 
> Paolo

Hi Paolo,

Thanks for your suggestions. I have updated my patches, and sent out patchset v2 to you.

-Geliang

> 
> > ---
> >  net/mptcp/options.c    | 49 +++++++++++++++++++++++++----
> >  net/mptcp/pm.c         | 71 ++++++++++++++++++++++++++++++++++++++----
> >  net/mptcp/pm_netlink.c | 47 +++++++++++++++++++++++++++-
> >  net/mptcp/protocol.c   | 12 +++++--
> >  net/mptcp/protocol.h   | 26 +++++++++++++---
> >  net/mptcp/subflow.c    |  1 +
> >  6 files changed, 187 insertions(+), 19 deletions(-)
> > 
> > diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> > index 19707c07efc1..0d4d334fbc08 100644
> > --- a/net/mptcp/options.c
> > +++ b/net/mptcp/options.c
> > @@ -572,10 +572,10 @@ static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
> >  }
> >  #endif
> >  
> > -static bool mptcp_established_options_addr(struct sock *sk,
> > -					   unsigned int *size,
> > -					   unsigned int remaining,
> > -					   struct mptcp_out_options *opts)
> > +static bool mptcp_established_options_add_addr(struct sock *sk,
> > +					       unsigned int *size,
> > +					       unsigned int remaining,
> > +					       struct mptcp_out_options *opts)
> >  {
> >  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
> >  	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
> > @@ -583,7 +583,7 @@ static bool mptcp_established_options_addr(struct sock *sk,
> >  	int len;
> >  
> >  	if (!mptcp_pm_should_signal(msk) ||
> > -	    !(mptcp_pm_addr_signal(msk, remaining, &saddr)))
> > +	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr)))
> >  		return false;
> >  
> >  	len = mptcp_add_addr_len(saddr.family);
> > @@ -615,6 +615,31 @@ static bool mptcp_established_options_addr(struct sock *sk,
> >  	return true;
> >  }
> >  
> > +static bool mptcp_established_options_rm_addr(struct sock *sk,
> > +					      unsigned int *size,
> > +					      unsigned int remaining,
> > +					      struct mptcp_out_options *opts)
> > +{
> > +	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
> > +	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
> > +	u8 rm_id;
> > +
> > +	if (!mptcp_pm_should_rm_signal(msk) ||
> > +	    !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
> > +		return false;
> > +
> > +	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
> > +		return false;
> > +
> > +	*size = TCPOLEN_MPTCP_RM_ADDR_BASE;
> > +	opts->suboptions |= OPTION_MPTCP_RM_ADDR;
> > +	opts->rm_id = rm_id;
> > +
> > +	pr_debug("rm_id=%d", opts->rm_id);
> > +
> > +	return true;
> > +}
> > +
> >  bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
> >  			       unsigned int *size, unsigned int remaining,
> >  			       struct mptcp_out_options *opts)
> > @@ -641,7 +666,13 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
> >  
> >  	*size += opt_size;
> >  	remaining -= opt_size;
> > -	if (mptcp_established_options_addr(sk, &opt_size, remaining, opts)) {
> > +	if (mptcp_established_options_add_addr(sk, &opt_size, remaining, opts)) {
> > +		*size += opt_size;
> > +		remaining -= opt_size;
> > +		ret = true;
> > +	}
> > +
> > +	if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
> >  		*size += opt_size;
> >  		remaining -= opt_size;
> >  		ret = true;
> > @@ -729,6 +760,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
> >  	subflow->can_ack = 1;
> >  
> >  fully_established:
> > +	mptcp_pm_addr_update(msk);
> >  	if (likely(subflow->pm_notified))
> >  		return true;
> >  
> > @@ -845,6 +877,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;
> >  
> > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> > index a8ad20559aaa..c811559ca78f 100644
> > --- a/net/mptcp/pm.c
> > +++ b/net/mptcp/pm.c
> > @@ -18,13 +18,17 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
> >  	pr_debug("msk=%p, local_id=%d", msk, addr->id);
> >  
> >  	msk->pm.local = *addr;
> > -	WRITE_ONCE(msk->pm.addr_signal, true);
> > +	WRITE_ONCE(msk->pm.add_addr_signal, true);
> >  	return 0;
> >  }
> >  
> >  int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
> >  {
> > -	return -ENOTSUPP;
> > +	pr_debug("msk=%p, local_id=%d", msk, local_id);
> > +
> > +	msk->pm.rm_id = local_id;
> > +	WRITE_ONCE(msk->pm.rm_addr_signal, true);
> > +	return 0;
> >  }
> >  
> >  int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id)
> > @@ -81,6 +85,24 @@ static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
> >  	return true;
> >  }
> >  
> > +void mptcp_pm_addr_update(struct mptcp_sock *msk)
> > +{
> > +	struct mptcp_pm_data *pm = &msk->pm;
> > +
> > +	pr_debug("msk=%p", msk);
> > +
> > +	/* try to avoid acquiring the lock below */
> > +	if (!READ_ONCE(pm->work_pending))
> > +		return;
> > +
> > +	spin_lock_bh(&pm->lock);
> > +
> > +	if (READ_ONCE(pm->work_pending))
> > +		mptcp_pm_schedule_work(msk, MPTCP_PM_ADDR_UPDATE);
> > +
> > +	spin_unlock_bh(&pm->lock);
> > +}
> > +
> >  void mptcp_pm_fully_established(struct mptcp_sock *msk)
> >  {
> >  	struct mptcp_pm_data *pm = &msk->pm;
> > @@ -151,8 +173,8 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
> >  
> >  /* path manager helpers */
> >  
> > -bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> > -			  struct mptcp_addr_info *saddr)
> > +bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> > +			      struct mptcp_addr_info *saddr)
> >  {
> >  	int ret = false;
> >  
> > @@ -166,7 +188,42 @@ bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> >  		goto out_unlock;
> >  
> >  	*saddr = msk->pm.local;
> > -	WRITE_ONCE(msk->pm.addr_signal, false);
> > +	WRITE_ONCE(msk->pm.add_addr_signal, false);
> > +	ret = true;
> > +
> > +out_unlock:
> > +	spin_unlock_bh(&msk->pm.lock);
> > +	return ret;
> > +}
> > +
> > +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);
> > +}
> > +
> > +bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> > +			     u8 *rm_id)
> > +{
> > +	int ret = false;
> > +
> > +	spin_lock_bh(&msk->pm.lock);
> > +
> > +	/* double check after the lock is acquired */
> > +	if (!mptcp_pm_should_rm_signal(msk))
> > +		goto out_unlock;
> > +
> > +	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
> > +		goto out_unlock;
> > +
> > +	*rm_id = msk->pm.rm_id;
> > +	WRITE_ONCE(msk->pm.rm_addr_signal, false);
> >  	ret = true;
> >  
> >  out_unlock:
> > @@ -186,9 +243,11 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
> >  	msk->pm.local_addr_used = 0;
> >  	msk->pm.subflows = 0;
> >  	WRITE_ONCE(msk->pm.work_pending, false);
> > -	WRITE_ONCE(msk->pm.addr_signal, false);
> > +	WRITE_ONCE(msk->pm.add_addr_signal, false);
> > +	WRITE_ONCE(msk->pm.rm_addr_signal, false);
> >  	WRITE_ONCE(msk->pm.accept_addr, false);
> >  	WRITE_ONCE(msk->pm.accept_subflow, false);
> > +	WRITE_ONCE(msk->pm.addr_updated, false);
> >  	msk->pm.status = 0;
> >  
> >  	spin_lock_init(&msk->pm.lock);
> > diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
> > index c8820c4156e6..c9933387be09 100644
> > --- a/net/mptcp/pm_netlink.c
> > +++ b/net/mptcp/pm_netlink.c
> > @@ -39,6 +39,7 @@ struct pm_nl_pernet {
> >  	unsigned int		local_addr_max;
> >  	unsigned int		subflows_max;
> >  	unsigned int		next_id;
> > +	unsigned int		rm_id;
> >  };
> >  
> >  #define MPTCP_PM_ADDR_MAX	8
> > @@ -165,7 +166,7 @@ static void check_work_pending(struct mptcp_sock *msk)
> >  {
> >  	if (msk->pm.add_addr_signaled == msk->pm.add_addr_signal_max &&
> >  	    (msk->pm.local_addr_used == msk->pm.local_addr_max ||
> > -	     msk->pm.subflows == msk->pm.subflows_max))
> > +	     msk->pm.subflows == msk->pm.subflows_max) && msk->pm.addr_updated)
> >  		WRITE_ONCE(msk->pm.work_pending, false);
> >  }
> >  
> > @@ -196,6 +197,11 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
> >  			msk->pm.local_addr_used = msk->pm.add_addr_signal_max;
> >  		}
> >  
> > +		check_work_pending(msk);
> > +	} else if (msk->pm.add_addr_signaled > msk->pm.add_addr_signal_max) {
> > +		msk->pm.add_addr_signaled--;
> > +		mptcp_pm_remove_addr(msk, pernet->rm_id);
> > +
> >  		check_work_pending(msk);
> >  	}
> >  
> > @@ -261,6 +267,26 @@ 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;
> > +
> > +	pr_debug("remote_id %d", msk->pm.rm_id);
> > +
> > +	msk->pm.add_addr_accepted--;
> > +	msk->pm.subflows--;
> > +	WRITE_ONCE(msk->pm.accept_addr, true);
> > +
> > +	list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
> > +		struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
> > +
> > +		if (msk->pm.rm_id == subflow->remote_id) {
> > +			mptcp_subflow_shutdown(tcp_sk, 1, 1, msk->write_seq);
> > +			list_del(&subflow->node);
> > +		}
> > +	}
> > +}
> > +
> >  static bool address_use_port(struct mptcp_pm_addr_entry *entry)
> >  {
> >  	return (entry->flags &
> > @@ -354,6 +380,24 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
> >  	return ret;
> >  }
> >  
> > +void mptcp_pm_nl_addr_update(struct mptcp_sock *msk)
> > +{
> > +	struct mptcp_pm_data *pm = &msk->pm;
> > +	struct pm_nl_pernet *pernet;
> > +
> > +	pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
> > +
> > +	if (pm->add_addr_signal_max != pernet->add_addr_signal_max) {
> > +		pm->add_addr_signal_max = READ_ONCE(pernet->add_addr_signal_max);
> > +		pm->add_addr_accept_max = READ_ONCE(pernet->add_addr_accept_max);
> > +
> > +		mptcp_pm_create_subflow_or_signal_addr(msk);
> > +		WRITE_ONCE(pm->addr_updated, true);
> > +	} else {
> > +		WRITE_ONCE(pm->addr_updated, false);
> > +	}
> > +}
> > +
> >  void mptcp_pm_nl_data_init(struct mptcp_sock *msk)
> >  {
> >  	struct mptcp_pm_data *pm = &msk->pm;
> > @@ -541,6 +585,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
> >  		pernet->local_addr_max--;
> >  
> >  	pernet->addrs--;
> > +	pernet->rm_id = addr.addr.id;
> >  	list_del_rcu(&entry->list);
> >  	kfree_rcu(entry, rcu);
> >  out:
> > diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> > index dbe43e0cd734..31b836ed0786 100644
> > --- a/net/mptcp/protocol.c
> > +++ b/net/mptcp/protocol.c
> > @@ -1225,6 +1225,14 @@ 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_ADDR_UPDATE)) {
> > +		pm->status &= ~BIT(MPTCP_PM_ADDR_UPDATE);
> > +		mptcp_pm_nl_addr_update(msk);
> > +	}
> >  	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
> >  		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
> >  		mptcp_pm_nl_fully_established(msk);
> > @@ -1381,8 +1389,8 @@ static void mptcp_cancel_work(struct sock *sk)
> >  		sock_put(sk);
> >  }
> >  
> > -static void mptcp_subflow_shutdown(struct sock *ssk, int how,
> > -				   bool data_fin_tx_enable, u64 data_fin_tx_seq)
> > +void mptcp_subflow_shutdown(struct sock *ssk, int how,
> > +			    bool data_fin_tx_enable, u64 data_fin_tx_seq)
> >  {
> >  	lock_sock(ssk);
> >  
> > diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> > index e5baaef5ec89..5587613f5b03 100644
> > --- a/net/mptcp/protocol.h
> > +++ b/net/mptcp/protocol.h
> > @@ -150,6 +150,8 @@ struct mptcp_addr_info {
> >  
> >  enum mptcp_pm_status {
> >  	MPTCP_PM_ADD_ADDR_RECEIVED,
> > +	MPTCP_PM_RM_ADDR_RECEIVED,
> > +	MPTCP_PM_ADDR_UPDATE,
> >  	MPTCP_PM_ESTABLISHED,
> >  	MPTCP_PM_SUBFLOW_ESTABLISHED,
> >  };
> > @@ -160,11 +162,13 @@ struct mptcp_pm_data {
> >  
> >  	spinlock_t	lock;		/*protects the whole PM data */
> >  
> > -	bool		addr_signal;
> > +	bool		add_addr_signal;
> > +	bool		rm_addr_signal;
> >  	bool		server_side;
> >  	bool		work_pending;
> >  	bool		accept_addr;
> >  	bool		accept_subflow;
> > +	bool		addr_updated;
> >  	u8		add_addr_signaled;
> >  	u8		add_addr_accepted;
> >  	u8		local_addr_used;
> > @@ -174,6 +178,7 @@ struct mptcp_pm_data {
> >  	u8		local_addr_max;
> >  	u8		subflows_max;
> >  	u8		status;
> > +	u8		rm_id;
> >  };
> >  
> >  struct mptcp_data_frag {
> > @@ -344,6 +349,8 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow)
> >  int mptcp_is_enabled(struct net *net);
> >  bool mptcp_subflow_data_available(struct sock *sk);
> >  void __init mptcp_subflow_init(void);
> > +void mptcp_subflow_shutdown(struct sock *ssk, int how,
> > +			    bool data_fin_tx_enable, u64 data_fin_tx_seq);
> >  
> >  /* called with sk socket lock held */
> >  int __mptcp_subflow_connect(struct sock *sk, int ifindex,
> > @@ -419,8 +426,10 @@ void mptcp_pm_connection_closed(struct mptcp_sock *msk);
> >  void mptcp_pm_subflow_established(struct mptcp_sock *msk,
> >  				  struct mptcp_subflow_context *subflow);
> >  void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
> > +void mptcp_pm_addr_update(struct mptcp_sock *msk);
> >  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);
> > @@ -429,7 +438,12 @@ int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id);
> >  
> >  static inline bool mptcp_pm_should_signal(struct mptcp_sock *msk)
> >  {
> > -	return READ_ONCE(msk->pm.addr_signal);
> > +	return READ_ONCE(msk->pm.add_addr_signal);
> > +}
> > +
> > +static inline bool mptcp_pm_should_rm_signal(struct mptcp_sock *msk)
> > +{
> > +	return READ_ONCE(msk->pm.rm_addr_signal);
> >  }
> >  
> >  static inline unsigned int mptcp_add_addr_len(int family)
> > @@ -439,15 +453,19 @@ static inline unsigned int mptcp_add_addr_len(int family)
> >  	return TCPOLEN_MPTCP_ADD_ADDR6;
> >  }
> >  
> > -bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> > -			  struct mptcp_addr_info *saddr);
> > +bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> > +			      struct mptcp_addr_info *saddr);
> > +bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> > +			     u8 *rm_id);
> >  int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
> >  
> >  void __init mptcp_pm_nl_init(void);
> >  void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
> > +void mptcp_pm_nl_addr_update(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)
> > diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> > index 9f7f3772c13c..326c2df256b7 100644
> > --- a/net/mptcp/subflow.c
> > +++ b/net/mptcp/subflow.c
> > @@ -989,6 +989,7 @@ int __mptcp_subflow_connect(struct sock *sk, int ifindex,
> >  	subflow->remote_key = msk->remote_key;
> >  	subflow->local_key = msk->local_key;
> >  	subflow->token = msk->token;
> > +	subflow->remote_id = remote->id;
> >  	mptcp_info2sockaddr(loc, &addr);
> >  
> >  	addrlen = sizeof(struct sockaddr_in);
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread
* [MPTCP] Re: [PATCH net-next] mptcp: add REMOVE_ADDR support v1
@ 2020-07-16 14:41 Paolo Abeni
  0 siblings, 0 replies; 2+ messages in thread
From: Paolo Abeni @ 2020-07-16 14:41 UTC (permalink / raw)
  To: mptcp 

[-- Attachment #1: Type: text/plain, Size: 17183 bytes --]

Hi,

On Thu, 2020-07-16 at 16:45 +0800, Geliang Tang wrote:
> Add REMOVE_ADDR support.
> 
> Signed-off-by: Geliang Tang <geliangtang(a)gmail.com>
> ---
>  This is the first version of REMOVE_ADDR support. It's not finished yet but
>  it works. I'll add selftest case and patch commit description later. Please
>  give me some advice on how to improve it. Thanks.

I think this code could be split in a few patches:

* one renaming the existing add_addr related functions
* one doing the rm_addr option parsing/writing
* one implementing the rm addr logic

This latter part is the least clear to me. If I read the code
correctly, the idea is having each msk checking in the data path if any
address has been removed via the PM netlink APIs. Is the above correct?

I think it would be better triggering the remove addr in the reverse
way: when the PM netlink removes an address it should traverse all the
existing msk sockets - using the recently introduced
mptcp_token_iter_next() helper - and set 'rm_addr_signal' on the
relevant sockets - the ones that already announced it.

This latter condition is possibly a bit hard to track. As far as I read
the RFC, we could use a simpler one: send the RM_ADDR on the msk with a
subflows using the relevant addr.

The idea behind the above is that servers should not usually send
RM_ADDR, while clients should have a limited number of open MPTCP
connections, so traversing all the token table should not be a
problem. 

Not sure if the above is somewhat readable - we can discuss it in the
mtg soon!

Please see also:

https://github.com/multipath-tcp/mptcp_net-next/issues/19

which is somewhat related.

Cheers,

Paolo

> ---
>  net/mptcp/options.c    | 49 +++++++++++++++++++++++++----
>  net/mptcp/pm.c         | 71 ++++++++++++++++++++++++++++++++++++++----
>  net/mptcp/pm_netlink.c | 47 +++++++++++++++++++++++++++-
>  net/mptcp/protocol.c   | 12 +++++--
>  net/mptcp/protocol.h   | 26 +++++++++++++---
>  net/mptcp/subflow.c    |  1 +
>  6 files changed, 187 insertions(+), 19 deletions(-)
> 
> diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> index 19707c07efc1..0d4d334fbc08 100644
> --- a/net/mptcp/options.c
> +++ b/net/mptcp/options.c
> @@ -572,10 +572,10 @@ static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
>  }
>  #endif
>  
> -static bool mptcp_established_options_addr(struct sock *sk,
> -					   unsigned int *size,
> -					   unsigned int remaining,
> -					   struct mptcp_out_options *opts)
> +static bool mptcp_established_options_add_addr(struct sock *sk,
> +					       unsigned int *size,
> +					       unsigned int remaining,
> +					       struct mptcp_out_options *opts)
>  {
>  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
>  	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
> @@ -583,7 +583,7 @@ static bool mptcp_established_options_addr(struct sock *sk,
>  	int len;
>  
>  	if (!mptcp_pm_should_signal(msk) ||
> -	    !(mptcp_pm_addr_signal(msk, remaining, &saddr)))
> +	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr)))
>  		return false;
>  
>  	len = mptcp_add_addr_len(saddr.family);
> @@ -615,6 +615,31 @@ static bool mptcp_established_options_addr(struct sock *sk,
>  	return true;
>  }
>  
> +static bool mptcp_established_options_rm_addr(struct sock *sk,
> +					      unsigned int *size,
> +					      unsigned int remaining,
> +					      struct mptcp_out_options *opts)
> +{
> +	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
> +	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
> +	u8 rm_id;
> +
> +	if (!mptcp_pm_should_rm_signal(msk) ||
> +	    !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
> +		return false;
> +
> +	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
> +		return false;
> +
> +	*size = TCPOLEN_MPTCP_RM_ADDR_BASE;
> +	opts->suboptions |= OPTION_MPTCP_RM_ADDR;
> +	opts->rm_id = rm_id;
> +
> +	pr_debug("rm_id=%d", opts->rm_id);
> +
> +	return true;
> +}
> +
>  bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
>  			       unsigned int *size, unsigned int remaining,
>  			       struct mptcp_out_options *opts)
> @@ -641,7 +666,13 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
>  
>  	*size += opt_size;
>  	remaining -= opt_size;
> -	if (mptcp_established_options_addr(sk, &opt_size, remaining, opts)) {
> +	if (mptcp_established_options_add_addr(sk, &opt_size, remaining, opts)) {
> +		*size += opt_size;
> +		remaining -= opt_size;
> +		ret = true;
> +	}
> +
> +	if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
>  		*size += opt_size;
>  		remaining -= opt_size;
>  		ret = true;
> @@ -729,6 +760,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *sk,
>  	subflow->can_ack = 1;
>  
>  fully_established:
> +	mptcp_pm_addr_update(msk);
>  	if (likely(subflow->pm_notified))
>  		return true;
>  
> @@ -845,6 +877,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;
>  
> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index a8ad20559aaa..c811559ca78f 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -18,13 +18,17 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
>  	pr_debug("msk=%p, local_id=%d", msk, addr->id);
>  
>  	msk->pm.local = *addr;
> -	WRITE_ONCE(msk->pm.addr_signal, true);
> +	WRITE_ONCE(msk->pm.add_addr_signal, true);
>  	return 0;
>  }
>  
>  int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
>  {
> -	return -ENOTSUPP;
> +	pr_debug("msk=%p, local_id=%d", msk, local_id);
> +
> +	msk->pm.rm_id = local_id;
> +	WRITE_ONCE(msk->pm.rm_addr_signal, true);
> +	return 0;
>  }
>  
>  int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id)
> @@ -81,6 +85,24 @@ static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
>  	return true;
>  }
>  
> +void mptcp_pm_addr_update(struct mptcp_sock *msk)
> +{
> +	struct mptcp_pm_data *pm = &msk->pm;
> +
> +	pr_debug("msk=%p", msk);
> +
> +	/* try to avoid acquiring the lock below */
> +	if (!READ_ONCE(pm->work_pending))
> +		return;
> +
> +	spin_lock_bh(&pm->lock);
> +
> +	if (READ_ONCE(pm->work_pending))
> +		mptcp_pm_schedule_work(msk, MPTCP_PM_ADDR_UPDATE);
> +
> +	spin_unlock_bh(&pm->lock);
> +}
> +
>  void mptcp_pm_fully_established(struct mptcp_sock *msk)
>  {
>  	struct mptcp_pm_data *pm = &msk->pm;
> @@ -151,8 +173,8 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
>  
>  /* path manager helpers */
>  
> -bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> -			  struct mptcp_addr_info *saddr)
> +bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> +			      struct mptcp_addr_info *saddr)
>  {
>  	int ret = false;
>  
> @@ -166,7 +188,42 @@ bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
>  		goto out_unlock;
>  
>  	*saddr = msk->pm.local;
> -	WRITE_ONCE(msk->pm.addr_signal, false);
> +	WRITE_ONCE(msk->pm.add_addr_signal, false);
> +	ret = true;
> +
> +out_unlock:
> +	spin_unlock_bh(&msk->pm.lock);
> +	return ret;
> +}
> +
> +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);
> +}
> +
> +bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> +			     u8 *rm_id)
> +{
> +	int ret = false;
> +
> +	spin_lock_bh(&msk->pm.lock);
> +
> +	/* double check after the lock is acquired */
> +	if (!mptcp_pm_should_rm_signal(msk))
> +		goto out_unlock;
> +
> +	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
> +		goto out_unlock;
> +
> +	*rm_id = msk->pm.rm_id;
> +	WRITE_ONCE(msk->pm.rm_addr_signal, false);
>  	ret = true;
>  
>  out_unlock:
> @@ -186,9 +243,11 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
>  	msk->pm.local_addr_used = 0;
>  	msk->pm.subflows = 0;
>  	WRITE_ONCE(msk->pm.work_pending, false);
> -	WRITE_ONCE(msk->pm.addr_signal, false);
> +	WRITE_ONCE(msk->pm.add_addr_signal, false);
> +	WRITE_ONCE(msk->pm.rm_addr_signal, false);
>  	WRITE_ONCE(msk->pm.accept_addr, false);
>  	WRITE_ONCE(msk->pm.accept_subflow, false);
> +	WRITE_ONCE(msk->pm.addr_updated, false);
>  	msk->pm.status = 0;
>  
>  	spin_lock_init(&msk->pm.lock);
> diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
> index c8820c4156e6..c9933387be09 100644
> --- a/net/mptcp/pm_netlink.c
> +++ b/net/mptcp/pm_netlink.c
> @@ -39,6 +39,7 @@ struct pm_nl_pernet {
>  	unsigned int		local_addr_max;
>  	unsigned int		subflows_max;
>  	unsigned int		next_id;
> +	unsigned int		rm_id;
>  };
>  
>  #define MPTCP_PM_ADDR_MAX	8
> @@ -165,7 +166,7 @@ static void check_work_pending(struct mptcp_sock *msk)
>  {
>  	if (msk->pm.add_addr_signaled == msk->pm.add_addr_signal_max &&
>  	    (msk->pm.local_addr_used == msk->pm.local_addr_max ||
> -	     msk->pm.subflows == msk->pm.subflows_max))
> +	     msk->pm.subflows == msk->pm.subflows_max) && msk->pm.addr_updated)
>  		WRITE_ONCE(msk->pm.work_pending, false);
>  }
>  
> @@ -196,6 +197,11 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
>  			msk->pm.local_addr_used = msk->pm.add_addr_signal_max;
>  		}
>  
> +		check_work_pending(msk);
> +	} else if (msk->pm.add_addr_signaled > msk->pm.add_addr_signal_max) {
> +		msk->pm.add_addr_signaled--;
> +		mptcp_pm_remove_addr(msk, pernet->rm_id);
> +
>  		check_work_pending(msk);
>  	}
>  
> @@ -261,6 +267,26 @@ 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;
> +
> +	pr_debug("remote_id %d", msk->pm.rm_id);
> +
> +	msk->pm.add_addr_accepted--;
> +	msk->pm.subflows--;
> +	WRITE_ONCE(msk->pm.accept_addr, true);
> +
> +	list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
> +		struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
> +
> +		if (msk->pm.rm_id == subflow->remote_id) {
> +			mptcp_subflow_shutdown(tcp_sk, 1, 1, msk->write_seq);
> +			list_del(&subflow->node);
> +		}
> +	}
> +}
> +
>  static bool address_use_port(struct mptcp_pm_addr_entry *entry)
>  {
>  	return (entry->flags &
> @@ -354,6 +380,24 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
>  	return ret;
>  }
>  
> +void mptcp_pm_nl_addr_update(struct mptcp_sock *msk)
> +{
> +	struct mptcp_pm_data *pm = &msk->pm;
> +	struct pm_nl_pernet *pernet;
> +
> +	pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
> +
> +	if (pm->add_addr_signal_max != pernet->add_addr_signal_max) {
> +		pm->add_addr_signal_max = READ_ONCE(pernet->add_addr_signal_max);
> +		pm->add_addr_accept_max = READ_ONCE(pernet->add_addr_accept_max);
> +
> +		mptcp_pm_create_subflow_or_signal_addr(msk);
> +		WRITE_ONCE(pm->addr_updated, true);
> +	} else {
> +		WRITE_ONCE(pm->addr_updated, false);
> +	}
> +}
> +
>  void mptcp_pm_nl_data_init(struct mptcp_sock *msk)
>  {
>  	struct mptcp_pm_data *pm = &msk->pm;
> @@ -541,6 +585,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
>  		pernet->local_addr_max--;
>  
>  	pernet->addrs--;
> +	pernet->rm_id = addr.addr.id;
>  	list_del_rcu(&entry->list);
>  	kfree_rcu(entry, rcu);
>  out:
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index dbe43e0cd734..31b836ed0786 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -1225,6 +1225,14 @@ 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_ADDR_UPDATE)) {
> +		pm->status &= ~BIT(MPTCP_PM_ADDR_UPDATE);
> +		mptcp_pm_nl_addr_update(msk);
> +	}
>  	if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
>  		pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
>  		mptcp_pm_nl_fully_established(msk);
> @@ -1381,8 +1389,8 @@ static void mptcp_cancel_work(struct sock *sk)
>  		sock_put(sk);
>  }
>  
> -static void mptcp_subflow_shutdown(struct sock *ssk, int how,
> -				   bool data_fin_tx_enable, u64 data_fin_tx_seq)
> +void mptcp_subflow_shutdown(struct sock *ssk, int how,
> +			    bool data_fin_tx_enable, u64 data_fin_tx_seq)
>  {
>  	lock_sock(ssk);
>  
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index e5baaef5ec89..5587613f5b03 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -150,6 +150,8 @@ struct mptcp_addr_info {
>  
>  enum mptcp_pm_status {
>  	MPTCP_PM_ADD_ADDR_RECEIVED,
> +	MPTCP_PM_RM_ADDR_RECEIVED,
> +	MPTCP_PM_ADDR_UPDATE,
>  	MPTCP_PM_ESTABLISHED,
>  	MPTCP_PM_SUBFLOW_ESTABLISHED,
>  };
> @@ -160,11 +162,13 @@ struct mptcp_pm_data {
>  
>  	spinlock_t	lock;		/*protects the whole PM data */
>  
> -	bool		addr_signal;
> +	bool		add_addr_signal;
> +	bool		rm_addr_signal;
>  	bool		server_side;
>  	bool		work_pending;
>  	bool		accept_addr;
>  	bool		accept_subflow;
> +	bool		addr_updated;
>  	u8		add_addr_signaled;
>  	u8		add_addr_accepted;
>  	u8		local_addr_used;
> @@ -174,6 +178,7 @@ struct mptcp_pm_data {
>  	u8		local_addr_max;
>  	u8		subflows_max;
>  	u8		status;
> +	u8		rm_id;
>  };
>  
>  struct mptcp_data_frag {
> @@ -344,6 +349,8 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow)
>  int mptcp_is_enabled(struct net *net);
>  bool mptcp_subflow_data_available(struct sock *sk);
>  void __init mptcp_subflow_init(void);
> +void mptcp_subflow_shutdown(struct sock *ssk, int how,
> +			    bool data_fin_tx_enable, u64 data_fin_tx_seq);
>  
>  /* called with sk socket lock held */
>  int __mptcp_subflow_connect(struct sock *sk, int ifindex,
> @@ -419,8 +426,10 @@ void mptcp_pm_connection_closed(struct mptcp_sock *msk);
>  void mptcp_pm_subflow_established(struct mptcp_sock *msk,
>  				  struct mptcp_subflow_context *subflow);
>  void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
> +void mptcp_pm_addr_update(struct mptcp_sock *msk);
>  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);
> @@ -429,7 +438,12 @@ int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id);
>  
>  static inline bool mptcp_pm_should_signal(struct mptcp_sock *msk)
>  {
> -	return READ_ONCE(msk->pm.addr_signal);
> +	return READ_ONCE(msk->pm.add_addr_signal);
> +}
> +
> +static inline bool mptcp_pm_should_rm_signal(struct mptcp_sock *msk)
> +{
> +	return READ_ONCE(msk->pm.rm_addr_signal);
>  }
>  
>  static inline unsigned int mptcp_add_addr_len(int family)
> @@ -439,15 +453,19 @@ static inline unsigned int mptcp_add_addr_len(int family)
>  	return TCPOLEN_MPTCP_ADD_ADDR6;
>  }
>  
> -bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> -			  struct mptcp_addr_info *saddr);
> +bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> +			      struct mptcp_addr_info *saddr);
> +bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
> +			     u8 *rm_id);
>  int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
>  
>  void __init mptcp_pm_nl_init(void);
>  void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
> +void mptcp_pm_nl_addr_update(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)
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 9f7f3772c13c..326c2df256b7 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -989,6 +989,7 @@ int __mptcp_subflow_connect(struct sock *sk, int ifindex,
>  	subflow->remote_key = msk->remote_key;
>  	subflow->local_key = msk->local_key;
>  	subflow->token = msk->token;
> +	subflow->remote_id = remote->id;
>  	mptcp_info2sockaddr(loc, &addr);
>  
>  	addrlen = sizeof(struct sockaddr_in);


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-07-22  9:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-07-22  9:02 [MPTCP] Re: [PATCH net-next] mptcp: add REMOVE_ADDR support v1 Geliang Tang
  -- strict thread matches above, loose matches on Subject: below --
2020-07-16 14:41 Paolo Abeni

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.