@@ -106,6 +106,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
106106{
107107 struct sk_buff_head temp ;
108108 struct sctp_ulpevent * event ;
109+ int event_eor = 0 ;
109110
110111 /* Create an event from the incoming chunk. */
111112 event = sctp_ulpevent_make_rcvmsg (chunk -> asoc , chunk , gfp );
@@ -127,10 +128,12 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
127128 /* Send event to the ULP. 'event' is the sctp_ulpevent for
128129 * very first SKB on the 'temp' list.
129130 */
130- if (event )
131+ if (event ) {
132+ event_eor = (event -> msg_flags & MSG_EOR ) ? 1 : 0 ;
131133 sctp_ulpq_tail_event (ulpq , event );
134+ }
132135
133- return 0 ;
136+ return event_eor ;
134137}
135138
136139/* Add a new event for propagation to the ULP. */
@@ -540,14 +543,19 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
540543 ctsn = cevent -> tsn ;
541544
542545 switch (cevent -> msg_flags & SCTP_DATA_FRAG_MASK ) {
546+ case SCTP_DATA_FIRST_FRAG :
547+ if (!first_frag )
548+ return NULL ;
549+ goto done ;
543550 case SCTP_DATA_MIDDLE_FRAG :
544551 if (!first_frag ) {
545552 first_frag = pos ;
546553 next_tsn = ctsn + 1 ;
547554 last_frag = pos ;
548- } else if (next_tsn == ctsn )
555+ } else if (next_tsn == ctsn ) {
549556 next_tsn ++ ;
550- else
557+ last_frag = pos ;
558+ } else
551559 goto done ;
552560 break ;
553561 case SCTP_DATA_LAST_FRAG :
@@ -651,6 +659,14 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
651659 } else
652660 goto done ;
653661 break ;
662+
663+ case SCTP_DATA_LAST_FRAG :
664+ if (!first_frag )
665+ return NULL ;
666+ else
667+ goto done ;
668+ break ;
669+
654670 default :
655671 return NULL ;
656672 }
@@ -962,20 +978,43 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,
962978 struct sk_buff_head * list , __u16 needed )
963979{
964980 __u16 freed = 0 ;
965- __u32 tsn ;
966- struct sk_buff * skb ;
981+ __u32 tsn , last_tsn ;
982+ struct sk_buff * skb , * flist , * last ;
967983 struct sctp_ulpevent * event ;
968984 struct sctp_tsnmap * tsnmap ;
969985
970986 tsnmap = & ulpq -> asoc -> peer .tsn_map ;
971987
972- while ((skb = __skb_dequeue_tail (list )) != NULL ) {
973- freed += skb_headlen (skb );
988+ while ((skb = skb_peek_tail (list )) != NULL ) {
974989 event = sctp_skb2event (skb );
975990 tsn = event -> tsn ;
976991
992+ /* Don't renege below the Cumulative TSN ACK Point. */
993+ if (TSN_lte (tsn , sctp_tsnmap_get_ctsn (tsnmap )))
994+ break ;
995+
996+ /* Events in ordering queue may have multiple fragments
997+ * corresponding to additional TSNs. Sum the total
998+ * freed space; find the last TSN.
999+ */
1000+ freed += skb_headlen (skb );
1001+ flist = skb_shinfo (skb )-> frag_list ;
1002+ for (last = flist ; flist ; flist = flist -> next ) {
1003+ last = flist ;
1004+ freed += skb_headlen (last );
1005+ }
1006+ if (last )
1007+ last_tsn = sctp_skb2event (last )-> tsn ;
1008+ else
1009+ last_tsn = tsn ;
1010+
1011+ /* Unlink the event, then renege all applicable TSNs. */
1012+ __skb_unlink (skb , list );
9771013 sctp_ulpevent_free (event );
978- sctp_tsnmap_renege (tsnmap , tsn );
1014+ while (TSN_lte (tsn , last_tsn )) {
1015+ sctp_tsnmap_renege (tsnmap , tsn );
1016+ tsn ++ ;
1017+ }
9791018 if (freed >= needed )
9801019 return freed ;
9811020 }
@@ -1002,16 +1041,28 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
10021041 struct sctp_ulpevent * event ;
10031042 struct sctp_association * asoc ;
10041043 struct sctp_sock * sp ;
1044+ __u32 ctsn ;
1045+ struct sk_buff * skb ;
10051046
10061047 asoc = ulpq -> asoc ;
10071048 sp = sctp_sk (asoc -> base .sk );
10081049
10091050 /* If the association is already in Partial Delivery mode
1010- * we have noting to do.
1051+ * we have nothing to do.
10111052 */
10121053 if (ulpq -> pd_mode )
10131054 return ;
10141055
1056+ /* Data must be at or below the Cumulative TSN ACK Point to
1057+ * start partial delivery.
1058+ */
1059+ skb = skb_peek (& asoc -> ulpq .reasm );
1060+ if (skb != NULL ) {
1061+ ctsn = sctp_skb2event (skb )-> tsn ;
1062+ if (!TSN_lte (ctsn , sctp_tsnmap_get_ctsn (& asoc -> peer .tsn_map )))
1063+ return ;
1064+ }
1065+
10151066 /* If the user enabled fragment interleave socket option,
10161067 * multiple associations can enter partial delivery.
10171068 * Otherwise, we can only enter partial delivery if the
@@ -1054,12 +1105,16 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
10541105 }
10551106 /* If able to free enough room, accept this chunk. */
10561107 if (chunk && (freed >= needed )) {
1057- __u32 tsn ;
1058- tsn = ntohl (chunk -> subh .data_hdr -> tsn );
1059- sctp_tsnmap_mark (& asoc -> peer .tsn_map , tsn , chunk -> transport );
1060- sctp_ulpq_tail_data (ulpq , chunk , gfp );
1061-
1062- sctp_ulpq_partial_delivery (ulpq , gfp );
1108+ int retval ;
1109+ retval = sctp_ulpq_tail_data (ulpq , chunk , gfp );
1110+ /*
1111+ * Enter partial delivery if chunk has not been
1112+ * delivered; otherwise, drain the reassembly queue.
1113+ */
1114+ if (retval <= 0 )
1115+ sctp_ulpq_partial_delivery (ulpq , gfp );
1116+ else if (retval == 1 )
1117+ sctp_ulpq_reasm_drain (ulpq );
10631118 }
10641119
10651120 sk_mem_reclaim (asoc -> base .sk );
0 commit comments