diff mbox

[ovs-dev,1/2] packets: Fix UDP over IPv6 checksum

Message ID 1455006125-13898-1-git-send-email-cascardo@redhat.com
State Changes Requested
Headers show

Commit Message

Thadeu Lima de Souza Cascardo Feb. 9, 2016, 8:22 a.m. UTC
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(-)

Comments

Ben Pfaff Feb. 23, 2016, 12:10 a.m. UTC | #1
On Tue, Feb 09, 2016 at 06:22:04AM -0200, Thadeu Lima de Souza Cascardo wrote:
> 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>

Thank you for the fix.

The corresponding function for IPv4 has a test in tests/test-csum.c, in
the function test_pseudo().  Can you please add such a test for IPv6?

Thanks,

Ben.
Thadeu Lima de Souza Cascardo Feb. 23, 2016, 11:09 a.m. UTC | #2
On Mon, Feb 22, 2016 at 04:10:06PM -0800, Ben Pfaff wrote:
> On Tue, Feb 09, 2016 at 06:22:04AM -0200, Thadeu Lima de Souza Cascardo wrote:
> > 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>
> 
> Thank you for the fix.
> 
> The corresponding function for IPv4 has a test in tests/test-csum.c, in
> the function test_pseudo().  Can you please add such a test for IPv6?
> 
> Thanks,
> 
> Ben.

Sure, will do for both patches.

Thanks.
diff mbox

Patch

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. */