As OVS adds userspace support for being the endpoint in protocols like tunnels, it will need to be able to calculate pseudoheaders as part of the checksum calculation.
Signed-off-by: Jesse Gross <je...@nicira.com> --- lib/packets.c | 14 ++++++++++++++ lib/packets.h | 1 + tests/library.at | 2 +- tests/test-csum.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/packets.c b/lib/packets.c index 07cf2eb..419c6af 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -1043,3 +1043,17 @@ compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN], dp_packet_set_frame(b, eth); dp_packet_set_l3(b, arp); } + +uint32_t +packet_csum_pseudoheader(const struct ip_header *ip) +{ + uint32_t partial = 0; + + partial = csum_add32(partial, get_16aligned_be32(&ip->ip_src)); + partial = csum_add32(partial, get_16aligned_be32(&ip->ip_dst)); + partial = csum_add16(partial, htons(ip->ip_proto)); + partial = csum_add16(partial, htons(ntohs(ip->ip_tot_len) - + IP_IHL(ip->ip_ihl_ver) * 4)); + + return partial; +} diff --git a/lib/packets.h b/lib/packets.h index 2bbe6d9..29ea54f 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -806,5 +806,6 @@ void packet_format_tcp_flags(struct ds *, uint16_t); const char *packet_tcp_flag_to_string(uint32_t flag); void compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN], ovs_be32 ip_src, ovs_be32 ip_dst); +uint32_t packet_csum_pseudoheader(const struct ip_header *); #endif /* packets.h */ diff --git a/tests/library.at b/tests/library.at index 2507688..426b206 100644 --- a/tests/library.at +++ b/tests/library.at @@ -7,7 +7,7 @@ AT_CHECK([ovstest test-flows flows pcap], [0], [checked 247 packets, 0 errors AT_CLEANUP AT_SETUP([test TCP/IP checksumming]) -AT_CHECK([ovstest test-csum], [0], [....#....#....###................................#................................# +AT_CHECK([ovstest test-csum], [0], [....#....#....####................................#................................# ]) AT_CLEANUP diff --git a/tests/test-csum.c b/tests/test-csum.c index e25fb3d..2685f67 100644 --- a/tests/test-csum.c +++ b/tests/test-csum.c @@ -20,11 +20,13 @@ #include <assert.h> #include <inttypes.h> #include <netinet/in.h> +#include <netinet/ip.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "crc32c.h" #include "ovstest.h" +#include "packets.h" #include "random.h" #include "unaligned.h" #include "util.h" @@ -175,6 +177,34 @@ test_crc32c(void) mark('#'); } +/* Check the IP pseudoheader calculation. */ +static void +test_pseudo(void) +{ + /* Try an IP header similar to one that the tunnel code + * might generate. */ + struct ip_header ip = { + .ip_ihl_ver = IP_IHL_VER(5, 4), + .ip_tos = 0, + .ip_tot_len = htons(134), + .ip_id = 0, + .ip_frag_off = htons(IP_DF), + .ip_ttl = 64, + .ip_proto = IPPROTO_UDP, + .ip_csum = htons(0x1265), + .ip_src = { .hi = htons(0x1400), .lo = htons(0x0002) }, + .ip_dst = { .hi = htons(0x1400), .lo = htons(0x0001) } + }; + + assert(packet_csum_pseudoheader(&ip) == 0x8628); + + /* And also test something totally different to check for + * corner cases. */ + memset(&ip, 0xff, sizeof ip); + assert(packet_csum_pseudoheader(&ip) == 0x5c2fb); + + mark('#'); +} static void test_csum_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) @@ -239,6 +269,7 @@ test_csum_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) test_rfc1624(); test_crc32c(); + test_pseudo(); /* Test recalc_csum16(). */ for (i = 0; i < 32; i++) { -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev