summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-04-17 11:23:04 +0200
committerHarald Welte <laforge@gnumonks.org>2018-04-17 19:52:30 +0000
commit2d86affc8cbff74dd71f0467388608cc78fafa95 (patch)
tree518f9c6fb0c3b6705f9800ee26b48ced8b605d98
parent7ef51aa2a28d3d1e1d30efa39fc45f11fe06f510 (diff)
IPA: Fix wrong CCM ID_ACK logic; disable CCM on CTRL interface
Our TTCN3 implementation of the IPA multiplex with CCM handshaking has been based on some wrong assumptions about the protocol logic. To make the code stricter, we * send an ID_ACK immediately after connecting TCP in a client * separate client and server CCM responder logic * always respond with ID_ACK to ID_RESP (we accept any identity) Also, as the Osmocom CTRL interface uses an IPA multiplex but no CCM, we introduce a boolean variable (and function argument) to clearly enable/disable CCM support in a given IPA_Emulation component. The CTRL_Adapter has been modified to use this flag to disable CCM. This also removes the need of cherry-picking "HACK: Work around IPA CCM bug in OsmoBSC" Change-Id: I304535d28a165f76a0a140dc0a15dd81a9db28c8 from the laforge/bsc-workaround branch. Change-Id: I6d9eaf0d69457caacc03b9049a8bc57976480617
-rw-r--r--library/IPA_Emulation.ttcnpp62
-rw-r--r--library/Osmocom_CTRL_Adapter.ttcn3
2 files changed, 53 insertions, 12 deletions
diff --git a/library/IPA_Emulation.ttcnpp b/library/IPA_Emulation.ttcnpp
index c3cfe8d..be64dd1 100644
--- a/library/IPA_Emulation.ttcnpp
+++ b/library/IPA_Emulation.ttcnpp
@@ -164,6 +164,7 @@ type component IPA_Emulation_CT {
var boolean g_is_bsc_mgw;
var IpaMode g_mode;
+ var boolean g_ccm_enabled;
var IPA_CCM_Parameters g_ccm_pars := c_IPA_default_ccm_pars;
}
@@ -331,19 +332,39 @@ template PDU_IPA_CCM ts_IPA_ID_GET := {
}
/* receive IPA CCM message */
-private function f_ccm_rx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
+private function f_ccm_rx_client(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
select (ccm.msg_type) {
case (IPAC_MSGT_PING) {
f_ccm_tx(valueof(ts_IPA_PONG));
}
case (IPAC_MSGT_ID_ACK) {
- f_ccm_tx(valueof(ts_IPA_ACK));
+ f_send_IPA_EVT(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_ID_ACK));
}
case (IPAC_MSGT_ID_GET) {
f_ccm_tx(f_ccm_make_id_resp(ccm));
}
+ case else {
+ log("Unknown/unsupported IPA CCM message type", ccm);
+ }
+ }
+}
+
+private function f_ccm_rx_server(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
+ select (ccm.msg_type) {
+ case (IPAC_MSGT_PING) {
+ f_ccm_tx(valueof(ts_IPA_PONG));
+ }
+ case (IPAC_MSGT_ID_ACK) {
+ /* the IPA server should at some point receive an ID_ACK from the client,
+ * in case of RSL/OML from nanoBTS, this is actually the first message after
+ * the TCP connection is established. Other implementations may differ.
+ * We currently ignore it completely - but actually we should make sure that
+ * one ID_ACK is received by the server at some point */
+ }
case (IPAC_MSGT_ID_RESP) {
log("IPA ID RESP: ", ccm.u.resp);
+ /* acknowledge any identity that the client may have sent */
+ f_ccm_tx(valueof(ts_IPA_ACK));
}
case else {
log("Unknown/unsupported IPA CCM message type", ccm);
@@ -377,16 +398,24 @@ private function f_from_rsl(IPL4asp_Types.ConnectionId connId, ASP_RSL_Unitdata
/* main function to use for a client-side IPA implementation */
function main_client(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
charstring local_host, IPL4asp_Types.PortNumber local_port,
- IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
+ IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars,
+ boolean ccm_enabled := true) runs on IPA_Emulation_CT {
g_mode := IPA_MODE_CLIENT;
+ g_ccm_enabled := ccm_enabled;
f_connect(remote_host, remote_port, local_host, local_port, ccm_pars);
+ if (g_ccm_enabled) {
+ /* we're a client: Send ID_ACK immediately after connect */
+ f_ccm_tx(valueof(ts_IPA_ACK));
+ }
f_send_IPA_EVT(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP));
ScanEvents();
}
/* main function to use for a server-side IPA implementation */
-function main_server(charstring local_host, IPL4asp_Types.PortNumber local_port) runs on IPA_Emulation_CT {
+function main_server(charstring local_host, IPL4asp_Types.PortNumber local_port,
+ boolean ccm_enabled := true) runs on IPA_Emulation_CT {
g_mode := IPA_MODE_SERVER;
+ g_ccm_enabled := ccm_enabled;
f_bind(local_host, local_port);
ScanEvents();
}
@@ -454,13 +483,24 @@ private function ScanEvents() runs on IPA_Emulation_CT {
while (true) {
alt {
/* Received IPA -> up into SCCP stack */
- [] IPA_PORT.receive(IPA_RecvFrom: ?) -> value ipa_rx {
- select (ipa_rx.streamId) {
- case (IPAC_PROTO_CCM) {
- var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
- log("CCM Rx:", ccm);
- f_ccm_rx(ccm);
+ [g_ccm_enabled] IPA_PORT.receive(IPA_RecvFrom:{?,IPAC_PROTO_CCM,omit,?}) -> value ipa_rx {
+ var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
+ log("CCM Rx:", ccm);
+ select (g_mode) {
+ case (IPA_MODE_CLIENT) {
+ f_ccm_rx_client(ccm);
+ }
+ case (IPA_MODE_SERVER) {
+ f_ccm_rx_server(ccm);
+ }
+ case else {
+ setverdict(fail, "Unknown mode");
+ self.stop;
+ }
}
+ }
+ [] IPA_PORT.receive(IPA_RecvFrom:?) -> value ipa_rx {
+ select (ipa_rx.streamId) {
#ifdef IPA_EMULATION_SCCP
case (IPAC_PROTO_SCCP) {
var ASP_MTP3_TRANSFERind mtp;
@@ -513,7 +553,7 @@ private function ScanEvents() runs on IPA_Emulation_CT {
log("IPA: Connected");
g_ipa_conn_id := asp_evt.connOpened.connId;
f_send_IPA_EVT(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP));
- if (g_mode == IPA_MODE_SERVER) {
+ if (g_mode == IPA_MODE_SERVER and g_ccm_enabled) {
f_ccm_tx(valueof(ts_IPA_ID_GET));
}
}
diff --git a/library/Osmocom_CTRL_Adapter.ttcn b/library/Osmocom_CTRL_Adapter.ttcn
index 9baa6a2..22195c8 100644
--- a/library/Osmocom_CTRL_Adapter.ttcn
+++ b/library/Osmocom_CTRL_Adapter.ttcn
@@ -29,7 +29,8 @@ runs on CTRL_Adapter_CT {
map(vc_CTRL_IPA:IPA_PORT, system:IPA_CODEC_PT);
connect(vc_CTRL_IPA:IPA_CTRL_PORT, self:IPA_CTRL);
- vc_CTRL_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", -1));
+ vc_CTRL_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", -1,
+ c_IPA_default_ccm_pars, false));
/* wait for IPA CTRL link to connect and send UP */
T.start;