diff options
Diffstat (limited to 'net/sctp')
-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: |