diff options
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r-- | net/sctp/outqueue.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index e7aa177c9522..1b4a7f8ec3fd 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -63,6 +63,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn); | |||
63 | static void sctp_check_transmitted(struct sctp_outq *q, | 63 | static void sctp_check_transmitted(struct sctp_outq *q, |
64 | struct list_head *transmitted_queue, | 64 | struct list_head *transmitted_queue, |
65 | struct sctp_transport *transport, | 65 | struct sctp_transport *transport, |
66 | union sctp_addr *saddr, | ||
66 | struct sctp_sackhdr *sack, | 67 | struct sctp_sackhdr *sack, |
67 | __u32 *highest_new_tsn); | 68 | __u32 *highest_new_tsn); |
68 | 69 | ||
@@ -299,6 +300,7 @@ void sctp_outq_free(struct sctp_outq *q) | |||
299 | /* Put a new chunk in an sctp_outq. */ | 300 | /* Put a new chunk in an sctp_outq. */ |
300 | int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | 301 | int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) |
301 | { | 302 | { |
303 | struct net *net = sock_net(q->asoc->base.sk); | ||
302 | int error = 0; | 304 | int error = 0; |
303 | 305 | ||
304 | SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n", | 306 | SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n", |
@@ -337,15 +339,15 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
337 | 339 | ||
338 | sctp_outq_tail_data(q, chunk); | 340 | sctp_outq_tail_data(q, chunk); |
339 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) | 341 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) |
340 | SCTP_INC_STATS(SCTP_MIB_OUTUNORDERCHUNKS); | 342 | SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS); |
341 | else | 343 | else |
342 | SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS); | 344 | SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS); |
343 | q->empty = 0; | 345 | q->empty = 0; |
344 | break; | 346 | break; |
345 | } | 347 | } |
346 | } else { | 348 | } else { |
347 | list_add_tail(&chunk->list, &q->control_chunk_list); | 349 | list_add_tail(&chunk->list, &q->control_chunk_list); |
348 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 350 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
349 | } | 351 | } |
350 | 352 | ||
351 | if (error < 0) | 353 | if (error < 0) |
@@ -478,11 +480,12 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
478 | void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, | 480 | void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, |
479 | sctp_retransmit_reason_t reason) | 481 | sctp_retransmit_reason_t reason) |
480 | { | 482 | { |
483 | struct net *net = sock_net(q->asoc->base.sk); | ||
481 | int error = 0; | 484 | int error = 0; |
482 | 485 | ||
483 | switch(reason) { | 486 | switch(reason) { |
484 | case SCTP_RTXR_T3_RTX: | 487 | case SCTP_RTXR_T3_RTX: |
485 | SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS); | 488 | SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS); |
486 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); | 489 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); |
487 | /* Update the retran path if the T3-rtx timer has expired for | 490 | /* Update the retran path if the T3-rtx timer has expired for |
488 | * the current retran path. | 491 | * the current retran path. |
@@ -493,15 +496,15 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, | |||
493 | transport->asoc->unack_data; | 496 | transport->asoc->unack_data; |
494 | break; | 497 | break; |
495 | case SCTP_RTXR_FAST_RTX: | 498 | case SCTP_RTXR_FAST_RTX: |
496 | SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); | 499 | SCTP_INC_STATS(net, SCTP_MIB_FAST_RETRANSMITS); |
497 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); | 500 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); |
498 | q->fast_rtx = 1; | 501 | q->fast_rtx = 1; |
499 | break; | 502 | break; |
500 | case SCTP_RTXR_PMTUD: | 503 | case SCTP_RTXR_PMTUD: |
501 | SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); | 504 | SCTP_INC_STATS(net, SCTP_MIB_PMTUD_RETRANSMITS); |
502 | break; | 505 | break; |
503 | case SCTP_RTXR_T1_RTX: | 506 | case SCTP_RTXR_T1_RTX: |
504 | SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS); | 507 | SCTP_INC_STATS(net, SCTP_MIB_T1_RETRANSMITS); |
505 | transport->asoc->init_retries++; | 508 | transport->asoc->init_retries++; |
506 | break; | 509 | break; |
507 | default: | 510 | default: |
@@ -589,9 +592,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
589 | * next chunk. | 592 | * next chunk. |
590 | */ | 593 | */ |
591 | if (chunk->tsn_gap_acked) { | 594 | if (chunk->tsn_gap_acked) { |
592 | list_del(&chunk->transmitted_list); | 595 | list_move_tail(&chunk->transmitted_list, |
593 | list_add_tail(&chunk->transmitted_list, | 596 | &transport->transmitted); |
594 | &transport->transmitted); | ||
595 | continue; | 597 | continue; |
596 | } | 598 | } |
597 | 599 | ||
@@ -655,9 +657,8 @@ redo: | |||
655 | /* The append was successful, so add this chunk to | 657 | /* The append was successful, so add this chunk to |
656 | * the transmitted list. | 658 | * the transmitted list. |
657 | */ | 659 | */ |
658 | list_del(&chunk->transmitted_list); | 660 | list_move_tail(&chunk->transmitted_list, |
659 | list_add_tail(&chunk->transmitted_list, | 661 | &transport->transmitted); |
660 | &transport->transmitted); | ||
661 | 662 | ||
662 | /* Mark the chunk as ineligible for fast retransmit | 663 | /* Mark the chunk as ineligible for fast retransmit |
663 | * after it is retransmitted. | 664 | * after it is retransmitted. |
@@ -1139,9 +1140,10 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc, | |||
1139 | * Process the SACK against the outqueue. Mostly, this just frees | 1140 | * Process the SACK against the outqueue. Mostly, this just frees |
1140 | * things off the transmitted queue. | 1141 | * things off the transmitted queue. |
1141 | */ | 1142 | */ |
1142 | int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | 1143 | int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) |
1143 | { | 1144 | { |
1144 | struct sctp_association *asoc = q->asoc; | 1145 | struct sctp_association *asoc = q->asoc; |
1146 | struct sctp_sackhdr *sack = chunk->subh.sack_hdr; | ||
1145 | struct sctp_transport *transport; | 1147 | struct sctp_transport *transport; |
1146 | struct sctp_chunk *tchunk = NULL; | 1148 | struct sctp_chunk *tchunk = NULL; |
1147 | struct list_head *lchunk, *transport_list, *temp; | 1149 | struct list_head *lchunk, *transport_list, *temp; |
@@ -1210,7 +1212,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1210 | /* Run through the retransmit queue. Credit bytes received | 1212 | /* Run through the retransmit queue. Credit bytes received |
1211 | * and free those chunks that we can. | 1213 | * and free those chunks that we can. |
1212 | */ | 1214 | */ |
1213 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn); | 1215 | sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn); |
1214 | 1216 | ||
1215 | /* Run through the transmitted queue. | 1217 | /* Run through the transmitted queue. |
1216 | * Credit bytes received and free those chunks which we can. | 1218 | * Credit bytes received and free those chunks which we can. |
@@ -1219,7 +1221,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1219 | */ | 1221 | */ |
1220 | list_for_each_entry(transport, transport_list, transports) { | 1222 | list_for_each_entry(transport, transport_list, transports) { |
1221 | sctp_check_transmitted(q, &transport->transmitted, | 1223 | sctp_check_transmitted(q, &transport->transmitted, |
1222 | transport, sack, &highest_new_tsn); | 1224 | transport, &chunk->source, sack, |
1225 | &highest_new_tsn); | ||
1223 | /* | 1226 | /* |
1224 | * SFR-CACC algorithm: | 1227 | * SFR-CACC algorithm: |
1225 | * C) Let count_of_newacks be the number of | 1228 | * C) Let count_of_newacks be the number of |
@@ -1326,6 +1329,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q) | |||
1326 | static void sctp_check_transmitted(struct sctp_outq *q, | 1329 | static void sctp_check_transmitted(struct sctp_outq *q, |
1327 | struct list_head *transmitted_queue, | 1330 | struct list_head *transmitted_queue, |
1328 | struct sctp_transport *transport, | 1331 | struct sctp_transport *transport, |
1332 | union sctp_addr *saddr, | ||
1329 | struct sctp_sackhdr *sack, | 1333 | struct sctp_sackhdr *sack, |
1330 | __u32 *highest_new_tsn_in_sack) | 1334 | __u32 *highest_new_tsn_in_sack) |
1331 | { | 1335 | { |
@@ -1633,8 +1637,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1633 | /* Mark the destination transport address as | 1637 | /* Mark the destination transport address as |
1634 | * active if it is not so marked. | 1638 | * active if it is not so marked. |
1635 | */ | 1639 | */ |
1636 | if ((transport->state == SCTP_INACTIVE) || | 1640 | if ((transport->state == SCTP_INACTIVE || |
1637 | (transport->state == SCTP_UNCONFIRMED)) { | 1641 | transport->state == SCTP_UNCONFIRMED) && |
1642 | sctp_cmp_addr_exact(&transport->ipaddr, saddr)) { | ||
1638 | sctp_assoc_control_transport( | 1643 | sctp_assoc_control_transport( |
1639 | transport->asoc, | 1644 | transport->asoc, |
1640 | transport, | 1645 | transport, |
@@ -1914,6 +1919,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) | |||
1914 | 1919 | ||
1915 | if (ftsn_chunk) { | 1920 | if (ftsn_chunk) { |
1916 | list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); | 1921 | list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); |
1917 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 1922 | SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS); |
1918 | } | 1923 | } |
1919 | } | 1924 | } |