[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
Thu Aug 11 16:04:12 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 (#12).

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, 814 insertions(+), 2 deletions(-)


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

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..5dafdbb
--- /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 header compressed packet */
+int gprs_sndcp_pcomp_expand(uint8_t *packet, int packet_len, int pcomp,
+			      const struct llist_head *comp_entities);
+
+/* Expand header compressed packet */
+int gprs_sndcp_pcomp_compress(uint8_t *packet, int packet_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..b64d223 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -88,6 +88,13 @@
 
 	int dynamic_lookup;
 
+	/* RFC1144 TCP/IP Header compression */
+	struct {
+		int passive;
+		int active;
+		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..786bcff
--- /dev/null
+++ b/openbsc/src/gprs/gprs_sndcp_pcomp.c
@@ -0,0 +1,300 @@
+/* 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>
+
+/* 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);
+}
+
+
+/* Display compressor status */
+static void gprs_sndcp_pcomp_rfc1144_stat(struct slcompress *comp)
+{
+	slhc_i_status(comp);
+	slhc_o_status(comp);
+}
+
+
+/* Compress a packet using Van Jacobson RFC1144 header compression */
+static int gprs_sndcp_pcomp_rfc1144_compress(struct slcompress *comp,
+					       uint8_t *packet,
+					       int packet_len,
+					       int *pcomp_index)
+{
+	uint8_t *packet_compressed;
+	uint8_t *packet_compressed_ptr;	/* Not used */
+	int packet_compressed_len;
+
+	/* Reserve some space for to store the compression result */
+	packet_compressed = talloc_zero_size(NULL, packet_len);
+
+	/* Run compressor */
+	memcpy(packet_compressed, packet, packet_len);
+	packet_compressed_len =
+	    slhc_compress(comp, packet, packet_len,
+			  (uint8_t *) packet_compressed,
+			  &packet_compressed_ptr, 0);
+
+	/* Copy back compression result */
+	memcpy(packet, packet_compressed, packet_len);
+	talloc_free(packet_compressed);
+
+	/* Generate pcomp_index */
+	if ((packet[0] & SL_TYPE_COMPRESSED_TCP) == SL_TYPE_COMPRESSED_TCP) {
+		*pcomp_index = 2;
+	} else if ((packet[0] & SL_TYPE_UNCOMPRESSED_TCP) ==
+		   SL_TYPE_UNCOMPRESSED_TCP) {
+		*pcomp_index = 1;
+
+		/* Remove tag for uncompressed TCP, because the
+		 * packet type is already define by pcomp */
+		packet[0] &= 0x4F;	
+	} else
+		*pcomp_index = 0;
+
+	return packet_compressed_len;
+}
+
+/* Expand a packet using Van Jacobson RFC1144 header compression */
+static int gprs_sndcp_pcomp_rfc1144_expand(struct slcompress *comp,
+					     uint8_t *packet,
+					     int packet_len,
+					     int pcomp_index)
+{
+	int packet_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 packet type by the PCOMP index */
+	switch (pcomp_index) {
+	case 1:
+		type = SL_TYPE_UNCOMPRESSED_TCP;
+		break;
+	case 2:
+		type = SL_TYPE_COMPRESSED_TCP;
+		break;
+	}
+
+	/* Restore the original version nibble on
+	 * marked uncompressed packets */
+	if (type == SL_TYPE_UNCOMPRESSED_TCP) {
+		LOGP(DSNDCP, LOGL_INFO,
+		     "Uncompressed rfc1144 packet received...\n");
+
+
+		/* Just in case the phone tags uncompressed tcp-packets
+		 * (normally this is handled by pcomp so there is
+		 * no need for tagging the packets) */
+		packet[0] &= 0x4F;
+		packet_decompressed_len =
+		    slhc_remember(comp, packet, packet_len);
+		return packet_decompressed_len;
+	}
+
+	/* Uncompress compressed packets */
+	else if (type == SL_TYPE_COMPRESSED_TCP) {
+		LOGP(DSNDCP, LOGL_INFO,
+		     "Compressed rfc1144 packet received...\n");
+		packet_decompressed_len =
+		    slhc_uncompress(comp, packet, packet_len);
+		return packet_decompressed_len;
+	}
+
+
+	/* Regular or unknown packets will not be touched */
+	return packet_len;
+}
+
+
+/* Expand header compressed packet */
+int gprs_sndcp_pcomp_expand(uint8_t *packet, int packet_len, int pcomp,
+			      const struct llist_head *comp_entities)
+{
+	int rc;
+	int pcomp_index = 0;
+	struct gprs_sndcp_comp *comp_entity;
+
+	/* Skip on pcomp=0 */
+	if (pcomp == 0) {
+		LOGP(DSNDCP, LOGL_INFO,
+		     "Uncompressed packet received (pcomp=0), skipping compression...\n");
+		return packet_len;
+	}
+
+	/* Find out which compression entity handles the packet */
+	comp_entity =
+	    gprs_sndcp_comp_by_comp(comp_entities, pcomp);
+
+	/* Skip compression if no suitable compression entity can be found! */
+	if (comp_entity == NULL) {
+		LOGP(DSNDCP, LOGL_ERROR,
+		     "Compressed packet received (pcomp=%i) but no suitable compression entity found, skipping compression...\n",
+		     pcomp);
+		return packet_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((struct slcompress *)
+					       comp_entity->state, packet,
+					       packet_len, pcomp_index);
+	gprs_sndcp_pcomp_rfc1144_stat((struct slcompress *) comp_entity->
+					state);
+
+
+	LOGP(DSNDCP, LOGL_DEBUG,
+	     "Header expansion done, old length=%i, new length=%i, pcomp=%i, pcomp_index=%i\n",
+	     packet_len, rc, pcomp, pcomp_index);
+
+	return rc;
+}
+
+
+/* Expand header compressed packet */
+int gprs_sndcp_pcomp_compress(uint8_t *packet, int packet_len,
+				int *pcomp,
+				const struct llist_head *comp_entities,
+				int nsapi)
+{
+	int rc;
+	int pcomp_index = 0;
+	struct gprs_sndcp_comp *comp_entity;
+
+	/* Find out which compression entity handles the packet */
+	comp_entity = gprs_sndcp_comp_by_nsapi(comp_entities, nsapi);
+
+	/* Skip compression if no suitable compression entity can be found! */
+	if (comp_entity == NULL) {
+		LOGP(DSNDCP, LOGL_INFO,
+		     "No suitable compression entity found for nsapi %i, skipping compression...\n",
+		     nsapi);
+		*pcomp = 0;
+		return packet_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((struct slcompress *)
+						 comp_entity->state,
+						 packet, packet_len,
+						 &pcomp_index);
+	gprs_sndcp_pcomp_rfc1144_stat((struct slcompress *) 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, pcomp=%i, pcomp_index=%i\n",
+	     packet_len, rc, *pcomp, pcomp_index);
+	return rc;
+}
+
+
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index e6dc68d..2cbf002 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -269,6 +269,19 @@
 	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.passive && g_cfg->pcomp_rfc1144.active) {
+		vty_out(vty, " compression rfc1144 negotiation both s01 %d%s",
+			    g_cfg->pcomp_rfc1144.s01, VTY_NEWLINE);
+	} else if (g_cfg->pcomp_rfc1144.passive) {
+		vty_out(vty, " compression rfc1144 negotiation passive s01 %d%s",
+			    g_cfg->pcomp_rfc1144.s01, VTY_NEWLINE);
+	} else if (g_cfg->pcomp_rfc1144.active) {
+		vty_out(vty, " compression rfc1144 negotiation active s01 %d%s",
+			    g_cfg->pcomp_rfc1144.s01, VTY_NEWLINE);
+	} else {
+		vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
+	}
+
 	return CMD_SUCCESS;
 }
 
@@ -1074,6 +1087,41 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
+      "no compression rfc1144",
+      NO_STR "disable rfc1144 TCP/IP header compression\n")
+{
+	g_cfg->pcomp_rfc1144.active = 0;
+	g_cfg->pcomp_rfc1144.passive = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
+      "compression rfc1144 negotiation (active|passive|both) s01 <0-255>",
+      NO_STR "GPRS compression scheme\n")
+{
+	switch (argv[0][0]) {
+	case 'a':
+		g_cfg->pcomp_rfc1144.active = 1;
+		g_cfg->pcomp_rfc1144.passive = 0;
+	break;
+	case 'p':
+		g_cfg->pcomp_rfc1144.active = 0;
+		g_cfg->pcomp_rfc1144.passive = 1;
+	break;
+	case 'b':
+		g_cfg->pcomp_rfc1144.active = 1;
+		g_cfg->pcomp_rfc1144.passive = 1;
+	break;
+	default:
+		g_cfg->pcomp_rfc1144.active = 0;
+		g_cfg->pcomp_rfc1144.passive = 0;
+	}
+
+	g_cfg->pcomp_rfc1144.s01 = atoi(argv[1]);
+	return CMD_SUCCESS;
+}
+
 int sgsn_vty_init(void)
 {
 	install_element_ve(&show_sgsn_cmd);
@@ -1128,6 +1176,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: 12
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