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:
parent
9bc42ec47b
commit
6292c8d44d
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue