| module PCU_Tests_SNS { |
| |
| /* Osmocom PCU test suite for IP Sub-Network-Service (SNS) in TTCN-3 |
| * (C) 2018-2019 Harald Welte <laforge@gnumonks.org> |
| * All rights reserved. |
| * |
| * Released under the terms of GNU General Public License, Version 2 or |
| * (at your option) any later version. |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| |
| import from Osmocom_Types all; |
| import from PCU_Tests_NS all; |
| import from SGSN_Components all; |
| import from Osmocom_Gb_Types all; |
| import from NS_Emulation all; |
| import from NS_CodecPort all; |
| import from NS_Types all; |
| import from RAW_NS all; |
| |
| /********************************************************************************** |
| * Modern Gb/IP bring-up test cases using IP Sub-Network Service (SNS) |
| **********************************************************************************/ |
| |
| /* perform inbound SNS-SIZE procedure */ |
| function f_incoming_sns_size(template (omit) NsCause cause := omit, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_incoming_sns_size(idx=", idx, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0]; |
| |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| /* expect one single SNS-SIZE with RESET flag; 4x v4 EP; no v6 EP */ |
| rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 8, |
| num_v4 := 4, num_v6 := omit), idx); |
| } else { |
| /* expect one single SNS-SIZE with RESET flag; no v4 EP; 4x v6 EP */ |
| rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 8, |
| num_v4 := omit, num_v6 := 4), idx); |
| } |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE_ACK(g_nsconfig[idx].nsei, cause))); |
| } |
| |
| /* perform outbound SNS-SIZE procedure */ |
| function f_outgoing_sns_size(template (omit) NsCause cause := omit, integer idx:= 0) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_size(idx=", idx, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0]; |
| |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 1, |
| num_v4 := 1, num_v6 := omit) |
| )); |
| } else { |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 1, |
| num_v4 := omit, num_v6 := 1) |
| )); |
| } |
| /* expect one single SNS-SIZE with RESET flag; 4x v4 EP; no v6 EP */ |
| rx := f_ns_exp(tr_SNS_SIZE_ACK(g_nsconfig[idx].nsei, cause), idx); |
| } |
| |
| /* perform inbound SNS-CONFIG procedure */ |
| function f_incoming_sns_config(template (omit) NsCause cause := omit, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_incoming_sns_config(idx=", idx, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0]; |
| |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| var template IP4_Elements v4_elem := { tr_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip, |
| nsvc_cfg.provider.ip.remote_udp_port) }; |
| rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig[idx].nsei, end_flag := true, v4 := v4_elem), idx); |
| } else { |
| var template IP6_Elements v6_elem := { tr_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip, |
| nsvc_cfg.provider.ip.remote_udp_port) }; |
| rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig[idx].nsei, end_flag := true, v6 := v6_elem), idx); |
| } |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause))); |
| } |
| |
| /* perform outbound SNS-CONFIG procedure */ |
| function f_outgoing_sns_config(template (omit) NsCause cause := omit, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_config(idx=", idx, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx].nsvc[0]; |
| |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port) } |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4))); |
| } else { |
| var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port) } |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, omit, v6))); |
| } |
| rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx); |
| } |
| |
| /* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */ |
| function f_outgoing_sns_config_1c1u(template (omit) NsCause cause := omit, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_config_1c1u(idx=", idx, ")"); |
| var PDU_NS rx; |
| |
| if (mp_nsconfig.nsvc[0].provider.ip.address_family == AF_INET) { |
| var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[0].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[0].nsvc[0].provider.ip.local_udp_port, 1, 0), |
| ts_SNS_IPv4(g_nsconfig[1].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 0, 1) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4))); |
| } else { |
| var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[0].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[0].nsvc[0].provider.ip.local_udp_port, 1, 0), |
| ts_SNS_IPv6(g_nsconfig[1].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 0, 1) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, omit, v6))); |
| } |
| rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx); |
| } |
| |
| /* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */ |
| function f_outgoing_sns_config_1c1u_separate(template (omit) NsCause cause := omit, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_config_1c1u_separate(idx=", idx, ")"); |
| var PDU_NS rx; |
| if (mp_nsconfig.nsvc[0].provider.ip.address_family == AF_INET) { |
| var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[1].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 1, 0), |
| ts_SNS_IPv4(g_nsconfig[2].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[2].nsvc[0].provider.ip.local_udp_port, 0, 1) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4))); |
| } else { |
| var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig[1].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[1].nsvc[0].provider.ip.local_udp_port, 1, 0), |
| ts_SNS_IPv6(g_nsconfig[2].nsvc[0].provider.ip.local_ip, |
| g_nsconfig[2].nsvc[0].provider.ip.local_udp_port, 0, 1) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, omit, v6))); |
| } |
| rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx); |
| } |
| |
| function f_outgoing_sns_add(integer idx_add, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0, template (omit) NsCause cause := omit) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_add(idx_add=", idx_add, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_add].nsvc[0]; |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port, |
| w_sig, w_user) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_ADD(g_nsconfig[idx].nsei, 23, v4))); |
| rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 23, cause, v4)); |
| } else { |
| var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port, |
| w_sig, w_user) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_ADD(g_nsconfig[idx].nsei, 23, omit, v6))); |
| rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 23, cause, omit, v6)); |
| } |
| } |
| |
| function f_outgoing_sns_del(integer idx_del, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_del(idx_del=", idx_del, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_del].nsvc[0]; |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port, |
| w_sig, w_user) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_DEL(g_nsconfig[idx].nsei, 24, omit, v4))); |
| rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 24, omit, v4)); |
| } else { |
| var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port, |
| w_sig, w_user) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_DEL(g_nsconfig[idx].nsei, 24, omit, omit, v6))); |
| rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 24, omit, omit, v6)); |
| } |
| } |
| |
| function f_outgoing_sns_chg_weight(integer idx_chg, uint8_t w_sig, uint8_t w_user, integer idx := 0) |
| runs on RAW_NS_CT { |
| log("f_outgoing_sns_chg_weight(idx_chg=", idx_chg, ")"); |
| var PDU_NS rx; |
| var NSVCConfiguration nsvc_cfg := g_nsconfig[idx_chg].nsvc[0]; |
| if (nsvc_cfg.provider.ip.address_family == AF_INET) { |
| var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port, |
| w_sig, w_user) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CHG_WEIGHT(g_nsconfig[idx].nsei, 25, v4))); |
| rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 25, omit, v4)); |
| } else { |
| var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip, |
| nsvc_cfg.provider.ip.local_udp_port, |
| w_sig, w_user) }; |
| NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CHG_WEIGHT(g_nsconfig[idx].nsei, 25, omit, v6))); |
| rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 25, omit, omit, v6)); |
| } |
| } |
| |
| |
| |
| |
| |
| /* PCU-originated SNS-SIZE: successful case */ |
| testcase TC_sns_po_size_success() runs on RAW_Test_CT { |
| f_init_ns_codec(mp_nsconfig); |
| f_init_pcuif(); |
| f_incoming_sns_size(); |
| f_sleep(1.0); |
| setverdict(pass); |
| } |
| |
| /* PCU-originated SNS-SIZE: NACK from our side */ |
| testcase TC_sns_po_size_nack() runs on RAW_Test_CT { |
| f_init_ns_codec(mp_nsconfig); |
| f_init_pcuif(); |
| f_incoming_sns_size(NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED); |
| /* FIXME: ensure we don't get a SNS-CONFIG */ |
| /* FIXME: ensure we get re-transmitted SNS-SIZE attempts */ |
| f_sleep(10.0); |
| setverdict(pass); |
| } |
| |
| /* PCU-originated SNS-CONFIG: successful case */ |
| testcase TC_sns_po_config_success() runs on RAW_Test_CT { |
| f_init_ns_codec(mp_nsconfig); |
| f_init_pcuif(); |
| f_incoming_sns_size(); |
| f_incoming_sns_config(); |
| f_sleep(1.0); |
| setverdict(pass); |
| } |
| |
| /* PCU-originated SNS-CONFIG: successful case */ |
| testcase TC_sns_po_config_nack() runs on RAW_Test_CT { |
| f_init_ns_codec(mp_nsconfig); |
| f_init_pcuif(); |
| f_incoming_sns_size(); |
| f_incoming_sns_config(NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED); |
| /* FIXME: ensure we get re-transmitted SNS-CONFIG attempts */ |
| f_sleep(10.0); |
| setverdict(pass); |
| } |
| |
| |
| /* SGSN-originated SNS-SIZE: successful case */ |
| testcase TC_sns_so_config_success() runs on RAW_Test_CT { |
| f_init_ns_codec(mp_nsconfig); |
| f_init_pcuif(); |
| f_incoming_sns_size(); |
| f_incoming_sns_config(); |
| f_outgoing_sns_config(); |
| |
| /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */ |
| as_rx_alive_tx_ack(oneshot := true); |
| activate(as_rx_alive_tx_ack()); |
| |
| f_outgoing_ns_alive(); |
| |
| /* Expect BVC-RESET for signaling (0) and ptp BVCI */ |
| as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true); |
| as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true); |
| as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true); |
| |
| /* wait for one FLOW-CONTROL BVC and then ACK any further in the future */ |
| as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true); |
| activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci)); |
| setverdict(pass); |
| } |
| |
| private function f_sns_bringup_1c1u(boolean sgsn_originated_reset := false) runs on RAW_Test_CT { |
| /* Activate two NS codec ports */ |
| f_init_ns_codec(mp_nsconfig); |
| f_init_ns_codec(mp_nsconfig, 1); |
| f_init_pcuif(); |
| /* Perform Size + BSS-originated config */ |
| f_incoming_sns_size(); |
| f_incoming_sns_config(); |
| /* perform SGSN-originated config using idx==0 for signalling and idx==1 for user traffic */ |
| f_outgoing_sns_config_1c1u(); |
| |
| /* wait for one ALIVE cycle, then ACK any further ALIVE in the background |
| * for both NS-VCs */ |
| as_rx_alive_tx_ack(oneshot := true, idx := 0); |
| activate(as_rx_alive_tx_ack(idx := 0)); |
| as_rx_alive_tx_ack(oneshot := true, idx := 1); |
| activate(as_rx_alive_tx_ack(idx := 1)); |
| |
| /* perform outgoing ALIVE procedure for both NS-VCs */ |
| f_outgoing_ns_alive(0); |
| f_outgoing_ns_alive(1); |
| |
| if (sgsn_originated_reset) { |
| /* Expect BVC-RESET, but ignore it to prevent a race condition of BVC RESETs */ |
| var template PDU_NS pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, 0, omit)); |
| f_ns_exp(pdu); |
| /* SGSN originated BVC-RESET on an uninitialized signalling BVC */ |
| f_tx_bvc_reset_rx_ack(0, omit, omit); |
| |
| /* Expect BVC-RESET PTP BVC, but ignore it to prevent a race condition of BVC RESETs */ |
| pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id)); |
| f_ns_exp(pdu); |
| /* SGSN originated BVC-RESET on an uninitialized PTP BVC */ |
| f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id); |
| } else { |
| /* Expect BVC-RESET for signaling BVCI=0 */ |
| as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true); |
| /* Expect BVC-RESET from the PCU on PTP BVC */ |
| as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true); |
| } |
| /* Expect UNBLOCK for ptp BVCI on signaling NS-VC (idx==0) */ |
| as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true); |
| |
| /* wait for one FLOW-CONTROL BVC and then ACK any further in the future. Flow |
| * control happens on the p-t-p BVCI and hence on index 1 */ |
| as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 1); |
| activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, idx := 1)); |
| } |
| |
| /* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only */ |
| testcase TC_sns_1c1u() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u(); |
| setverdict(pass); |
| } |
| |
| private function f_sns_bringup_1c1u_separate(boolean sgsn_originated_reset := false) runs on RAW_Test_CT { |
| /* Activate two NS codec ports */ |
| f_init_ns_codec(mp_nsconfig); |
| f_init_ns_codec(mp_nsconfig, 1); |
| f_init_ns_codec(mp_nsconfig, 2); |
| f_init_pcuif(); |
| /* Perform Size + BSS-originated config */ |
| f_incoming_sns_size(); |
| f_incoming_sns_config(); |
| /* perform SGSN-originated config using idx==0 for signalling and idx==1 for user traffic */ |
| f_outgoing_sns_config_1c1u_separate(); |
| |
| /* wait for one ALIVE cycle, then ACK any further ALIVE in the background |
| * for both NS-VCs */ |
| as_rx_alive_tx_ack(oneshot := true, idx := 1); |
| activate(as_rx_alive_tx_ack(idx := 1)); |
| as_rx_alive_tx_ack(oneshot := true, idx := 2); |
| activate(as_rx_alive_tx_ack(idx := 2)); |
| /* ensure there's no NS-ALIVE received on idx==0 */ |
| f_ensure_no_ns(t_NS_ALIVE, idx := 0); |
| |
| /* perform outgoing ALIVE procedure for both NS-VCs */ |
| f_outgoing_ns_alive(1); |
| f_outgoing_ns_alive(2); |
| /* ensure there's no response to NS-ALIVE sent on idx==0 */ |
| f_outgoing_ns_alive_no_ack(idx := 0); |
| |
| if (sgsn_originated_reset) { |
| /* Expect BVC-RESET, but ignore it to prevent a race condition of BVC RESETs */ |
| var template PDU_NS pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, 0, omit)); |
| f_ns_exp(pdu, idx := 1); |
| /* SGSN originated BVC-RESET on an uninitialized sign BVC */ |
| f_tx_bvc_reset_rx_ack(0, omit, omit, idx := 1); |
| |
| /* Expect BVC-RESET PTP BVC, but ignore it to prevent a race condition of BVC RESETs */ |
| pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id)); |
| f_ns_exp(pdu, idx := 1); |
| f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id, idx := 1); |
| } else { |
| /* Expect BVC-RESET for signaling BVCI=0 */ |
| as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true, idx := 1); |
| /* Expect BVC-RESET from the PCU on PTP BVC */ |
| as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true, idx := 1); |
| } |
| /* Expect UNBLOCK for ptp BVCI on signaling NS-VC (idx==1) */ |
| as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 1); |
| |
| /* wait for one FLOW-CONTROL BVC and then ACK any further in the future. Flow |
| * control happens on the p-t-p BVCI and hence on index 1 */ |
| as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 2); |
| activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, idx := 2)); |
| } |
| |
| /* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only - and where |
| * the initial IP/port for the SNS procedure is *not* part of the NS-VCs later */ |
| testcase TC_sns_1c1u_separate() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u_separate(); |
| setverdict(pass); |
| } |
| |
| /* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only and use |
| * SGSN-originated BVC-RESET rather than BSS-originated */ |
| testcase TC_sns_1c1u_so_bvc_reset() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u_separate(sgsn_originated_reset := true); |
| setverdict(pass); |
| } |
| |
| /* Transmit BVC-RESET before NS-ALIVE of PCU was ACKed: expect no response */ |
| testcase TC_sns_1c1u_so_bvc_reset_too_early() runs on RAW_Test_CT { |
| /* Activate two NS codec ports */ |
| f_init_ns_codec(mp_nsconfig); |
| f_init_ns_codec(mp_nsconfig, 1); |
| f_init_ns_codec(mp_nsconfig, 2); |
| f_init_pcuif(); |
| /* Perform Size + BSS-originated config */ |
| f_incoming_sns_size(); |
| f_incoming_sns_config(); |
| /* perform SGSN-originated config using idx==0 for signalling and idx==1 for user traffic */ |
| f_outgoing_sns_config_1c1u_separate(); |
| |
| /* DON'T ACK ANY INBOUND NS-ALIVE HERE! */ |
| |
| /* perform outgoing ALIVE procedure for both NS-VCs */ |
| f_outgoing_ns_alive(1); |
| f_outgoing_ns_alive(2); |
| /* ensure there's no response to NS-ALIVE sent on idx==0 */ |
| f_outgoing_ns_alive_no_ack(idx := 0); |
| |
| /* Transmit BVC-RESET and expect no ACK*/ |
| f_tx_bvc_reset_rx_ack(0, omit, omit, idx := 1, exp_ack := false); |
| f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id, idx := 1, exp_ack := false); |
| } |
| |
| /* Test adding new IP endpoints at runtime */ |
| testcase TC_sns_add() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u(); |
| |
| /* create another NS codec port on the tester side */ |
| f_init_ns_codec(mp_nsconfig, 2); |
| |
| f_outgoing_sns_add(idx_add := 2, w_sig := 0, w_user := 1, idx := 0); |
| |
| /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */ |
| as_rx_alive_tx_ack(oneshot := true, idx := 2); |
| activate(as_rx_alive_tx_ack(idx := 2)); |
| |
| f_outgoing_ns_alive(2); |
| setverdict(pass); |
| } |
| |
| /* Test adding an already present IP endpoint at runtime */ |
| testcase TC_sns_add_nack() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u(); |
| |
| f_outgoing_sns_add(idx_add := 0, w_sig := 0, w_user := 1, idx := 0, cause := NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED); |
| setverdict(pass); |
| } |
| |
| /* Test deleting IP endpoints at runtime */ |
| testcase TC_sns_del() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u(); |
| |
| f_outgoing_sns_del(idx_del := 1, w_sig := 0, w_user := 1, idx := 0); |
| /* FIXME: ensure we don't receive anything on just-deleted NS-VC anymore */ |
| setverdict(pass); |
| } |
| |
| /* Test changing weights at runtime */ |
| testcase TC_sns_chg_weight() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u(); |
| |
| /* change w_user from 1 to 200 */ |
| f_outgoing_sns_chg_weight(idx_chg := 1, w_sig := 0, w_user := 200, idx := 0); |
| setverdict(pass); |
| } |
| |
| import from PCUIF_Types all; |
| import from PCUIF_CodecPort all; |
| |
| altstep as_pcu_activate() runs on RAW_PCU_CT { |
| var PCUIF_send_data sd; |
| [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_ACT_REQ(?, ?, ?))) -> value sd { repeat; } |
| |
| } |
| |
| testcase TC_pcuif_rach() runs on RAW_Test_CT { |
| f_sns_bringup_1c1u(); |
| activate(as_pcu_activate()); |
| |
| f_pcuif_tx(ts_PCUIF_RACH_IND(bts_nr:=0, trx_nr:=0, ts_nr:=0, ra:=23, |
| is_11bit:=0, burst_type:=BURST_TYPE_0, |
| fn:=42, arfcn:=871, qta:=0)); |
| PCU.receive(t_SD_PCUIF(g_pcu_conn_id, |
| tr_PCUIF_DATA_REQ(bts_nr:=0, trx_nr:=0, ts_nr:=0, block_nr:=?, fn:=?, |
| sapi:=PCU_IF_SAPI_AGCH, data:=?))); |
| setverdict(pass); |
| } |
| |
| |
| |
| control { |
| execute( TC_sns_po_size_success() ); |
| execute( TC_sns_po_size_nack() ); |
| execute( TC_sns_po_config_success() ); |
| execute( TC_sns_po_config_nack() ); |
| execute( TC_sns_so_config_success() ); |
| execute( TC_sns_1c1u() ); |
| execute( TC_sns_1c1u_separate() ); |
| execute( TC_sns_1c1u_so_bvc_reset() ); |
| execute( TC_sns_1c1u_so_bvc_reset_too_early() ); |
| execute( TC_sns_add() ); |
| execute( TC_sns_add_nack() ); |
| execute( TC_sns_del() ); |
| execute( TC_sns_chg_weight() ); |
| |
| execute( TC_pcuif_rach() ); |
| } |
| |
| } |