All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vlad Yasevich <vyasevich@gmail.com>
To: linux-sctp@vger.kernel.org
Subject: Re: Try to Implement load balancer for transmit & retransmit
Date: Thu, 12 Dec 2013 21:05:34 +0000	[thread overview]
Message-ID: <52AA251E.6040605@gmail.com> (raw)
In-Reply-To: <1386880952-18756-1-git-send-email-changxiangzhong@gmail.com>

On 12/12/2013 03:42 PM, Chang Xiangzhong wrote:
> The current implementation uses only one path as the "active path" and one
> path as a "retran path". This patch tries to use all of the pathes for
> transmission. But I'm afraid there must be something missing, such things like
> state update and etcs. 
> 
> The current implementation is very simple - just distribute the load on all of
> the pathes - just check if it satisifes cwnd>flight_size.
> 

If you are interested in pursuing this work I recommend you look at
https://tools.ietf.org/id/draft-tuexen-tsvwg-sctp-multipath-06.txt

-vlad

> And comments would be appreciated! 
> ---
>  include/net/sctp/cmt.h   |    5 +++-
>  net/sctp/Makefile        |    4 +--
>  net/sctp/associola.c     |   33 +++++++++++++++++++--
>  net/sctp/cmt_debug.c     |    2 +-
>  net/sctp/outqueue.c      |   73 +++++++++++++++++++++++++++++++++++-----------
>  net/sctp/protocol.c      |    1 +
>  net/sctp/sm_sideeffect.c |    2 +-
>  7 files changed, 95 insertions(+), 25 deletions(-)
> 
> diff --git a/include/net/sctp/cmt.h b/include/net/sctp/cmt.h
> index edbbfc2..858def8 100644
> --- a/include/net/sctp/cmt.h
> +++ b/include/net/sctp/cmt.h
> @@ -47,8 +47,11 @@
>  	extern char* cmt_print_assoc(struct sctp_association *asoc);
>  	extern char* cmt_print_sackhdr(struct sctp_sackhdr *sack);
>  	extern char* cmt_print_queued_tsn(struct list_head *queue, 
> -					  struct sctp_transport *transport);
> +					  struct sctp_transport *t);
>  	extern char* cmt_print_cwnd(struct list_head *transport_list);
> +	
> +	extern struct sctp_transport* sctp_assoc_most_vacant_path(
> +			struct sctp_association *asoc);
>  #endif
>  
>  /* SACK Chunk Specific Flags*/
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index 626bdca..28f1f60 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1295,6 +1295,33 @@ void sctp_assoc_update(struct sctp_association *asoc,
>  	sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC);
>  }
>  
> +struct sctp_transport*
> +sctp_assoc_most_vacant_path(struct sctp_association *asoc, int threshold)
> +{
> +	struct sctp_transport *t, *ret = NULL;
> +	int vacancy, best=-1;
> +	if (threshold < 0)
> +		threshold = 0;
> +	list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) {
> +		vacancy = t->cwnd - t->flight_size;
> +		if (t->state != SCTP_ACTIVE || vacancy <= threshold /*t->pathmtu/4*/)
> +			continue;
> +		// This is in slow-start state
> +		if (t->ssthresh > t->cwnd) {
> +			ret = t;
> +			break;
> +		}
> +		if (vacancy > best) {
> +			best = vacancy;
> +			ret = t;	
> +		}
> +
> +
> +	}
> +	cmt_debug("==>Find a most vacant path: %p\n", ret);
> +	return ret;
> +}
> +
> 
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index d20816d..9010080 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -57,13 +57,13 @@
>  
>  #include <net/sctp/sctp.h>
>  #include <net/sctp/sm.h>
> -#include <net/sctp/cmt_debug.h>
> +#include <net/sctp/cmt.h>
>  
>  
>  /* Declare internal functions here.  */
> @@ -920,14 +920,32 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
>  		 * current cwnd).
>  		 */
>  		if (!list_empty(&q->retransmit)) {
> -			if (asoc->peer.retran_path->state = SCTP_UNCONFIRMED)
> -				goto sctp_flush_out;
> -			if (transport = asoc->peer.retran_path)
> -				goto retran;
>  
> -			/* Switch transports & prepare the packet.  */
> -
> -			transport = asoc->peer.retran_path;
> +if (q->fast_rtx && !rtx_timeout)
> +{
> +	struct sctp_chunk *chunk, *chunk1;
> +	int chunk_size = 0; // not count the header!
> +	list_for_each_entry_safe(
> +			chunk, chunk1, &q->retransmit, transmitted_list) {
> +		// not the one to fast_rtx
> +		if (sctp_chunk_abandoned(chunk) 
> +		    || chunk->tsn_gap_acked
> +		    || !chunk->fast_retransmit) {
> +			continue;
> +		}
> +		// found the chunk to fast_rtx
> +		chunk_size = ntohs(chunk->chunk_hdr->length);
> +		break;	
> +	}
> +	transport = sctp_assoc_most_vacant_path(asoc, chunk_size);
> +	cmt_debug("%s: fast_rtx most vacant=%p, chunk_size=%d", __func__, transport, chunk_size);
> +} else {
> +	transport = sctp_assoc_most_vacant_path(asoc, -1);
> +}
> +			if (!transport) {
> +				cmt_debug("could not find a vacant path!\n");
> +				goto sctp_flush_out;
> +			}
>  
>  			if (list_empty(&transport->send_ready)) {
>  				list_add_tail(&transport->send_ready,
> @@ -989,12 +1007,22 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
>  			/* If there is a specified transport, use it.
>  			 * Otherwise, we want to use the active path.
>  			 */
> -			new_transport = chunk->transport;
> +			bool path_specified;
> +retry:			new_transport = chunk->transport;
>  			if (!new_transport ||
>  			    ((new_transport->state = SCTP_INACTIVE) ||
>  			     (new_transport->state = SCTP_UNCONFIRMED) ||
> -			     (new_transport->state = SCTP_PF)))
> -				new_transport = asoc->peer.active_path;
> +			     (new_transport->state = SCTP_PF))) {
> +				path_specified = false;
> +				// new_transport = asoc->peer.active_path;
> +				new_transport = sctp_assoc_most_vacant_path(
> +						asoc, -1);
> +				if (!new_transport) {// no available path
> +					sctp_outq_head_data(q, chunk);
> +					goto sctp_flush_out;
> +				}
> +			} else 
> +				path_specified = true;
>  			if (new_transport->state = SCTP_UNCONFIRMED)
>  				continue;
>  
> @@ -1032,7 +1060,18 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
>  
>  			switch (status) {
>  			case SCTP_XMIT_CWND_FULL:// 3
> -			case SCTP_XMIT_PMTU_FULL://1
> +				cmt_debug("==>CWND full\n");
> +				// The App didn't specify a path, so the path
> +				// was chosen by us. Then we could retry with
> +				// another path
> +				if (!path_specified) {
> +					cmt_debug("==>retry!\n");
> +					goto retry;
> +				}	       
> +			// PMTU_FULL not likely. As sctp_packet_transmit_chunk
> +			// would flush the transport and transmit the next 
> +			// chunk in the queue if PMTU_FULL happens.
> +			case SCTP_XMIT_PMTU_FULL://1 
>  			case SCTP_XMIT_RWND_FULL://2
>  			case SCTP_XMIT_NAGLE_DELAY://4
>  				/* We could not append this chunk, so put
> 


  reply	other threads:[~2013-12-12 21:05 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-12 20:42 Try to Implement load balancer for transmit & retransmit Chang Xiangzhong
2013-12-12 21:05 ` Vlad Yasevich [this message]
2013-12-12 21:39 ` Neil Horman
2013-12-12 21:48 ` Chang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52AA251E.6040605@gmail.com \
    --to=vyasevich@gmail.com \
    --cc=linux-sctp@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.