mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
				synced 2025-11-03 21:43:32 +00:00 
			
		
		
		
	mscsplit: getting grips on header scopes
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								openbsc/src/libmsc/msc_api.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								openbsc/src/libmsc/msc_api.c
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -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? */
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user