From 23e7f28c5c77a57aad5331c5e27b29e2eccfe7c3 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Fri, 12 Feb 2016 14:28:11 +0100 Subject: [PATCH] mscsplit: getting grips on header scopes --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/iu_cs.h | 2 -- openbsc/include/openbsc/msc_ifaces.h | 41 ++++++++++++++++++---- openbsc/src/libbsc/bsc_api.c | 2 ++ openbsc/src/libmsc/Makefile.am | 2 +- openbsc/src/libmsc/iu_cs.c | 8 ----- openbsc/src/libmsc/msc_api.c | 51 ++++++++++++++++++++++++++++ openbsc/src/libmsc/msc_api.h | 17 ++++++++-- openbsc/src/libmsc/msc_ifaces.c | 50 +++++++++++++++++++++------ openbsc/src/libmsc/osmo_msc.c | 23 +------------ 10 files changed, 144 insertions(+), 54 deletions(-) create mode 100644 openbsc/src/libmsc/msc_api.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 907119e04..4869603f2 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -19,7 +19,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ gprs_gsup_client.h bsc_msg_filter.h \ oap.h oap_messages.h \ gtphub.h \ - iu.h iu_cs.h \ + msc_ifaces.h iu.h iu_cs.h \ common.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h diff --git a/openbsc/include/openbsc/iu_cs.h b/openbsc/include/openbsc/iu_cs.h index 9c2be4176..656c4f6a4 100644 --- a/openbsc/include/openbsc/iu_cs.h +++ b/openbsc/include/openbsc/iu_cs.h @@ -6,5 +6,3 @@ struct gsm_subscriber_connection *subscr_conn_allocate_iu(struct gsm_network *ne uint8_t link_id, uint32_t conn_id); -int iucs_submit_dtap(struct gsm_subscriber_connection *conn, - struct msgb *msg); diff --git a/openbsc/include/openbsc/msc_ifaces.h b/openbsc/include/openbsc/msc_ifaces.h index dc2b9e1da..2dee3918a 100644 --- a/openbsc/include/openbsc/msc_ifaces.h +++ b/openbsc/include/openbsc/msc_ifaces.h @@ -9,28 +9,55 @@ * 2G will use the A-interface, * 3G aka UMTS will use the Iu-interface (for the MSC, it's IuCS). * - * Below callback structures allows linking parts of the MSC code without + * Below callback structures allow linking parts of the MSC code without * having to include entire infrastructures of external libraries. For example, * a unit test does not need to link against external ASN1 libraries if it is * never going to encode actual outgoing messages. It is up to each building - * scope to plug real world functions or to have mere dummy implementations. */ + * scope to plug real world functions or to have mere dummy implementations. + * + * For example, for msc_tx_foo(ifaces, conn, msg), depending on + * conn->via_iface, either ifaces->a.tx() or ifaces.iu_cs.tx() is called to + * dispatch the msg. + * + * To replace the default dummy implementations, a user would do the likes of: + * + * int my_iu_cs_tx(...) + * { + * ... + * } + * + * int main(void) + * { + * global_msc_ifaces->network = my_network; + * global_msc_ifaces->iu_cs.tx = my_iu_cs_tx; + * ... + * } + * + * (or use readily available implementations like iu_tx() from libiu) + */ -extern struct { +struct msc_ifaces { + + /* global gsm_network to lookup BSC|RNC connections etc. */ + struct gsm_network *network; struct { /* libmsc calls this to send out messages to an A-interface */ int (*tx)(struct msgb *msg, uint8_t sapi); + /* TODO: I don't understand sapi yet, may not apply to A-iface */ } a; struct { /* libmsc calls this to send out messages to an Iu-interface */ int (*tx)(struct msgb *msg, uint8_t sapi); + /* TODO: I don't understand sapi yet */ } iu_cs; -} msc_ifaces; +}; + +extern struct msc_ifaces *global_msc_ifaces; +int msc_tx_dtap(struct gsm_subscriber_connection *conn, + struct msgb *msg); -/* Depending on conn->via_iface (A or IuCS), submit msg to the proper link api. */ -extern int msc_submit_dtap(struct gsm_subscriber_connection *conn, - struct msgb *msg); diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index cd6b87e15..9dc394c9c 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -242,6 +242,8 @@ static int handle_new_assignment(struct gsm_subscriber_connection *conn, int cha /* Allocate a subscriber connection for A-interface link. For Iu-CS see * subscr_con_allocate_iu(). */ +/* TODO this shall move to libmsc, behind an actual A-interface, and lchan will + * not be involved. */ struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan) { struct gsm_subscriber_connection *conn; diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index 18314a386..fbbcbdc77 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -21,7 +21,7 @@ libmsc_a_SOURCES = auth.c \ vty_interface_layer3.c \ transaction.c \ osmo_msc.c ctrl_commands.c meas_feed.c \ - msc_api.c iu_cs.c + msc_api.c msc_ifaces.c iu_cs.c if BUILD_SMPP noinst_HEADERS += smpp_smsc.h diff --git a/openbsc/src/libmsc/iu_cs.c b/openbsc/src/libmsc/iu_cs.c index 289fe1410..b0426e82c 100644 --- a/openbsc/src/libmsc/iu_cs.c +++ b/openbsc/src/libmsc/iu_cs.c @@ -109,11 +109,3 @@ int gsm0408_rcvmsg_iucs(struct gsm_network *network, struct msgb *msg) } -int iucs_submit_dtap(struct gsm_subscriber_connection *conn, - struct msgb *msg) -{ - OSMO_ASSERT(conn->via_iface == IFACE_IU); - msg->dst = conn->iu.ue_ctx; - return iu_tx(msg, 0); -} - diff --git a/openbsc/src/libmsc/msc_api.c b/openbsc/src/libmsc/msc_api.c new file mode 100644 index 000000000..e896b24c9 --- /dev/null +++ b/openbsc/src/libmsc/msc_api.c @@ -0,0 +1,51 @@ +/* Implementations for receiving or sending MM|CC|... messages from/to the + * BSC|RNC direction, regardless of which particular external interface is + * actually involved (A or IuCS). */ + +/* (C) 2016 by sysmocom s.m.f.c GmbH + * + * Based on parts of osmo_msc.c: + * (C) 2010,2013 by Holger Hans Peter Freyther + * (C) 2010 by On-Waves + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, + uint16_t chosen_channel) +{ + gsm0408_new_conn(conn); + gsm0408_dispatch(conn, msg); + + /* + * If this is a silent call we want the channel to remain open as long as + * possible and this is why we accept this connection regardless of any + * pending transaction or ongoing operation. + */ + if (conn->silent_call) + return MSC_CONN_ACCEPT; + if (conn->loc_operation || conn->sec_operation || conn->anch_operation) + return MSC_CONN_ACCEPT; + if (trans_has_conn(conn)) + return MSC_CONN_ACCEPT; + + LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n"); + return MSC_CONN_REJECT; +} + diff --git a/openbsc/src/libmsc/msc_api.h b/openbsc/src/libmsc/msc_api.h index 4b4d32501..e3459a6ae 100644 --- a/openbsc/src/libmsc/msc_api.h +++ b/openbsc/src/libmsc/msc_api.h @@ -2,9 +2,22 @@ /* These functions receive or send MM|CC|... messages from/to the BSC|RNC * direction, while they are not concerned with which particular external - * interface is actually involved (A or IuCS). */ + * interface is actually involved (A or IuCS). + * + * For the interface specific decisions see msc_iface.[hc] */ -/* receive a Level 3 Complete message */ +#include + +struct gsm_subscriber_connection; +struct msgb; + +enum { + MSC_CONN_ACCEPT = 0, + MSC_CONN_REJECT = 1, +}; + +/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or + * MSC_CONN_REJECT */ int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, uint16_t chosen_channel); /* TODO: is chosen_channel NITB legacy? */ diff --git a/openbsc/src/libmsc/msc_ifaces.c b/openbsc/src/libmsc/msc_ifaces.c index f50ab3275..88100926d 100644 --- a/openbsc/src/libmsc/msc_ifaces.c +++ b/openbsc/src/libmsc/msc_ifaces.c @@ -1,4 +1,4 @@ -/* MSC decisions which interface to send messages out on. */ +/* Implementation for MSC decisions which interface to send messages out on. */ /* (C) 2016 by sysmocom s.m.f.c GmbH * @@ -16,35 +16,63 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ #include #include #include -#include +#include -#include "msc_api.h" +static int tx_dummy_a(struct msgb *msg, uint8_t sapi) +{ + LOGP(DMSC, LOGL_ERROR, + "attempt to send message via uninitialized A-interface\n"); + return -1 +} -int msc_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg) +static int tx_dummy_iu_cs(struct msgb *msg, uint8_t sapi) +{ + LOGP(DMSC, LOGL_ERROR, + "attempt to send message via uninitialized IuCS-interface\n"); + return -1 +} + +struct msc_ifaces *global_msc_ifaces = { + .a = { + .tx = tx_dummy_a, + }, + .iu_cs = { + .tx = tx_dummy_iu_cs, + } +}; + + +static int msc_tx(struct msc_ifaces *ifaces, + struct gsm_subscriber_connection *conn, + struct msgb *msg) { switch (conn->via_iface) { case IFACE_A: - //return gsm0808_submit_dtap(conn, msg, link_id, allow_sacch); - LOGP(DMSC, LOGL_ERROR, - "submit dtap: A-interface not implemented\n"); - return -1; + /* TODO: msg->dst = */ + return ifaces->a.tx(msg, 0); case IFACE_IUCS: - return iucs_submit_dtap(conn, msg); + msg->dst = conn->iu.ue_ctx; + return ifaces->iu_cs.tx(msg, 0); default: LOGP(DMSC, LOGL_ERROR, - "submit dtap: conn->via_iface invalid (%d)\n", + "msc_tx(): conn->via_iface invalid (%d)\n", conn->via_iface); return -1; } } +int msc_tx_dtap(struct gsm_subscriber_connection *conn, + struct msgb *msg) +{ + msc_tx(global_msc_ifaces, conn, msg); +} + diff --git a/openbsc/src/libmsc/osmo_msc.c b/openbsc/src/libmsc/osmo_msc.c index 7f9dabb1b..8618b00f7 100644 --- a/openbsc/src/libmsc/osmo_msc.c +++ b/openbsc/src/libmsc/osmo_msc.c @@ -26,6 +26,7 @@ #include #include +#include #include static void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci) @@ -42,28 +43,6 @@ static int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca return 1; } -int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, - uint16_t chosen_channel) -{ - gsm0408_new_conn(conn); - gsm0408_dispatch(conn, msg); - - /* - * If this is a silent call we want the channel to remain open as long as - * possible and this is why we accept this connection regardless of any - * pending transaction or ongoing operation. - */ - if (conn->silent_call) - return BSC_API_CONN_POL_ACCEPT; - if (conn->loc_operation || conn->sec_operation || conn->anch_operation) - return BSC_API_CONN_POL_ACCEPT; - if (trans_has_conn(conn)) - return BSC_API_CONN_POL_ACCEPT; - - LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n"); - return BSC_API_CONN_POL_REJECT; -} - static void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) { gsm0408_dispatch(conn, msg);