@@ -3460,6 +3460,19 @@ void *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
3460
3460
}
3461
3461
EXPORT_SYMBOL_GPL (skb_pull_rcsum );
3462
3462
3463
+ static inline skb_frag_t skb_head_frag_to_page_desc (struct sk_buff * frag_skb )
3464
+ {
3465
+ skb_frag_t head_frag ;
3466
+ struct page * page ;
3467
+
3468
+ page = virt_to_head_page (frag_skb -> head );
3469
+ head_frag .page .p = page ;
3470
+ head_frag .page_offset = frag_skb -> data -
3471
+ (unsigned char * )page_address (page );
3472
+ head_frag .size = skb_headlen (frag_skb );
3473
+ return head_frag ;
3474
+ }
3475
+
3463
3476
/**
3464
3477
* skb_segment - Perform protocol segmentation on skb.
3465
3478
* @head_skb: buffer to segment
@@ -3664,15 +3677,19 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
3664
3677
3665
3678
while (pos < offset + len ) {
3666
3679
if (i >= nfrags ) {
3667
- BUG_ON (skb_headlen (list_skb ));
3668
-
3669
3680
i = 0 ;
3670
3681
nfrags = skb_shinfo (list_skb )-> nr_frags ;
3671
3682
frag = skb_shinfo (list_skb )-> frags ;
3672
3683
frag_skb = list_skb ;
3684
+ if (!skb_headlen (list_skb )) {
3685
+ BUG_ON (!nfrags );
3686
+ } else {
3687
+ BUG_ON (!list_skb -> head_frag );
3673
3688
3674
- BUG_ON (!nfrags );
3675
-
3689
+ /* to make room for head_frag. */
3690
+ i -- ;
3691
+ frag -- ;
3692
+ }
3676
3693
if (skb_orphan_frags (frag_skb , GFP_ATOMIC ) ||
3677
3694
skb_zerocopy_clone (nskb , frag_skb ,
3678
3695
GFP_ATOMIC ))
@@ -3689,7 +3706,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
3689
3706
goto err ;
3690
3707
}
3691
3708
3692
- * nskb_frag = * frag ;
3709
+ * nskb_frag = ( i < 0 ) ? skb_head_frag_to_page_desc ( frag_skb ) : * frag ;
3693
3710
__skb_frag_ref (nskb_frag );
3694
3711
size = skb_frag_size (nskb_frag );
3695
3712
0 commit comments