Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756003Ab0FCHqo (ORCPT ); Thu, 3 Jun 2010 03:46:44 -0400 Received: from cn.fujitsu.com ([222.73.24.84]:63374 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1752148Ab0FCHqm (ORCPT ); Thu, 3 Jun 2010 03:46:42 -0400 Message-ID: <4C075D36.8030706@cn.fujitsu.com> Date: Thu, 03 Jun 2010 15:43:50 +0800 From: Wei Yongjun User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100423 Thunderbird/3.0.4 MIME-Version: 1.0 To: Yaogong Wang CC: linux-sctp@vger.kernel.org, Vlad Yasevich , Sridhar Samudrala , linux-kernel@vger.kernel.org Subject: Re: [PATCH 2/6] sctp multistream scheduling: provide pluggable SCTP scheduling framework References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10769 Lines: 335 > Provide a general interface for implementing new SCTP multistream > scheduling algorithms as kernel modules. > > after apply this patch, the SCTP will be broken, this will broken git bisect. > Signed-off-by: Yaogong Wang > --- > 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) { > why not use sctp_outq_dequeue_data() as help function instead of direct using q->asoc->sched_ops->dequeue_data()? and also the others. > /* 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 > +#include > +#include > +#include > + > +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@vger.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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/