Skip site navigation (1)Skip section navigation (2)
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>