diff options
Diffstat (limited to 'net/sctp/ulpevent.c')
| -rw-r--r-- | net/sctp/ulpevent.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index ba97f974f57c..ee236784a6bb 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
| @@ -51,6 +51,8 @@ | |||
| 51 | static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | 51 | static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, |
| 52 | struct sctp_association *asoc); | 52 | struct sctp_association *asoc); |
| 53 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); | 53 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); |
| 54 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event); | ||
| 55 | |||
| 54 | 56 | ||
| 55 | /* Initialize an ULP event from an given skb. */ | 57 | /* Initialize an ULP event from an given skb. */ |
| 56 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) | 58 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) |
| @@ -883,6 +885,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | |||
| 883 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | 885 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) |
| 884 | { | 886 | { |
| 885 | struct sk_buff *skb, *frag; | 887 | struct sk_buff *skb, *frag; |
| 888 | unsigned int len; | ||
| 886 | 889 | ||
| 887 | /* Current stack structures assume that the rcv buffer is | 890 | /* Current stack structures assume that the rcv buffer is |
| 888 | * per socket. For UDP style sockets this is not true as | 891 | * per socket. For UDP style sockets this is not true as |
| @@ -892,7 +895,30 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
| 892 | */ | 895 | */ |
| 893 | 896 | ||
| 894 | skb = sctp_event2skb(event); | 897 | skb = sctp_event2skb(event); |
| 895 | sctp_assoc_rwnd_increase(event->asoc, skb_headlen(skb)); | 898 | len = skb->len; |
| 899 | |||
| 900 | if (!skb->data_len) | ||
| 901 | goto done; | ||
| 902 | |||
| 903 | /* Don't forget the fragments. */ | ||
| 904 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | ||
| 905 | /* NOTE: skb_shinfos are recursive. Although IP returns | ||
| 906 | * skb's with only 1 level of fragments, SCTP reassembly can | ||
| 907 | * increase the levels. | ||
| 908 | */ | ||
| 909 | sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); | ||
| 910 | } | ||
| 911 | |||
| 912 | done: | ||
| 913 | sctp_assoc_rwnd_increase(event->asoc, len); | ||
| 914 | sctp_ulpevent_release_owner(event); | ||
| 915 | } | ||
| 916 | |||
| 917 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) | ||
| 918 | { | ||
| 919 | struct sk_buff *skb, *frag; | ||
| 920 | |||
| 921 | skb = sctp_event2skb(event); | ||
| 896 | 922 | ||
| 897 | if (!skb->data_len) | 923 | if (!skb->data_len) |
| 898 | goto done; | 924 | goto done; |
| @@ -903,7 +929,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
| 903 | * skb's with only 1 level of fragments, SCTP reassembly can | 929 | * skb's with only 1 level of fragments, SCTP reassembly can |
| 904 | * increase the levels. | 930 | * increase the levels. |
| 905 | */ | 931 | */ |
| 906 | sctp_ulpevent_release_data(sctp_skb2event(frag)); | 932 | sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); |
| 907 | } | 933 | } |
| 908 | 934 | ||
| 909 | done: | 935 | done: |
