[PATCH] openbsc[master]: SLHC (RFC1144 header compression) integration

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

dexter gerrit-no-reply at lists.osmocom.org
Wed Aug 10 15:54:57 UTC 2016


Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/635

to look at the new patch set (#4).

SLHC (RFC1144 header compression) integration

The previously pushed slhc implementation has been modified to compile
and function outside of the kernel. Also debug log messages were added
and datatypes ware matched. The implementation is now ready to be used

Change-Id: I7a638e88a43b3eb9d006751a03ef2570e36613f0
---
M openbsc/include/openbsc/Makefile.am
M openbsc/include/openbsc/debug.h
R openbsc/include/openbsc/slhc.h
M openbsc/src/gprs/Makefile.am
M openbsc/src/gprs/slhc.c
M openbsc/tests/sgsn/Makefile.am
6 files changed, 115 insertions(+), 89 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/35/635/4

diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index e200b05..f402fea 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -18,7 +18,8 @@
 		 gprs_gb_parse.h smpp.h meas_feed.h \
 		 gprs_gsup_client.h bsc_msg_filter.h \
 		 oap.h oap_messages.h \
-		 gtphub.h gprs_llc_xid.h gprs_sndcp.h gprs_sndcp_xid.h
+		 gtphub.h gprs_llc_xid.h gprs_sndcp.h gprs_sndcp_xid.h \
+		slhc.h
 
 openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
 openbscdir = $(includedir)/openbsc
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
index 43ebb19..90ddca5 100644
--- a/openbsc/include/openbsc/debug.h
+++ b/openbsc/include/openbsc/debug.h
@@ -29,6 +29,7 @@
 	DBSSGP,
 	DLLC,
 	DSNDCP,
+	DSLHC,
 	DNAT,
 	DCTRL,
 	DSMPP,
diff --git a/openbsc/include/openbsc/slhc_vj.h b/openbsc/include/openbsc/slhc.h
similarity index 97%
rename from openbsc/include/openbsc/slhc_vj.h
rename to openbsc/include/openbsc/slhc.h
index 8716d59..cd5a47c 100644
--- a/openbsc/include/openbsc/slhc_vj.h
+++ b/openbsc/include/openbsc/slhc.h
@@ -171,7 +171,8 @@
 #define NULLSLCOMPR	(struct slcompress *)0
 
 /* In slhc.c: */
-struct slcompress *slhc_init(int rslots, int tslots);
+struct slcompress *slhc_init(const void *ctx, int rslots, int tslots);
+
 void slhc_free(struct slcompress *comp);
 
 int slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
@@ -180,4 +181,7 @@
 int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize);
 int slhc_toss(struct slcompress *comp);
 
+void slhc_i_status(struct slcompress *comp);
+void slhc_o_status(struct slcompress *comp);
+
 #endif	/* _SLHC_H */
diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am
index fa4a3dd..245636b 100644
--- a/openbsc/src/gprs/Makefile.am
+++ b/openbsc/src/gprs/Makefile.am
@@ -26,7 +26,8 @@
 			sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \
 			gprs_utils.c gprs_gsup_client.c \
 			sgsn_cdr.c sgsn_ares.c \
-			oap.c oap_messages.c gprs_llc_xid.c gprs_sndcp_xid.c
+			oap.c oap_messages.c gprs_llc_xid.c gprs_sndcp_xid.c \
+			slhc.c
 osmo_sgsn_LDADD = 	\
 			$(top_builddir)/src/libcommon/libcommon.a \
 			-lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \
diff --git a/openbsc/src/gprs/slhc.c b/openbsc/src/gprs/slhc.c
index 27ed252..ed095f9 100644
--- a/openbsc/src/gprs/slhc.c
+++ b/openbsc/src/gprs/slhc.c
@@ -50,61 +50,77 @@
  *	driver code belonging close to PPP and SLIP
  */
 
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <net/slhc_vj.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/talloc.h>
+#include <openbsc/slhc.h>
+#include <openbsc/debug.h>
 
-#ifdef CONFIG_INET
-/* Entire module is for IP only */
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/termios.h>
-#include <linux/in.h>
-#include <linux/fcntl.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <net/icmp.h>
-#include <net/tcp.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <linux/timer.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-#include <asm/unaligned.h>
+#define ERR_PTR(x) x
+
 
 static unsigned char *encode(unsigned char *cp, unsigned short n);
 static long decode(unsigned char **cpp);
 static unsigned char * put16(unsigned char *cp, unsigned short x);
 static unsigned short pull16(unsigned char **cpp);
 
+/* Replacement for kernel space function ip_fast_csum() */
+static uint16_t ip_fast_csum(uint8_t *iph, int ihl)
+{
+	int i;
+	uint16_t temp;
+	uint32_t accumulator = 0xFFFF;
+
+	for(i=0;i<ihl*2;i++)
+	{
+		temp = ((*iph) << 8)&0xFF00;
+		iph++;
+		temp |= (*iph)&0xFF;
+		iph++;
+
+		accumulator+=temp;
+		if(accumulator>0xFFFF)
+		{
+			accumulator++;
+			accumulator&=0xFFFF;
+		}
+	}
+
+    return (uint16_t)(htons(~accumulator)&0xFFFF);
+}
+
+/* Replacement for kernel space function put_unaligned() */
+static void put_unaligned(uint16_t val, void *ptr)
+{
+	memcpy(ptr,&val,sizeof(val));
+}
+
+
 /* Allocate compression data structure
  *	slots must be in range 0 to 255 (zero meaning no compression)
  * Returns pointer to structure or ERR_PTR() on error.
  */
 struct slcompress *
-slhc_init(int rslots, int tslots)
+slhc_init(const void *ctx, int rslots, int tslots)
 {
 	register short i;
 	register struct cstate *ts;
 	struct slcompress *comp;
 
 	if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255)
-		return ERR_PTR(-EINVAL);
+		return NULL;
 
-	comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
+	comp = (struct slcompress *)talloc_zero_size(ctx,sizeof(struct slcompress));
 	if (! comp)
 		goto out_fail;
 
 	if (rslots > 0) {
 		size_t rsize = rslots * sizeof(struct cstate);
-		comp->rstate = kzalloc(rsize, GFP_KERNEL);
+		comp->rstate = (struct cstate *) talloc_zero_size(ctx, rsize);
 		if (! comp->rstate)
 			goto out_free;
 		comp->rslot_limit = rslots - 1;
@@ -112,7 +128,7 @@
 
 	if (tslots > 0) {
 		size_t tsize = tslots * sizeof(struct cstate);
-		comp->tstate = kzalloc(tsize, GFP_KERNEL);
+		comp->tstate = (struct cstate *) talloc_zero_size(ctx, tsize);
 		if (! comp->tstate)
 			goto out_free2;
 		comp->tslot_limit = tslots - 1;
@@ -141,11 +157,11 @@
 	return comp;
 
 out_free2:
-	kfree(comp->rstate);
+	talloc_free(comp->rstate);
 out_free:
-	kfree(comp);
+	talloc_free(comp);
 out_fail:
-	return ERR_PTR(-ENOMEM);
+	return NULL;
 }
 
 
@@ -153,16 +169,18 @@
 void
 slhc_free(struct slcompress *comp)
 {
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_free(): Freeing compression states...\n");
+
 	if ( comp == NULLSLCOMPR )
 		return;
 
 	if ( comp->tstate != NULLSLSTATE )
-		kfree( comp->tstate );
+		talloc_free(comp->tstate );
 
 	if ( comp->rstate != NULLSLSTATE )
-		kfree( comp->rstate );
+		talloc_free( comp->rstate );
 
-	kfree( comp );
+	talloc_free( comp );
 }
 
 
@@ -256,6 +274,7 @@
 			comp->sls_o_nontcp++;
 		else
 			comp->sls_o_tcp++;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Not a TCP packat, will not touch...\n");
 		return isize;
 	}
 	/* Extract TCP header */
@@ -271,6 +290,7 @@
 	    ! (th->ack)){
 		/* TCP connection stuff; send as regular IP */
 		comp->sls_o_tcp++;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Packet is part of a TCP connection, will not touch...\n");
 		return isize;
 	}
 	/*
@@ -287,6 +307,9 @@
 	 * states via linear search.  If we don't find a state
 	 * for the datagram, the oldest state is (re-)used.
 	 */
+
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Compressible packet detected!\n");
+
 	for ( ; ; ) {
 		if( ip->saddr == cs->cs_ip.saddr
 		 && ip->daddr == cs->cs_ip.daddr
@@ -310,11 +333,14 @@
 	 * state points to the newest and we only need to set
 	 * xmit_oldest to update the lru linkage.
 	 */
+
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Header not yet seen, will memorize header for the next turn...\n");
 	comp->sls_o_misses++;
 	comp->xmit_oldest = lcs->cs_this;
 	goto uncompressed;
 
 found:
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Header already seen, trying to compress...\n");
 	/*
 	 * Found it -- move to the front on the connection list.
 	 */
@@ -351,6 +377,7 @@
 	 || th->doff != cs->cs_tcp.doff
 	 || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
 	 || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): The header contains unexpected changes, can't compress...\n");
 		goto uncompressed;
 	}
 
@@ -369,6 +396,7 @@
 		 * implementation should never do this but RFC793
 		 * doesn't prohibit the change so we have to deal
 		 * with it. */
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): URG not set but urp changed, can't compress...\n");
 		goto uncompressed;
 	}
 	if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
@@ -376,14 +404,18 @@
 		changes |= NEW_W;
 	}
 	if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
-		if(deltaA > 0x0000ffff)
+		if(deltaA > 0x0000ffff)	{
+			LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): (deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L, can't compress...\n");
 			goto uncompressed;
+		}
 		cp = encode(cp,deltaA);
 		changes |= NEW_A;
 	}
 	if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
-		if(deltaS > 0x0000ffff)
+		if(deltaS > 0x0000ffff)	{
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): (deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L, can't compress...\n");
 			goto uncompressed;
+		}
 		cp = encode(cp,deltaS);
 		changes |= NEW_S;
 	}
@@ -399,12 +431,14 @@
 		if(ip->tot_len != cs->cs_ip.tot_len &&
 		   ntohs(cs->cs_ip.tot_len) == hlen)
 			break;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Retransmitted packet detected, can't compress...\n");
 		goto uncompressed;
 	case SPECIAL_I:
 	case SPECIAL_D:
 		/* actual changes match one of our special case encodings --
 		 * send packet uncompressed.
 		 */
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Special case detected, can't compress...\n");
 		goto uncompressed;
 	case NEW_S|NEW_A:
 		if(deltaS == deltaA &&
@@ -467,6 +501,7 @@
 	 * to use on future compressed packets in the protocol field).
 	 */
 uncompressed:
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_compress(): Packet will be sent uncompressed...\n");
 	memcpy(&cs->cs_ip,ip,20);
 	memcpy(&cs->cs_tcp,th,20);
 	if (ip->ihl > 5)
@@ -538,6 +573,8 @@
 
 	switch(changes & SPECIALS_MASK){
 	case SPECIAL_I:		/* Echoed terminal traffic */
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): Echoed terminal traffic detected\n");
+
 		{
 		register short i;
 		i = ntohs(ip->tot_len) - hdrlen;
@@ -547,11 +584,13 @@
 		break;
 
 	case SPECIAL_D:			/* Unidirectional data */
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): Unidirectional data detected\n");
 		thp->seq = htonl( ntohl(thp->seq) +
 				  ntohs(ip->tot_len) - hdrlen);
 		break;
 
 	default:
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): default packet type detected\n");
 		if(changes & NEW_U){
 			thp->urg = 1;
 			if((x = decode(&cp)) == -1) {
@@ -601,6 +640,7 @@
 	ip->tot_len = htons(len);
 	ip->check = 0;
 
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): making space for the reconstructed header...\n");
 	memmove(icp + hdrlen, cp, len - hdrlen);
 
 	cp = icp;
@@ -625,6 +665,7 @@
 
 	return len;
 bad:
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_uncompress(): bad packet detected!\n");
 	comp->sls_i_error++;
 	return slhc_toss( comp );
 }
