@@ -1000,15 +1000,18 @@ udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
if (udp->udp_csum) {
uint32_t csum;
+ size_t udp_len;
+ udp_len = dp_packet_size(packet) -
+ ((const unsigned char *) udp -
+ (const unsigned char *) dp_packet_l2(packet));
if (is_header_ipv6(dp_packet_data(packet))) {
- csum = packet_csum_pseudoheader6(dp_packet_l3(packet));
+ csum = packet_csum_pseudoheader6(dp_packet_l3(packet),
+ htonl(udp_len));
} else {
csum = packet_csum_pseudoheader(dp_packet_l3(packet));
}
- csum = csum_continue(csum, udp, dp_packet_size(packet) -
- ((const unsigned char *)udp -
- (const unsigned char *)dp_packet_l2(packet)));
+ csum = csum_continue(csum, udp, udp_len);
if (csum_finish(csum)) {
return NULL;
}
@@ -1048,7 +1051,8 @@ push_udp_header(struct dp_packet *packet,
if (udp->udp_csum) {
uint32_t csum;
if (is_header_ipv6(dp_packet_data(packet))) {
- csum = packet_csum_pseudoheader6(ipv6_hdr(dp_packet_data(packet)));
+ csum = packet_csum_pseudoheader6(ipv6_hdr(dp_packet_data(packet)),
+ htonl(ip_tot_size));
} else {
csum = packet_csum_pseudoheader(ip_hdr(dp_packet_data(packet)));
}
@@ -1271,7 +1271,8 @@ packet_csum_pseudoheader(const struct ip_header *ip)
#ifndef __CHECKER__
uint32_t
-packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *ip6)
+packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *ip6,
+ ovs_be32 plen)
{
uint32_t partial = 0;
@@ -1284,10 +1285,9 @@ packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *ip6)
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[2])));
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[3])));
+ partial = csum_add32(partial, plen);
partial = csum_add16(partial, 0);
- partial = csum_add16(partial, ip6->ip6_plen);
- partial = csum_add16(partial, 0);
- partial = csum_add16(partial, ip6->ip6_nxt);
+ partial = csum_add16(partial, htons(ip6->ip6_nxt));
return partial;
}
@@ -838,7 +838,7 @@ struct icmp6_header {
};
BUILD_ASSERT_DECL(ICMP6_HEADER_LEN == sizeof(struct icmp6_header));
-uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *);
+uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *, ovs_be32);
/* Neighbor Discovery option field.
* ND options are always a multiple of 8 bytes in size. */
Fix the IPv6 pseudoheader checksum. Requires that the payload length is given to the function. Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com> --- lib/netdev-vport.c | 14 +++++++++----- lib/packets.c | 8 ++++---- lib/packets.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-)