|
@@ -915,22 +915,28 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
|
|
case SCTP_CID_ECN_ECNE:
|
|
case SCTP_CID_ECN_ECNE:
|
|
case SCTP_CID_ASCONF:
|
|
case SCTP_CID_ASCONF:
|
|
case SCTP_CID_FWD_TSN:
|
|
case SCTP_CID_FWD_TSN:
|
|
|
|
+ case SCTP_CID_RECONF:
|
|
status = sctp_packet_transmit_chunk(packet, chunk,
|
|
status = sctp_packet_transmit_chunk(packet, chunk,
|
|
one_packet, gfp);
|
|
one_packet, gfp);
|
|
if (status != SCTP_XMIT_OK) {
|
|
if (status != SCTP_XMIT_OK) {
|
|
/* put the chunk back */
|
|
/* put the chunk back */
|
|
list_add(&chunk->list, &q->control_chunk_list);
|
|
list_add(&chunk->list, &q->control_chunk_list);
|
|
- } else {
|
|
|
|
- asoc->stats.octrlchunks++;
|
|
|
|
- /* PR-SCTP C5) If a FORWARD TSN is sent, the
|
|
|
|
- * sender MUST assure that at least one T3-rtx
|
|
|
|
- * timer is running.
|
|
|
|
- */
|
|
|
|
- if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
|
|
|
|
- sctp_transport_reset_t3_rtx(transport);
|
|
|
|
- transport->last_time_sent = jiffies;
|
|
|
|
- }
|
|
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ asoc->stats.octrlchunks++;
|
|
|
|
+ /* PR-SCTP C5) If a FORWARD TSN is sent, the
|
|
|
|
+ * sender MUST assure that at least one T3-rtx
|
|
|
|
+ * timer is running.
|
|
|
|
+ */
|
|
|
|
+ if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
|
|
|
|
+ sctp_transport_reset_t3_rtx(transport);
|
|
|
|
+ transport->last_time_sent = jiffies;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (chunk == asoc->strreset_chunk)
|
|
|
|
+ sctp_transport_reset_reconf_timer(transport);
|
|
|
|
+
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
@@ -1016,6 +1022,8 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
|
|
|
|
|
|
/* Finally, transmit new packets. */
|
|
/* Finally, transmit new packets. */
|
|
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
|
|
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
|
|
|
|
+ __u32 sid = ntohs(chunk->subh.data_hdr->stream);
|
|
|
|
+
|
|
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
|
|
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
|
|
* stream identifier.
|
|
* stream identifier.
|
|
*/
|
|
*/
|
|
@@ -1038,6 +1046,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (asoc->stream->out[sid].state == SCTP_STREAM_CLOSED) {
|
|
|
|
+ sctp_outq_head_data(q, chunk);
|
|
|
|
+ goto sctp_flush_out;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* If there is a specified transport, use it.
|
|
/* If there is a specified transport, use it.
|
|
* Otherwise, we want to use the active path.
|
|
* Otherwise, we want to use the active path.
|
|
*/
|
|
*/
|