diff options
Diffstat (limited to 'tools/testing')
| -rw-r--r-- | tools/testing/selftests/net/txtimestamp.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/tools/testing/selftests/net/txtimestamp.c b/tools/testing/selftests/net/txtimestamp.c index 170be192f5c7..f7bdf30b78d9 100644 --- a/tools/testing/selftests/net/txtimestamp.c +++ b/tools/testing/selftests/net/txtimestamp.c @@ -418,19 +418,25 @@ static uint16_t get_ip_csum(const uint16_t *start, int num_words, return ~sum; } -static uint16_t get_udp_csum(const struct udphdr *udph, int alen) +static uint16_t get_udp_csum(const struct udphdr *udph, bool is_ipv4) { - unsigned long pseudo_sum, csum_len; - const void *csum_start = udph; + const void *addr = is_ipv4 ? (void *)&daddr.sin_addr : &daddr6.sin6_addr; + int alen = is_ipv4 ? sizeof(struct in_addr) : sizeof(struct in6_addr); + uint16_t addr16[sizeof(struct in6_addr) / sizeof(uint16_t)]; + unsigned long pseudo_sum; + int i; pseudo_sum = htons(IPPROTO_UDP); pseudo_sum += udph->len; - /* checksum ip(v6) addresses + udp header + payload */ - csum_start -= alen * 2; - csum_len = ntohs(udph->len) + alen * 2; + /* pseudo-header source and destination: both are daddr */ + memcpy(addr16, addr, alen); + for (i = 0; i < alen / 2; i++) + pseudo_sum += 2 * addr16[i]; - return get_ip_csum(csum_start, csum_len >> 1, pseudo_sum); + /* checksum udp header + payload */ + return get_ip_csum((const uint16_t *)udph, ntohs(udph->len) >> 1, + pseudo_sum); } static int fill_header_ipv4(void *p) @@ -479,8 +485,7 @@ static void fill_header_udp(void *p, bool is_ipv4) udph->len = ntohs(sizeof(*udph) + cfg_payload_len); udph->check = 0; - udph->check = get_udp_csum(udph, is_ipv4 ? sizeof(struct in_addr) : - sizeof(struct in6_addr)); + udph->check = get_udp_csum(udph, is_ipv4); } static void do_test(int family, unsigned int report_opt) |
