laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/libosmo-netif/+/42463?usp=email )

Change subject: Introduce ip_checksum API
......................................................................

Introduce ip_checksum API

ip_checksum.* files are copied from checksum.* in osmo-ggsn.git
1.14.0 (ebd1bf8adbc8d5bec9e36d70e3a78e8838226e7a).

Change-Id: Ia09645a4715ac133036d7c89297b0fa10cf9aa3b
---
M TODO-RELEASE
M include/osmocom/netif/Makefile.am
A include/osmocom/netif/ip_checksum.h
M src/Makefile.am
A src/ip_checksum.c
5 files changed, 226 insertions(+), 0 deletions(-)

Approvals:
  Jenkins Builder: Verified
  osmith: Looks good to me, but someone else must approve
  fixeria: Looks good to me, approved
  laforge: Looks good to me, approved




diff --git a/TODO-RELEASE b/TODO-RELEASE
index 0ed7189..7aebf84 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -7,3 +7,4 @@
 # If any interfaces have been added since the last public release: c:r:a + 1.
 # If any interfaces have been removed or changed since the last public 
release: c:r:0.
 #library       what                    description / commit summary line
+netif     add       osmo_ip_checksum API
diff --git a/include/osmocom/netif/Makefile.am 
b/include/osmocom/netif/Makefile.am
index 71f0931..f509221 100644
--- a/include/osmocom/netif/Makefile.am
+++ b/include/osmocom/netif/Makefile.am
@@ -20,6 +20,7 @@
 osmonetif_HEADERS = \
        amr.h \
        datagram.h \
+       ip_checksum.h \
        ipa.h \
        ipa_unit.h \
        jibuf.h \
diff --git a/include/osmocom/netif/ip_checksum.h 
b/include/osmocom/netif/ip_checksum.h
new file mode 100644
index 0000000..b5130ee
--- /dev/null
+++ b/include/osmocom/netif/ip_checksum.h
@@ -0,0 +1,11 @@
+#pragma once
+#include <stdint.h>
+#include <netinet/in.h>
+
+uint16_t osmo_ip_checksum_fast_csum(const void *iph, unsigned int ihl);
+uint32_t osmo_ip_checksum_csum_partial(const void *buff, int len, uint32_t 
wsum);
+uint16_t osmo_ip_checksum_compute_csum(const void *buff, int len);
+
+uint16_t osmo_ip_checksum_csum_ipv6_magic(const struct in6_addr *saddr,
+                                         const struct in6_addr *daddr,
+                                         uint32_t len, uint8_t proto, uint32_t 
csum);
diff --git a/src/Makefile.am b/src/Makefile.am
index 753bac2..4484e02 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,6 +15,7 @@

 libosmonetif_la_SOURCES = amr.c                        \
                          datagram.c            \
+                         ip_checksum.c         \
                          ipa.c                 \
                          ipa_keepalive.c       \
                          ipa_unit.c            \
