Merge branch 'csum_fixes'

Tom Herbert says:

====================
Fixes related to some recent checksum modifications.

- Fix GSO constants to match NETIF flags
- Fix logic in saving checksum complete in __skb_checksum_complete
- Call __skb_checksum_complete from UDP if we are checksumming over
whole packet in order to save checksum.
- Fixes to VXLAN to work correctly with checksum complete
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

Changed files
+60 -25
drivers
net
include
net
+2 -9
drivers/net/vxlan.c
··· 1156 1156 if (!vs) 1157 1157 goto drop; 1158 1158 1159 - /* If the NIC driver gave us an encapsulated packet 1160 - * with the encapsulation mark, the device checksummed it 1161 - * for us. Otherwise force the upper layers to verify it. 1162 - */ 1163 - if ((skb->ip_summed != CHECKSUM_UNNECESSARY && skb->ip_summed != CHECKSUM_PARTIAL) || 1164 - !skb->encapsulation) 1165 - skb->ip_summed = CHECKSUM_NONE; 1166 - 1167 - skb->encapsulation = 0; 1159 + skb_pop_rcv_encapsulation(skb); 1168 1160 1169 1161 vs->rcv(vs, skb, vxh->vx_vni); 1170 1162 return 0; ··· 1193 1201 skb_reset_mac_header(skb); 1194 1202 skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev))); 1195 1203 skb->protocol = eth_type_trans(skb, vxlan->dev); 1204 + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); 1196 1205 1197 1206 /* Ignore packet loops (and multicast echo) */ 1198 1207 if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
+1
include/linux/netdev_features.h
··· 117 117 #define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP) 118 118 #define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT) 119 119 #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) 120 + #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM) 120 121 #define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS) 121 122 #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) 122 123 #define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
+7
include/linux/netdevice.h
··· 3305 3305 BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT)); 3306 3306 BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT)); 3307 3307 BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT)); 3308 + BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT)); 3309 + BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT)); 3310 + BUILD_BUG_ON(SKB_GSO_IPIP != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT)); 3311 + BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT)); 3312 + BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT)); 3313 + BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT)); 3314 + BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT)); 3308 3315 3309 3316 return (features & feature) == feature; 3310 3317 }
+18 -5
include/linux/skbuff.h
··· 338 338 339 339 SKB_GSO_GRE = 1 << 6, 340 340 341 - SKB_GSO_IPIP = 1 << 7, 341 + SKB_GSO_GRE_CSUM = 1 << 7, 342 342 343 - SKB_GSO_SIT = 1 << 8, 343 + SKB_GSO_IPIP = 1 << 8, 344 344 345 - SKB_GSO_UDP_TUNNEL = 1 << 9, 345 + SKB_GSO_SIT = 1 << 9, 346 346 347 - SKB_GSO_MPLS = 1 << 10, 347 + SKB_GSO_UDP_TUNNEL = 1 << 10, 348 348 349 349 SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11, 350 350 351 - SKB_GSO_GRE_CSUM = 1 << 12, 351 + SKB_GSO_MPLS = 1 << 12, 352 + 352 353 }; 353 354 354 355 #if BITS_PER_LONG > 32 ··· 1852 1851 static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len) 1853 1852 { 1854 1853 return pskb_may_pull(skb, skb_network_offset(skb) + len); 1854 + } 1855 + 1856 + static inline void skb_pop_rcv_encapsulation(struct sk_buff *skb) 1857 + { 1858 + /* Only continue with checksum unnecessary if device indicated 1859 + * it is valid across encapsulation (skb->encapsulation was set). 1860 + */ 1861 + if (skb->ip_summed == CHECKSUM_UNNECESSARY && !skb->encapsulation) 1862 + skb->ip_summed = CHECKSUM_NONE; 1863 + 1864 + skb->encapsulation = 0; 1865 + skb->csum_valid = 0; 1855 1866 } 1856 1867 1857 1868 /*
+3 -1
include/net/udp.h
··· 111 111 */ 112 112 static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) 113 113 { 114 - return __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov); 114 + return (UDP_SKB_CB(skb)->cscov == skb->len ? 115 + __skb_checksum_complete(skb) : 116 + __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov)); 115 117 } 116 118 117 119 static inline int udp_lib_checksum_complete(struct sk_buff *skb)
+26 -10
net/core/datagram.c
··· 739 739 __sum16 sum; 740 740 741 741 sum = csum_fold(skb_checksum(skb, 0, len, skb->csum)); 742 - if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && !sum && 743 - !skb->csum_complete_sw) 744 - netdev_rx_csum_fault(skb->dev); 745 - 746 - /* Save checksum complete for later use */ 747 - skb->csum = sum; 748 - skb->ip_summed = CHECKSUM_COMPLETE; 749 - skb->csum_complete_sw = 1; 750 - 742 + if (likely(!sum)) { 743 + if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && 744 + !skb->csum_complete_sw) 745 + netdev_rx_csum_fault(skb->dev); 746 + } 747 + skb->csum_valid = !sum; 751 748 return sum; 752 749 } 753 750 EXPORT_SYMBOL(__skb_checksum_complete_head); 754 751 755 752 __sum16 __skb_checksum_complete(struct sk_buff *skb) 756 753 { 757 - return __skb_checksum_complete_head(skb, skb->len); 754 + __wsum csum; 755 + __sum16 sum; 756 + 757 + csum = skb_checksum(skb, 0, skb->len, 0); 758 + 759 + /* skb->csum holds pseudo checksum */ 760 + sum = csum_fold(csum_add(skb->csum, csum)); 761 + if (likely(!sum)) { 762 + if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && 763 + !skb->csum_complete_sw) 764 + netdev_rx_csum_fault(skb->dev); 765 + } 766 + 767 + /* Save full packet checksum */ 768 + skb->csum = csum; 769 + skb->ip_summed = CHECKSUM_COMPLETE; 770 + skb->csum_complete_sw = 1; 771 + skb->csum_valid = !sum; 772 + 773 + return sum; 758 774 } 759 775 EXPORT_SYMBOL(__skb_checksum_complete); 760 776
+3
net/core/skbuff.c
··· 689 689 new->ooo_okay = old->ooo_okay; 690 690 new->no_fcs = old->no_fcs; 691 691 new->encapsulation = old->encapsulation; 692 + new->encap_hdr_csum = old->encap_hdr_csum; 693 + new->csum_valid = old->csum_valid; 694 + new->csum_complete_sw = old->csum_complete_sw; 692 695 #ifdef CONFIG_XFRM 693 696 new->sp = secpath_get(old->sp); 694 697 #endif