mscsplit: getting grips on header scopes

This commit is contained in:
Neels Hofmeyr
2016-02-12 14:28:11 +01:00
parent 243c7cb044
commit 23e7f28c5c
10 changed files with 144 additions and 54 deletions

View File

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

View File

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

View File

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

View File

@@ -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;

View File

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

View File

@@ -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);
}

View File

@@ -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 <info@sysmocom.de>
*
* Based on parts of osmo_msc.c:
* (C) 2010,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
* (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 <http://www.gnu.org/licenses/>.
*/
#include <openbsc/msc_api.h>
#include <openbsc/gsm_data.h>
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;
}

View File

@@ -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 <stdint.h>
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? */

View File

@@ -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 <info@sysmocom.de>
*
@@ -16,35 +16,63 @@
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/core/logging.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/iu_cs.h>
#include <openbsc/msc_ifaces.h>
#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 = <A-iface token> */
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);
}

View File

@@ -26,6 +26,7 @@
#include <openbsc/transaction.h>
#include <openbsc/db.h>
#include <openbsc/msc_api.h>
#include <openbsc/gsm_04_11.h>
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);