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
This commit is contained in:
Daniel Willmann 2016-05-21 17:35:57 +02:00 committed by Neels Hofmeyr
parent 9bc42ec47b
commit 6292c8d44d
7 changed files with 239 additions and 3 deletions

View File

@ -14,6 +14,8 @@ int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable);
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
uint16_t *sai);
int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx);
int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
struct gprs_llc_llme *llme);

View File

@ -226,6 +226,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
const struct gprs_ra_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
/* look-up by matching TLLI and P-TMSI (think twice before using this) */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
@ -234,6 +235,8 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
/* Allocate a new SGSN MM context */
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
const struct gprs_ra_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,

View File

@ -3,6 +3,10 @@ AM_CFLAGS=-Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) $(LIBOSMOGB_CFLAGS) $(COVERAGE_CFLAGS) \
$(LIBCARES_CFLAGS) $(LIBCRYPTO_CFLAGS) $(LIBGTP_CFLAGS)
if BUILD_IU
AM_CFLAGS += $(LIBASN1C_CFLAGS) $(LIBOSMOSIGTRAN_CFLAGS) $(LIBOSMORANAP_CFLAGS)
endif
OSMO_LIBS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
$(LIBOSMOCTRL_LIBS) $(LIBOSMOGB_LIBS)
@ -28,9 +32,15 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \
sgsn_cdr.c sgsn_ares.c \
oap.c oap_messages.c gprs_llc_xid.c
osmo_sgsn_LDADD = \
$(top_builddir)/src/libcommon/libcommon.a \
-lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \
$(top_builddir)/src/libcommon/libcommon.a
if BUILD_IU
osmo_sgsn_LDADD += $(top_builddir)/src/libiu/libiu.a
endif
osmo_sgsn_LDADD += -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \
$(LIBCRYPTO_LIBS) -lrt
if BUILD_IU
osmo_sgsn_LDADD += $(LIBOSMOSIGTRAN_LIBS) $(LIBOSMORANAP_LIBS) $(LIBASN1C_LIBS)
endif
osmo_gtphub_SOURCES = gtphub_main.c gtphub.c gtphub_sock.c gtphub_ares.c \
gtphub_vty.c sgsn_ares.c gprs_utils.c

View File

@ -33,6 +33,8 @@
#include <openssl/rand.h>
#include "bscconfig.h"
#include <openbsc/db.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
@ -45,6 +47,10 @@
#include <osmocom/gprs/gprs_bssgp.h>
#ifdef BUILD_IU
#include <osmocom/ranap/ranap_ies_defs.h>
#endif
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
@ -58,6 +64,10 @@
#include <openbsc/sgsn.h>
#include <openbsc/signal.h>
#ifdef BUILD_IU
#include <openbsc/iu.h>
#endif
#include <pdp.h>
#define PTMSI_ALLOC
@ -97,6 +107,45 @@ static const struct tlv_definition gsm48_sm_att_tlvdef = {
static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx);
#ifdef BUILD_IU
int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies);
int sgsn_ranap_iu_event(struct ue_conn_ctx *ctx, enum iu_event_type type, void *data)
{
struct sgsn_mm_ctx *mm;
int rc = -1;
mm = sgsn_mm_ctx_by_ue_ctx(ctx);
if (!mm) {
LOGP(DRANAP, LOGL_NOTICE, "Cannot find mm ctx for IU event %i!\n", type);
return rc;
}
switch (type) {
case IU_EVENT_RAB_ASSIGN:
rc = sgsn_ranap_rab_ass_resp(mm, (RANAP_RAB_SetupOrModifiedItemIEs_t *)data);
break;
case IU_EVENT_IU_RELEASE:
/* fall thru */
case IU_EVENT_LINK_INVALIDATED:
/* Clean up ue_conn_ctx here */
LOGMMCTXP(LOGL_INFO, mm, "IU release for imsi %s\n", mm->imsi);
rc = 0;
break;
case IU_EVENT_SECURITY_MODE_COMPLETE:
/* Continue authentication here */
mm->iu.ue_ctx->integrity_active = 1;
rc = gsm48_gmm_authorize(mm);
break;
default:
LOGP(DRANAP, LOGL_NOTICE, "Unknown event received: %i\n", type);
rc = -1;
break;
}
return rc;
}
#endif
/* Our implementation, should be kept in SGSN */
static void mmctx_timer_cb(void *_mm);
@ -2193,6 +2242,45 @@ int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx)
return rc;
}
/* Main entry point for incoming 04.08 GPRS messages from Iu */
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
uint16_t *sai)
{
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
uint8_t pdisc = gsm48_hdr_pdisc(gh);
struct sgsn_mm_ctx *mmctx;
int rc = -EINVAL;
mmctx = sgsn_mm_ctx_by_ue_ctx(msg->dst);
if (mmctx) {
rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
if (ra_id)
memcpy(&mmctx->ra, ra_id, sizeof(mmctx->ra));
}
/* MMCTX can be NULL */
switch (pdisc) {
case GSM48_PDISC_MM_GPRS:
rc = gsm0408_rcv_gmm(mmctx, msg, NULL, false);
#warning "set drop_cipherable arg for gsm0408_rcv_gmm() from IuPS?"
break;
case GSM48_PDISC_SM_GPRS:
rc = gsm0408_rcv_gsm(mmctx, msg, NULL);
break;
default:
LOGMMCTXP(LOGL_NOTICE, mmctx,
"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
/* FIXME: return status message */
break;
}
/* MMCTX can be invalid */
return rc;
}
/* Main entry point for incoming 04.08 GPRS messages from Gb */
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable)

