diff options
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/chunk.c | 11 | ||||
| -rw-r--r-- | net/sctp/outqueue.c | 19 | ||||
| -rw-r--r-- | net/sctp/protocol.c | 1 | ||||
| -rw-r--r-- | net/sctp/socket.c | 6 | ||||
| -rw-r--r-- | net/sctp/stream.c | 79 | ||||
| -rw-r--r-- | net/sctp/stream_sched.c | 25 | ||||
| -rw-r--r-- | net/sctp/stream_sched_prio.c | 7 | ||||
| -rw-r--r-- | net/sctp/stream_sched_rr.c | 7 |
8 files changed, 124 insertions, 31 deletions
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 7b261afc47b9..7f8baa48e7c2 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
| @@ -53,6 +53,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg) | |||
| 53 | msg->send_failed = 0; | 53 | msg->send_failed = 0; |
| 54 | msg->send_error = 0; | 54 | msg->send_error = 0; |
| 55 | msg->can_delay = 1; | 55 | msg->can_delay = 1; |
| 56 | msg->abandoned = 0; | ||
| 56 | msg->expires_at = 0; | 57 | msg->expires_at = 0; |
| 57 | INIT_LIST_HEAD(&msg->chunks); | 58 | INIT_LIST_HEAD(&msg->chunks); |
| 58 | } | 59 | } |
| @@ -304,6 +305,13 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) | |||
| 304 | if (!chunk->asoc->peer.prsctp_capable) | 305 | if (!chunk->asoc->peer.prsctp_capable) |
| 305 | return 0; | 306 | return 0; |
| 306 | 307 | ||
| 308 | if (chunk->msg->abandoned) | ||
| 309 | return 1; | ||
| 310 | |||
| 311 | if (!chunk->has_tsn && | ||
| 312 | !(chunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)) | ||
| 313 | return 0; | ||
| 314 | |||
| 307 | if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && | 315 | if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && |
| 308 | time_after(jiffies, chunk->msg->expires_at)) { | 316 | time_after(jiffies, chunk->msg->expires_at)) { |
| 309 | struct sctp_stream_out *streamout = | 317 | struct sctp_stream_out *streamout = |
| @@ -316,6 +324,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) | |||
| 316 | chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; | 324 | chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; |
| 317 | streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; | 325 | streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; |
| 318 | } | 326 | } |
| 327 | chunk->msg->abandoned = 1; | ||
| 319 | return 1; | 328 | return 1; |
| 320 | } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && | 329 | } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && |
| 321 | chunk->sent_count > chunk->sinfo.sinfo_timetolive) { | 330 | chunk->sent_count > chunk->sinfo.sinfo_timetolive) { |
| @@ -324,10 +333,12 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) | |||
| 324 | 333 | ||
| 325 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; | 334 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; |
| 326 | streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++; | 335 | streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++; |
| 336 | chunk->msg->abandoned = 1; | ||
| 327 | return 1; | 337 | return 1; |
| 328 | } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) && | 338 | } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) && |
| 329 | chunk->msg->expires_at && | 339 | chunk->msg->expires_at && |
| 330 | time_after(jiffies, chunk->msg->expires_at)) { | 340 | time_after(jiffies, chunk->msg->expires_at)) { |
| 341 | chunk->msg->abandoned = 1; | ||
| 331 | return 1; | 342 | return 1; |
| 332 | } | 343 | } |
| 333 | /* PRIO policy is processed by sendmsg, not here */ | 344 | /* PRIO policy is processed by sendmsg, not here */ |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 4db012aa25f7..7d67feeeffc1 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -364,10 +364,12 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, | |||
| 364 | list_for_each_entry_safe(chk, temp, queue, transmitted_list) { | 364 | list_for_each_entry_safe(chk, temp, queue, transmitted_list) { |
| 365 | struct sctp_stream_out *streamout; | 365 | struct sctp_stream_out *streamout; |
| 366 | 366 | ||
| 367 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | 367 | if (!chk->msg->abandoned && |
| 368 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) | 368 | (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || |
| 369 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)) | ||
| 369 | continue; | 370 | continue; |
| 370 | 371 | ||
| 372 | chk->msg->abandoned = 1; | ||
| 371 | list_del_init(&chk->transmitted_list); | 373 | list_del_init(&chk->transmitted_list); |
| 372 | sctp_insert_list(&asoc->outqueue.abandoned, | 374 | sctp_insert_list(&asoc->outqueue.abandoned, |
| 373 | &chk->transmitted_list); | 375 | &chk->transmitted_list); |
| @@ -377,7 +379,8 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, | |||
| 377 | asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; | 379 | asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; |
| 378 | streamout->ext->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; | 380 | streamout->ext->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; |
| 379 | 381 | ||
| 380 | if (!chk->tsn_gap_acked) { | 382 | if (queue != &asoc->outqueue.retransmit && |
| 383 | !chk->tsn_gap_acked) { | ||
| 381 | if (chk->transport) | 384 | if (chk->transport) |
| 382 | chk->transport->flight_size -= | 385 | chk->transport->flight_size -= |
| 383 | sctp_data_size(chk); | 386 | sctp_data_size(chk); |
| @@ -403,10 +406,13 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, | |||
| 403 | q->sched->unsched_all(&asoc->stream); | 406 | q->sched->unsched_all(&asoc->stream); |
| 404 | 407 | ||
| 405 | list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) { | 408 | list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) { |
| 406 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | 409 | if (!chk->msg->abandoned && |
| 407 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) | 410 | (!(chk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG) || |
| 411 | !SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | ||
| 412 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)) | ||
| 408 | continue; | 413 | continue; |
| 409 | 414 | ||
| 415 | chk->msg->abandoned = 1; | ||
| 410 | sctp_sched_dequeue_common(q, chk); | 416 | sctp_sched_dequeue_common(q, chk); |
| 411 | asoc->sent_cnt_removable--; | 417 | asoc->sent_cnt_removable--; |
| 412 | asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; | 418 | asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; |
| @@ -1434,7 +1440,8 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1434 | /* If this chunk has not been acked, stop | 1440 | /* If this chunk has not been acked, stop |
| 1435 | * considering it as 'outstanding'. | 1441 | * considering it as 'outstanding'. |
| 1436 | */ | 1442 | */ |
| 1437 | if (!tchunk->tsn_gap_acked) { | 1443 | if (transmitted_queue != &q->retransmit && |
| 1444 | !tchunk->tsn_gap_acked) { | ||
| 1438 | if (tchunk->transport) | 1445 | if (tchunk->transport) |
| 1439 | tchunk->transport->flight_size -= | 1446 | tchunk->transport->flight_size -= |
| 1440 | sctp_data_size(tchunk); | 1447 | sctp_data_size(tchunk); |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index f5172c21349b..6a38c2503649 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -1499,6 +1499,7 @@ static __init int sctp_init(void) | |||
| 1499 | INIT_LIST_HEAD(&sctp_address_families); | 1499 | INIT_LIST_HEAD(&sctp_address_families); |
| 1500 | sctp_v4_pf_init(); | 1500 | sctp_v4_pf_init(); |
| 1501 | sctp_v6_pf_init(); | 1501 | sctp_v6_pf_init(); |
| 1502 | sctp_sched_ops_init(); | ||
| 1502 | 1503 | ||
| 1503 | status = register_pernet_subsys(&sctp_defaults_ops); | 1504 | status = register_pernet_subsys(&sctp_defaults_ops); |
| 1504 | if (status) | 1505 | if (status) |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3204a9b29407..014847e25648 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -188,13 +188,13 @@ static void sctp_for_each_tx_datachunk(struct sctp_association *asoc, | |||
| 188 | list_for_each_entry(chunk, &t->transmitted, transmitted_list) | 188 | list_for_each_entry(chunk, &t->transmitted, transmitted_list) |
| 189 | cb(chunk); | 189 | cb(chunk); |
| 190 | 190 | ||
| 191 | list_for_each_entry(chunk, &q->retransmit, list) | 191 | list_for_each_entry(chunk, &q->retransmit, transmitted_list) |
| 192 | cb(chunk); | 192 | cb(chunk); |
| 193 | 193 | ||
| 194 | list_for_each_entry(chunk, &q->sacked, list) | 194 | list_for_each_entry(chunk, &q->sacked, transmitted_list) |
| 195 | cb(chunk); | 195 | cb(chunk); |
| 196 | 196 | ||
| 197 | list_for_each_entry(chunk, &q->abandoned, list) | 197 | list_for_each_entry(chunk, &q->abandoned, transmitted_list) |
| 198 | cb(chunk); | 198 | cb(chunk); |
| 199 | 199 | ||
| 200 | list_for_each_entry(chunk, &q->out_chunk_list, list) | 200 | list_for_each_entry(chunk, &q->out_chunk_list, list) |
diff --git a/net/sctp/stream.c b/net/sctp/stream.c index a11db21dc8a0..76ea66be0bbe 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c | |||
| @@ -64,7 +64,7 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream, | |||
| 64 | */ | 64 | */ |
| 65 | 65 | ||
| 66 | /* Mark as failed send. */ | 66 | /* Mark as failed send. */ |
| 67 | sctp_chunk_fail(ch, SCTP_ERROR_INV_STRM); | 67 | sctp_chunk_fail(ch, (__force __u32)SCTP_ERROR_INV_STRM); |
| 68 | if (asoc->peer.prsctp_capable && | 68 | if (asoc->peer.prsctp_capable && |
| 69 | SCTP_PR_PRIO_ENABLED(ch->sinfo.sinfo_flags)) | 69 | SCTP_PR_PRIO_ENABLED(ch->sinfo.sinfo_flags)) |
| 70 | asoc->sent_cnt_removable--; | 70 | asoc->sent_cnt_removable--; |
| @@ -254,6 +254,30 @@ static int sctp_send_reconf(struct sctp_association *asoc, | |||
| 254 | return retval; | 254 | return retval; |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static bool sctp_stream_outq_is_empty(struct sctp_stream *stream, | ||
| 258 | __u16 str_nums, __be16 *str_list) | ||
| 259 | { | ||
| 260 | struct sctp_association *asoc; | ||
| 261 | __u16 i; | ||
| 262 | |||
| 263 | asoc = container_of(stream, struct sctp_association, stream); | ||
| 264 | if (!asoc->outqueue.out_qlen) | ||
| 265 | return true; | ||
| 266 | |||
| 267 | if (!str_nums) | ||
| 268 | return false; | ||
| 269 | |||
| 270 | for (i = 0; i < str_nums; i++) { | ||
| 271 | __u16 sid = ntohs(str_list[i]); | ||
| 272 | |||
| 273 | if (stream->out[sid].ext && | ||
| 274 | !list_empty(&stream->out[sid].ext->outq)) | ||
| 275 | return false; | ||
| 276 | } | ||
| 277 | |||
| 278 | return true; | ||
| 279 | } | ||
| 280 | |||
| 257 | int sctp_send_reset_streams(struct sctp_association *asoc, | 281 | int sctp_send_reset_streams(struct sctp_association *asoc, |
| 258 | struct sctp_reset_streams *params) | 282 | struct sctp_reset_streams *params) |
| 259 | { | 283 | { |
| @@ -317,6 +341,11 @@ int sctp_send_reset_streams(struct sctp_association *asoc, | |||
| 317 | for (i = 0; i < str_nums; i++) | 341 | for (i = 0; i < str_nums; i++) |
| 318 | nstr_list[i] = htons(str_list[i]); | 342 | nstr_list[i] = htons(str_list[i]); |
| 319 | 343 | ||
| 344 | if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) { | ||
| 345 | retval = -EAGAIN; | ||
| 346 | goto out; | ||
| 347 | } | ||
| 348 | |||
| 320 | chunk = sctp_make_strreset_req(asoc, str_nums, nstr_list, out, in); | 349 | chunk = sctp_make_strreset_req(asoc, str_nums, nstr_list, out, in); |
| 321 | 350 | ||
| 322 | kfree(nstr_list); | 351 | kfree(nstr_list); |
| @@ -377,6 +406,9 @@ int sctp_send_reset_assoc(struct sctp_association *asoc) | |||
| 377 | if (asoc->strreset_outstanding) | 406 | if (asoc->strreset_outstanding) |
| 378 | return -EINPROGRESS; | 407 | return -EINPROGRESS; |
| 379 | 408 | ||
| 409 | if (!sctp_outq_is_empty(&asoc->outqueue)) | ||
| 410 | return -EAGAIN; | ||
| 411 | |||
| 380 | chunk = sctp_make_strreset_tsnreq(asoc); | 412 | chunk = sctp_make_strreset_tsnreq(asoc); |
| 381 | if (!chunk) | 413 | if (!chunk) |
| 382 | return -ENOMEM; | 414 | return -ENOMEM; |
| @@ -563,7 +595,7 @@ struct sctp_chunk *sctp_process_strreset_outreq( | |||
| 563 | flags = SCTP_STREAM_RESET_INCOMING_SSN; | 595 | flags = SCTP_STREAM_RESET_INCOMING_SSN; |
| 564 | } | 596 | } |
| 565 | 597 | ||
| 566 | nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2; | 598 | nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16); |
| 567 | if (nums) { | 599 | if (nums) { |
| 568 | str_p = outreq->list_of_streams; | 600 | str_p = outreq->list_of_streams; |
| 569 | for (i = 0; i < nums; i++) { | 601 | for (i = 0; i < nums; i++) { |
| @@ -627,7 +659,7 @@ struct sctp_chunk *sctp_process_strreset_inreq( | |||
| 627 | goto out; | 659 | goto out; |
| 628 | } | 660 | } |
| 629 | 661 | ||
| 630 | nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2; | 662 | nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); |
| 631 | str_p = inreq->list_of_streams; | 663 | str_p = inreq->list_of_streams; |
| 632 | for (i = 0; i < nums; i++) { | 664 | for (i = 0; i < nums; i++) { |
| 633 | if (ntohs(str_p[i]) >= stream->outcnt) { | 665 | if (ntohs(str_p[i]) >= stream->outcnt) { |
| @@ -636,6 +668,12 @@ struct sctp_chunk *sctp_process_strreset_inreq( | |||
| 636 | } | 668 | } |
| 637 | } | 669 | } |
| 638 | 670 | ||
| 671 | if (!sctp_stream_outq_is_empty(stream, nums, str_p)) { | ||
| 672 | result = SCTP_STRRESET_IN_PROGRESS; | ||
| 673 | asoc->strreset_inseq--; | ||
| 674 | goto err; | ||
| 675 | } | ||
| 676 | |||
| 639 | chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); | 677 | chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); |
| 640 | if (!chunk) | 678 | if (!chunk) |
| 641 | goto out; | 679 | goto out; |
| @@ -687,12 +725,18 @@ struct sctp_chunk *sctp_process_strreset_tsnreq( | |||
| 687 | i = asoc->strreset_inseq - request_seq - 1; | 725 | i = asoc->strreset_inseq - request_seq - 1; |
| 688 | result = asoc->strreset_result[i]; | 726 | result = asoc->strreset_result[i]; |
| 689 | if (result == SCTP_STRRESET_PERFORMED) { | 727 | if (result == SCTP_STRRESET_PERFORMED) { |
| 690 | next_tsn = asoc->next_tsn; | 728 | next_tsn = asoc->ctsn_ack_point + 1; |
| 691 | init_tsn = | 729 | init_tsn = |
| 692 | sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1; | 730 | sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1; |
| 693 | } | 731 | } |
| 694 | goto err; | 732 | goto err; |
| 695 | } | 733 | } |
| 734 | |||
| 735 | if (!sctp_outq_is_empty(&asoc->outqueue)) { | ||
| 736 | result = SCTP_STRRESET_IN_PROGRESS; | ||
| 737 | goto err; | ||
| 738 | } | ||
| 739 | |||
| 696 | asoc->strreset_inseq++; | 740 | asoc->strreset_inseq++; |
| 697 | 741 | ||
| 698 | if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) | 742 | if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) |
| @@ -703,9 +747,10 @@ struct sctp_chunk *sctp_process_strreset_tsnreq( | |||
| 703 | goto out; | 747 | goto out; |
| 704 | } | 748 | } |
| 705 | 749 | ||
| 706 | /* G3: The same processing as though a SACK chunk with no gap report | 750 | /* G4: The same processing as though a FWD-TSN chunk (as defined in |
| 707 | * and a cumulative TSN ACK of the Sender's Next TSN minus 1 were | 751 | * [RFC3758]) with all streams affected and a new cumulative TSN |
| 708 | * received MUST be performed. | 752 | * ACK of the Receiver's Next TSN minus 1 were received MUST be |
| 753 | * performed. | ||
| 709 | */ | 754 | */ |
| 710 | max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map); | 755 | max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map); |
| 711 | sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen); | 756 | sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen); |
| @@ -720,10 +765,9 @@ struct sctp_chunk *sctp_process_strreset_tsnreq( | |||
| 720 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, | 765 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, |
| 721 | init_tsn, GFP_ATOMIC); | 766 | init_tsn, GFP_ATOMIC); |
| 722 | 767 | ||
| 723 | /* G4: The same processing as though a FWD-TSN chunk (as defined in | 768 | /* G3: The same processing as though a SACK chunk with no gap report |
| 724 | * [RFC3758]) with all streams affected and a new cumulative TSN | 769 | * and a cumulative TSN ACK of the Sender's Next TSN minus 1 were |
| 725 | * ACK of the Receiver's Next TSN minus 1 were received MUST be | 770 | * received MUST be performed. |
| 726 | * performed. | ||
| 727 | */ | 771 | */ |
| 728 | sctp_outq_free(&asoc->outqueue); | 772 | sctp_outq_free(&asoc->outqueue); |
| 729 | 773 | ||
| @@ -927,7 +971,8 @@ struct sctp_chunk *sctp_process_strreset_resp( | |||
| 927 | 971 | ||
| 928 | outreq = (struct sctp_strreset_outreq *)req; | 972 | outreq = (struct sctp_strreset_outreq *)req; |
| 929 | str_p = outreq->list_of_streams; | 973 | str_p = outreq->list_of_streams; |
| 930 | nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) / 2; | 974 | nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) / |
| 975 | sizeof(__u16); | ||
| 931 | 976 | ||
| 932 | if (result == SCTP_STRRESET_PERFORMED) { | 977 | if (result == SCTP_STRRESET_PERFORMED) { |
| 933 | if (nums) { | 978 | if (nums) { |
| @@ -956,7 +1001,8 @@ struct sctp_chunk *sctp_process_strreset_resp( | |||
| 956 | 1001 | ||
| 957 | inreq = (struct sctp_strreset_inreq *)req; | 1002 | inreq = (struct sctp_strreset_inreq *)req; |
| 958 | str_p = inreq->list_of_streams; | 1003 | str_p = inreq->list_of_streams; |
| 959 | nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / 2; | 1004 | nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / |
| 1005 | sizeof(__u16); | ||
| 960 | 1006 | ||
| 961 | *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, | 1007 | *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, |
| 962 | nums, str_p, GFP_ATOMIC); | 1008 | nums, str_p, GFP_ATOMIC); |
| @@ -975,6 +1021,7 @@ struct sctp_chunk *sctp_process_strreset_resp( | |||
| 975 | if (result == SCTP_STRRESET_PERFORMED) { | 1021 | if (result == SCTP_STRRESET_PERFORMED) { |
| 976 | __u32 mtsn = sctp_tsnmap_get_max_tsn_seen( | 1022 | __u32 mtsn = sctp_tsnmap_get_max_tsn_seen( |
| 977 | &asoc->peer.tsn_map); | 1023 | &asoc->peer.tsn_map); |
| 1024 | LIST_HEAD(temp); | ||
| 978 | 1025 | ||
| 979 | sctp_ulpq_reasm_flushtsn(&asoc->ulpq, mtsn); | 1026 | sctp_ulpq_reasm_flushtsn(&asoc->ulpq, mtsn); |
| 980 | sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); | 1027 | sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); |
| @@ -983,7 +1030,13 @@ struct sctp_chunk *sctp_process_strreset_resp( | |||
| 983 | SCTP_TSN_MAP_INITIAL, | 1030 | SCTP_TSN_MAP_INITIAL, |
| 984 | stsn, GFP_ATOMIC); | 1031 | stsn, GFP_ATOMIC); |
| 985 | 1032 | ||
| 1033 | /* Clean up sacked and abandoned queues only. As the | ||
| 1034 | * out_chunk_list may not be empty, splice it to temp, | ||
| 1035 | * then get it back after sctp_outq_free is done. | ||
| 1036 | */ | ||
| 1037 | list_splice_init(&asoc->outqueue.out_chunk_list, &temp); | ||
| 986 | sctp_outq_free(&asoc->outqueue); | 1038 | sctp_outq_free(&asoc->outqueue); |
| 1039 | list_splice_init(&temp, &asoc->outqueue.out_chunk_list); | ||
| 987 | 1040 | ||
| 988 | asoc->next_tsn = rtsn; | 1041 | asoc->next_tsn = rtsn; |
| 989 | asoc->ctsn_ack_point = asoc->next_tsn - 1; | 1042 | asoc->ctsn_ack_point = asoc->next_tsn - 1; |
diff --git a/net/sctp/stream_sched.c b/net/sctp/stream_sched.c index 0b83ec51e43b..d8c162a4089c 100644 --- a/net/sctp/stream_sched.c +++ b/net/sctp/stream_sched.c | |||
| @@ -119,16 +119,27 @@ static struct sctp_sched_ops sctp_sched_fcfs = { | |||
| 119 | .unsched_all = sctp_sched_fcfs_unsched_all, | 119 | .unsched_all = sctp_sched_fcfs_unsched_all, |
| 120 | }; | 120 | }; |
| 121 | 121 | ||
| 122 | static void sctp_sched_ops_fcfs_init(void) | ||
| 123 | { | ||
| 124 | sctp_sched_ops_register(SCTP_SS_FCFS, &sctp_sched_fcfs); | ||
| 125 | } | ||
| 126 | |||
| 122 | /* API to other parts of the stack */ | 127 | /* API to other parts of the stack */ |
| 123 | 128 | ||
| 124 | extern struct sctp_sched_ops sctp_sched_prio; | 129 | static struct sctp_sched_ops *sctp_sched_ops[SCTP_SS_MAX + 1]; |
| 125 | extern struct sctp_sched_ops sctp_sched_rr; | ||
| 126 | 130 | ||
| 127 | static struct sctp_sched_ops *sctp_sched_ops[] = { | 131 | void sctp_sched_ops_register(enum sctp_sched_type sched, |
| 128 | &sctp_sched_fcfs, | 132 | struct sctp_sched_ops *sched_ops) |
| 129 | &sctp_sched_prio, | 133 | { |
| 130 | &sctp_sched_rr, | 134 | sctp_sched_ops[sched] = sched_ops; |
| 131 | }; | 135 | } |
| 136 | |||
| 137 | void sctp_sched_ops_init(void) | ||
| 138 | { | ||
| 139 | sctp_sched_ops_fcfs_init(); | ||
| 140 | sctp_sched_ops_prio_init(); | ||
| 141 | sctp_sched_ops_rr_init(); | ||
| 142 | } | ||
| 132 | 143 | ||
| 133 | int sctp_sched_set_sched(struct sctp_association *asoc, | 144 | int sctp_sched_set_sched(struct sctp_association *asoc, |
| 134 | enum sctp_sched_type sched) | 145 | enum sctp_sched_type sched) |
diff --git a/net/sctp/stream_sched_prio.c b/net/sctp/stream_sched_prio.c index 384dbf3c8760..7997d35dd0fd 100644 --- a/net/sctp/stream_sched_prio.c +++ b/net/sctp/stream_sched_prio.c | |||
| @@ -333,7 +333,7 @@ static void sctp_sched_prio_unsched_all(struct sctp_stream *stream) | |||
| 333 | sctp_sched_prio_unsched(soute); | 333 | sctp_sched_prio_unsched(soute); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | struct sctp_sched_ops sctp_sched_prio = { | 336 | static struct sctp_sched_ops sctp_sched_prio = { |
| 337 | .set = sctp_sched_prio_set, | 337 | .set = sctp_sched_prio_set, |
| 338 | .get = sctp_sched_prio_get, | 338 | .get = sctp_sched_prio_get, |
| 339 | .init = sctp_sched_prio_init, | 339 | .init = sctp_sched_prio_init, |
| @@ -345,3 +345,8 @@ struct sctp_sched_ops sctp_sched_prio = { | |||
| 345 | .sched_all = sctp_sched_prio_sched_all, | 345 | .sched_all = sctp_sched_prio_sched_all, |
| 346 | .unsched_all = sctp_sched_prio_unsched_all, | 346 | .unsched_all = sctp_sched_prio_unsched_all, |
| 347 | }; | 347 | }; |
| 348 | |||
| 349 | void sctp_sched_ops_prio_init(void) | ||
| 350 | { | ||
| 351 | sctp_sched_ops_register(SCTP_SS_PRIO, &sctp_sched_prio); | ||
| 352 | } | ||
diff --git a/net/sctp/stream_sched_rr.c b/net/sctp/stream_sched_rr.c index 7612a438c5b9..1155692448f1 100644 --- a/net/sctp/stream_sched_rr.c +++ b/net/sctp/stream_sched_rr.c | |||
| @@ -187,7 +187,7 @@ static void sctp_sched_rr_unsched_all(struct sctp_stream *stream) | |||
| 187 | sctp_sched_rr_unsched(stream, soute); | 187 | sctp_sched_rr_unsched(stream, soute); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | struct sctp_sched_ops sctp_sched_rr = { | 190 | static struct sctp_sched_ops sctp_sched_rr = { |
| 191 | .set = sctp_sched_rr_set, | 191 | .set = sctp_sched_rr_set, |
| 192 | .get = sctp_sched_rr_get, | 192 | .get = sctp_sched_rr_get, |
| 193 | .init = sctp_sched_rr_init, | 193 | .init = sctp_sched_rr_init, |
| @@ -199,3 +199,8 @@ struct sctp_sched_ops sctp_sched_rr = { | |||
| 199 | .sched_all = sctp_sched_rr_sched_all, | 199 | .sched_all = sctp_sched_rr_sched_all, |
| 200 | .unsched_all = sctp_sched_rr_unsched_all, | 200 | .unsched_all = sctp_sched_rr_unsched_all, |
| 201 | }; | 201 | }; |
| 202 | |||
| 203 | void sctp_sched_ops_rr_init(void) | ||
| 204 | { | ||
| 205 | sctp_sched_ops_register(SCTP_SS_RR, &sctp_sched_rr); | ||
| 206 | } | ||
