@@ -3460,6 +3460,19 @@ void *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
34603460}
34613461EXPORT_SYMBOL_GPL (skb_pull_rcsum );
34623462
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+
34633476/**
34643477 * skb_segment - Perform protocol segmentation on skb.
34653478 * @head_skb: buffer to segment
@@ -3664,15 +3677,19 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
36643677
36653678 while (pos < offset + len ) {
36663679 if (i >= nfrags ) {
3667- BUG_ON (skb_headlen (list_skb ));
3668-
36693680 i = 0 ;
36703681 nfrags = skb_shinfo (list_skb )-> nr_frags ;
36713682 frag = skb_shinfo (list_skb )-> frags ;
36723683 frag_skb = list_skb ;
3684+ if (!skb_headlen (list_skb )) {
3685+ BUG_ON (!nfrags );
3686+ } else {
3687+ BUG_ON (!list_skb -> head_frag );
36733688
3674- BUG_ON (!nfrags );
3675-
3689+ /* to make room for head_frag. */
3690+ i -- ;
3691+ frag -- ;
3692+ }
36763693 if (skb_orphan_frags (frag_skb , GFP_ATOMIC ) ||
36773694 skb_zerocopy_clone (nskb , frag_skb ,
36783695 GFP_ATOMIC ))
@@ -3689,7 +3706,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
36893706 goto err ;
36903707 }
36913708
3692- * nskb_frag = * frag ;
3709+ * nskb_frag = ( i < 0 ) ? skb_head_frag_to_page_desc ( frag_skb ) : * frag ;
36933710 __skb_frag_ref (nskb_frag );
36943711 size = skb_frag_size (nskb_frag );
36953712
0 commit comments