View File

@ -39,6 +39,7 @@
#include <openbsc/gprs_utils.h>
#include <openbsc/signal.h>
#include "openbsc/gprs_llc.h"
#include <openbsc/iu.h>
#include <pdp.h>
@ -130,6 +131,20 @@ void sgsn_rate_ctr_init() {
sgsn->rate_ctrs = rate_ctr_group_alloc(tall_bsc_ctx, &sgsn_ctrg_desc, 0);
}
/* look-up an SGSN MM context based on Iu UE context (struct ue_conn_ctx)*/
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx)
{
struct sgsn_mm_ctx *ctx;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
if (ctx->ran_type == MM_CTX_T_UTRAN_Iu
&& uectx == ctx->iu.ue_ctx)
return ctx;
}
return NULL;
}
/* look-up a SGSN MM context based on TLLI + RAI */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
const struct gprs_ra_id *raid)
@ -218,6 +233,32 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
return ctx;
}
/* Allocate a new SGSN MM context */
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx)
{
struct sgsn_mm_ctx *ctx;
ctx = talloc_zero(tall_bsc_ctx, struct sgsn_mm_ctx);
if (!ctx)
return NULL;
ctx->ran_type = MM_CTX_T_UTRAN_Iu;
ctx->iu.ue_ctx = uectx;
ctx->mm_state = GMM_DEREGISTERED;
ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, 0);
/* Need to get RAID from IU conn */
ctx->ra = ctx->iu.ue_ctx->ra_id;
INIT_LLIST_HEAD(&ctx->pdp_list);
llist_add(&ctx->list, &sgsn_mm_ctxts);
return ctx;
}
/* this is a hard _free_ function, it doesn't clean up the PDP contexts
* in libgtp! */
static void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm)

View File

@ -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)
{

View File

@ -56,6 +56,8 @@
#include <openbsc/sgsn.h>
#include <openbsc/gprs_llc.h>
#include <openbsc/gprs_gmm.h>
#include <openbsc/iu.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/ports.h>
@ -300,6 +302,13 @@ static const struct log_info gprs_log_info = {
.num_cat = ARRAY_SIZE(gprs_categories),
};
/* Implement the extern asn_debug from libasn1c to indicate whether the ASN.1
* binary code decoded and encoded during Iu communication should be logged to
* stderr. See osmocom's libasn1c, asn_internal.h, at "if (asn_debug)":
* http://git.osmocom.org/libasn1c/tree/include/asn1c/asn_internal.h */
int asn_debug = 0;
int sgsn_ranap_iu_event(struct ue_conn_ctx *ctx, enum iu_event_type type, void *data);
int main(int argc, char **argv)
{
@ -326,6 +335,9 @@ int main(int argc, char **argv)
osmo_stats_vty_add_cmds(&gprs_log_info);
sgsn_vty_init();
ctrl_vty_init(tall_bsc_ctx);
#ifdef BUILD_IU
iu_vty_init(&asn_debug);
#endif
handle_options(argc, argv);
@ -417,6 +429,10 @@ int main(int argc, char **argv)
}
}
#ifdef BUILD_IU
iu_init(tall_bsc_ctx, "127.0.0.2", 14001, gsm0408_gprs_rcvmsg_iu, sgsn_ranap_iu_event);
#endif
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {