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>
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;
}
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)));
}
#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;
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;
}
};
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. */