mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
sctp: fix association hangs due to errors when reneging events from the ordering queue
In sctp_ulpq_renege_list(), events being reneged from the ordering queue may correspond to multiple TSNs. Identify all affected packets; sum freed space and renege from the tsnmap. Signed-off-by: Lee A. Roberts <lee.roberts@hp.com> Acked-by: Vlad Yasevich <vyasevich@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com>
This commit is contained in:
parent
e67f85ecd8
commit
95ac7b859f
@ -962,8 +962,8 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,
|
||||
struct sk_buff_head *list, __u16 needed)
|
||||
{
|
||||
__u16 freed = 0;
|
||||
__u32 tsn;
|
||||
struct sk_buff *skb;
|
||||
__u32 tsn, last_tsn;
|
||||
struct sk_buff *skb, *flist, *last;
|
||||
struct sctp_ulpevent *event;
|
||||
struct sctp_tsnmap *tsnmap;
|
||||
|
||||
@ -977,10 +977,28 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,
|
||||
if (TSN_lte(tsn, sctp_tsnmap_get_ctsn(tsnmap)))
|
||||
break;
|
||||
|
||||
__skb_unlink(skb, list);
|
||||
/* Events in ordering queue may have multiple fragments
|
||||
* corresponding to additional TSNs. Sum the total
|
||||
* freed space; find the last TSN.
|
||||
*/
|
||||
freed += skb_headlen(skb);
|
||||
flist = skb_shinfo(skb)->frag_list;
|
||||
for (last = flist; flist; flist = flist->next) {
|
||||
last = flist;
|
||||
freed += skb_headlen(last);
|
||||
}
|
||||
if (last)
|
||||
last_tsn = sctp_skb2event(last)->tsn;
|
||||
else
|
||||
last_tsn = tsn;
|
||||
|
||||
/* Unlink the event, then renege all applicable TSNs. */
|
||||
__skb_unlink(skb, list);
|
||||
sctp_ulpevent_free(event);
|
||||
sctp_tsnmap_renege(tsnmap, tsn);
|
||||
while (TSN_lte(tsn, last_tsn)) {
|
||||
sctp_tsnmap_renege(tsnmap, tsn);
|
||||
tsn++;
|
||||
}
|
||||
if (freed >= needed)
|
||||
return freed;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user