diff --git a/src/ip_checksum.c b/src/ip_checksum.c
new file mode 100644
index 0000000..1fa6f42
--- /dev/null
+++ b/src/ip_checksum.c
@@ -0,0 +1,212 @@
+/*
+ *
+ * INET                An implementation of the TCP/IP protocol suite for the 
LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             IP/TCP/UDP checksumming routines
+ *
+ * Authors:    Jorge Cwik, <[email protected]>
+ *             Arnt Gulbrandsen, <[email protected]>
+ *             Tom May, <[email protected]>
+ *             Andreas Schwab, <[email protected]>
+ *             Lots of code moved from tcp.c and ip.c; see those files
+ *             for more names.
+ *
+ * 03/02/96    Jes Sorensen, Andreas Schwab, Roman Hodek:
+ *             Fixed some nasty bugs, causing some horrible crashes.
+ *             A: At some points, the sum (%0) was used as
+ *             length-counter instead of the length counter
+ *             (%1). Thanks to Roman Hodek for pointing this out.
+ *             B: GCC seems to mess up if one uses too many
+ *             data-registers to hold input values and one tries to
+ *             specify d0 and d1 as scratch registers. Letting gcc
+ *             choose these registers itself solves the problem.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+
+/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
+ kills, so most of the assembly has to go. */
+
+#if defined(__FreeBSD__)
+#define _KERNEL        /* needed on FreeBSD 10.x for s6_addr32 */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/endian.h>
+#endif
+
+#include <arpa/inet.h>
+
+#include <osmocom/netif/ip_checksum.h>
+
+static inline unsigned short from32to16(unsigned int x)
+{
+       /* add up 16-bit and 16-bit for 16+c bit */
+       x = (x & 0xffff) + (x >> 16);
+       /* add up carry.. */
+       x = (x & 0xffff) + (x >> 16);
+       return x;
+}
+
+static unsigned int do_csum(const unsigned char *buff, int len)
+{
+       int odd;
+       unsigned int result = 0;
+
+       if (len <= 0)
+               goto out;
+       odd = 1 & (unsigned long) buff;
+       if (odd) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+               result += (*buff << 8);
+#else
+               result = *buff;
+#endif
+               len--;
+               buff++;
+       }
+       if (len >= 2) {
+               if (2 & (unsigned long) buff) {
+                       result += *(unsigned short *) buff;
+                       len -= 2;
+                       buff += 2;
+               }
+               if (len >= 4) {
+                       const unsigned char *end = buff + ((unsigned)len & ~3);
+                       unsigned int carry = 0;
+                       do {
+                               unsigned int w = *(unsigned int *) buff;
+                               buff += 4;
+                               result += carry;
+                               result += w;
+                               carry = (w > result);
+                       } while (buff < end);
+                       result += carry;
+                       result = (result & 0xffff) + (result >> 16);
+               }
+               if (len & 2) {
+                       result += *(unsigned short *) buff;
+                       buff += 2;
+               }
+       }
+       if (len & 1)
+#if BYTE_ORDER == LITTLE_ENDIAN
+               result += *buff;
+#else
+               result += (*buff << 8);
+#endif
+       result = from32to16(result);
+       if (odd)
+               result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+       return result;
+}
+
+/* fold a partial checksum */
+static uint16_t csum_fold(uint32_t csum)
+{
+       uint32_t sum = (uint32_t)csum;
+       sum = (sum & 0xffff) + (sum >> 16);
+       sum = (sum & 0xffff) + (sum >> 16);
+       return (uint16_t)~sum;
+}
+
+/*
+ *     This is a version of ip_compute_csum() optimized for IP headers,
+ *     which always checksum on 4 octet boundaries.
+ */
+uint16_t osmo_ip_checksum_fast_csum(const void *iph, unsigned int ihl)
+{
+       return (uint16_t)~do_csum(iph, ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+uint32_t osmo_ip_checksum_csum_partial(const void *buff, int len, uint32_t 
wsum)
+{
+       unsigned int sum = (unsigned int)wsum;
+       unsigned int result = do_csum(buff, len);
+
+       /* add in old sum, and carry.. */
+       result += sum;
+       if (sum > result)
+               result += 1;
+       return (uint32_t)result;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+uint16_t osmo_ip_checksum_compute_csum(const void *buff, int len)
+{
+       return (uint16_t)~do_csum(buff, len);
+}
+
+uint16_t osmo_ip_checksum_csum_ipv6_magic(const struct in6_addr *saddr,
+                                         const struct in6_addr *daddr,
+                                         uint32_t len, uint8_t proto, uint32_t 
csum)
+{
+       int carry;
+       uint32_t ulen;
+       uint32_t uproto;
+       uint32_t sum = (uint32_t)csum;
+
+       sum += (uint32_t)saddr->s6_addr32[0];
+       carry = (sum < (uint32_t)saddr->s6_addr32[0]);
+       sum += carry;
+
+       sum += (uint32_t)saddr->s6_addr32[1];
+       carry = (sum < (uint32_t)saddr->s6_addr32[1]);
+       sum += carry;
+
+       sum += (uint32_t)saddr->s6_addr32[2];
+       carry = (sum < (uint32_t)saddr->s6_addr32[2]);
+       sum += carry;
+
+       sum += (uint32_t)saddr->s6_addr32[3];
+       carry = (sum < (uint32_t)saddr->s6_addr32[3]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[0];
+       carry = (sum < (uint32_t)daddr->s6_addr32[0]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[1];
+       carry = (sum < (uint32_t)daddr->s6_addr32[1]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[2];
+       carry = (sum < (uint32_t)daddr->s6_addr32[2]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[3];
+       carry = (sum < (uint32_t)daddr->s6_addr32[3]);
+       sum += carry;
+
+       ulen = (uint32_t)htonl((uint32_t) len);
+       sum += ulen;
+       carry = (sum < ulen);
+       sum += carry;
+
+       uproto = (uint32_t)htonl(proto);
+       sum += uproto;
+       carry = (sum < uproto);
+       sum += carry;
+
+       return csum_fold((uint32_t)sum);
+}

--
To view, visit https://gerrit.osmocom.org/c/libosmo-netif/+/42463?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Change-Id: Ia09645a4715ac133036d7c89297b0fa10cf9aa3b
Gerrit-Change-Number: 42463
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>

Reply via email to