diff options
author | Tom Rini <trini@ti.com> | 2015-01-26 17:44:49 -0500 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2015-01-26 17:44:49 -0500 |
commit | ab92da9f47d51d363c7de42e2a7bd807e2c1bd54 (patch) | |
tree | dfabc29929e39a1ecc47edf5a4cf839ead062acd /net/checksum.c | |
parent | aed03faa064cca56847571b13cbd4c849c6116aa (diff) | |
parent | e43ade3749ff10bc313f33bf23705465e4163896 (diff) | |
download | u-boot-imx-ab92da9f47d51d363c7de42e2a7bd807e2c1bd54.zip u-boot-imx-ab92da9f47d51d363c7de42e2a7bd807e2c1bd54.tar.gz u-boot-imx-ab92da9f47d51d363c7de42e2a7bd807e2c1bd54.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot-x86
Diffstat (limited to 'net/checksum.c')
-rw-r--r-- | net/checksum.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/net/checksum.c b/net/checksum.c new file mode 100644 index 0000000..a8c9ff5 --- /dev/null +++ b/net/checksum.c @@ -0,0 +1,60 @@ +/* + * This file was originally taken from the FreeBSD project. + * + * Copyright (c) 2001 Charles Mott <cm@linktel.net> + * Copyright (c) 2008 coresystems GmbH + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <common.h> +#include <net.h> + +unsigned compute_ip_checksum(const void *vptr, unsigned nbytes) +{ + int sum, oddbyte; + const unsigned short *ptr = vptr; + + sum = 0; + while (nbytes > 1) { + sum += *ptr++; + nbytes -= 2; + } + if (nbytes == 1) { + oddbyte = 0; + ((u8 *)&oddbyte)[0] = *(u8 *)ptr; + ((u8 *)&oddbyte)[1] = 0; + sum += oddbyte; + } + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + sum = ~sum & 0xffff; + + return sum; +} + +unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new) +{ + unsigned long checksum; + + sum = ~sum & 0xffff; + new = ~new & 0xffff; + if (offset & 1) { + /* + * byte-swap the sum if it came from an odd offset; since the + * computation is endian independant this works. + */ + new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00); + } + checksum = sum + new; + if (checksum > 0xffff) + checksum -= 0xffff; + + return (~checksum) & 0xffff; +} + +int ip_checksum_ok(const void *addr, unsigned nbytes) +{ + return !(compute_ip_checksum(addr, nbytes) & 0xfffe); +} |