diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-01 18:02:27 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-01 18:02:27 -0400 |
| commit | ceeec3dc375e3b0618f16b34efc56fe093918f8b (patch) | |
| tree | 2293d02721ee05131aaf1c60e4fba7e281585eec /net/sctp/ulpqueue.c | |
| parent | fbff868db3a4cc6a89d51da9a6d49b26c29d04fb (diff) | |
| parent | e3ee3b78f83688a0ae4315e8be71b2eac559904a (diff) | |
/spare/repo/netdev-2.6 branch 'ieee80211'
Diffstat (limited to 'net/sctp/ulpqueue.c')
| -rw-r--r-- | net/sctp/ulpqueue.c | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 8bbc279d6c99..ec2c857eae7f 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
| @@ -50,9 +50,9 @@ | |||
| 50 | 50 | ||
| 51 | /* Forward declarations for internal helpers. */ | 51 | /* Forward declarations for internal helpers. */ |
| 52 | static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq, | 52 | static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq, |
| 53 | struct sctp_ulpevent *); | 53 | struct sctp_ulpevent *); |
| 54 | static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *, | 54 | static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *, |
| 55 | struct sctp_ulpevent *); | 55 | struct sctp_ulpevent *); |
| 56 | 56 | ||
| 57 | /* 1st Level Abstractions */ | 57 | /* 1st Level Abstractions */ |
| 58 | 58 | ||
| @@ -125,7 +125,9 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
| 125 | event = sctp_ulpq_order(ulpq, event); | 125 | event = sctp_ulpq_order(ulpq, event); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | /* Send event to the ULP. */ | 128 | /* Send event to the ULP. 'event' is the sctp_ulpevent for |
| 129 | * very first SKB on the 'temp' list. | ||
| 130 | */ | ||
| 129 | if (event) | 131 | if (event) |
| 130 | sctp_ulpq_tail_event(ulpq, event); | 132 | sctp_ulpq_tail_event(ulpq, event); |
| 131 | 133 | ||
| @@ -158,14 +160,18 @@ static int sctp_ulpq_clear_pd(struct sctp_ulpq *ulpq) | |||
| 158 | return sctp_clear_pd(ulpq->asoc->base.sk); | 160 | return sctp_clear_pd(ulpq->asoc->base.sk); |
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | 163 | /* If the SKB of 'event' is on a list, it is the first such member | |
| 162 | 164 | * of that list. | |
| 165 | */ | ||
| 163 | int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | 166 | int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) |
| 164 | { | 167 | { |
| 165 | struct sock *sk = ulpq->asoc->base.sk; | 168 | struct sock *sk = ulpq->asoc->base.sk; |
| 166 | struct sk_buff_head *queue; | 169 | struct sk_buff_head *queue, *skb_list; |
| 170 | struct sk_buff *skb = sctp_event2skb(event); | ||
| 167 | int clear_pd = 0; | 171 | int clear_pd = 0; |
| 168 | 172 | ||
| 173 | skb_list = (struct sk_buff_head *) skb->prev; | ||
| 174 | |||
| 169 | /* If the socket is just going to throw this away, do not | 175 | /* If the socket is just going to throw this away, do not |
| 170 | * even try to deliver it. | 176 | * even try to deliver it. |
| 171 | */ | 177 | */ |
| @@ -197,10 +203,10 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
| 197 | /* If we are harvesting multiple skbs they will be | 203 | /* If we are harvesting multiple skbs they will be |
| 198 | * collected on a list. | 204 | * collected on a list. |
| 199 | */ | 205 | */ |
| 200 | if (sctp_event2skb(event)->list) | 206 | if (skb_list) |
| 201 | sctp_skb_list_tail(sctp_event2skb(event)->list, queue); | 207 | sctp_skb_list_tail(skb_list, queue); |
| 202 | else | 208 | else |
| 203 | __skb_queue_tail(queue, sctp_event2skb(event)); | 209 | __skb_queue_tail(queue, skb); |
| 204 | 210 | ||
| 205 | /* Did we just complete partial delivery and need to get | 211 | /* Did we just complete partial delivery and need to get |
| 206 | * rolling again? Move pending data to the receive | 212 | * rolling again? Move pending data to the receive |
| @@ -214,10 +220,11 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
| 214 | return 1; | 220 | return 1; |
| 215 | 221 | ||
| 216 | out_free: | 222 | out_free: |
| 217 | if (sctp_event2skb(event)->list) | 223 | if (skb_list) |
| 218 | sctp_queue_purge_ulpevents(sctp_event2skb(event)->list); | 224 | sctp_queue_purge_ulpevents(skb_list); |
| 219 | else | 225 | else |
| 220 | sctp_ulpevent_free(event); | 226 | sctp_ulpevent_free(event); |
| 227 | |||
| 221 | return 0; | 228 | return 0; |
| 222 | } | 229 | } |
| 223 | 230 | ||
| @@ -269,7 +276,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, | |||
| 269 | * payload was fragmented on the way and ip had to reassemble them. | 276 | * payload was fragmented on the way and ip had to reassemble them. |
| 270 | * We add the rest of skb's to the first skb's fraglist. | 277 | * We add the rest of skb's to the first skb's fraglist. |
| 271 | */ | 278 | */ |
| 272 | static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag) | 279 | static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag) |
| 273 | { | 280 | { |
| 274 | struct sk_buff *pos; | 281 | struct sk_buff *pos; |
| 275 | struct sctp_ulpevent *event; | 282 | struct sctp_ulpevent *event; |
| @@ -294,7 +301,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, | |||
| 294 | skb_shinfo(f_frag)->frag_list = pos; | 301 | skb_shinfo(f_frag)->frag_list = pos; |
| 295 | 302 | ||
| 296 | /* Remove the first fragment from the reassembly queue. */ | 303 | /* Remove the first fragment from the reassembly queue. */ |
| 297 | __skb_unlink(f_frag, f_frag->list); | 304 | __skb_unlink(f_frag, queue); |
| 298 | while (pos) { | 305 | while (pos) { |
| 299 | 306 | ||
| 300 | pnext = pos->next; | 307 | pnext = pos->next; |
| @@ -304,7 +311,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff *f_frag, | |||
| 304 | f_frag->data_len += pos->len; | 311 | f_frag->data_len += pos->len; |
| 305 | 312 | ||
| 306 | /* Remove the fragment from the reassembly queue. */ | 313 | /* Remove the fragment from the reassembly queue. */ |
| 307 | __skb_unlink(pos, pos->list); | 314 | __skb_unlink(pos, queue); |
| 308 | 315 | ||
| 309 | /* Break if we have reached the last fragment. */ | 316 | /* Break if we have reached the last fragment. */ |
| 310 | if (pos == l_frag) | 317 | if (pos == l_frag) |
| @@ -375,7 +382,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_u | |||
| 375 | done: | 382 | done: |
| 376 | return retval; | 383 | return retval; |
| 377 | found: | 384 | found: |
| 378 | retval = sctp_make_reassembled_event(first_frag, pos); | 385 | retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos); |
| 379 | if (retval) | 386 | if (retval) |
| 380 | retval->msg_flags |= MSG_EOR; | 387 | retval->msg_flags |= MSG_EOR; |
| 381 | goto done; | 388 | goto done; |
| @@ -435,7 +442,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq | |||
| 435 | * further. | 442 | * further. |
| 436 | */ | 443 | */ |
| 437 | done: | 444 | done: |
| 438 | retval = sctp_make_reassembled_event(first_frag, last_frag); | 445 | retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag); |
| 439 | if (retval && is_last) | 446 | if (retval && is_last) |
| 440 | retval->msg_flags |= MSG_EOR; | 447 | retval->msg_flags |= MSG_EOR; |
| 441 | 448 | ||
| @@ -527,7 +534,7 @@ static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *u | |||
| 527 | * further. | 534 | * further. |
| 528 | */ | 535 | */ |
| 529 | done: | 536 | done: |
| 530 | retval = sctp_make_reassembled_event(first_frag, last_frag); | 537 | retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag); |
| 531 | return retval; | 538 | return retval; |
| 532 | } | 539 | } |
| 533 | 540 | ||
| @@ -537,6 +544,7 @@ done: | |||
| 537 | static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, | 544 | static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, |
| 538 | struct sctp_ulpevent *event) | 545 | struct sctp_ulpevent *event) |
| 539 | { | 546 | { |
| 547 | struct sk_buff_head *event_list; | ||
| 540 | struct sk_buff *pos, *tmp; | 548 | struct sk_buff *pos, *tmp; |
| 541 | struct sctp_ulpevent *cevent; | 549 | struct sctp_ulpevent *cevent; |
| 542 | struct sctp_stream *in; | 550 | struct sctp_stream *in; |
| @@ -547,6 +555,8 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, | |||
| 547 | ssn = event->ssn; | 555 | ssn = event->ssn; |
| 548 | in = &ulpq->asoc->ssnmap->in; | 556 | in = &ulpq->asoc->ssnmap->in; |
| 549 | 557 | ||
| 558 | event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev; | ||
| 559 | |||
| 550 | /* We are holding the chunks by stream, by SSN. */ | 560 | /* We are holding the chunks by stream, by SSN. */ |
| 551 | sctp_skb_for_each(pos, &ulpq->lobby, tmp) { | 561 | sctp_skb_for_each(pos, &ulpq->lobby, tmp) { |
| 552 | cevent = (struct sctp_ulpevent *) pos->cb; | 562 | cevent = (struct sctp_ulpevent *) pos->cb; |
| @@ -567,10 +577,10 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, | |||
| 567 | /* Found it, so mark in the ssnmap. */ | 577 | /* Found it, so mark in the ssnmap. */ |
| 568 | sctp_ssn_next(in, sid); | 578 | sctp_ssn_next(in, sid); |
| 569 | 579 | ||
| 570 | __skb_unlink(pos, pos->list); | 580 | __skb_unlink(pos, &ulpq->lobby); |
| 571 | 581 | ||
| 572 | /* Attach all gathered skbs to the event. */ | 582 | /* Attach all gathered skbs to the event. */ |
| 573 | __skb_queue_tail(sctp_event2skb(event)->list, pos); | 583 | __skb_queue_tail(event_list, pos); |
| 574 | } | 584 | } |
| 575 | } | 585 | } |
| 576 | 586 | ||
| @@ -626,7 +636,7 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq, | |||
| 626 | } | 636 | } |
| 627 | 637 | ||
| 628 | static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, | 638 | static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, |
| 629 | struct sctp_ulpevent *event) | 639 | struct sctp_ulpevent *event) |
| 630 | { | 640 | { |
| 631 | __u16 sid, ssn; | 641 | __u16 sid, ssn; |
| 632 | struct sctp_stream *in; | 642 | struct sctp_stream *in; |
| @@ -667,7 +677,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq) | |||
| 667 | { | 677 | { |
| 668 | struct sk_buff *pos, *tmp; | 678 | struct sk_buff *pos, *tmp; |
| 669 | struct sctp_ulpevent *cevent; | 679 | struct sctp_ulpevent *cevent; |
| 670 | struct sctp_ulpevent *event = NULL; | 680 | struct sctp_ulpevent *event; |
| 671 | struct sctp_stream *in; | 681 | struct sctp_stream *in; |
| 672 | struct sk_buff_head temp; | 682 | struct sk_buff_head temp; |
| 673 | __u16 csid, cssn; | 683 | __u16 csid, cssn; |
| @@ -675,6 +685,8 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq) | |||
| 675 | in = &ulpq->asoc->ssnmap->in; | 685 | in = &ulpq->asoc->ssnmap->in; |
| 676 | 686 | ||
| 677 | /* We are holding the chunks by stream, by SSN. */ | 687 | /* We are holding the chunks by stream, by SSN. */ |
| 688 | skb_queue_head_init(&temp); | ||
| 689 | event = NULL; | ||
| 678 | sctp_skb_for_each(pos, &ulpq->lobby, tmp) { | 690 | sctp_skb_for_each(pos, &ulpq->lobby, tmp) { |
| 679 | cevent = (struct sctp_ulpevent *) pos->cb; | 691 | cevent = (struct sctp_ulpevent *) pos->cb; |
| 680 | csid = cevent->stream; | 692 | csid = cevent->stream; |
| @@ -686,19 +698,20 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq) | |||
| 686 | /* Found it, so mark in the ssnmap. */ | 698 | /* Found it, so mark in the ssnmap. */ |
| 687 | sctp_ssn_next(in, csid); | 699 | sctp_ssn_next(in, csid); |
| 688 | 700 | ||
| 689 | __skb_unlink(pos, pos->list); | 701 | __skb_unlink(pos, &ulpq->lobby); |
| 690 | if (!event) { | 702 | if (!event) { |
| 691 | /* Create a temporary list to collect chunks on. */ | 703 | /* Create a temporary list to collect chunks on. */ |
| 692 | event = sctp_skb2event(pos); | 704 | event = sctp_skb2event(pos); |
| 693 | skb_queue_head_init(&temp); | ||
| 694 | __skb_queue_tail(&temp, sctp_event2skb(event)); | 705 | __skb_queue_tail(&temp, sctp_event2skb(event)); |
| 695 | } else { | 706 | } else { |
| 696 | /* Attach all gathered skbs to the event. */ | 707 | /* Attach all gathered skbs to the event. */ |
| 697 | __skb_queue_tail(sctp_event2skb(event)->list, pos); | 708 | __skb_queue_tail(&temp, pos); |
| 698 | } | 709 | } |
| 699 | } | 710 | } |
| 700 | 711 | ||
| 701 | /* Send event to the ULP. */ | 712 | /* Send event to the ULP. 'event' is the sctp_ulpevent for |
| 713 | * very first SKB on the 'temp' list. | ||
| 714 | */ | ||
| 702 | if (event) | 715 | if (event) |
| 703 | sctp_ulpq_tail_event(ulpq, event); | 716 | sctp_ulpq_tail_event(ulpq, event); |
| 704 | } | 717 | } |
