@@ -126,8 +126,8 @@ static u8 ip4_frag_ecn(u8 tos)
126126
127127static struct inet_frags ip4_frags ;
128128
129- static int ip_frag_reasm (struct ipq * qp , struct sk_buff * prev ,
130- struct net_device * dev );
129+ static int ip_frag_reasm (struct ipq * qp , struct sk_buff * skb ,
130+ struct sk_buff * prev_tail , struct net_device * dev );
131131
132132
133133static void ip4_frag_init (struct inet_frag_queue * q , const void * a )
@@ -219,7 +219,12 @@ static void ip_expire(struct timer_list *t)
219219 head = skb_rb_first (& qp -> q .rb_fragments );
220220 if (!head )
221221 goto out ;
222- rb_erase (& head -> rbnode , & qp -> q .rb_fragments );
222+ if (FRAG_CB (head )-> next_frag )
223+ rb_replace_node (& head -> rbnode ,
224+ & FRAG_CB (head )-> next_frag -> rbnode ,
225+ & qp -> q .rb_fragments );
226+ else
227+ rb_erase (& head -> rbnode , & qp -> q .rb_fragments );
223228 memset (& head -> rbnode , 0 , sizeof (head -> rbnode ));
224229 barrier ();
225230 }
@@ -320,7 +325,7 @@ static int ip_frag_reinit(struct ipq *qp)
320325 return - ETIMEDOUT ;
321326 }
322327
323- sum_truesize = skb_rbtree_purge (& qp -> q .rb_fragments );
328+ sum_truesize = inet_frag_rbtree_purge (& qp -> q .rb_fragments );
324329 sub_frag_mem_limit (qp -> q .net , sum_truesize );
325330
326331 qp -> q .flags = 0 ;
@@ -329,6 +334,7 @@ static int ip_frag_reinit(struct ipq *qp)
329334 qp -> q .fragments = NULL ;
330335 qp -> q .rb_fragments = RB_ROOT ;
331336 qp -> q .fragments_tail = NULL ;
337+ qp -> q .last_run_head = NULL ;
332338 qp -> iif = 0 ;
333339 qp -> ecn = 0 ;
334340
@@ -340,7 +346,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
340346{
341347 struct net * net = container_of (qp -> q .net , struct net , ipv4 .frags );
342348 struct rb_node * * rbn , * parent ;
343- struct sk_buff * skb1 ;
349+ struct sk_buff * skb1 , * prev_tail ;
344350 struct net_device * dev ;
345351 unsigned int fragsize ;
346352 int flags , offset ;
@@ -418,38 +424,41 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
418424 */
419425
420426 /* Find out where to put this fragment. */
421- skb1 = qp -> q .fragments_tail ;
422- if (!skb1 ) {
423- /* This is the first fragment we've received. */
424- rb_link_node (& skb -> rbnode , NULL , & qp -> q .rb_fragments .rb_node );
425- qp -> q .fragments_tail = skb ;
426- } else if ((skb1 -> ip_defrag_offset + skb1 -> len ) < end ) {
427- /* This is the common/special case: skb goes to the end. */
427+ prev_tail = qp -> q .fragments_tail ;
428+ if (!prev_tail )
429+ ip4_frag_create_run (& qp -> q , skb ); /* First fragment. */
430+ else if (prev_tail -> ip_defrag_offset + prev_tail -> len < end ) {
431+ /* This is the common case: skb goes to the end. */
428432 /* Detect and discard overlaps. */
429- if (offset < ( skb1 -> ip_defrag_offset + skb1 -> len ) )
433+ if (offset < prev_tail -> ip_defrag_offset + prev_tail -> len )
430434 goto discard_qp ;
431- /* Insert after skb1. */
432- rb_link_node (& skb -> rbnode , & skb1 -> rbnode , & skb1 -> rbnode .rb_right );
433- qp -> q .fragments_tail = skb ;
435+ if (offset == prev_tail -> ip_defrag_offset + prev_tail -> len )
436+ ip4_frag_append_to_last_run (& qp -> q , skb );
437+ else
438+ ip4_frag_create_run (& qp -> q , skb );
434439 } else {
435- /* Binary search. Note that skb can become the first fragment, but
436- * not the last (covered above). */
440+ /* Binary search. Note that skb can become the first fragment,
441+ * but not the last (covered above).
442+ */
437443 rbn = & qp -> q .rb_fragments .rb_node ;
438444 do {
439445 parent = * rbn ;
440446 skb1 = rb_to_skb (parent );
441447 if (end <= skb1 -> ip_defrag_offset )
442448 rbn = & parent -> rb_left ;
443- else if (offset >= skb1 -> ip_defrag_offset + skb1 -> len )
449+ else if (offset >= skb1 -> ip_defrag_offset +
450+ FRAG_CB (skb1 )-> frag_run_len )
444451 rbn = & parent -> rb_right ;
445452 else /* Found an overlap with skb1. */
446453 goto discard_qp ;
447454 } while (* rbn );
448455 /* Here we have parent properly set, and rbn pointing to
449- * one of its NULL left/right children. Insert skb. */
456+ * one of its NULL left/right children. Insert skb.
457+ */
458+ ip4_frag_init_run (skb );
450459 rb_link_node (& skb -> rbnode , parent , rbn );
460+ rb_insert_color (& skb -> rbnode , & qp -> q .rb_fragments );
451461 }
452- rb_insert_color (& skb -> rbnode , & qp -> q .rb_fragments );
453462
454463 if (dev )
455464 qp -> iif = dev -> ifindex ;
@@ -476,7 +485,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
476485 unsigned long orefdst = skb -> _skb_refdst ;
477486
478487 skb -> _skb_refdst = 0UL ;
479- err = ip_frag_reasm (qp , skb , dev );
488+ err = ip_frag_reasm (qp , skb , prev_tail , dev );
480489 skb -> _skb_refdst = orefdst ;
481490 return err ;
482491 }
@@ -495,7 +504,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
495504
496505/* Build a new IP datagram from all its fragments. */
497506static int ip_frag_reasm (struct ipq * qp , struct sk_buff * skb ,
498- struct net_device * dev )
507+ struct sk_buff * prev_tail , struct net_device * dev )
499508{
500509 struct net * net = container_of (qp -> q .net , struct net , ipv4 .frags );
501510 struct iphdr * iph ;
@@ -519,10 +528,16 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
519528 fp = skb_clone (skb , GFP_ATOMIC );
520529 if (!fp )
521530 goto out_nomem ;
522- rb_replace_node (& skb -> rbnode , & fp -> rbnode , & qp -> q .rb_fragments );
531+ FRAG_CB (fp )-> next_frag = FRAG_CB (skb )-> next_frag ;
532+ if (RB_EMPTY_NODE (& skb -> rbnode ))
533+ FRAG_CB (prev_tail )-> next_frag = fp ;
534+ else
535+ rb_replace_node (& skb -> rbnode , & fp -> rbnode ,
536+ & qp -> q .rb_fragments );
523537 if (qp -> q .fragments_tail == skb )
524538 qp -> q .fragments_tail = fp ;
525539 skb_morph (skb , head );
540+ FRAG_CB (skb )-> next_frag = FRAG_CB (head )-> next_frag ;
526541 rb_replace_node (& head -> rbnode , & skb -> rbnode ,
527542 & qp -> q .rb_fragments );
528543 consume_skb (head );
@@ -558,7 +573,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
558573 for (i = 0 ; i < skb_shinfo (head )-> nr_frags ; i ++ )
559574 plen += skb_frag_size (& skb_shinfo (head )-> frags [i ]);
560575 clone -> len = clone -> data_len = head -> data_len - plen ;
561- skb -> truesize += clone -> truesize ;
576+ head -> truesize += clone -> truesize ;
562577 clone -> csum = 0 ;
563578 clone -> ip_summed = head -> ip_summed ;
564579 add_frag_mem_limit (qp -> q .net , clone -> truesize );
@@ -571,24 +586,36 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
571586 skb_push (head , head -> data - skb_network_header (head ));
572587
573588 /* Traverse the tree in order, to build frag_list. */
589+ fp = FRAG_CB (head )-> next_frag ;
574590 rbn = rb_next (& head -> rbnode );
575591 rb_erase (& head -> rbnode , & qp -> q .rb_fragments );
576- while (rbn ) {
577- struct rb_node * rbnext = rb_next (rbn );
578- fp = rb_to_skb (rbn );
579- rb_erase (rbn , & qp -> q .rb_fragments );
580- rbn = rbnext ;
581- * nextp = fp ;
582- nextp = & fp -> next ;
583- fp -> prev = NULL ;
584- memset (& fp -> rbnode , 0 , sizeof (fp -> rbnode ));
585- head -> data_len += fp -> len ;
586- head -> len += fp -> len ;
587- if (head -> ip_summed != fp -> ip_summed )
588- head -> ip_summed = CHECKSUM_NONE ;
589- else if (head -> ip_summed == CHECKSUM_COMPLETE )
590- head -> csum = csum_add (head -> csum , fp -> csum );
591- head -> truesize += fp -> truesize ;
592+ while (rbn || fp ) {
593+ /* fp points to the next sk_buff in the current run;
594+ * rbn points to the next run.
595+ */
596+ /* Go through the current run. */
597+ while (fp ) {
598+ * nextp = fp ;
599+ nextp = & fp -> next ;
600+ fp -> prev = NULL ;
601+ memset (& fp -> rbnode , 0 , sizeof (fp -> rbnode ));
602+ head -> data_len += fp -> len ;
603+ head -> len += fp -> len ;
604+ if (head -> ip_summed != fp -> ip_summed )
605+ head -> ip_summed = CHECKSUM_NONE ;
606+ else if (head -> ip_summed == CHECKSUM_COMPLETE )
607+ head -> csum = csum_add (head -> csum , fp -> csum );
608+ head -> truesize += fp -> truesize ;
609+ fp = FRAG_CB (fp )-> next_frag ;
610+ }
611+ /* Move to the next run. */
612+ if (rbn ) {
613+ struct rb_node * rbnext = rb_next (rbn );
614+
615+ fp = rb_to_skb (rbn );
616+ rb_erase (rbn , & qp -> q .rb_fragments );
617+ rbn = rbnext ;
618+ }
592619 }
593620 sub_frag_mem_limit (qp -> q .net , head -> truesize );
594621
@@ -624,6 +651,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
624651 qp -> q .fragments = NULL ;
625652 qp -> q .rb_fragments = RB_ROOT ;
626653 qp -> q .fragments_tail = NULL ;
654+ qp -> q .last_run_head = NULL ;
627655 return 0 ;
628656
629657out_nomem :
0 commit comments