Skip to content

Commit e4f7ae9

Browse files
committed
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 <[email protected]>
2 parents 63c6f81 + f79b064 commit e4f7ae9

File tree

7 files changed

+60
-25
lines changed

7 files changed

+60
-25
lines changed

drivers/net/vxlan.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,15 +1156,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
11561156
if (!vs)
11571157
goto drop;
11581158

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);
11681160

11691161
vs->rcv(vs, skb, vxh->vx_vni);
11701162
return 0;
@@ -1201,6 +1193,7 @@ static void vxlan_rcv(struct vxlan_sock *vs,
12011193
skb_reset_mac_header(skb);
12021194
skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev)));
12031195
skb->protocol = eth_type_trans(skb, vxlan->dev);
1196+
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
12041197

12051198
/* Ignore packet loops (and multicast echo) */
12061199
if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))

include/linux/netdev_features.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ enum {
117117
#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP)
118118
#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
119119
#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)
120121
#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS)
121122
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
122123
#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)

include/linux/netdevice.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3305,6 +3305,13 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
33053305
BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));
33063306
BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT));
33073307
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));
33083315

33093316
return (features & feature) == feature;
33103317
}

include/linux/skbuff.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,17 +338,18 @@ enum {
338338

339339
SKB_GSO_GRE = 1 << 6,
340340

341-
SKB_GSO_IPIP = 1 << 7,
341+
SKB_GSO_GRE_CSUM = 1 << 7,
342342

343-
SKB_GSO_SIT = 1 << 8,
343+
SKB_GSO_IPIP = 1 << 8,
344344

345-
SKB_GSO_UDP_TUNNEL = 1 << 9,
345+
SKB_GSO_SIT = 1 << 9,
346346

347-
SKB_GSO_MPLS = 1 << 10,
347+
SKB_GSO_UDP_TUNNEL = 1 << 10,
348348

349349
SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
350350

351-
SKB_GSO_GRE_CSUM = 1 << 12,
351+
SKB_GSO_MPLS = 1 << 12,
352+
352353
};
353354

354355
#if BITS_PER_LONG > 32
@@ -1853,6 +1854,18 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
18531854
return pskb_may_pull(skb, skb_network_offset(skb) + len);
18541855
}
18551856

1857+
static inline void skb_pop_rcv_encapsulation(struct sk_buff *skb)
1858+
{
1859+
/* Only continue with checksum unnecessary if device indicated
1860+
* it is valid across encapsulation (skb->encapsulation was set).
1861+
*/
1862+
if (skb->ip_summed == CHECKSUM_UNNECESSARY && !skb->encapsulation)
1863+
skb->ip_summed = CHECKSUM_NONE;
1864+
1865+
skb->encapsulation = 0;
1866+
skb->csum_valid = 0;
1867+
}
1868+
18561869
/*
18571870
* CPUs often take a performance hit when accessing unaligned memory
18581871
* locations. The actual performance hit varies, it can be small if the

include/net/udp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ struct sk_buff;
111111
*/
112112
static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
113113
{
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));
115117
}
116118

117119
static inline int udp_lib_checksum_complete(struct sk_buff *skb)

net/core/datagram.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -739,22 +739,38 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
739739
__sum16 sum;
740740

741741
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;
751748
return sum;
752749
}
753750
EXPORT_SYMBOL(__skb_checksum_complete_head);
754751

755752
__sum16 __skb_checksum_complete(struct sk_buff *skb)
756753
{
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;
758774
}
759775
EXPORT_SYMBOL(__skb_checksum_complete);
760776

net/core/skbuff.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
689689
new->ooo_okay = old->ooo_okay;
690690
new->no_fcs = old->no_fcs;
691691
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;
692695
#ifdef CONFIG_XFRM
693696
new->sp = secpath_get(old->sp);
694697
#endif

0 commit comments

Comments
 (0)