diff options
Diffstat (limited to 'net/sctp/outqueue.c')
| -rw-r--r-- | net/sctp/outqueue.c | 51 | 
1 files changed, 18 insertions, 33 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 94df7587786..9c77947c059 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -22,9 +22,8 @@   * See the GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with GNU CC; see the file COPYING.  If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * along with GNU CC; see the file COPYING.  If not, see + * <http://www.gnu.org/licenses/>.   *   * Please send any bug reports or fixes you make to the   * email address(es): @@ -111,7 +110,7 @@ static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary,  				       struct sctp_transport *transport,  				       int count_of_newacks)  { -	if (count_of_newacks >=2 && transport != primary) +	if (count_of_newacks >= 2 && transport != primary)  		return 1;  	return 0;  } @@ -208,8 +207,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)  	INIT_LIST_HEAD(&q->retransmit);  	INIT_LIST_HEAD(&q->sacked);  	INIT_LIST_HEAD(&q->abandoned); - -	q->empty = 1;  }  /* Free the outqueue structure and any related pending chunks. @@ -332,7 +329,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)  				SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);  			else  				SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS); -			q->empty = 0;  			break;  		}  	} else { @@ -446,6 +442,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,  				transport->rto_pending = 0;  			} +			chunk->resent = 1; +  			/* Move the chunk to the retransmit queue. The chunks  			 * on the retransmit queue are always kept in order.  			 */ @@ -469,7 +467,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,  	struct net *net = sock_net(q->asoc->base.sk);  	int error = 0; -	switch(reason) { +	switch (reason) {  	case SCTP_RTXR_T3_RTX:  		SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS);  		sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); @@ -652,7 +650,6 @@ redo:  			if (chunk->fast_retransmit == SCTP_NEED_FRTX)  				chunk->fast_retransmit = SCTP_DONT_FRTX; -			q->empty = 0;  			q->asoc->stats.rtxchunks++;  			break;  		} @@ -1063,8 +1060,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)  			sctp_transport_reset_timers(transport); -			q->empty = 0; -  			/* Only let one DATA chunk get bundled with a  			 * COOKIE-ECHO chunk.  			 */ @@ -1087,7 +1082,7 @@ sctp_flush_out:  	 *  	 * --xguo  	 */ -	while ((ltransport = sctp_list_dequeue(&transport_list)) != NULL ) { +	while ((ltransport = sctp_list_dequeue(&transport_list)) != NULL) {  		struct sctp_transport *t = list_entry(ltransport,  						      struct sctp_transport,  						      send_ready); @@ -1216,7 +1211,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)  		 * destinations for which cacc_saw_newack is set.  		 */  		if (transport->cacc.cacc_saw_newack) -			count_of_newacks ++; +			count_of_newacks++;  	}  	/* Move the Cumulative TSN Ack Point if appropriate.  */ @@ -1273,29 +1268,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)  		 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,  		 asoc->adv_peer_ack_point); -	/* See if all chunks are acked. -	 * Make sure the empty queue handler will get run later. -	 */ -	q->empty = (list_empty(&q->out_chunk_list) && -		    list_empty(&q->retransmit)); -	if (!q->empty) -		goto finish; - -	list_for_each_entry(transport, transport_list, transports) { -		q->empty = q->empty && list_empty(&transport->transmitted); -		if (!q->empty) -			goto finish; -	} - -	pr_debug("%s: sack queue is empty\n", __func__); -finish: -	return q->empty; +	return sctp_outq_is_empty(q);  } -/* Is the outqueue empty?  */ +/* Is the outqueue empty? + * The queue is empty when we have not pending data, no in-flight data + * and nothing pending retransmissions. + */  int sctp_outq_is_empty(const struct sctp_outq *q)  { -	return q->empty; +	return q->out_qlen == 0 && q->outstanding_bytes == 0 && +	       list_empty(&q->retransmit);  }  /******************************************************************** @@ -1375,6 +1358,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,  				 * instance).  				 */  				if (!tchunk->tsn_gap_acked && +				    !tchunk->resent &&  				    tchunk->rtt_in_progress) {  					tchunk->rtt_in_progress = 0;  					rtt = jiffies - tchunk->sent_at; @@ -1391,7 +1375,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,  			 */  			if (!tchunk->tsn_gap_acked) {  				tchunk->tsn_gap_acked = 1; -				*highest_new_tsn_in_sack = tsn; +				if (TSN_lt(*highest_new_tsn_in_sack, tsn)) +					*highest_new_tsn_in_sack = tsn;  				bytes_acked += sctp_data_size(tchunk);  				if (!tchunk->transport)  					migrate_bytes += sctp_data_size(tchunk);  | 
