mirror of
https://github.com/openvswitch/ovs
synced 2025-10-15 14:17:18 +00:00
This basically backport commit: commit 179bc67f69b6cb53ad68cfdec5a917c2a2248355 Author: Edward Cree <ecree@solarflare.com> Date: Thu Feb 11 20:48:04 2016 +0000 net: local checksum offload for encapsulation The arithmetic properties of the ones-complement checksum mean that a correctly checksummed inner packet, including its checksum, has a ones complement sum depending only on whatever value was used to initialise the checksum field before checksumming (in the case of TCP and UDP, this is the ones complement sum of the pseudo header, complemented). Consequently, if we are going to offload the inner checksum with CHECKSUM_PARTIAL, we can compute the outer checksum based only on the packed data not covered by the inner checksum, and the initial value of the inner checksum field. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Jesse Gross <jesse@kernel.org>
47 lines
1.3 KiB
C
47 lines
1.3 KiB
C
#include <linux/version.h>
|
|
|
|
#ifndef USE_UPSTREAM_TUNNEL
|
|
|
|
#include <net/udp.h>
|
|
|
|
/* Function to set UDP checksum for an IPv4 UDP packet. This is intended
|
|
* for the simple case like when setting the checksum for a UDP tunnel.
|
|
*/
|
|
void rpl_udp_set_csum(bool nocheck, struct sk_buff *skb,
|
|
__be32 saddr, __be32 daddr, int len)
|
|
{
|
|
struct udphdr *uh = udp_hdr(skb);
|
|
|
|
|
|
if (nocheck) {
|
|
uh->check = 0;
|
|
} else if (skb_is_gso(skb)) {
|
|
uh->check = ~udp_v4_check(len, saddr, daddr, 0);
|
|
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
uh->check = 0;
|
|
uh->check = udp_v4_check(len, saddr, daddr, lco_csum(skb));
|
|
if (uh->check == 0)
|
|
uh->check = CSUM_MANGLED_0;
|
|
} else {
|
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
|
skb->csum_start = skb_transport_header(skb) - skb->head;
|
|
skb->csum_offset = offsetof(struct udphdr, check);
|
|
uh->check = ~udp_v4_check(len, saddr, daddr, 0);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(rpl_udp_set_csum);
|
|
|
|
#endif /* Linux version < 3.16 */
|
|
|
|
#ifdef OVS_CHECK_UDP_TUNNEL_ZERO_CSUM
|
|
void rpl_udp6_csum_zero_error(struct sk_buff *skb)
|
|
{
|
|
/* RFC 2460 section 8.1 says that we SHOULD log
|
|
* this error. Well, it is reasonable.
|
|
*/
|
|
net_dbg_ratelimited("IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u\n",
|
|
&ipv6_hdr(skb)->saddr, ntohs(udp_hdr(skb)->source),
|
|
&ipv6_hdr(skb)->daddr, ntohs(udp_hdr(skb)->dest));
|
|
}
|
|
#endif
|