Fix the IPv6 pseudoheader checksum. Requires that the payload length is given to the function.
Signed-off-by: Thadeu Lima de Souza Cascardo <casca...@redhat.com> --- lib/netdev-vport.c | 14 +++++++++----- lib/packets.c | 8 ++++---- lib/packets.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 88f5022..a2d5093 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -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))); } diff --git a/lib/packets.c b/lib/packets.c index d82341d..93d75bc 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -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; } diff --git a/lib/packets.h b/lib/packets.h index f1445de..b8fa8db 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -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. */ -- 2.5.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev