aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/sgsn_libgtp.c
diff options
context:
space:
mode:
authorDaniel Willmann <dwillmann@sysmocom.de>2016-05-21 17:35:57 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2016-09-01 23:41:10 +0200
commit6292c8d44d0c5b053518cbdf20b2384090aa03a3 (patch)
treebbf94ae7b5e80f53d752379251ddafca0784cfff /openbsc/src/gprs/sgsn_libgtp.c
parent9bc42ec47b292ce2b51dc1967458e228eb0bf221 (diff)
IuPS: osmo-sgsn: add core IuPS impl, call iu_init()
Add main Iu entry points for IuPS: * gsm0408_gprs_rcvmsg_iu() * sgsn_ranap_iu_event() * sgsn_ranap_rab_ass_resp() Add main MM context management for IuPS: * sgsn_mm_ctx_by_ue_ctx() * sgsn_mm_ctx_alloc_iu() Call iu_init() from sgsn_main.c. Add asn_debug impl ("extern" from libasn1c). Initialize asn_debug VTY command (iu_vty_init()). osmo-sgsn build: add libiu and libasn1c, libosmo-sigtran, libosmo-ranap Change-Id: I469ae6ca9ef254d04ee0d2d79bdd65aebcd027b5
Diffstat (limited to 'openbsc/src/gprs/sgsn_libgtp.c')
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index be7637a85..4a14cf611 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -34,6 +34,8 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include "bscconfig.h"
+
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
@@ -48,6 +50,11 @@
#include <openbsc/gprs_gmm.h>
#include <openbsc/gsm_subscriber.h>
+#ifdef BUILD_IU
+#include <openbsc/iu.h>
+#include <osmocom/ranap/ranap_ies_defs.h>
+#endif
+
#include <gtp.h>
#include <pdp.h>
@@ -218,7 +225,10 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
memcpy(pdp->gsnlc.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
- /* SGSN address for user plane */
+ /* SGSN address for user plane
+ * Default to the control plane addr for now. If we are connected to a
+ * hnbgw via IuPS we'll need to send a PDP context update with the
+ * correct IP address after the RAB Assignment is complete */
pdp->gsnlu.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
memcpy(pdp->gsnlu.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
@@ -383,6 +393,72 @@ reject:
return EOF;
}
+#ifdef BUILD_IU
+/* Callback for RAB assignment response */
+int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies)
+{
+ uint8_t rab_id;
+ bool require_pdp_update = false;
+ struct sgsn_pdp_ctx *pdp = NULL;
+ RANAP_RAB_SetupOrModifiedItem_t *item = &setup_ies->raB_SetupOrModifiedItem;
+
+ rab_id = item->rAB_ID.buf[0];
+
+ pdp = sgsn_pdp_ctx_by_nsapi(ctx, rab_id);
+ if (!pdp) {
+ LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Response for unknown RAB/NSAPI=%u\n", rab_id);
+ return -1;
+ }
+
+ if (item->transportLayerAddress) {
+ LOGPC(DRANAP, LOGL_INFO, " Setup: (%u/%s)", rab_id, osmo_hexdump(item->transportLayerAddress->buf,
+ item->transportLayerAddress->size));
+ switch (item->transportLayerAddress->size) {
+ case 7:
+ /* It must be IPv4 inside a X213 NSAP */
+ memcpy(pdp->lib->gsnlu.v, &item->transportLayerAddress->buf[3], 4);
+ break;
+ case 4:
+ /* It must be a raw IPv4 address */
+ memcpy(pdp->lib->gsnlu.v, item->transportLayerAddress->buf, 4);
+ break;
+ case 16:
+ /* TODO: It must be a raw IPv6 address */
+ case 19:
+ /* TODO: It must be IPv6 inside a X213 NSAP */
+ default:
+ LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Resp: Unknown "
+ "transport layer address size %u\n",
+ item->transportLayerAddress->size);
+ return -1;
+ }
+ require_pdp_update = true;
+ }
+
+ /* The TEI on the RNC side might have changed, too */
+ if (item->iuTransportAssociation &&
+ item->iuTransportAssociation->present == RANAP_IuTransportAssociation_PR_gTP_TEI &&
+ item->iuTransportAssociation->choice.gTP_TEI.buf &&
+ item->iuTransportAssociation->choice.gTP_TEI.size >= 4) {
+ uint32_t tei = osmo_load32be(item->iuTransportAssociation->choice.gTP_TEI.buf);
+ LOGP(DRANAP, LOGL_DEBUG, "Updating TEID on RNC side from 0x%08x to 0x%08x\n",
+ pdp->lib->teid_own, tei);
+ pdp->lib->teid_own = tei;
+ require_pdp_update = true;
+ }
+
+ if (require_pdp_update)
+ gtp_update_context(pdp->ggsn->gsn, pdp->lib, pdp, &pdp->lib->hisaddr0);
+
+ if (pdp->state != PDP_STATE_CR_CONF) {
+ send_act_pdp_cont_acc(pdp);
+ pdp->state = PDP_STATE_CR_CONF;
+ }
+ return 0;
+
+}
+#endif
+
/* Confirmation of a PDP Context Delete */
static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
{