lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <4C07C351.8060501@hp.com>
Date:	Thu, 03 Jun 2010 10:59:29 -0400
From:	Vlad Yasevich <vladislav.yasevich@...com>
To:	Yaogong Wang <ywang15@...u.edu>
CC:	linux-sctp@...r.kernel.org, Sridhar Samudrala <sri@...ibm.com>,
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/6] sctp multistream scheduling: provide pluggable SCTP
 	scheduling framework



Yaogong Wang wrote:
> Provide a general interface for implementing new SCTP multistream
> scheduling algorithms as kernel modules.
> 

Here is a suggestion.

Create an intermediate patch that turns out_chunk_list into a pointer
and update the old outqueue code to use it.  This would be patch 2.
In the description you can say that subsequent patches may have multiple
data queues.

Then you can introduce FCFS code as patch 3.  Nothing would really use
it.  It's just a reference.

Then in patch 4, you can introduce this framework and plug the FCFS
code in.

-vlad

> Signed-off-by: Yaogong Wang <ywang15@...u.edu>
> ---
> diff -uprN -X linux-2.6.32.8/Documentation/dontdiff
> p1/include/net/sctp/structs.h p2/include/net/sctp/structs.h
> --- p1/include/net/sctp/structs.h	2010-05-28 10:33:12.000000000 -0700
> +++ p2/include/net/sctp/structs.h	2010-06-02 13:02:14.000000000 -0700
> @@ -1158,7 +1158,7 @@ struct sctp_outq {
>  	struct sctp_association *asoc;
> 
>  	/* Data pending that has never been transmitted.  */
> -	struct list_head out_chunk_list;
> +	struct list_head *out_chunk_list;
> 
>  	unsigned out_qlen;	/* Total length of queued data chunks. */
> 
> @@ -1199,7 +1199,7 @@ struct sctp_outq {
>  	char malloced;
>  };
> 
> -void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
> +int sctp_outq_init(struct sctp_association *, struct sctp_outq *, gfp_t gfp);
>  void sctp_outq_teardown(struct sctp_outq *);
>  void sctp_outq_free(struct sctp_outq*);
>  int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
> diff -uprN -X linux-2.6.32.8/Documentation/dontdiff
> p1/net/sctp/Makefile p2/net/sctp/Makefile
> --- p1/net/sctp/Makefile	2010-05-28 10:05:50.000000000 -0700
> +++ p2/net/sctp/Makefile	2010-06-02 12:55:13.000000000 -0700
> @@ -9,7 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o
>  	  transport.o chunk.o sm_make_chunk.o ulpevent.o \
>  	  inqueue.o outqueue.o ulpqueue.o command.o \
>  	  tsnmap.o bind_addr.o socket.o primitive.o \
> -	  output.o input.o debug.o ssnmap.o auth.o
> +	  output.o input.o debug.o ssnmap.o auth.o sched.o
> 
>  sctp-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o
>  sctp-$(CONFIG_PROC_FS) += proc.o
> diff -uprN -X linux-2.6.32.8/Documentation/dontdiff
> p1/net/sctp/associola.c p2/net/sctp/associola.c
> --- p1/net/sctp/associola.c	2010-05-28 10:05:50.000000000 -0700
> +++ p2/net/sctp/associola.c	2010-06-02 12:56:23.000000000 -0700
> @@ -185,6 +185,9 @@ static struct sctp_association *sctp_ass
>  	asoc->max_init_timeo =
>  		 msecs_to_jiffies(sp->initmsg.sinit_max_init_timeo);
> 
> +	/* Multistream scheduling  */
> +	asoc->sched_ops = sp->sched_ops;
> +
>  	/* Allocate storage for the ssnmap after the inbound and outbound
>  	 * streams have been negotiated during Init.
>  	 */
> @@ -280,7 +283,9 @@ static struct sctp_association *sctp_ass
>  	sctp_inq_set_th_handler(&asoc->base.inqueue, sctp_assoc_bh_rcv);
> 
>  	/* Create an output queue.  */
> -	sctp_outq_init(asoc, &asoc->outqueue);
> +	err = sctp_outq_init(asoc, &asoc->outqueue, gfp);
> +	if (err)
> +		goto fail_init;
> 
>  	if (!sctp_ulpq_init(&asoc->ulpq, asoc))
>  		goto fail_init;
> diff -uprN -X linux-2.6.32.8/Documentation/dontdiff
> p1/net/sctp/outqueue.c p2/net/sctp/outqueue.c
> --- p1/net/sctp/outqueue.c	2010-05-28 10:05:50.000000000 -0700
> +++ p2/net/sctp/outqueue.c	2010-06-02 12:55:13.000000000 -0700
> @@ -73,38 +73,6 @@ static void sctp_generate_fwdtsn(struct
> 
>  static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout);
> 
> -/* Add data to the front of the queue. */
> -static inline void sctp_outq_head_data(struct sctp_outq *q,
> -					struct sctp_chunk *ch)
> -{
> -	list_add(&ch->list, &q->out_chunk_list);
> -	q->out_qlen += ch->skb->len;
> -	return;
> -}
> -
> -/* Take data from the front of the queue. */
> -static inline struct sctp_chunk *sctp_outq_dequeue_data(struct sctp_outq *q)
> -{
> -	struct sctp_chunk *ch = NULL;
> -
> -	if (!list_empty(&q->out_chunk_list)) {
> -		struct list_head *entry = q->out_chunk_list.next;
> -
> -		ch = list_entry(entry, struct sctp_chunk, list);
> -		list_del_init(entry);
> -		q->out_qlen -= ch->skb->len;
> -	}
> -	return ch;
> -}
> -/* Add data chunk to the end of the queue. */
> -static inline void sctp_outq_tail_data(struct sctp_outq *q,
> -				       struct sctp_chunk *ch)
> -{
> -	list_add_tail(&ch->list, &q->out_chunk_list);
> -	q->out_qlen += ch->skb->len;
> -	return;
> -}
> -
>  /*
>   * SFR-CACC algorithm:
>   * D) If count_of_newacks is greater than or equal to 2
> @@ -201,10 +169,15 @@ static inline int sctp_cacc_skip(struct
>   * You still need to define handlers if you really want to DO
>   * something with this structure...
>   */
> -void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
> +int sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q,
> +			gfp_t gfp)
>  {
> -	q->asoc = asoc;
> -	INIT_LIST_HEAD(&q->out_chunk_list);
> +	int err = 0;
> +
> +	q->asoc = asoc;
> +	err = q->asoc->sched_ops->init(q, gfp);
> +	if (err)
> +		goto fail_init;
>  	INIT_LIST_HEAD(&q->control_chunk_list);
>  	INIT_LIST_HEAD(&q->retransmit);
>  	INIT_LIST_HEAD(&q->sacked);
> @@ -217,6 +190,9 @@ void sctp_outq_init(struct sctp_associat
> 
>  	q->malloced = 0;
>  	q->out_qlen = 0;
> +
> +fail_init:
> +	return err;
>  }
> 
>  /* Free the outqueue structure and any related pending chunks.
> @@ -267,7 +243,7 @@ void sctp_outq_teardown(struct sctp_outq
>  	}
> 
>  	/* Throw away any leftover data chunks. */
> -	while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
> +	while ((chunk = q->asoc->sched_ops->dequeue_data(q)) != NULL) {
> 
>  		/* Mark as send failure. */
>  		sctp_chunk_fail(chunk, q->error);
> @@ -289,6 +265,8 @@ void sctp_outq_free(struct sctp_outq *q)
>  	/* Throw away leftover chunks. */
>  	sctp_outq_teardown(q);
> 
> +	q->asoc->sched_ops->release(q);
> +
>  	/* If we were kmalloc()'d, free the memory.  */
>  	if (q->malloced)
>  		kfree(q);
> @@ -334,7 +312,7 @@ int sctp_outq_tail(struct sctp_outq *q,
>  			  sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type))
>  			  : "Illegal Chunk");
> 
> -			sctp_outq_tail_data(q, chunk);
> +			q->asoc->sched_ops->enqueue_tail_data(q, chunk);
>  			if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
>  				SCTP_INC_STATS(SCTP_MIB_OUTUNORDERCHUNKS);
>  			else
> @@ -922,7 +900,7 @@ static int sctp_outq_flush(struct sctp_o
>  		}
> 
>  		/* Finally, transmit new packets.  */
> -		while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
> +		while ((chunk = q->asoc->sched_ops->dequeue_data(q)) != NULL) {
>  			/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
>  			 * stream identifier.
>  			 */
> @@ -996,7 +974,7 @@ static int sctp_outq_flush(struct sctp_o
>  					"not transmit TSN: 0x%x, status: %d\n",
>  					ntohl(chunk->subh.data_hdr->tsn),
>  					status);
> -				sctp_outq_head_data(q, chunk);
> +				q->asoc->sched_ops->enqueue_head_data(q, chunk);
>  				goto sctp_flush_out;
>  				break;
> 
> @@ -1252,7 +1230,7 @@ int sctp_outq_sack(struct sctp_outq *q,
>  	/* See if all chunks are acked.
>  	 * Make sure the empty queue handler will get run later.
>  	 */
> -	q->empty = (list_empty(&q->out_chunk_list) &&
> +	q->empty = (q->asoc->sched_ops->is_empty(q) &&
>  		    list_empty(&q->retransmit));
>  	if (!q->empty)
>  		goto finish;
> diff -uprN -X linux-2.6.32.8/Documentation/dontdiff
> p1/net/sctp/sched.c p2/net/sctp/sched.c
> --- p1/net/sctp/sched.c	1969-12-31 16:00:00.000000000 -0800
> +++ p2/net/sctp/sched.c	2010-06-02 12:59:40.000000000 -0700
> @@ -0,0 +1,116 @@
> +/*
> + * Plugable SCTP scheduling support and FCFS
> + * Based on ideas from pluggable TCP congestion control.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/list.h>
> +#include <net/sctp/sctp.h>
> +
> +static DEFINE_SPINLOCK(sctp_sched_list_lock);
> +static LIST_HEAD(sctp_sched_list);
> +
> +/* Simple linear search, don't expect many entries! */
> +static struct sctp_sched_ops *sctp_sched_find(const char *name)
> +{
> +	struct sctp_sched_ops *e;
> +
> +	list_for_each_entry_rcu(e, &sctp_sched_list, list) {
> +		if (strcmp(e->name, name) == 0)
> +			return e;
> +	}
> +
> +	return NULL;
> +}
> +
> +/*
> + * Attach new scheduling algorithm to the list
> + * of available options.
> + */
> +int sctp_register_sched(struct sctp_sched_ops *sched)
> +{
> +	int ret = 0;
> +
> +	/* all algorithms must implement enqueue and dequeue ops */
> +	if (!sched->init || !sched->release || !sched->is_empty
> +		|| !sched->enqueue_head_data || !sched->enqueue_tail_data
> +		|| !sched->dequeue_data) {
> +		printk(KERN_ERR "SCTP %s does not implement required ops\n",
> +		       sched->name);
> +		return -EINVAL;
> +	}
> +
> +	spin_lock(&sctp_sched_list_lock);
> +	if (sctp_sched_find(sched->name)) {
> +		printk(KERN_NOTICE "SCTP %s already registered\n", sched->name);
> +		ret = -EEXIST;
> +	} else {
> +		list_add_tail_rcu(&sched->list, &sctp_sched_list);
> +		printk(KERN_INFO "SCTP %s registered\n", sched->name);
> +	}
> +	spin_unlock(&sctp_sched_list_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(sctp_register_sched);
> +
> +/*
> + * Remove scheduling algorithm, called from
> + * the module's remove function.  Module ref counts are used
> + * to ensure that this can't be done till all sockets using
> + * that method are closed.
> + */
> +void sctp_unregister_sched(struct sctp_sched_ops *sched)
> +{
> +	spin_lock(&sctp_sched_list_lock);
> +	list_del_rcu(&sched->list);
> +	spin_unlock(&sctp_sched_list_lock);
> +}
> +EXPORT_SYMBOL_GPL(sctp_unregister_sched);
> +
> +/* Manage refcounts on socket close. */
> +void sctp_cleanup_sched(struct sock *sk)
> +{
> +	module_put(sctp_sk(sk)->sched_ops->owner);
> +}
> +
> +/* Change scheduling algorithm for socket */
> +int sctp_set_sched(struct sock *sk, const char *name)
> +{
> +	struct sctp_sock *sp = sctp_sk(sk);
> +	struct sctp_sched_ops *sched;
> +	int err = 0;
> +
> +	rcu_read_lock();
> +	sched = sctp_sched_find(name);
> +
> +	/* no change asking for existing value */
> +	if (sched == sp->sched_ops)
> +		goto out;
> +
> +#ifdef CONFIG_MODULES
> +	/* not found attempt to autoload module */
> +	if (!sched && capable(CAP_NET_ADMIN)) {
> +		rcu_read_unlock();
> +		request_module("sctp_%s", name);
> +		rcu_read_lock();
> +		sched = sctp_sched_find(name);
> +	}
> +#endif
> +	if (!sched)
> +		err = -ENOENT;
> +
> +	else if (!try_module_get(sched->owner))
> +		err = -EBUSY;
> +
> +	else {
> +		sctp_cleanup_sched(sk);
> +		sp->sched_ops = sched;
> +	}
> +out:
> +	rcu_read_unlock();
> +	return err;
> +}
> +
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