diff --git a/bts/BTS_Tests.cfg b/bts/BTS_Tests.cfg index aaffbf678..36d81e2cf 100644 --- a/bts/BTS_Tests.cfg +++ b/bts/BTS_Tests.cfg @@ -31,6 +31,7 @@ BTS_Tests.mp_pcu_socket := "/tmp/pcu_sock" #BTS_Tests.mp_tolerance_rxlev := 10; #BTS_Tests.mp_tolerance_rxqual := 1; +BTS_Tests_OML.mp_pcu_socket := "/tmp/pcu_sock" [MAIN_CONTROLLER] diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn index e8554056d..a08c3ff42 100644 --- a/bts/BTS_Tests.ttcn +++ b/bts/BTS_Tests.ttcn @@ -70,6 +70,7 @@ friend module BTS_Tests_VAMOS; friend module BTS_Tests_virtphy; friend module BTS_Tests_LAPDm; friend module BTS_Tests_perf; +friend module BTS_Tests_OML; /* The tests assume a BTS with the following timeslot configuration: * TS0 : Combined CCCH + SDCCH/4 @@ -440,7 +441,7 @@ friend function f_connhdlr_init_vty_bsc() runs on ConnHdlr { } /* PCU socket may at any time receive a new INFO.ind */ -private altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id, +friend altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id, out PCUIF_Message pcu_last_info) { var PCUIF_send_data sd; [] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(0, ?))) -> value sd { diff --git a/bts/BTS_Tests_OML.ttcn b/bts/BTS_Tests_OML.ttcn index 00c66c33b..40fb5cd1d 100644 --- a/bts/BTS_Tests_OML.ttcn +++ b/bts/BTS_Tests_OML.ttcn @@ -16,6 +16,13 @@ import from Osmocom_Types all; import from AbisOML_Types all; import from IPA_Emulation all; import from IPA_Types all; +import from Misc_Helpers all; + +import from PCUIF_Types all; +import from PCUIF_CodecPort all; +import from PCUIF_CodecPort all; + +import from BTS_Tests all; const integer NUM_TRX := 8; @@ -43,6 +50,8 @@ modulepar { uint8_t mp_air_timer := 100; uint8_t mp_ny1 := 10; uint8_t mp_bsic := 63; + + charstring mp_pcu_socket := PCU_SOCK_DEFAULT; }; /* BSC side OML component */ @@ -52,8 +61,17 @@ type component BSC_OML_CT { /* Port for OML */ port IPA_OML_PT OML; var uint8_t g_bts_nr := 0; + /* Port for Abis/Osmo/PCU */ port IPA_OSMO_PCU_PT IPA_OSMO_PCU; + /* PCU Interface of BTS */ + port PCUIF_CODEC_PT PCU; + var integer g_pcu_conn_id; + /* Last PCU INFO IND we received */ + var PCUIF_Message g_pcu_last_info; + + /* As rxed by Get Attributes Response NM_ATT_MANUF_ID IE, see f_oml_getattr() */ + var bitstring g_bts_features; /* global test case guard timer */ timer T_oml_guard := 60.0; @@ -112,6 +130,27 @@ function f_init_oml(charstring id) runs on BSC_OML_CT { activate(as_IPA_evt()); } +private function f_init_pcu(PCUIF_CODEC_PT pt, charstring id, + out integer pcu_conn_id, out PCUIF_Message pcu_last_info) { + timer T := 2.0; + var PCUIF_send_data sd; + + if (mp_pcu_socket == "") { + pcu_conn_id := -1; + return; + } + map(self:PCU, system:PCU); + pcu_conn_id := f_pcuif_connect(pt, mp_pcu_socket); + + T.start; + alt { + [] as_pcu_info_ind(pt, pcu_conn_id, pcu_last_info); + [] T.timeout { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU INFO_IND"); + } + } + pt.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, testcasename()))); +} /* Perform an "OPSTART" procedure with the speciifed MO" */ private function f_oml_opstart(template (value) OML_FOM_ObjectClass obj_class, @@ -290,12 +329,15 @@ private function f_oml_send_exp_no_resp(template (value) OML_PDU tx, charstring } } -private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg) runs on BSC_OML_CT +private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg) + runs on BSC_OML_CT return OML_PDU { + var OML_PDU rx; timer T := 5.0; + T.start; alt { - [] OML.receive(exp_rx) { + [] OML.receive(exp_rx) -> value rx { setverdict(pass); } [] OML.receive { repeat; } @@ -303,6 +345,7 @@ private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg) runs setverdict(fail, "Timeout waiting for ", err_msg); } } + return rx; } /* Send an OML message and expect a failure event report in response */ @@ -351,7 +394,23 @@ private function f_oml_send_exp_nack(template (value) OML_PDU tx, template OML_F } +private function f_oml_getattr(template OML_PDU exp_rx := tr_OML_GetAttributesResponse(NM_OC_BTS, ?, ?)) runs on BSC_OML_CT +{ + var OML_FOM_ObjectInstance obj_inst := valueof(ts_OML_ObjectInstance(g_bts_nr, 255, 255)); + var OML_FOM_IE_Type attr_li[2] := { NM_ATT_MANUF_ID, NM_ATT_SW_CONFIG }; + var octetstring req_attr := ''O; + for (var integer i := 0; i < lengthof(attr_li); i := i + 1) { + req_attr := req_attr & int2oct(enum2int(attr_li[i]), 1); + } + var OML_PDU cmd := valueof(ts_OML_GetAttributes(NM_OC_BTS, obj_inst, req_attr)); + OML.send(cmd); + var OML_PDU rx := f_oml_exp_rx(exp_rx, "BTS GetAttributes Response"); + + var OML_FOM_IE_Body ie_ari := f_OML_FOM_get_ie(rx.u.fom, NM_ATT_GET_ARI); + var OML_FOM_IE_Body manuf_id := f_OML_FOM_IE_List_get_ie(ie_ari.ari.ies, NM_ATT_MANUF_ID); + g_bts_features := oct2bit(manuf_id.other.payload); +} @@ -616,6 +675,57 @@ testcase TC_ipa_rsl_connect_nack() runs on BSC_OML_CT { } } +/* Make sure that the IUT forwards Container PCUIF messages between BSC and PCU */ +testcase TC_ipa_osmo_pcu_anr_fwd() runs on BSC_OML_CT { + var PCUIF_send_data pcu_sd_msg; + var PCUIF_Message msg_rx; + timer T := 2.0; + var octetstring payloadReq := f_rnd_octstring(300); + var octetstring payloadRep := f_rnd_octstring(300); + + f_init_oml(testcasename()); + f_init_pcu(PCU, testcasename(), g_pcu_conn_id, g_pcu_last_info); + f_oml_getattr(); + + log("BTS Features:", g_bts_features); + if (lengthof(g_bts_features) < 21 or g_bts_features[20] != '1'B) { + setverdict(fail, "Feature ABIS_OSMO_PCU not supported!"); + } + + IPA_OSMO_PCU.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)); + IPA_OSMO_PCU.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP)); + IPA_OSMO_PCU.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)); + + IPA_OSMO_PCU.send(ts_PCUIF_CONTAINER(0, ts_PCUIF_CONT_OTHER(100, payloadReq))) + T.start; + alt { + [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_CONTAINER(0, tr_PCUIF_CONT_OTHER(100, payloadReq)))) { + setverdict(pass); + } + [] PCU.receive(PCUIF_send_data:?) -> value pcu_sd_msg { + setverdict(fail, "Unexpected message received: ", pcu_sd_msg.data, " vs exp: ", + t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_CONTAINER(0, tr_PCUIF_CONT_OTHER(100, payloadReq)))); + } + [] T.timeout { setverdict(fail, "Timeout waiting for ANR request on PCU inteface");} + } + T.stop; + + /* Send back the response: */ + PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_CONTAINER(0, ts_PCUIF_CONT_OTHER(100, payloadRep)))) + T.start; + alt { + [] IPA_OSMO_PCU.receive(tr_PCUIF_CONTAINER(0, tr_PCUIF_CONT_OTHER(100, payloadRep))) { + setverdict(pass); + } + [] IPA_OSMO_PCU.receive(PCUIF_Message:?) -> value msg_rx { + setverdict(fail, "Unexpected message received: ", msg_rx, " vs exp: ", + tr_PCUIF_CONTAINER(0, tr_PCUIF_CONT_OTHER(100, payloadRep))); + } + [] T.timeout { setverdict(fail, "Timeout waiting for ANR request on BSC inteface"); } + } + setverdict(pass); +} + control { execute( TC_wrong_mdisc() ); @@ -634,6 +744,8 @@ control { execute( TC_ts_opstart_noattr() ); execute( TC_initial_state_reports() ); execute( TC_ipa_rsl_connect_nack() ); + + execute( TC_ipa_osmo_pcu_anr_fwd() ); } /* BTS: diff --git a/library/AbisOML_Types.ttcn b/library/AbisOML_Types.ttcn index 6229f2539..ae39671ba 100644 --- a/library/AbisOML_Types.ttcn +++ b/library/AbisOML_Types.ttcn @@ -1226,6 +1226,21 @@ function f_OML_make_nack_exp(OML_PDU orig, template OML_FOM_NackCause cause) ret return resp; } +function f_OML_FOM_IE_List_get_ie(OML_FOM_IE_List ie_list, OML_FOM_IE_Type iei) return OML_FOM_IE_Body +{ + for (var integer i := 0; i < lengthof(ie_list); i := i + 1) { + if (ie_list[i].iei == iei) { + return ie_list[i].body; + } + } + var OML_FOM_IE_Body dummy; + return dummy; /*TODO: setverdict(fail?) */ +} + +function f_OML_FOM_get_ie(OML_FOM fom, OML_FOM_IE_Type iei) return OML_FOM_IE_Body +{ + return f_OML_FOM_IE_List_get_ie(fom.ies, iei); +} /*********************************************************************** diff --git a/library/PCUIF_Types.ttcn b/library/PCUIF_Types.ttcn index 6cfe41009..1e57fb283 100644 --- a/library/PCUIF_Types.ttcn +++ b/library/PCUIF_Types.ttcn @@ -37,7 +37,8 @@ type enumerated PCUIF_MsgType { PCU_IF_MSG_TIME_IND ('52'O), PCU_IF_MSG_INTERF_IND ('53'O), PCU_IF_MSG_PAG_REQ ('60'O), - PCU_IF_MSG_TXT_IND ('70'O) + PCU_IF_MSG_TXT_IND ('70'O), + PCU_IF_MSG_CONTAINER ('80'O) } with { variant "FIELDLENGTH(8)" }; type enumerated PCUIF_Sapi { @@ -253,6 +254,26 @@ type record PCUIF_susp_req { variant (tlli) "BYTEORDER(last)" }; +type union PCUIF_ContainerMsgUnion { + /* This field can be removed once first container message is added, see + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=574469 */ + octetstring tmp_fixme, + octetstring other +} with { variant "" }; + +type record PCUIF_container { + uint8_t msg_type, + OCT1 spare, + uint16_t len, /* network byte order */ + PCUIF_ContainerMsgUnion u +} with { + variant (len) "BYTEORDER(last)" + variant (len) "LENGTHTO(u)" + variant (u) "CROSSTAG( + tmp_fixme, msg_type = 255; + other, OTHERWISE)" +}; + type union PCUIF_MsgUnion { PCUIF_data data_req, @@ -268,7 +289,8 @@ type union PCUIF_MsgUnion { PCUIF_time_ind time_ind, PCUIF_interf_ind interf_ind, PCUIF_pag_req pag_req, - PCUIF_app_info_req app_info_req + PCUIF_app_info_req app_info_req, + PCUIF_container container } with { variant "" }; type record PCUIF_Message { @@ -290,7 +312,8 @@ type record PCUIF_Message { time_ind, msg_type = PCU_IF_MSG_TIME_IND; interf_ind, msg_type = PCU_IF_MSG_INTERF_IND; pag_req, msg_type = PCU_IF_MSG_PAG_REQ; - app_info_req, msg_type = PCU_IF_MSG_APP_INFO_REQ)" + app_info_req, msg_type = PCU_IF_MSG_APP_INFO_REQ; + container, msg_type = PCU_IF_MSG_CONTAINER)" /* PCUIFv10: 1006 * 8 = 8048 bits */ variant "PADDING(8048)" }; @@ -984,6 +1007,43 @@ template (present) PCUIF_Message tr_PCUIF_APP_INFO_REQ(template (present) uint8_ } +template (value) PCUIF_Message ts_PCUIF_CONTAINER(template (value) uint8_t bts_nr, + template (value) PCUIF_container container) := { + msg_type := PCU_IF_MSG_CONTAINER, + bts_nr := bts_nr, + spare := '0000'O, + u := { + container := container + } +} +template (present) PCUIF_Message tr_PCUIF_CONTAINER(template (present) uint8_t bts_nr, + template (present) PCUIF_container container) := { + msg_type := PCU_IF_MSG_CONTAINER, + bts_nr := bts_nr, + spare := '0000'O, + u := { + container := container + } +} + +template (value) PCUIF_container ts_PCUIF_CONT_OTHER(uint8_t msg_type, template (value) octetstring payload) := { + msg_type := msg_type, + spare := '00'O, + len := lengthof(payload), + u := { + other := payload + } +} +template (present) PCUIF_container tr_PCUIF_CONT_OTHER(template (present) uint8_t msg_type, + template (present) octetstring payload) := { + msg_type := msg_type, + spare := '00'O, + len := ?, + u := { + other := payload + } +} + function f_PCUIF_PDCHMask_set(inout PCUIF_info_ind info, BIT8 pdch_mask, template (present) uint8_t trx_nr := ?) {