@@ -641,6 +682,7 @@
 	if(isize < 20) {
 		/* The packet is shorter than a legal IP header */
 		comp->sls_i_runt++;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): The packet is shorter than a legal IP header ==> slhc_toss()\n");
 		return slhc_toss( comp );
 	}
 	/* Peek at the IP header's IHL field to find its length */
@@ -648,6 +690,7 @@
 	if(ihl < 20 / 4){
 		/* The IP header length field is too small */
 		comp->sls_i_runt++;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): The IP header length field is too small ==> slhc_toss()\n");
 		return slhc_toss( comp );
 	}
 	index = icp[9];
@@ -656,10 +699,12 @@
 	if (ip_fast_csum(icp, ihl)) {
 		/* Bad IP header checksum; discard */
 		comp->sls_i_badcheck++;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): Bad IP header checksum; discard ==> slhc_toss()\n");
 		return slhc_toss( comp );
 	}
 	if(index > comp->rslot_limit) {
 		comp->sls_i_error++;
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_remember(): index > comp->rslot_limit ==> slhc_toss()\n");
 		return slhc_toss(comp);
 	}
 
@@ -683,6 +728,7 @@
 int
 slhc_toss(struct slcompress *comp)
 {
+	LOGP(DSLHC, LOGL_DEBUG, "slhc_toss(): Reset compression state...\n");
 	if ( comp == NULLSLCOMPR )
 		return 0;
 
@@ -690,55 +736,27 @@
 	return 0;
 }
 
-#else /* CONFIG_INET */
-
-int
-slhc_toss(struct slcompress *comp)
+void slhc_i_status(struct slcompress *comp)
 {
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
-  return -EINVAL;
-}
-int
-slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
-  return -EINVAL;
-}
-int
-slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
-	unsigned char *ocp, unsigned char **cpp, int compress_cid)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
-  return -EINVAL;
+	if (comp != NULLSLCOMPR) {
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_i_status(): %d Cmp, %d Uncmp, %d Bad, %d Tossed\n",
+			comp->sls_i_compressed,
+			comp->sls_i_uncompressed,
+			comp->sls_i_error,
+			comp->sls_i_tossed);
+	}
 }
 
-int
-slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
+void slhc_o_status(struct slcompress *comp)
 {
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
-  return -EINVAL;
+	if (comp != NULLSLCOMPR) {
+		LOGP(DSLHC, LOGL_DEBUG, "slhc_o_status(): %d Cmp, %d Uncmp, %d AsIs, %d NotTCP %d Searches, %d Misses\n",
+			comp->sls_o_compressed,
+			comp->sls_o_uncompressed,
+			comp->sls_o_tcp,
+			comp->sls_o_nontcp,
+			comp->sls_o_searches,
+			comp->sls_o_misses);
+	}
 }
 
-void
-slhc_free(struct slcompress *comp)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
-}
-struct slcompress *
-slhc_init(int rslots, int tslots)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
-  return NULL;
-}
-
-#endif /* CONFIG_INET */
-
-/* VJ header compression */
-EXPORT_SYMBOL(slhc_init);
-EXPORT_SYMBOL(slhc_free);
-EXPORT_SYMBOL(slhc_remember);
-EXPORT_SYMBOL(slhc_compress);
-EXPORT_SYMBOL(slhc_uncompress);
-EXPORT_SYMBOL(slhc_toss);
-
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am
index 45d1780..3e66978 100644
--- a/openbsc/tests/sgsn/Makefile.am
+++ b/openbsc/tests/sgsn/Makefile.am
@@ -32,6 +32,7 @@
 	$(top_builddir)/src/gprs/oap_messages.o \
         $(top_builddir)/src/gprs/gprs_llc_xid.o \
 	$(top_builddir)/src/gprs/gprs_sndcp_xid.o \
+        $(top_builddir)/src/gprs/slhc.o \
 	$(top_builddir)/src/libcommon/libcommon.a \
 	$(LIBOSMOABIS_LIBS) \
 	$(LIBOSMOCORE_LIBS) \

-- 
To view, visit https://gerrit.osmocom.org/635
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I7a638e88a43b3eb9d006751a03ef2570e36613f0
Gerrit-PatchSet: 4
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list