@@ -601,19 +601,20 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
601
601
struct list_head * sublist )
602
602
{
603
603
u8 hbytes [sizeof (struct ipv6hdr )];
604
- struct sk_buff * first_skb , * next , * skb ;
604
+ struct sk_buff * defer , * first_skb , * next , * skb ;
605
605
const unsigned char * old_mac ;
606
606
struct xfrm_iptfs_data * xtfs ;
607
607
struct iphdr * iph ;
608
608
struct net * net ;
609
- u32 remaining , iplen , iphlen , tail ;
609
+ u32 first_iplen , iphlen , iplen , remaining , tail ;
610
610
u32 capturelen ;
611
611
u64 seq ;
612
612
613
613
xtfs = x -> mode_data ;
614
614
net = xs_net (x );
615
615
skb = skbseq -> root_skb ;
616
616
first_skb = NULL ;
617
+ defer = NULL ;
617
618
618
619
seq = __esp_seq (skb );
619
620
@@ -688,23 +689,92 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
688
689
skb_prepare_seq_read (save , data , tail , skbseq );
689
690
}
690
691
691
- if (!first_skb )
692
+ if (first_skb ) {
693
+ skb = NULL ;
694
+ } else {
692
695
first_skb = skb ;
696
+ first_iplen = iplen ;
697
+
698
+ /* We are going to skip over `data` bytes to reach the
699
+ * start of the IP header of `iphlen` len for `iplen`
700
+ * inner packet.
701
+ */
702
+
703
+ if (skb_has_frag_list (skb )) {
704
+ defer = skb ;
705
+ skb = NULL ;
706
+ } else if (data + iphlen <= skb_headlen (skb ) &&
707
+ /* make sure our header is 32-bit aligned? */
708
+ /* ((uintptr_t)(skb->data + data) & 0x3) == 0 && */
709
+ skb_tailroom (skb ) + tail - data >= iplen ) {
710
+ /* Reuse the received skb.
711
+ *
712
+ * We have enough headlen to pull past any
713
+ * initial fragment data, leaving at least the
714
+ * IP header in the linear buffer space.
715
+ *
716
+ * For linear buffer space we only require that
717
+ * linear buffer space is large enough to
718
+ * eventually hold the entire reassembled
719
+ * packet (by including tailroom in the check).
720
+ *
721
+ * For non-linear tailroom is 0 and so we only
722
+ * re-use if the entire packet is present
723
+ * already.
724
+ *
725
+ * NOTE: there are many more options for
726
+ * sharing, KISS for now. Also, this can produce
727
+ * skb's with the IP header unaligned to 32
728
+ * bits. If that ends up being a problem then a
729
+ * check should be added to the conditional
730
+ * above that the header lies on a 32-bit
731
+ * boundary as well.
732
+ */
733
+ skb_pull (skb , data );
734
+
735
+ /* our range just changed */
736
+ data = 0 ;
737
+ tail = skb -> len ;
738
+ remaining = skb -> len ;
739
+
740
+ skb -> protocol = protocol ;
741
+ skb_mac_header_rebuild (skb );
742
+ if (skb -> mac_len )
743
+ eth_hdr (skb )-> h_proto = skb -> protocol ;
744
+
745
+ /* all pointers could be changed now reset walk */
746
+ skb_abort_seq_read (skbseq );
747
+ skb_prepare_seq_read (skb , data , tail , skbseq );
748
+ } else {
749
+ /* We couldn't reuse the input skb so allocate a
750
+ * new one.
751
+ */
752
+ defer = skb ;
753
+ skb = NULL ;
754
+ }
755
+
756
+ /* Don't trim `first_skb` until the end as we are
757
+ * walking that data now.
758
+ */
759
+ }
693
760
694
761
capturelen = min (iplen , remaining );
695
- skb = iptfs_pskb_extract_seq (iplen , skbseq , data , capturelen );
696
762
if (!skb ) {
697
- /* skip to next packet or done */
698
- data += capturelen ;
699
- continue ;
700
- }
763
+ skb = iptfs_pskb_extract_seq (iplen , skbseq , data ,
764
+ capturelen );
765
+ if (!skb ) {
766
+ /* skip to next packet or done */
767
+ data += capturelen ;
768
+ continue ;
769
+ }
701
770
702
- skb -> protocol = protocol ;
703
- if (old_mac ) {
704
- /* rebuild the mac header */
705
- skb_set_mac_header (skb , - first_skb -> mac_len );
706
- memcpy (skb_mac_header (skb ), old_mac , first_skb -> mac_len );
707
- eth_hdr (skb )-> h_proto = skb -> protocol ;
771
+ skb -> protocol = protocol ;
772
+ if (old_mac ) {
773
+ /* rebuild the mac header */
774
+ skb_set_mac_header (skb , - first_skb -> mac_len );
775
+ memcpy (skb_mac_header (skb ), old_mac , first_skb -> mac_len );
776
+ eth_hdr (skb )-> h_proto = skb -> protocol ;
777
+ }
708
778
}
709
779
710
780
data += capturelen ;
@@ -735,14 +805,37 @@ static bool __input_process_payload(struct xfrm_state *x, u32 data,
735
805
/* this should not happen from the above code */
736
806
XFRM_INC_STATS (net , LINUX_MIB_XFRMINIPTFSERROR );
737
807
808
+ if (first_skb && first_iplen && !defer && first_skb != xtfs -> ra_newskb ) {
809
+ /* first_skb is queued b/c !defer and not partial */
810
+ if (pskb_trim (first_skb , first_iplen )) {
811
+ /* error trimming */
812
+ list_del (& first_skb -> list );
813
+ defer = first_skb ;
814
+ }
815
+ first_skb -> ip_summed = CHECKSUM_NONE ;
816
+ }
817
+
738
818
/* Send the packets! */
739
819
list_for_each_entry_safe (skb , next , sublist , list ) {
740
820
skb_list_del_init (skb );
741
821
if (xfrm_input (skb , 0 , 0 , -2 ))
742
822
kfree_skb (skb );
743
823
}
744
824
done :
745
- return false;
825
+ skb = skbseq -> root_skb ;
826
+ skb_abort_seq_read (skbseq );
827
+
828
+ if (defer ) {
829
+ consume_skb (defer );
830
+ } else if (!first_skb ) {
831
+ /* skb is the original passed in skb, but we didn't get far
832
+ * enough to process it as the first_skb, if we had it would
833
+ * either be save in ra_newskb, trimmed and sent on as an skb or
834
+ * placed in defer to be freed.
835
+ */
836
+ kfree_skb (skb );
837
+ }
838
+ return true;
746
839
}
747
840
748
841
/**
0 commit comments