forked from luck/tmp_suning_uos_patched
udp: Changes to udp_offload to support remote checksum offload
Add a new GSO type, SKB_GSO_TUNNEL_REMCSUM, which indicates remote checksum offload being done (in this case inner checksum must not be offloaded to the NIC). Added logic in __skb_udp_tunnel_segment to handle remote checksum offload case. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5024c33ac3
commit
e585f23636
|
@ -48,8 +48,9 @@ enum {
|
||||||
NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
|
NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
|
||||||
NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
|
NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
|
||||||
NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */
|
NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */
|
||||||
|
NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
|
||||||
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
|
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
|
||||||
NETIF_F_GSO_MPLS_BIT,
|
NETIF_F_GSO_TUNNEL_REMCSUM_BIT,
|
||||||
|
|
||||||
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
|
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
|
||||||
NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */
|
NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */
|
||||||
|
@ -119,6 +120,7 @@ enum {
|
||||||
#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_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_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
|
||||||
#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)
|
||||||
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
|
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
|
||||||
|
|
|
@ -3584,6 +3584,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
|
||||||
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> 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_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));
|
BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT));
|
||||||
|
BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
|
||||||
|
|
||||||
return (features & feature) == feature;
|
return (features & feature) == feature;
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,6 +373,7 @@ enum {
|
||||||
|
|
||||||
SKB_GSO_MPLS = 1 << 12,
|
SKB_GSO_MPLS = 1 << 12,
|
||||||
|
|
||||||
|
SKB_GSO_TUNNEL_REMCSUM = 1 << 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if BITS_PER_LONG > 32
|
#if BITS_PER_LONG > 32
|
||||||
|
@ -603,7 +604,8 @@ struct sk_buff {
|
||||||
#endif
|
#endif
|
||||||
__u8 ipvs_property:1;
|
__u8 ipvs_property:1;
|
||||||
__u8 inner_protocol_type:1;
|
__u8 inner_protocol_type:1;
|
||||||
/* 4 or 6 bit hole */
|
__u8 remcsum_offload:1;
|
||||||
|
/* 3 or 5 bit hole */
|
||||||
|
|
||||||
#ifdef CONFIG_NET_SCHED
|
#ifdef CONFIG_NET_SCHED
|
||||||
__u16 tc_index; /* traffic control index */
|
__u16 tc_index; /* traffic control index */
|
||||||
|
|
|
@ -3013,7 +3013,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
|
||||||
if (nskb->len == len + doffset)
|
if (nskb->len == len + doffset)
|
||||||
goto perform_csum_check;
|
goto perform_csum_check;
|
||||||
|
|
||||||
if (!sg) {
|
if (!sg && !nskb->remcsum_offload) {
|
||||||
nskb->ip_summed = CHECKSUM_NONE;
|
nskb->ip_summed = CHECKSUM_NONE;
|
||||||
nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
|
nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
|
||||||
skb_put(nskb, len),
|
skb_put(nskb, len),
|
||||||
|
@ -3085,7 +3085,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
|
||||||
nskb->truesize += nskb->data_len;
|
nskb->truesize += nskb->data_len;
|
||||||
|
|
||||||
perform_csum_check:
|
perform_csum_check:
|
||||||
if (!csum) {
|
if (!csum && !nskb->remcsum_offload) {
|
||||||
nskb->csum = skb_checksum(nskb, doffset,
|
nskb->csum = skb_checksum(nskb, doffset,
|
||||||
nskb->len - doffset, 0);
|
nskb->len - doffset, 0);
|
||||||
nskb->ip_summed = CHECKSUM_NONE;
|
nskb->ip_summed = CHECKSUM_NONE;
|
||||||
|
|
|
@ -1222,6 +1222,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
|
||||||
SKB_GSO_TCPV6 |
|
SKB_GSO_TCPV6 |
|
||||||
SKB_GSO_UDP_TUNNEL |
|
SKB_GSO_UDP_TUNNEL |
|
||||||
SKB_GSO_UDP_TUNNEL_CSUM |
|
SKB_GSO_UDP_TUNNEL_CSUM |
|
||||||
|
SKB_GSO_TUNNEL_REMCSUM |
|
||||||
SKB_GSO_MPLS |
|
SKB_GSO_MPLS |
|
||||||
0)))
|
0)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -97,6 +97,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
|
||||||
SKB_GSO_MPLS |
|
SKB_GSO_MPLS |
|
||||||
SKB_GSO_UDP_TUNNEL |
|
SKB_GSO_UDP_TUNNEL |
|
||||||
SKB_GSO_UDP_TUNNEL_CSUM |
|
SKB_GSO_UDP_TUNNEL_CSUM |
|
||||||
|
SKB_GSO_TUNNEL_REMCSUM |
|
||||||
0) ||
|
0) ||
|
||||||
!(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
|
!(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -41,7 +41,8 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
||||||
unsigned int oldlen;
|
unsigned int oldlen;
|
||||||
bool need_csum = !!(skb_shinfo(skb)->gso_type &
|
bool need_csum = !!(skb_shinfo(skb)->gso_type &
|
||||||
SKB_GSO_UDP_TUNNEL_CSUM);
|
SKB_GSO_UDP_TUNNEL_CSUM);
|
||||||
bool offload_csum = false, dont_encap = need_csum;
|
bool remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM);
|
||||||
|
bool offload_csum = false, dont_encap = (need_csum || remcsum);
|
||||||
|
|
||||||
oldlen = (u16)~skb->len;
|
oldlen = (u16)~skb->len;
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
||||||
skb->mac_len = skb_inner_network_offset(skb);
|
skb->mac_len = skb_inner_network_offset(skb);
|
||||||
skb->protocol = new_protocol;
|
skb->protocol = new_protocol;
|
||||||
skb->encap_hdr_csum = need_csum;
|
skb->encap_hdr_csum = need_csum;
|
||||||
|
skb->remcsum_offload = remcsum;
|
||||||
|
|
||||||
/* Try to offload checksum if possible */
|
/* Try to offload checksum if possible */
|
||||||
offload_csum = !!(need_csum &&
|
offload_csum = !!(need_csum &&
|
||||||
|
@ -108,11 +110,22 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
||||||
uh->check = ~csum_fold((__force __wsum)
|
uh->check = ~csum_fold((__force __wsum)
|
||||||
((__force u32)uh->check +
|
((__force u32)uh->check +
|
||||||
(__force u32)delta));
|
(__force u32)delta));
|
||||||
|
|
||||||
if (offload_csum) {
|
if (offload_csum) {
|
||||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||||
skb->csum_start = skb_transport_header(skb) - skb->head;
|
skb->csum_start = skb_transport_header(skb) - skb->head;
|
||||||
skb->csum_offset = offsetof(struct udphdr, check);
|
skb->csum_offset = offsetof(struct udphdr, check);
|
||||||
|
} else if (remcsum) {
|
||||||
|
/* Need to calculate checksum from scratch,
|
||||||
|
* inner checksums are never when doing
|
||||||
|
* remote_checksum_offload.
|
||||||
|
*/
|
||||||
|
|
||||||
|
skb->csum = skb_checksum(skb, udp_offset,
|
||||||
|
skb->len - udp_offset,
|
||||||
|
0);
|
||||||
|
uh->check = csum_fold(skb->csum);
|
||||||
|
if (uh->check == 0)
|
||||||
|
uh->check = CSUM_MANGLED_0;
|
||||||
} else {
|
} else {
|
||||||
uh->check = gso_make_checksum(skb, ~uh->check);
|
uh->check = gso_make_checksum(skb, ~uh->check);
|
||||||
|
|
||||||
|
@ -192,6 +205,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
|
||||||
if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
|
if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
|
||||||
SKB_GSO_UDP_TUNNEL |
|
SKB_GSO_UDP_TUNNEL |
|
||||||
SKB_GSO_UDP_TUNNEL_CSUM |
|
SKB_GSO_UDP_TUNNEL_CSUM |
|
||||||
|
SKB_GSO_TUNNEL_REMCSUM |
|
||||||
SKB_GSO_IPIP |
|
SKB_GSO_IPIP |
|
||||||
SKB_GSO_GRE | SKB_GSO_GRE_CSUM |
|
SKB_GSO_GRE | SKB_GSO_GRE_CSUM |
|
||||||
SKB_GSO_MPLS) ||
|
SKB_GSO_MPLS) ||
|
||||||
|
|
|
@ -78,6 +78,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
|
||||||
SKB_GSO_SIT |
|
SKB_GSO_SIT |
|
||||||
SKB_GSO_UDP_TUNNEL |
|
SKB_GSO_UDP_TUNNEL |
|
||||||
SKB_GSO_UDP_TUNNEL_CSUM |
|
SKB_GSO_UDP_TUNNEL_CSUM |
|
||||||
|
SKB_GSO_TUNNEL_REMCSUM |
|
||||||
SKB_GSO_MPLS |
|
SKB_GSO_MPLS |
|
||||||
SKB_GSO_TCPV6 |
|
SKB_GSO_TCPV6 |
|
||||||
0)))
|
0)))
|
||||||
|
|
|
@ -42,6 +42,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
|
||||||
SKB_GSO_DODGY |
|
SKB_GSO_DODGY |
|
||||||
SKB_GSO_UDP_TUNNEL |
|
SKB_GSO_UDP_TUNNEL |
|
||||||
SKB_GSO_UDP_TUNNEL_CSUM |
|
SKB_GSO_UDP_TUNNEL_CSUM |
|
||||||
|
SKB_GSO_TUNNEL_REMCSUM |
|
||||||
SKB_GSO_GRE |
|
SKB_GSO_GRE |
|
||||||
SKB_GSO_GRE_CSUM |
|
SKB_GSO_GRE_CSUM |
|
||||||
SKB_GSO_IPIP |
|
SKB_GSO_IPIP |
|
||||||
|
|
Loading…
Reference in New Issue
Block a user