Commit e4f7ae93 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 63c6f81c f79b064c
...@@ -1156,15 +1156,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) ...@@ -1156,15 +1156,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
if (!vs) if (!vs)
goto drop; goto drop;
/* If the NIC driver gave us an encapsulated packet skb_pop_rcv_encapsulation(skb);
* with the encapsulation mark, the device checksummed it
* for us. Otherwise force the upper layers to verify it.
*/
if ((skb->ip_summed != CHECKSUM_UNNECESSARY && skb->ip_summed != CHECKSUM_PARTIAL) ||
!skb->encapsulation)
skb->ip_summed = CHECKSUM_NONE;
skb->encapsulation = 0;
vs->rcv(vs, skb, vxh->vx_vni); vs->rcv(vs, skb, vxh->vx_vni);
return 0; return 0;
...@@ -1201,6 +1193,7 @@ static void vxlan_rcv(struct vxlan_sock *vs, ...@@ -1201,6 +1193,7 @@ static void vxlan_rcv(struct vxlan_sock *vs,
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev))); skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev)));
skb->protocol = eth_type_trans(skb, vxlan->dev); skb->protocol = eth_type_trans(skb, vxlan->dev);
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
/* Ignore packet loops (and multicast echo) */ /* Ignore packet loops (and multicast echo) */
if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
......
...@@ -117,6 +117,7 @@ enum { ...@@ -117,6 +117,7 @@ enum {
#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP) #define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP)
#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT) #define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS) #define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS)
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) #define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
......
...@@ -3305,6 +3305,13 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type) ...@@ -3305,6 +3305,13 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT)); BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_IPIP != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT));
return (features & feature) == feature; return (features & feature) == feature;
} }
......
...@@ -338,17 +338,18 @@ enum { ...@@ -338,17 +338,18 @@ enum {
SKB_GSO_GRE = 1 << 6, SKB_GSO_GRE = 1 << 6,
SKB_GSO_IPIP = 1 << 7, SKB_GSO_GRE_CSUM = 1 << 7,
SKB_GSO_SIT = 1 << 8, SKB_GSO_IPIP = 1 << 8,
SKB_GSO_UDP_TUNNEL = 1 << 9, SKB_GSO_SIT = 1 << 9,
SKB_GSO_MPLS = 1 << 10, SKB_GSO_UDP_TUNNEL = 1 << 10,
SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11, SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
SKB_GSO_GRE_CSUM = 1 << 12, SKB_GSO_MPLS = 1 << 12,
}; };
#if BITS_PER_LONG > 32 #if BITS_PER_LONG > 32
...@@ -1853,6 +1854,18 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len) ...@@ -1853,6 +1854,18 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
return pskb_may_pull(skb, skb_network_offset(skb) + len); return pskb_may_pull(skb, skb_network_offset(skb) + len);
} }
static inline void skb_pop_rcv_encapsulation(struct sk_buff *skb)
{
/* Only continue with checksum unnecessary if device indicated
* it is valid across encapsulation (skb->encapsulation was set).
*/
if (skb->ip_summed == CHECKSUM_UNNECESSARY && !skb->encapsulation)
skb->ip_summed = CHECKSUM_NONE;
skb->encapsulation = 0;
skb->csum_valid = 0;
}
/* /*
* CPUs often take a performance hit when accessing unaligned memory * CPUs often take a performance hit when accessing unaligned memory
* locations. The actual performance hit varies, it can be small if the * locations. The actual performance hit varies, it can be small if the
......
...@@ -111,7 +111,9 @@ struct sk_buff; ...@@ -111,7 +111,9 @@ struct sk_buff;
*/ */
static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
{ {
return __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov); return (UDP_SKB_CB(skb)->cscov == skb->len ?
__skb_checksum_complete(skb) :
__skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov));
} }
static inline int udp_lib_checksum_complete(struct sk_buff *skb) static inline int udp_lib_checksum_complete(struct sk_buff *skb)
......
...@@ -739,22 +739,38 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) ...@@ -739,22 +739,38 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
__sum16 sum; __sum16 sum;
sum = csum_fold(skb_checksum(skb, 0, len, skb->csum)); sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && !sum && if (likely(!sum)) {
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
!skb->csum_complete_sw) !skb->csum_complete_sw)
netdev_rx_csum_fault(skb->dev); netdev_rx_csum_fault(skb->dev);
}
/* Save checksum complete for later use */ skb->csum_valid = !sum;
skb->csum = sum;
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum_complete_sw = 1;
return sum; return sum;
} }
EXPORT_SYMBOL(__skb_checksum_complete_head); EXPORT_SYMBOL(__skb_checksum_complete_head);
__sum16 __skb_checksum_complete(struct sk_buff *skb) __sum16 __skb_checksum_complete(struct sk_buff *skb)
{ {
return __skb_checksum_complete_head(skb, skb->len); __wsum csum;
__sum16 sum;
csum = skb_checksum(skb, 0, skb->len, 0);
/* skb->csum holds pseudo checksum */
sum = csum_fold(csum_add(skb->csum, csum));
if (likely(!sum)) {
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
!skb->csum_complete_sw)
netdev_rx_csum_fault(skb->dev);
}
/* Save full packet checksum */
skb->csum = csum;
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum_complete_sw = 1;
skb->csum_valid = !sum;
return sum;
} }
EXPORT_SYMBOL(__skb_checksum_complete); EXPORT_SYMBOL(__skb_checksum_complete);
......
...@@ -689,6 +689,9 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) ...@@ -689,6 +689,9 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->ooo_okay = old->ooo_okay; new->ooo_okay = old->ooo_okay;
new->no_fcs = old->no_fcs; new->no_fcs = old->no_fcs;
new->encapsulation = old->encapsulation; new->encapsulation = old->encapsulation;
new->encap_hdr_csum = old->encap_hdr_csum;
new->csum_valid = old->csum_valid;
new->csum_complete_sw = old->csum_complete_sw;
#ifdef CONFIG_XFRM #ifdef CONFIG_XFRM
new->sp = secpath_get(old->sp); new->sp = secpath_get(old->sp);
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment