aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gprs_sndcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gprs/gprs_sndcp.c')
-rw-r--r--openbsc/src/gprs/gprs_sndcp.c87
1 files changed, 75 insertions, 12 deletions
diff --git a/openbsc/src/gprs/gprs_sndcp.c b/openbsc/src/gprs/gprs_sndcp.c
index c006d9bcf..0b18f816e 100644
--- a/openbsc/src/gprs/gprs_sndcp.c
+++ b/openbsc/src/gprs/gprs_sndcp.c
@@ -38,6 +38,7 @@
#include <openbsc/gprs_llc_xid.h>
#include <openbsc/gprs_sndcp_xid.h>
#include <openbsc/gprs_sndcp_pcomp.h>
+#include <openbsc/gprs_sndcp_dcomp.h>
#include <openbsc/gprs_sndcp_comp.h>
#define DEBUG_IP_PACKETS 0 /* 0=Disabled, 1=Enabled */
@@ -204,7 +205,8 @@ LLIST_HEAD(gprs_sndcp_entities);
/* Check if any compression parameters are set in the sgsn configuration */
static inline int any_pcomp_or_dcomp_active(struct sgsn_instance *sgsn) {
- if (sgsn->cfg.pcomp_rfc1144.active || sgsn->cfg.pcomp_rfc1144.passive)
+ if (sgsn->cfg.pcomp_rfc1144.active || sgsn->cfg.pcomp_rfc1144.passive ||
+ sgsn->cfg.dcomp_v42bis.active || sgsn->cfg.dcomp_v42bis.passive)
return true;
else
return false;
@@ -324,11 +326,22 @@ static int defrag_segments(struct gprs_sndcp_entity *sne)
#endif
if (any_pcomp_or_dcomp_active(sgsn)) {
- expnd = talloc_zero_size(msg, npdu_len + MAX_HDRDECOMPR_INCR);
+ expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
+ MAX_HDRDECOMPR_INCR);
memcpy(expnd, npdu, npdu_len);
+ /* Apply data decompression */
+ rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
+ sne->defrag.data);
+ if (rc < 0) {
+ LOGP(DSNDCP, LOGL_ERROR,
+ "Data decompression failed!\n");
+ talloc_free(expnd);
+ return -EIO;
+ }
+
/* Apply header decompression */
- rc = gprs_sndcp_pcomp_expand(expnd, npdu_len, sne->defrag.pcomp,
+ rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
sne->defrag.proto);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
@@ -653,6 +666,19 @@ int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi
* the new, compressed buffer size */
msgb_get(msg, msg->len);
msgb_put(msg, rc);
+
+ /* Apply data compression */
+ rc = gprs_sndcp_dcomp_compress(msg->data, msg->len, &dcomp,
+ lle->llme->comp.data, nsapi);
+ if (rc < 0) {
+ LOGP(DSNDCP, LOGL_ERROR, "Data compression failed!\n");
+ return -EIO;
+ }
+
+ /* Fixup pointer locations and sizes in message buffer to match
+ * the new, compressed buffer size */
+ msgb_get(msg, msg->len);
+ msgb_put(msg, rc);
}
#if DEBUG_IP_PACKETS == 1
DEBUGP(DSNDCP, "===================================================\n");
@@ -784,11 +810,22 @@ int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
#endif
if (any_pcomp_or_dcomp_active(sgsn)) {
- expnd = talloc_zero_size(msg, npdu_len + MAX_HDRDECOMPR_INCR);
+ expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
+ MAX_HDRDECOMPR_INCR);
memcpy(expnd, npdu, npdu_len);
+ /* Apply data decompression */
+ rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
+ sne->defrag.data);
+ if (rc < 0) {
+ LOGP(DSNDCP, LOGL_ERROR,
+ "Data decompression failed!\n");
+ talloc_free(expnd);
+ return -EIO;
+ }
+
/* Apply header decompression */
- rc = gprs_sndcp_pcomp_expand(expnd, npdu_len, sne->defrag.pcomp,
+ rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
sne->defrag.proto);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
@@ -884,8 +921,11 @@ static int gprs_llc_gen_sndcp_xid(uint8_t *bytes, int bytes_len, uint8_t nsapi)
LLIST_HEAD(comp_fields);
struct gprs_sndcp_pcomp_rfc1144_params rfc1144_params;
struct gprs_sndcp_comp_field rfc1144_comp_field;
+ struct gprs_sndcp_dcomp_v42bis_params v42bis_params;
+ struct gprs_sndcp_comp_field v42bis_comp_field;
memset(&rfc1144_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
+ memset(&v42bis_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
/* Setup rfc1144 */
if (sgsn->cfg.pcomp_rfc1144.active) {
@@ -903,6 +943,23 @@ static int gprs_llc_gen_sndcp_xid(uint8_t *bytes, int bytes_len, uint8_t nsapi)
llist_add(&rfc1144_comp_field.list, &comp_fields);
}
+ /* Setup V.42bis */
+ if (sgsn->cfg.dcomp_v42bis.active) {
+ v42bis_params.nsapi[0] = nsapi;
+ v42bis_params.nsapi_len = 1;
+ v42bis_params.p0 = sgsn->cfg.dcomp_v42bis.p0;
+ v42bis_params.p1 = sgsn->cfg.dcomp_v42bis.p1;
+ v42bis_params.p2 = sgsn->cfg.dcomp_v42bis.p2;
+ v42bis_comp_field.p = 1;
+ v42bis_comp_field.entity = entity;
+ v42bis_comp_field.algo = V42BIS;
+ v42bis_comp_field.comp[V42BIS_DCOMP1] = 1;
+ v42bis_comp_field.comp_len = V42BIS_DCOMP_NUM;
+ v42bis_comp_field.v42bis_params = &v42bis_params;
+ entity++;
+ llist_add(&v42bis_comp_field.list, &comp_fields);
+ }
+
/* Compile bytestream */
return gprs_sndcp_compile_xid(bytes, bytes_len, &comp_fields);
}
@@ -1008,13 +1065,19 @@ static int handle_dcomp_entities(struct gprs_sndcp_comp_field *comp_field,
/* Process proposed parameters */
switch (comp_field->algo) {
case V42BIS:
- /* V42BIS is not yet supported,
- * so we set applicable nsapis to zero */
- LOGP(DSNDCP, LOGL_DEBUG,
- "Rejecting V.42bis data compression...\n");
- comp_field->v42bis_params->nsapi_len = 0;
- gprs_sndcp_comp_delete(lle->llme->comp.data,
- comp_field->entity);
+ if (sgsn->cfg.dcomp_v42bis.passive &&
+ comp_field->v42bis_params->nsapi_len > 0) {
+ DEBUGP(DSNDCP,
+ "Accepting V.42bis data compression...\n");
+ gprs_sndcp_comp_add(lle->llme, lle->llme->comp.data,
+ comp_field);
+ } else {
+ LOGP(DSNDCP, LOGL_DEBUG,
+ "Rejecting V.42bis data compression...\n");
+ gprs_sndcp_comp_delete(lle->llme->comp.data,
+ comp_field->entity);
+ comp_field->v42bis_params->nsapi_len = 0;
+ }
break;
case V44:
/* V44 is not yet supported,