Commit 9b0e35cb4889eb04a7ea5dd648d73df0bf37cc68
1 parent
5da38086bd
Exists in
v2017.01-smarct4x
and in
37 other branches
net: Add a separate file for IP checksumming
Move the checksum code out into its own file so it can be used elsewhere. Also use a new version which supports a length which is not a multiple of 2 and add a new function to add two checksums. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 3 changed files with 91 additions and 0 deletions Side-by-side Diff
include/net.h
... | ... | @@ -482,6 +482,36 @@ |
482 | 482 | extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport, |
483 | 483 | int sport, int len); |
484 | 484 | |
485 | +/** | |
486 | + * compute_ip_checksum() - Compute IP checksum | |
487 | + * | |
488 | + * @addr: Address to check (must be 16-bit aligned) | |
489 | + * @nbytes: Number of bytes to check (normally a multiple of 2) | |
490 | + * @return 16-bit IP checksum | |
491 | + */ | |
492 | +unsigned compute_ip_checksum(const void *addr, unsigned nbytes); | |
493 | + | |
494 | +/** | |
495 | + * add_ip_checksums() - add two IP checksums | |
496 | + * | |
497 | + * @offset: Offset of first sum (if odd we do a byte-swap) | |
498 | + * @sum: First checksum | |
499 | + * @new_sum: New checksum to add | |
500 | + * @return updated 16-bit IP checksum | |
501 | + */ | |
502 | +unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum); | |
503 | + | |
504 | +/** | |
505 | + * ip_checksum_ok() - check if a checksum is correct | |
506 | + * | |
507 | + * This works by making sure the checksum sums to 0 | |
508 | + * | |
509 | + * @addr: Address to check (must be 16-bit aligned) | |
510 | + * @nbytes: Number of bytes to check (normally a multiple of 2) | |
511 | + * @return true if the checksum matches, false if not | |
512 | + */ | |
513 | +int ip_checksum_ok(const void *addr, unsigned nbytes); | |
514 | + | |
485 | 515 | /* Checksum */ |
486 | 516 | extern int NetCksumOk(uchar *, int); /* Return true if cksum OK */ |
487 | 517 | extern uint NetCksum(uchar *, int); /* Calculate the checksum */ |
net/Makefile
net/checksum.c
1 | +/* | |
2 | + * This file was originally taken from the FreeBSD project. | |
3 | + * | |
4 | + * Copyright (c) 2001 Charles Mott <cm@linktel.net> | |
5 | + * Copyright (c) 2008 coresystems GmbH | |
6 | + * All rights reserved. | |
7 | + * | |
8 | + * SPDX-License-Identifier: BSD-2-Clause | |
9 | + */ | |
10 | + | |
11 | +#include <common.h> | |
12 | +#include <net.h> | |
13 | + | |
14 | +unsigned compute_ip_checksum(const void *vptr, unsigned nbytes) | |
15 | +{ | |
16 | + int sum, oddbyte; | |
17 | + const unsigned short *ptr = vptr; | |
18 | + | |
19 | + sum = 0; | |
20 | + while (nbytes > 1) { | |
21 | + sum += *ptr++; | |
22 | + nbytes -= 2; | |
23 | + } | |
24 | + if (nbytes == 1) { | |
25 | + oddbyte = 0; | |
26 | + ((u8 *)&oddbyte)[0] = *(u8 *)ptr; | |
27 | + ((u8 *)&oddbyte)[1] = 0; | |
28 | + sum += oddbyte; | |
29 | + } | |
30 | + sum = (sum >> 16) + (sum & 0xffff); | |
31 | + sum += (sum >> 16); | |
32 | + sum = ~sum & 0xffff; | |
33 | + | |
34 | + return sum; | |
35 | +} | |
36 | + | |
37 | +unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new) | |
38 | +{ | |
39 | + unsigned long checksum; | |
40 | + | |
41 | + sum = ~sum & 0xffff; | |
42 | + new = ~new & 0xffff; | |
43 | + if (offset & 1) { | |
44 | + /* | |
45 | + * byte-swap the sum if it came from an odd offset; since the | |
46 | + * computation is endian independant this works. | |
47 | + */ | |
48 | + new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00); | |
49 | + } | |
50 | + checksum = sum + new; | |
51 | + if (checksum > 0xffff) | |
52 | + checksum -= 0xffff; | |
53 | + | |
54 | + return (~checksum) & 0xffff; | |
55 | +} | |
56 | + | |
57 | +int ip_checksum_ok(const void *addr, unsigned nbytes) | |
58 | +{ | |
59 | + return !(compute_ip_checksum(addr, nbytes) & 0xfffe); | |
60 | +} |