@@ -735,8 +735,33 @@ static int ipgre_rcv(struct sk_buff *skb)
735735 return 0 ;
736736}
737737
738+ static struct sk_buff * handle_offloads (struct sk_buff * skb )
739+ {
740+ int err ;
741+
742+ if (skb_is_gso (skb )) {
743+ err = skb_unclone (skb , GFP_ATOMIC );
744+ if (unlikely (err ))
745+ goto error ;
746+ skb_shinfo (skb )-> gso_type |= SKB_GSO_GRE ;
747+ return skb ;
748+ } else if (skb -> ip_summed == CHECKSUM_PARTIAL ) {
749+ err = skb_checksum_help (skb );
750+ if (unlikely (err ))
751+ goto error ;
752+ }
753+ skb -> ip_summed = CHECKSUM_NONE ;
754+
755+ return skb ;
756+
757+ error :
758+ kfree_skb (skb );
759+ return ERR_PTR (err );
760+ }
761+
738762static netdev_tx_t ipgre_tunnel_xmit (struct sk_buff * skb , struct net_device * dev )
739763{
764+ struct pcpu_tstats * tstats = this_cpu_ptr (dev -> tstats );
740765 struct ip_tunnel * tunnel = netdev_priv (dev );
741766 const struct iphdr * old_iph ;
742767 const struct iphdr * tiph ;
@@ -751,10 +776,19 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
751776 __be32 dst ;
752777 int mtu ;
753778 u8 ttl ;
779+ int err ;
780+ int pkt_len ;
754781
755- if (skb -> ip_summed == CHECKSUM_PARTIAL &&
756- skb_checksum_help (skb ))
757- goto tx_error ;
782+ skb = handle_offloads (skb );
783+ if (IS_ERR (skb )) {
784+ dev -> stats .tx_dropped ++ ;
785+ return NETDEV_TX_OK ;
786+ }
787+
788+ if (!skb -> encapsulation ) {
789+ skb_reset_inner_headers (skb );
790+ skb -> encapsulation = 1 ;
791+ }
758792
759793 old_iph = ip_hdr (skb );
760794
@@ -855,7 +889,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
855889 if (skb -> protocol == htons (ETH_P_IP )) {
856890 df |= (old_iph -> frag_off & htons (IP_DF ));
857891
858- if ((old_iph -> frag_off & htons (IP_DF )) &&
892+ if (!skb_is_gso (skb ) &&
893+ (old_iph -> frag_off & htons (IP_DF )) &&
859894 mtu < ntohs (old_iph -> tot_len )) {
860895 icmp_send (skb , ICMP_DEST_UNREACH , ICMP_FRAG_NEEDED , htonl (mtu ));
861896 ip_rt_put (rt );
@@ -875,7 +910,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
875910 }
876911 }
877912
878- if (mtu >= IPV6_MIN_MTU && mtu < skb -> len - tunnel -> hlen + gre_hlen ) {
913+ if (!skb_is_gso (skb ) &&
914+ mtu >= IPV6_MIN_MTU &&
915+ mtu < skb -> len - tunnel -> hlen + gre_hlen ) {
879916 icmpv6_send (skb , ICMPV6_PKT_TOOBIG , 0 , mtu );
880917 ip_rt_put (rt );
881918 goto tx_error ;
@@ -936,6 +973,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
936973 iph -> daddr = fl4 .daddr ;
937974 iph -> saddr = fl4 .saddr ;
938975 iph -> ttl = ttl ;
976+ iph -> id = 0 ;
939977
940978 if (ttl == 0 ) {
941979 if (skb -> protocol == htons (ETH_P_IP ))
@@ -964,17 +1002,39 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
9641002 * ptr = tunnel -> parms .o_key ;
9651003 ptr -- ;
9661004 }
967- if (tunnel -> parms .o_flags & GRE_CSUM ) {
1005+ /* Skip GRE checksum if skb is getting offloaded. */
1006+ if (!(skb_shinfo (skb )-> gso_type & SKB_GSO_GRE ) &&
1007+ (tunnel -> parms .o_flags & GRE_CSUM )) {
9681008 int offset = skb_transport_offset (skb );
9691009
1010+ if (skb_has_shared_frag (skb )) {
1011+ err = __skb_linearize (skb );
1012+ if (err ) {
1013+ ip_rt_put (rt );
1014+ goto tx_error ;
1015+ }
1016+ }
1017+
9701018 * ptr = 0 ;
9711019 * (__sum16 * )ptr = csum_fold (skb_checksum (skb , offset ,
9721020 skb -> len - offset ,
9731021 0 ));
9741022 }
9751023 }
9761024
977- iptunnel_xmit (skb , dev );
1025+ nf_reset (skb );
1026+
1027+ pkt_len = skb -> len - skb_transport_offset (skb );
1028+ err = ip_local_out (skb );
1029+ if (likely (net_xmit_eval (err ) == 0 )) {
1030+ u64_stats_update_begin (& tstats -> syncp );
1031+ tstats -> tx_bytes += pkt_len ;
1032+ tstats -> tx_packets ++ ;
1033+ u64_stats_update_end (& tstats -> syncp );
1034+ } else {
1035+ dev -> stats .tx_errors ++ ;
1036+ dev -> stats .tx_aborted_errors ++ ;
1037+ }
9781038 return NETDEV_TX_OK ;
9791039
9801040#if IS_ENABLED (CONFIG_IPV6 )
@@ -1044,6 +1104,11 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
10441104 mtu = 68 ;
10451105
10461106 tunnel -> hlen = addend ;
1107+ /* TCP offload with GRE SEQ is not supported. */
1108+ if (!(tunnel -> parms .o_flags & GRE_SEQ )) {
1109+ dev -> features |= NETIF_F_GSO_SOFTWARE ;
1110+ dev -> hw_features |= NETIF_F_GSO_SOFTWARE ;
1111+ }
10471112
10481113 return mtu ;
10491114}
@@ -1593,6 +1658,9 @@ static void ipgre_tap_setup(struct net_device *dev)
15931658
15941659 dev -> iflink = 0 ;
15951660 dev -> features |= NETIF_F_NETNS_LOCAL ;
1661+
1662+ dev -> features |= GRE_FEATURES ;
1663+ dev -> hw_features |= GRE_FEATURES ;
15961664}
15971665
15981666static int ipgre_newlink (struct net * src_net , struct net_device * dev , struct nlattr * tb [],
0 commit comments