[PATCH] openbsc[master]: Adding compression control

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
Tue Aug 16 15:37:37 UTC 2016


Hello Harald Welte, Jenkins Builder,

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

    https://gerrit.osmocom.org/642

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

Adding compression control

In this commit two modules were added:

gprs_sndcp_comp.h/c: This part handles the creation and
destruction of conpression entites. It handles the allocation
and freeing of the memory and offers functions to query
compression parameters (i.e. which compression entity should
be used if a packet from NSAPI x has to be compressed?)

gprs_sndcp_pcomp.c/h: This is the code that performs the
actual header compression. It takes care that the packets are
compressed/decompressed with the right modes etc.

It works, but is not yet ready for merging. Both files depend
on each other so that they only can be merged both at the same
time.

Change-Id: Ia00260dc09978844c2865957b4d43000b78b5e43
---
M openbsc/include/openbsc/Makefile.am
A openbsc/include/openbsc/gprs_sndcp_comp.h
A openbsc/include/openbsc/gprs_sndcp_pcomp.h
M openbsc/include/openbsc/sgsn.h
M openbsc/src/gprs/Makefile.am
A openbsc/src/gprs/gprs_sndcp_comp.c
A openbsc/src/gprs/gprs_sndcp_pcomp.c
M openbsc/src/gprs/sgsn_vty.c
M openbsc/tests/sgsn/Makefile.am
9 files changed, 827 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/42/642/13

diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index f402fea..88a7e2c 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -19,7 +19,7 @@
 		 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 \
-		slhc.h
+		slhc.h gprs_sndcp_comp.h gprs_sndcp_pcomp.h
 
 openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
 openbscdir = $(includedir)/openbsc
diff --git a/openbsc/include/openbsc/gprs_sndcp_comp.h b/openbsc/include/openbsc/gprs_sndcp_comp.h
new file mode 100644
index 0000000..e2d79ab
--- /dev/null
+++ b/openbsc/include/openbsc/gprs_sndcp_comp.h
@@ -0,0 +1,85 @@
+/* GPRS SNDCP header compression entity management tools */
+
+/* (C) 2016 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _GPRS_SNDCP_COMP_H
+#define _GPRS_SNDCP_COMP_H
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <openbsc/gprs_sndcp_xid.h>
+
+/* Header / Data compression entity */
+struct gprs_sndcp_comp {
+	struct llist_head list;
+
+	/* Serves as an ID in case we want to delete this entity later */
+	int entity;		/* see also: 6.5.1.1.3 and 6.6.1.1.3 */
+
+	/* Specifies to which NSAPIs the compression entity is assigned */
+	int nsapi_len;		/* Number of applicable NSAPIs (default 0) */
+	int nsapi[11];		/* Applicable NSAPIs (default 0) */
+
+	/* Assigned pcomp values */
+	int comp_len;		/* Number of contained PCOMP / DCOMP values */
+	int comp[16];		/* see also: 6.5.1.1.5 and 6.6.1.1.5 */
+
+	/* Algorithm parameters */
+	int algo;		/* Algorithm type (see gprs_sndcp_xid.h) */
+	int compclass;		/* See gprs_sndcp_xid.h/c */
+	void *state;		/* Algorithm status and parameters */
+};
+
+/* Free a list with compression entities */
+void gprs_sndcp_comp_free(struct llist_head *comp_entities);
+
+/* Delete a compression entity */
+void gprs_sndcp_comp_delete(struct llist_head *comp_entities, int entity);
+
+/* Create and Add a new compression entity
+ * (returns a pointer to the compression entity that has just been created) */
+struct gprs_sndcp_comp *gprs_sndcp_comp_entities_add(const void *ctx, struct
+						     llist_head
+						     *comp_entities, const struct
+						     gprs_sndcp_comp_field
+						     *comp_field);
+
+/* Find compression entity by its entity number */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_entity(const struct llist_head
+						  *comp_entities, int entity);
+
+/* Find which compression entity handles the specified pcomp/dcomp */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_comp(const struct llist_head
+						*comp_entities, int comp);
+
+/* Find which compression entity handles the specified nsapi */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_nsapi(const struct llist_head
+						 *comp_entities, int nsapi);
+
+/* Find a comp_index for a given pcomp/dcomp value */
+int gprs_sndcp_comp_get_idx(const struct gprs_sndcp_comp
+			    *comp_entity, int comp);
+
+/* Find a pcomp/dcomp value for a given comp_index */
+int gprs_sndcp_comp_get_comp(const struct gprs_sndcp_comp
+			     *comp_entity, int comp_index);
+
+#endif
diff --git a/openbsc/include/openbsc/gprs_sndcp_pcomp.h b/openbsc/include/openbsc/gprs_sndcp_pcomp.h
new file mode 100644
index 0000000..2444260
--- /dev/null
+++ b/openbsc/include/openbsc/gprs_sndcp_pcomp.h
@@ -0,0 +1,47 @@
+/* GPRS SNDCP header compression handler */
+
+/* (C) 2016 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _GPRS_SNDCP_pcomp_H
+#define _GPRS_SNDCP_pcomp_H
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <openbsc/gprs_sndcp_comp.h>
+
+/* Initalize header compression */
+int gprs_sndcp_pcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
+			    const struct gprs_sndcp_comp_field *comp_field);
+
+/* Terminate header compression */
+void gprs_sndcp_pcomp_term(struct gprs_sndcp_comp *comp_entity);
+
+/* Expand packet header */
+int gprs_sndcp_pcomp_expand(uint8_t *data_o, uint8_t *data_i, int len,
+			    int pcomp, const struct llist_head *comp_entities);
+
+/* Compress packet header */
+int gprs_sndcp_pcomp_compress(uint8_t *data_o, uint8_t *data_i, int len,
+			      int *pcomp,
+			      const struct llist_head *comp_entities,
+			      int nsapi);
+
+#endif
diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h
index 59126fe..2366d7a 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -88,6 +88,12 @@
 
 	int dynamic_lookup;
 
+	/* RFC1144 TCP/IP Header compression */
+	struct {
+		int enabled;
+		int s01;
+	} pcomp_rfc1144;
+
 	struct oap_config oap;
 };
 
diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am
index 245636b..2910c02 100644
--- a/openbsc/src/gprs/Makefile.am
+++ b/openbsc/src/gprs/Makefile.am
@@ -27,7 +27,7 @@
 			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 \
-			slhc.c
+			slhc.c gprs_sndcp_comp.c gprs_sndcp_pcomp.c
 osmo_sgsn_LDADD = 	\
 			$(top_builddir)/src/libcommon/libcommon.a \
 			-lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \
diff --git a/openbsc/src/gprs/gprs_sndcp_comp.c b/openbsc/src/gprs/gprs_sndcp_comp.c
new file mode 100644
index 0000000..8153fd2
--- /dev/null
+++ b/openbsc/src/gprs/gprs_sndcp_comp.c
@@ -0,0 +1,320 @@
+/* GPRS SNDCP header compression entity management tools */
+
+/* (C) 2016 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <math.h>
+#include <errno.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+
+#include <openbsc/debug.h>
+#include <openbsc/gprs_sndcp_xid.h>
+#include <openbsc/gprs_sndcp_comp.h>
+#include <openbsc/gprs_sndcp_pcomp.h>
+
+/* Create a new compression entity from a XID-Field */
+static struct gprs_sndcp_comp *gprs_sndcp_comp_create(const void
+						      *ctx, const struct
+						      gprs_sndcp_comp_field
+						      *comp_field)
+{
+	OSMO_ASSERT(comp_field);
+
+	struct gprs_sndcp_comp *comp_entity;
+	comp_entity = talloc_zero(ctx, struct gprs_sndcp_comp);
+
+	/* Copy relevant information from the SNDCP-XID field */
+	comp_entity->entity = comp_field->entity;
+	comp_entity->comp_len = comp_field->comp_len;
+	memcpy(comp_entity->comp, comp_field->comp,
+	       comp_field->comp_len * sizeof(int));
+
+	if (comp_field->rfc1144_params) {
+		comp_entity->nsapi_len = comp_field->rfc1144_params->nsapi_len;
+		memcpy(comp_entity->nsapi,
+		       comp_field->rfc1144_params->nsapi,
+		       comp_entity->nsapi_len * sizeof(int));
+	} else if (comp_field->rfc2507_params) {
+		comp_entity->nsapi_len = comp_field->rfc2507_params->nsapi_len;
+		memcpy(comp_entity->nsapi,
+		       comp_field->rfc2507_params->nsapi,
+		       comp_entity->nsapi_len * sizeof(int));
+	} else if (comp_field->rohc_params) {
+		comp_entity->nsapi_len = comp_field->rohc_params->nsapi_len;
+		memcpy(comp_entity->nsapi, comp_field->rohc_params->nsapi,
+		       comp_entity->nsapi_len * sizeof(int));
+	} else if (comp_field->v42bis_params) {
+		comp_entity->nsapi_len = comp_field->v42bis_params->nsapi_len;
+		memcpy(comp_entity->nsapi,
+		       comp_field->v42bis_params->nsapi,
+		       comp_entity->nsapi_len * sizeof(int));
+	} else if (comp_field->v44_params) {
+		comp_entity->nsapi_len = comp_field->v42bis_params->nsapi_len;
+		memcpy(comp_entity->nsapi,
+		       comp_field->v42bis_params->nsapi,
+		       comp_entity->nsapi_len * sizeof(int));
+	} else {
+		talloc_free(comp_entity);
+		LOGP(DSNDCP, LOGL_ERROR,
+		     "Comp field contained invalid parameters, compression entity not created!\n");
+		return NULL;
+	}
+
+	comp_entity->algo = comp_field->algo;
+	comp_entity->state = NULL;
+
+	/* Determine of which class our compression entity will be
+	 * (Protocol or Data compresson ?) */
+	comp_entity->compclass = gprs_sndcp_get_compression_class(comp_field);
+
+	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
+		if (gprs_sndcp_pcomp_init(ctx, comp_entity, comp_field) == 0)
+			LOGP(DSNDCP, LOGL_INFO,
+			     "New header compression entity (%i) created.\n",
+			     comp_entity->entity);
+		else {
+			talloc_free(comp_entity);
+			LOGP(DSNDCP, LOGL_ERROR,
+			     "Header compression entity (%i) creation failed!\n",
+			     comp_entity->entity);
+			return NULL;
+		}
+	} else {
+		LOGP(DSNDCP, LOGL_INFO,
+		     "New data compression entity (%i) created.\n",
+		     comp_entity->entity);
+	}
+
+	return comp_entity;
+}
+
+/* Free a list with compression entities */
+void gprs_sndcp_comp_free(struct llist_head *comp_entities)
+{
+	struct llist_head *ce, *ce2;
+	struct gprs_sndcp_comp *comp_entity;
+
+	OSMO_ASSERT(comp_entities);
+
+	llist_for_each_entry(comp_entity, comp_entities, list) {
+		/* Free compression entity */
+		if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
+			LOGP(DSNDCP, LOGL_INFO,
+			     "Deleting header compression entity %i ...\n",
+			     comp_entity->entity);
+			gprs_sndcp_pcomp_term(comp_entity);
+		} else {
+			LOGP(DSNDCP, LOGL_INFO,
+			     "Deleting data compression entity %i ...\n",
+			     comp_entity->entity);
+		}
+	}
+
+	llist_for_each_safe(ce, ce2, comp_entities) {
+		llist_del(ce);
+		talloc_free(ce);
+	}
+
+}
+
+/* Delete a compression entity */
+void gprs_sndcp_comp_delete(struct llist_head *comp_entities, int entity)
+{
+	struct gprs_sndcp_comp *comp_entity;
+	struct gprs_sndcp_comp *comp_entity_to_delete = NULL;
+
+	OSMO_ASSERT(comp_entities);
+
+	llist_for_each_entry(comp_entity, comp_entities, list) {
+		if (comp_entity->entity == entity)
+			comp_entity_to_delete = comp_entity;
+	}
+
+	if (comp_entity_to_delete) {
+		if (comp_entity_to_delete->compclass ==
+		    SNDCP_XID_PROTOCOL_COMPRESSION) {
+			LOGP(DSNDCP, LOGL_INFO,
+			     "Deleting header compression entity %i ...\n",
+			     comp_entity_to_delete->entity);
+			gprs_sndcp_pcomp_term(comp_entity_to_delete);
+		} else {
+			LOGP(DSNDCP, LOGL_INFO,
+			     "Deleting data compression entity %i ...\n",
+			     comp_entity_to_delete->entity);
+		}
+
+		/* Delete compression entity */
+		llist_del(&comp_entity_to_delete->list);
+		talloc_free(comp_entity_to_delete);
+	}
+
+}
+
+/* Create and Add a new compression entity
+ * (returns a pointer to the compression entity that has just been created) */
+struct gprs_sndcp_comp *gprs_sndcp_comp_entities_add(const void *ctx, struct
+						     llist_head
+						     *comp_entities, const struct
+						     gprs_sndcp_comp_field
+						     *comp_field)
+{
+	struct gprs_sndcp_comp *comp_entity;
+
+	OSMO_ASSERT(comp_entities);
+	OSMO_ASSERT(comp_field);
+
+	/* Just to be sure, if the entity is already in
+	 * the list it will be deleted now */
+	gprs_sndcp_comp_delete(comp_entities, comp_field->entity);
+
+	/* Create and add a new entity to the list */
+	comp_entity = gprs_sndcp_comp_create(ctx, comp_field);
+
+	if (comp_entity) {
+		llist_add(&comp_entity->list, comp_entities);
+		return comp_entity;
+	}
+
+	return NULL;
+}
+
+/* Find compression entity by its entity number */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_entity(const struct
+						  llist_head
+						  *comp_entities, int entity)
+{
+	struct gprs_sndcp_comp *comp_entity;
+
+	OSMO_ASSERT(comp_entities);
+
+	llist_for_each_entry(comp_entity, comp_entities, list) {
+		if (comp_entity->entity == entity)
+			return comp_entity;
+	}
+
+	LOGP(DSNDCP, LOGL_ERROR,
+	     "Could not find a matching compression entity for given entity number %i.\n",
+	     entity);
+	return NULL;
+}
+
+/* Find which compression entity handles the specified pcomp/dcomp */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_comp(const struct
+						llist_head
+						*comp_entities, int comp)
+{
+	struct gprs_sndcp_comp *comp_entity;
+	int i;
+
+	OSMO_ASSERT(comp_entities);
+
+	llist_for_each_entry(comp_entity, comp_entities, list) {
+		for (i = 0; i < comp_entity->comp_len; i++) {
+			if (comp_entity->comp[i] == comp)
+				return comp_entity;
+		}
+	}
+
+	LOGP(DSNDCP, LOGL_ERROR,
+	     "Could not find a matching compression entity for given pcomp/dcomp value %i.\n",
+	     comp);
+	return NULL;
+}
+
+/* Find which compression entity handles the specified nsapi */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_nsapi(const struct
+						 llist_head
+						 *comp_entities, int nsapi)
+{
+	struct gprs_sndcp_comp *comp_entity;
+	int i;
+
+	OSMO_ASSERT(comp_entities);
+
+	llist_for_each_entry(comp_entity, comp_entities, list) {
+		for (i = 0; i < comp_entity->nsapi_len; i++) {
+			if (comp_entity->nsapi[i] == nsapi)
+				return comp_entity;
+		}
+	}
+
+	LOGP(DSNDCP, LOGL_ERROR,
+	     "Could not find a matching compression entity for given nsapi value %i\n",
+	     nsapi);
+	return NULL;
+
+}
+
+/* Find a comp_index for a given pcomp/dcomp value */
+int gprs_sndcp_comp_get_idx(const struct
+			    gprs_sndcp_comp
+			    *comp_entity, int comp)
+{
+	int i;
+
+	OSMO_ASSERT(comp_entity);
+
+	/* A pcomp/dcomp field set to zero always disables
+	 * all sort of compression and is assigned fix. So we
+	 * just return zero in this case */
+	if (comp == 0)
+		return 0;
+
+	/* Look in the pcomp/dcomp list for the index */
+	for (i = 0; i < comp_entity->comp_len; i++) {
+		if (comp_entity->comp[i] == comp)
+			return i + 1;
+	}
+
+	LOGP(DSNDCP, LOGL_ERROR,
+	     "Could not find a matching comp_index for given pcomp/dcomp value %i\n",
+	     comp);
+	return 0;
+
+}
+
+/* Find a pcomp/dcomp value for a given comp_index */
+int gprs_sndcp_comp_get_comp(const struct
+			     gprs_sndcp_comp
+			     *comp_entity, int comp_index)
+{
+	OSMO_ASSERT(comp_entity);
+
+	/* A comp_index of zero translates to zero right away. */
+	if (comp_index == 0)
+		return 0;
+
+	if (comp_index > comp_entity->comp_len) {
+		LOGP(DSNDCP, LOGL_ERROR,
+		     "Could not find a matching pcomp/dcomp value for given comp_index value %i.\n",
+		     comp_index);
+		return 0;
+	}
+
+	/* Look in the pcomp/dcomp list for the comp_index */
+	return comp_entity->comp[comp_index - 1];
+
+}
diff --git a/openbsc/src/gprs/gprs_sndcp_pcomp.c b/openbsc/src/gprs/gprs_sndcp_pcomp.c
new file mode 100644
index 0000000..41f6c6a
--- /dev/null
+++ b/openbsc/src/gprs/gprs_sndcp_pcomp.c
@@ -0,0 +1,334 @@
+/* GPRS SNDCP header compression handler */
+
+/* (C) 2016 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <math.h>
+#include <errno.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/tlv.h>
+
+#include <openbsc/gprs_llc.h>
+#include <openbsc/sgsn.h>
+#include <openbsc/gprs_sndcp_xid.h>
+#include <openbsc/slhc.h>
+#include <openbsc/debug.h>
+#include <openbsc/gprs_sndcp_comp.h>
+#include <openbsc/gprs_sndcp_pcomp.h>
+
+#define DEBUG_RFC1144 1
+
+/* Show details of the RFC1144 compressed packet header */
+static void debug_rfc1144_header(uint8_t *header)
+{
+#if DEBUG_RFC1144 == 1
+
+	int t,c,i,p,s,a,w,u = 0;
+	t = (header[0] >> 7) & 1;
+	c = (header[0] >> 6) & 1;
+	i = (header[0] >> 5) & 1;
+	p = (header[0] >> 4) & 1;
+	s = (header[0] >> 3) & 1;
+	a = (header[0] >> 2) & 1;
+	w = (header[0] >> 1) & 1;
+	u = header[0] & 1;
+
+	DEBUGP(DSNDCP,"rfc1144 header:\n");
+	DEBUGP(DSNDCP," Tag bit = %d\n",t);
+	DEBUGP(DSNDCP," C = %d\n",c);
+	DEBUGP(DSNDCP," I = %d\n",i);
+	DEBUGP(DSNDCP," P = %d\n",p);
+	DEBUGP(DSNDCP," S = %d\n",s);
+	DEBUGP(DSNDCP," A = %d\n",a);
+	DEBUGP(DSNDCP," W = %d\n",w);
+	DEBUGP(DSNDCP," U = %d\n",u);
+
+	header++;
+	if(c) {
+		DEBUGP(DSNDCP," Connection number (C) = %d\n",*header);
+		header++;
+	}
+
+	DEBUGP(DSNDCP," TCP Checksum = %02x%02x\n",header[0],header[1]);
+	header+=2;
+
+	if(s && w && u)	{
+		DEBUGP(DSNDCP," Special case I (SPECIAL_I) => short header\n");
+		return;
+	} else if(s && a && w && u) {
+		DEBUGP(DSNDCP," Special case D (SPECIAL_D) => short header\n");
+		return;
+	}
+
+	if(u) {
+		DEBUGP(DSNDCP," Urgent Pointer (U) = %02x\n",*header);
+		header++;
+	}
+	if(w) {
+		DEBUGP(DSNDCP," Delta Window (W) = %02x\n",*header);
+		header++;
+	}
+	if(a) {
+		DEBUGP(DSNDCP," Delta Ack (A) = %02x\n",*header);
+		header++;
+	}
+	if(s) {
+		DEBUGP(DSNDCP," Delta Sequence (S) = %02x\n",*header);
+		header++;
+	}
+	if(i) {
+		DEBUGP(DSNDCP," Delta IP ID (I) = %02x\n",*header);
+		header++;
+	}
+
+	/* FIXME: Header values will be usually fit in 8 bits, implement
+	 * implement variable length decoding for values larger then 8 bit */
+#endif
+}
+
+
+/* Initalize header compression */
+int gprs_sndcp_pcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
+			  const struct gprs_sndcp_comp_field *comp_field)
+{
+	/* Note: This function is automatically called from
+	 * gprs_sndcp_comp.c when a new header compression
+	 * entity is created by gprs_sndcp.c */
+
+	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION
+	    && comp_entity->algo == RFC_1144) {
+		comp_entity->state =
+		    slhc_init(ctx, comp_field->rfc1144_params->s01 + 1,
+			      comp_field->rfc1144_params->s01 + 1);
+		LOGP(DSNDCP, LOGL_INFO,
+		     "RFC1144 header compression initalized.\n");
+		return 0;
+	}
+
+	/* Just in case someone tries to initalize an unknown or unsupported
+	 * header compresson. Since everything is checked during the SNDCP
+	 * negotiation process, this should never happen! */
+	OSMO_ASSERT(false);
+}
+
+/* Terminate header compression */
+void gprs_sndcp_pcomp_term(struct gprs_sndcp_comp *comp_entity)
+{
+	/* Note: This function is automatically called from
+	 * gprs_sndcp_comp.c when a header compression
+	 * entity is deleted by gprs_sndcp.c */
+
+	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION
+	    && comp_entity->algo == RFC_1144) {
+		if (comp_entity->state) {
+			slhc_free((struct slcompress *)comp_entity->state);
+			comp_entity->state = NULL;
+		}
+		LOGP(DSNDCP, LOGL_INFO,
+		     "RFC1144 header compression terminated.\n");
+		return;
+	}
+
+	/* Just in case someone tries to initalize an unknown or unsupported
+	 * header compresson. Since everything is checked during the SNDCP
+	 * negotiation process, this should never happen! */
+	OSMO_ASSERT(false);
+}
+
+/* Compress a packet using Van Jacobson RFC1144 header compression */
+static int gprs_sndcp_pcomp_rfc1144_compress(int *pcomp_index, uint8_t *data_o,
+					     uint8_t *data_i, int len,
+					     struct slcompress *comp)
+{
+	uint8_t *comp_ptr;	/* Not used */
+	int compr_len;
+
+	/* Create a working copy of the incoming data */
+	memcpy(data_o, data_i, len);
+
+	/* Run compressor */
+	compr_len = slhc_compress(comp, data_i, len, data_o, &comp_ptr, 0);
+
+	/* Generate pcomp_index */
+	if (data_o[0] & SL_TYPE_COMPRESSED_TCP) {
+		*pcomp_index = 2;
+		data_o[0] &= ~SL_TYPE_COMPRESSED_TCP;
+		debug_rfc1144_header(data_o);
+	} else if ((data_o[0] & SL_TYPE_UNCOMPRESSED_TCP) ==
+		   SL_TYPE_UNCOMPRESSED_TCP) {
+		*pcomp_index = 1;
+		data_o[0] &= 0x4F;
+	} else
+		*pcomp_index = 0;
+
+	return compr_len;
+}
+
+/* Expand a packet using Van Jacobson RFC1144 header compression */
+static int gprs_sndcp_pcomp_rfc1144_expand(uint8_t *data_o, uint8_t *data_i,
+					   int len, int pcomp_index,
+					   struct slcompress *comp)
+{
+	int data_decompressed_len;
+	int type = -1;
+
+	/* Note: this function should never be called with pcomp_index=0,
+	 * since this condition is already filtered
+	 * out by gprs_sndcp_pcomp_expand() */
+
+	/* Determine the data type by the PCOMP index */
+	switch (pcomp_index) {
+	case 1:
+		type = SL_TYPE_UNCOMPRESSED_TCP;
+		break;
+	case 2:
+		type = SL_TYPE_COMPRESSED_TCP;
+		break;
+	}
+
+	/* Create a working copy of the incoming data */
+	memcpy(data_o, data_i, len);
+
+	/* Restore the original version nibble on
+	 * marked uncompressed packets */
+	if (type == SL_TYPE_UNCOMPRESSED_TCP) {
+
+		/* Just in case the phone tags uncompressed tcp-datas
+		 * (normally this is handled by pcomp so there is
+		 * no need for tagging the datas) */
+		data_o[0] &= 0x4F;
+		data_decompressed_len = slhc_remember(comp, data_o, len);
+		return data_decompressed_len;
+	}
+
+	/* Uncompress compressed packets */
+	else if (type == SL_TYPE_COMPRESSED_TCP) {
+		data_decompressed_len = slhc_uncompress(comp, data_o, len);
+		return data_decompressed_len;
+	}
+
+	/* Regular or unknown packets will not be touched */
+	return len;
+}
+
+/* Expand packet header */
+int gprs_sndcp_pcomp_expand(uint8_t *data_o, uint8_t *data_i, int len,
+			    int pcomp, const struct llist_head *comp_entities)
+{
+	int rc;
+	int pcomp_index = 0;
+	struct gprs_sndcp_comp *comp_entity;
+
+	OSMO_ASSERT(data_o);
+	OSMO_ASSERT(data_i);
+	OSMO_ASSERT(comp_entities);
+
+	/* Skip on pcomp=0 */
+	if (pcomp == 0) {
+		memcpy(data_o,data_i,len);
+		return len;
+	}
+
+	/* Find out which compression entity handles the data */
+	comp_entity = gprs_sndcp_comp_by_comp(comp_entities, pcomp);
+
+	/* Skip compression if no suitable compression entity can be found */
+	if (comp_entity == NULL) {
+		memcpy(data_o,data_i,len);
+		return len;
+	}
+
+	/* Note: Only protocol compression entities may appear in
+	 * protocol compression context */
+	OSMO_ASSERT(comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION);
+
+	/* Note: Currently RFC1144 is the only compression method we
+	 * support, so the only allowed algorithm is RFC1144 */
+	OSMO_ASSERT(comp_entity->algo == RFC_1144);
+
+	/* Find pcomp_index */
+	pcomp_index = gprs_sndcp_comp_get_idx(comp_entity, pcomp);
+
+	/* Run decompression algo */
+	rc = gprs_sndcp_pcomp_rfc1144_expand(data_o, data_i, len, pcomp_index,
+					     comp_entity->state);
+	slhc_i_status(comp_entity->state);
+	slhc_o_status(comp_entity->state);
+
+	LOGP(DSNDCP, LOGL_DEBUG,
+	     "Header expansion done, old length=%i, new length=%i\n",
+	     len, rc);
+
+	return rc;
+}
+
+/* Compress packet header */
+int gprs_sndcp_pcomp_compress(uint8_t *data_o, uint8_t *data_i, int len,
+			      int *pcomp,
+			      const struct llist_head *comp_entities, int nsapi)
+{
+	int rc;
+	int pcomp_index = 0;
+	struct gprs_sndcp_comp *comp_entity;
+
+	OSMO_ASSERT(data_o);
+	OSMO_ASSERT(data_i);
+	OSMO_ASSERT(pcomp);
+	OSMO_ASSERT(comp_entities);
+
+	/* Find out which compression entity handles the data */
+	comp_entity = gprs_sndcp_comp_by_nsapi(comp_entities, nsapi);
+
+	/* Skip compression if no suitable compression entity can be found */
+	if (!comp_entity) {
+		*pcomp = 0;
+		memcpy(data_o,data_i,len);
+		return len;
+	}
+
+	/* Note: Only protocol compression entities may appear in
+	 * protocol compression context */
+	OSMO_ASSERT(comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION);
+
+	/* Note: Currently RFC1144 is the only compression method we
+	 * support, so the only allowed algorithm is RFC1144 */
+	OSMO_ASSERT(comp_entity->algo == RFC_1144);
+
+	/* Run compression algo */
+	rc = gprs_sndcp_pcomp_rfc1144_compress(&pcomp_index, data_o, data_i,
+					       len, comp_entity->state);
+	slhc_i_status(comp_entity->state);
+	slhc_o_status(comp_entity->state);
+
+	/* Find pcomp value */
+	*pcomp = gprs_sndcp_comp_get_comp(comp_entity, pcomp_index);
+
+	LOGP(DSNDCP, LOGL_DEBUG,
+	     "Header compression done, old length=%i, new length=%i\n",
+	     len, rc);
+	return rc;
+}
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index e6dc68d..aae1acb 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -269,6 +269,13 @@
 	vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
 	vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
 
+	if (g_cfg->pcomp_rfc1144.enabled) {
+		vty_out(vty, " compression rfc1144 slots %d%s",
+			    g_cfg->pcomp_rfc1144.s01+1, VTY_NEWLINE);
+	} else {
+		vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
+	}
+
 	return CMD_SUCCESS;
 }
 
@@ -1074,6 +1081,27 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
+      "no compression rfc1144",
+      NO_STR "compression\n"
+      "disable rfc1144 TCP/IP header compression\n")
+{
+	g_cfg->pcomp_rfc1144.enabled = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
+      "compression rfc1144 slots <1-256>",
+      "Configure compression\n"
+      "RFC1144 Header compresion scheme\n"
+      "Number of compression state slots\n"
+      "number\n")
+{
+	g_cfg->pcomp_rfc1144.enabled = 0;
+	g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
+	return CMD_SUCCESS;
+}
+
 int sgsn_vty_init(void)
 {
 	install_element_ve(&show_sgsn_cmd);
@@ -1128,6 +1156,9 @@
 	install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
 	install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
 
+	install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
+	install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
+
 	return 0;
 }
 
diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am
index 3e66978..1804280 100644
--- a/openbsc/tests/sgsn/Makefile.am
+++ b/openbsc/tests/sgsn/Makefile.am
@@ -33,6 +33,8 @@
         $(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/gprs/gprs_sndcp_comp.o \
+        $(top_builddir)/src/gprs/gprs_sndcp_pcomp.o \
 	$(top_builddir)/src/libcommon/libcommon.a \
 	$(LIBOSMOABIS_LIBS) \
 	$(LIBOSMOCORE_LIBS) \

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

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ia00260dc09978844c2865957b4d43000b78b5e43
Gerrit-PatchSet: 13
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