Date: Thu, 3 Feb 2011 20:44:49 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r218241 - head/sys/netinet Message-ID: <201102032044.p13KinL3057953@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Thu Feb 3 20:44:49 2011 New Revision: 218241 URL: http://svn.freebsd.org/changeset/base/218241 Log: Fix several bugs in the stream schedulers. From Robin Seggelmann. MFC after: 3 months. Modified: head/sys/netinet/sctp_output.c head/sys/netinet/sctp_ss_functions.c head/sys/netinet/sctp_structs.h head/sys/netinet/sctp_timer.c head/sys/netinet/sctp_usrreq.c head/sys/netinet/sctputil.c Modified: head/sys/netinet/sctp_output.c ============================================================================== --- head/sys/netinet/sctp_output.c Thu Feb 3 20:30:17 2011 (r218240) +++ head/sys/netinet/sctp_output.c Thu Feb 3 20:44:49 2011 (r218241) @@ -12342,7 +12342,7 @@ sctp_lower_sosend(struct socket *so, TAILQ_INIT(&asoc->strmout[i].outqueue); asoc->strmout[i].stream_no = i; asoc->strmout[i].last_msg_incomplete = 0; - asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i]); + asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); } } } Modified: head/sys/netinet/sctp_ss_functions.c ============================================================================== --- head/sys/netinet/sctp_ss_functions.c Thu Feb 3 20:30:17 2011 (r218240) +++ head/sys/netinet/sctp_ss_functions.c Thu Feb 3 20:44:49 2011 (r218241) @@ -1,6 +1,7 @@ /*- - * Copyright (c) 2010, by Randall Stewart & Michael Tuexen, - * All rights reserved. + * Copyright (c) 2010-2011, by Randall Stewart, rrs@lakerest.net and + * Michael Tuexen, tuexen@fh-muenster.de + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -56,6 +57,11 @@ sctp_ss_default_init(struct sctp_tcb *st uint16_t i; TAILQ_INIT(&asoc->ss_data.out_wheel); + /* + * If there is data in the stream queues already, the scheduler of + * an existing association has been changed. We need to add all + * stream queues to the wheel. + */ for (i = 0; i < stcb->asoc.streamoutcnt; i++) { if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { sctp_ss_default_add(stcb, &stcb->asoc, @@ -83,7 +89,7 @@ sctp_ss_default_clear(struct sctp_tcb *s } static void -sctp_ss_default_init_stream(struct sctp_stream_out *strq) +sctp_ss_default_init_stream(struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { strq->ss_params.rr.next_spoke.tqe_next = NULL; strq->ss_params.rr.next_spoke.tqe_prev = NULL; @@ -411,11 +417,15 @@ sctp_ss_prio_clear(struct sctp_tcb *stcb } static void -sctp_ss_prio_init_stream(struct sctp_stream_out *strq) +sctp_ss_prio_init_stream(struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { strq->ss_params.prio.next_spoke.tqe_next = NULL; strq->ss_params.prio.next_spoke.tqe_prev = NULL; - strq->ss_params.prio.priority = 0; + if (with_strq != NULL) { + strq->ss_params.prio.priority = with_strq->ss_params.prio.priority; + } else { + strq->ss_params.prio.priority = 0; + } return; } @@ -575,11 +585,15 @@ sctp_ss_fb_clear(struct sctp_tcb *stcb, } static void -sctp_ss_fb_init_stream(struct sctp_stream_out *strq) +sctp_ss_fb_init_stream(struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { strq->ss_params.fb.next_spoke.tqe_next = NULL; strq->ss_params.fb.next_spoke.tqe_prev = NULL; - strq->ss_params.fb.rounds = -1; + if (with_strq != NULL) { + strq->ss_params.fb.rounds = with_strq->ss_params.fb.rounds; + } else { + strq->ss_params.fb.rounds = -1; + } return; } @@ -697,28 +711,40 @@ sctp_ss_fb_scheduled(struct sctp_tcb *st * Maintains the order provided by the application. */ static void +sctp_ss_fcfs_add(struct sctp_tcb *stcb, struct sctp_association *asoc, + struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, + int holds_lock); + +static void sctp_ss_fcfs_init(struct sctp_tcb *stcb, struct sctp_association *asoc, int holds_lock) { - int x, element = 0, add_more = 1; + uint32_t x, n = 0, add_more = 1; struct sctp_stream_queue_pending *sp; uint16_t i; TAILQ_INIT(&asoc->ss_data.out_list); + /* + * If there is data in the stream queues already, the scheduler of + * an existing association has been changed. We can only cycle + * through the stream queues and add everything to the FCFS queue. + */ while (add_more) { add_more = 0; for (i = 0; i < stcb->asoc.streamoutcnt; i++) { - sp = TAILQ_FIRST(&asoc->ss_data.out_list); - x = element; - while (sp != NULL && x > 0) { + sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue); + x = 0; + /* Find n. message in current stream queue */ + while (sp != NULL && x < n) { sp = TAILQ_NEXT(sp, next); + x++; } if (sp != NULL) { - sctp_ss_default_add(stcb, &stcb->asoc, &stcb->asoc.strmout[i], NULL, holds_lock); + sctp_ss_fcfs_add(stcb, &stcb->asoc, &stcb->asoc.strmout[i], sp, holds_lock); add_more = 1; } } - element++; + n++; } return; } @@ -729,14 +755,14 @@ sctp_ss_fcfs_clear(struct sctp_tcb *stcb { if (clear_values) { while (!TAILQ_EMPTY(&asoc->ss_data.out_list)) { - TAILQ_REMOVE(&asoc->ss_data.out_list, TAILQ_FIRST(&asoc->ss_data.out_list), next); + TAILQ_REMOVE(&asoc->ss_data.out_list, TAILQ_FIRST(&asoc->ss_data.out_list), ss_next); } } return; } static void -sctp_ss_fcfs_init_stream(struct sctp_stream_out *strq) +sctp_ss_fcfs_init_stream(struct sctp_stream_out *strq, struct sctp_stream_out *with_strq) { /* Nothing to be done here */ return; @@ -750,9 +776,9 @@ sctp_ss_fcfs_add(struct sctp_tcb *stcb, if (holds_lock == 0) { SCTP_TCB_SEND_LOCK(stcb); } - if (sp && (sp->next.tqe_next == NULL) && - (sp->next.tqe_prev == NULL)) { - TAILQ_INSERT_TAIL(&asoc->ss_data.out_list, sp, next); + if (sp && (sp->ss_next.tqe_next == NULL) && + (sp->ss_next.tqe_prev == NULL)) { + TAILQ_INSERT_TAIL(&asoc->ss_data.out_list, sp, ss_next); } if (holds_lock == 0) { SCTP_TCB_SEND_UNLOCK(stcb); @@ -779,9 +805,9 @@ sctp_ss_fcfs_remove(struct sctp_tcb *stc SCTP_TCB_SEND_LOCK(stcb); } if (sp && - ((sp->next.tqe_next != NULL) || - (sp->next.tqe_prev != NULL))) { - TAILQ_REMOVE(&asoc->ss_data.out_list, sp, next); + ((sp->ss_next.tqe_next != NULL) || + (sp->ss_next.tqe_prev != NULL))) { + TAILQ_REMOVE(&asoc->ss_data.out_list, sp, ss_next); } if (holds_lock == 0) { SCTP_TCB_SEND_UNLOCK(stcb); @@ -819,7 +845,7 @@ default_again: if (TAILQ_FIRST(&strq->outqueue) && TAILQ_FIRST(&strq->outqueue)->net != NULL && TAILQ_FIRST(&strq->outqueue)->net != net) { - sp = TAILQ_NEXT(sp, next); + sp = TAILQ_NEXT(sp, ss_next); goto default_again; } } Modified: head/sys/netinet/sctp_structs.h ============================================================================== --- head/sys/netinet/sctp_structs.h Thu Feb 3 20:30:17 2011 (r218240) +++ head/sys/netinet/sctp_structs.h Thu Feb 3 20:44:49 2011 (r218241) @@ -1,5 +1,8 @@ /*- * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2008-2011, by Randall Stewart, rrs@lakerest.net and + * Michael Tuexen, tuexen@fh-muenster.de + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -475,6 +478,7 @@ struct sctp_stream_queue_pending { struct timeval ts; struct sctp_nets *net; TAILQ_ENTRY(sctp_stream_queue_pending) next; + TAILQ_ENTRY(sctp_stream_queue_pending) ss_next; uint32_t length; uint32_t timetolive; uint32_t ppid; @@ -652,7 +656,7 @@ struct sctp_ss_functions { int holds_lock); void (*sctp_ss_clear) (struct sctp_tcb *stcb, struct sctp_association *asoc, int clear_values, int holds_lock); - void (*sctp_ss_init_stream) (struct sctp_stream_out *strq); + void (*sctp_ss_init_stream) (struct sctp_stream_out *strq, struct sctp_stream_out *with_strq); void (*sctp_ss_add_to_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock); int (*sctp_ss_is_empty) (struct sctp_tcb *stcb, struct sctp_association *asoc); @@ -751,12 +755,7 @@ struct sctp_association { /* re-assembly queue for fragmented chunks on the inbound path */ struct sctpchunk_listhead reasmqueue; - /* - * this queue is used when we reach a condition that we can NOT put - * data into the socket buffer. We track the size of this queue and - * set our rwnd to the space in the socket minus also the - * size_on_delivery_queue. - */ + /* Scheduling queues */ union scheduling_data ss_data; /* Modified: head/sys/netinet/sctp_timer.c ============================================================================== --- head/sys/netinet/sctp_timer.c Thu Feb 3 20:30:17 2011 (r218240) +++ head/sys/netinet/sctp_timer.c Thu Feb 3 20:44:49 2011 (r218241) @@ -1,5 +1,8 @@ /*- * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2008-2011, by Randall Stewart, rrs@lakerest.net and + * Michael Tuexen, tuexen@fh-muenster.de + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -1510,32 +1513,17 @@ sctp_audit_stream_queues_for_size(struct stcb->asoc.sent_queue_retran_cnt); stcb->asoc.sent_queue_retran_cnt = 0; } - SCTP_TCB_SEND_LOCK(stcb); if (stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { - int cnt = 0; - - /* Check to see if a spoke fell off the wheel */ - for (i = 0; i < stcb->asoc.streamoutcnt; i++) { - if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { - stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, - &stcb->asoc, - &stcb->asoc.strmout[i], - NULL, - 1); - cnt++; - } - } - if (cnt) { - /* yep, we lost a spoke or two */ - SCTP_PRINTF("Found an additional %d streams NOT on outwheel, corrected\n", cnt); + /* No stream scheduler information, initialize scheduler */ + stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 0); + if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) { + /* yep, we lost a stream or two */ + SCTP_PRINTF("Found additional streams NOT managed by scheduler, corrected\n"); } else { - /* no spokes lost, */ + /* no streams lost */ stcb->asoc.total_output_queue_size = 0; } - SCTP_TCB_SEND_UNLOCK(stcb); - return; } - SCTP_TCB_SEND_UNLOCK(stcb); /* Check to see if some data queued, if so report it */ for (i = 0; i < stcb->asoc.streamoutcnt; i++) { if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { Modified: head/sys/netinet/sctp_usrreq.c ============================================================================== --- head/sys/netinet/sctp_usrreq.c Thu Feb 3 20:30:17 2011 (r218240) +++ head/sys/netinet/sctp_usrreq.c Thu Feb 3 20:44:49 2011 (r218241) @@ -3448,7 +3448,7 @@ sctp_setopt(struct socket *so, int optna stcb->asoc.strmout[i].next_sequence_sent = oldstream[i].next_sequence_sent; stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete; stcb->asoc.strmout[i].stream_no = i; - stcb->asoc.ss_functions.sctp_ss_init_stream(&oldstream[i]); + stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]); /* * now anything on those * queues? @@ -3475,7 +3475,7 @@ sctp_setopt(struct socket *so, int optna TAILQ_INIT(&stcb->asoc.strmout[i].outqueue); stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; - stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i]); + stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL); } stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + addstrmcnt; SCTP_FREE(oldstream, SCTP_M_STRMO); Modified: head/sys/netinet/sctputil.c ============================================================================== --- head/sys/netinet/sctputil.c Thu Feb 3 20:30:17 2011 (r218240) +++ head/sys/netinet/sctputil.c Thu Feb 3 20:44:49 2011 (r218241) @@ -1076,7 +1076,7 @@ sctp_init_asoc(struct sctp_inpcb *m, str TAILQ_INIT(&asoc->strmout[i].outqueue); asoc->strmout[i].stream_no = i; asoc->strmout[i].last_msg_incomplete = 0; - asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i]); + asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); } asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102032044.p13KinL3057953>