From 9c534fdbe8289ccfbf5d2d586acb38fff945aecd Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 12 Oct 2015 11:57:37 +0200 Subject: [PATCH] gsup/oap: add OAP to GSUP client. Trigger an OAP registration upon IPA connect. Feed incoming OAP messages to oap_handle() and send replies returned by it. Add oap_config to sgsn_config (todo: vty). Sponsored-by: On-Waves ehf [hfreyther: Fix coding style] --- openbsc/include/openbsc/gprs_gsup_client.h | 7 ++- openbsc/include/openbsc/sgsn.h | 3 ++ openbsc/src/gprs/gprs_gsup_client.c | 55 +++++++++++++++++++--- openbsc/src/gprs/gprs_subscriber.c | 3 +- openbsc/tests/sgsn/Makefile.am | 2 + 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gsup_client.h b/openbsc/include/openbsc/gprs_gsup_client.h index 9537db4c7..ccfa388bc 100644 --- a/openbsc/include/openbsc/gprs_gsup_client.h +++ b/openbsc/include/openbsc/gprs_gsup_client.h @@ -23,6 +23,8 @@ #include +#include + #define GPRS_GSUP_RECONNECT_INTERVAL 10 #define GPRS_GSUP_PING_INTERVAL 20 @@ -38,6 +40,8 @@ struct gprs_gsup_client { gprs_gsup_read_cb_t read_cb; void *data; + struct oap_state oap_state; + struct osmo_timer_list ping_timer; struct osmo_timer_list connect_timer; int is_connected; @@ -46,7 +50,8 @@ struct gprs_gsup_client { struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, unsigned int tcp_port, - gprs_gsup_read_cb_t read_cb); + gprs_gsup_read_cb_t read_cb, + struct oap_config *oap_config); void gprs_gsup_client_destroy(struct gprs_gsup_client *gsupc); int gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg); diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h index d4f991310..2b1b97caa 100644 --- a/openbsc/include/openbsc/sgsn.h +++ b/openbsc/include/openbsc/sgsn.h @@ -6,6 +6,7 @@ #include #include +#include #include @@ -61,6 +62,8 @@ struct sgsn_config { } timers; int dynamic_lookup; + + struct oap_config oap; }; struct sgsn_instance { diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c index 1f9e34c83..a4aca098c 100644 --- a/openbsc/src/gprs/gprs_gsup_client.c +++ b/openbsc/src/gprs/gprs_gsup_client.c @@ -108,6 +108,20 @@ static void gsup_client_send(struct gprs_gsup_client *gsupc, int proto_ext, stru /* msg_tx is now queued and will be freed. */ } +static void gsup_client_oap_register(struct gprs_gsup_client *gsupc) +{ + struct msgb *msg_tx; + int rc; + rc = oap_register(&gsupc->oap_state, &msg_tx); + + if ((rc < 0) || (!msg_tx)) { + LOGP(DGPRS, LOGL_ERROR, "GSUP OAP set up, but cannot register.\n"); + return; + } + + gsup_client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); +} + static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) { struct gprs_gsup_client *gsupc = link->data; @@ -120,6 +134,9 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) if (up) { start_test_procedure(gsupc); + if (gsupc->oap_state.state == OAP_INITIALIZED) + gsup_client_oap_register(gsupc); + osmo_timer_del(&gsupc->connect_timer); } else { osmo_timer_del(&gsupc->ping_timer); @@ -129,6 +146,22 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) } } +static int gsup_client_oap_handle(struct gprs_gsup_client *gsupc, struct msgb *msg_rx) +{ + int rc; + struct msgb *msg_tx; + + rc = oap_handle(&gsupc->oap_state, msg_rx, &msg_tx); + msgb_free(msg_rx); + if (rc < 0) + return rc; + + if (msg_tx) + gsup_client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); + + return 0; +} + static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) { struct ipaccess_head *hh = (struct ipaccess_head *) msg->data; @@ -168,16 +201,21 @@ static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) if (hh->proto != IPAC_PROTO_OSMO) goto invalid; - if (!he || msgb_l2len(msg) < sizeof(*he) || - he->proto != IPAC_PROTO_EXT_GSUP) + if (!he || msgb_l2len(msg) < sizeof(*he)) goto invalid; msg->l2h = &he->data[0]; - OSMO_ASSERT(gsupc->read_cb != NULL); - gsupc->read_cb(gsupc, msg); + if (he->proto == IPAC_PROTO_EXT_GSUP) { + OSMO_ASSERT(gsupc->read_cb != NULL); + gsupc->read_cb(gsupc, msg); + /* expecting read_cb() to free msg */ + } else if (he->proto == IPAC_PROTO_EXT_OAP) { + return gsup_client_oap_handle(gsupc, msg); + /* gsup_client_oap_handle frees msg */ + } else + goto invalid; - /* Not freeing msg here, because that must be done by the read_cb. */ return 0; invalid: @@ -222,7 +260,8 @@ static void start_test_procedure(struct gprs_gsup_client *gsupc) struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, unsigned int tcp_port, - gprs_gsup_read_cb_t read_cb) + gprs_gsup_read_cb_t read_cb, + struct oap_config *oap_config) { struct gprs_gsup_client *gsupc; int rc; @@ -230,6 +269,10 @@ struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, gsupc = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client); OSMO_ASSERT(gsupc); + rc = oap_init(oap_config, &gsupc->oap_state); + if (rc != 0) + goto failed; + gsupc->link = ipa_client_conn_create(gsupc, /* no e1inp */ NULL, 0, diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 8231e8cd8..3467293be 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -63,7 +63,8 @@ int gprs_subscr_init(struct sgsn_instance *sgi) sgi->gsup_client = gprs_gsup_client_create( addr_str, sgi->cfg.gsup_server_port, - &gsup_read_cb); + &gsup_read_cb, + &sgi->cfg.oap); if (!sgi->gsup_client) return -1; diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index 4c6ba9fd1..d432fb139 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -29,6 +29,8 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/gprs_subscriber.o \ $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ $(top_builddir)/src/gprs/gprs_gb_parse.o \ + $(top_builddir)/src/gprs/oap.o \ + $(top_builddir)/src/gprs/oap_messages.o \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOABIS_LIBS) \ $(LIBOSMOCORE_LIBS) \