diff --git a/include/net.h b/include/net.h
index 3da35fe981880500b9025ca813164c27a2aa8bdb..73ea88b42d7defb35ddea2da2d0ff30684c26b30 100644
--- a/include/net.h
+++ b/include/net.h
@@ -482,6 +482,36 @@ extern void net_set_ip_header(uchar *pkt, IPaddr_t dest, IPaddr_t source);
 extern void net_set_udp_header(uchar *pkt, IPaddr_t dest, int dport,
 				int sport, int len);
 
+/**
+ * compute_ip_checksum() - Compute IP checksum
+ *
+ * @addr:	Address to check (must be 16-bit aligned)
+ * @nbytes:	Number of bytes to check (normally a multiple of 2)
+ * @return 16-bit IP checksum
+ */
+unsigned compute_ip_checksum(const void *addr, unsigned nbytes);
+
+/**
+ * add_ip_checksums() - add two IP checksums
+ *
+ * @offset:	Offset of first sum (if odd we do a byte-swap)
+ * @sum:	First checksum
+ * @new_sum:	New checksum to add
+ * @return updated 16-bit IP checksum
+ */
+unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new_sum);
+
+/**
+ * ip_checksum_ok() - check if a checksum is correct
+ *
+ * This works by making sure the checksum sums to 0
+ *
+ * @addr:	Address to check (must be 16-bit aligned)
+ * @nbytes:	Number of bytes to check (normally a multiple of 2)
+ * @return true if the checksum matches, false if not
+ */
+int ip_checksum_ok(const void *addr, unsigned nbytes);
+
 /* Checksum */
 extern int	NetCksumOk(uchar *, int);	/* Return true if cksum OK */
 extern uint	NetCksum(uchar *, int);		/* Calculate the checksum */
diff --git a/net/Makefile b/net/Makefile
index 942595021dad1cf3fccb27531bde72e20e0acd88..e9cc8ada96a783ae18444c9f68a107bede6e0054 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -7,6 +7,7 @@
 
 #ccflags-y += -DDEBUG
 
+obj-y += checksum.o
 obj-$(CONFIG_CMD_NET)  += arp.o
 obj-$(CONFIG_CMD_NET)  += bootp.o
 obj-$(CONFIG_CMD_CDP)  += cdp.o
diff --git a/net/checksum.c b/net/checksum.c
new file mode 100644
index 0000000000000000000000000000000000000000..a8c9ff5ea456a76c59591aac9f52e118f2d89ba9
--- /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);
+}