Commit 2854ca1e authored by Yann Garcia's avatar Yann Garcia
Browse files

Adding GTP-U support to reply to ICMP from UE

parent 94bced26
Loading
Loading
Loading
Loading
+3 −0
Changes for etc/AtsNGAP/AtsNGAP_GNB_p_net.cfg_: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ LibNGAP_Pixits.PX_TIME_ZONE := '80'O # 0x40 for GMT+1, 0x80 for GMT+2
# User plane probe (TC_NGAP_GNB_PDU_01): the UPF tunnel endpoint given to the gNB is this host on N3, and the UE pings it
LibNGAP_Pixits.PX_TRANSPORT_LAYER_ADDRESS := '00001010101011100001001100001110'B # 10.174.19.14
LibNGAP_Pixits.PX_UT_PING_HOST := "10.174.19.14"
LibNGAP_Pics.PICS_USE_GTPU := true # The test system plays the UPF on N3 and checks the uplink G-PDUs (system.N3_gNB_1)

LibNGAP_Pixits.PX_PDU_SESSION_ID   := 1

@@ -100,6 +101,8 @@ LogEventTypes:= Yes

# Act as AMF, listen for incoming connections from gNB
system.NGAP_gNB_1.params := "NGAP/SCTP(local_server=10.174.19.14,server_mode=1,local_port=38412,debug=1)"
# N3 user plane (PICS_USE_GTPU): GTP-U on UDP port 2152 of this host; dst_ip is the N3 address of the gNB (Echo Responses, downlink)
system.N3_gNB_1.params := "GTPU(auto_echo_reply=1)/UDP(src_port=2152,dst_ip=10.174.19.10,dst_port=2152)"

# Open5GS pcap files
# Do not forget to set LibNGAP_Pics.PICS_OFFLINE_MODE to true
+112 −9
Changes for ttcn/AtsNGAP/NGAP_Steps.ttcn: 112 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -32,6 +32,11 @@ module NGAP_Steps { // TODO FSCOM f_xxx_UE_SecurityMode to be mmoved into NAG_NG

    // UpperTester
    import from UpperTesterCommon all;

    // LibGtpu
    import from LibGtpu_TypesAndValues all;
    import from LibGtpu_Templates all;
    import from LibGtpu_Functions all;
    import from UpperTesterPtcToMtcDefs all;
    import from UpperTesterFunctions all;

@@ -855,22 +860,26 @@ module NGAP_Steps { // TODO FSCOM f_xxx_UE_SecurityMode to be mmoved into NAG_NG
        /**
         * @brief  Have the real UE send user plane traffic over its data call: ping PX_UT_PING_HOST.
         * @details Unless PX_UT_PING_HOST is empty: asks the upper tester for PING (AT+QPING on the modem,
         *          PX_UT_PING_COUNT echo requests, PX_UT_PING_TIMEOUT s each) and waits for its result, which is
         *          only logged. The gNB is expected to forward the echo requests as uplink G-PDUs to the UPF
         *          tunnel endpoint of the PDU session (PX_TRANSPORT_LAYER_ADDRESS, PX_GTP_TEID); as the test
         *          system does not handle GTP-U yet, no reply comes back, and only a capture on the test system
         *          host (UDP port 2152) shows whether they arrived.
         *          PX_UT_PING_COUNT echo requests, PX_UT_PING_TIMEOUT s each) and waits for its result. The gNB is
         *          expected to forward the echo requests as uplink G-PDUs to the UPF tunnel endpoint of the PDU
         *          session (PX_TRANSPORT_LAYER_ADDRESS, PX_GTP_TEID). With PICS_USE_GTPU, the test system plays that
         *          UPF: each G-PDU received on N3_P meanwhile is checked (f_NGAP_gnb_check_uplink_gpdu), and the
         *          verdict is set to fail if one does not conform, or if none carries an echo request of the UE
         *          although the modem ran the pings. Echo requests are not answered (no downlink user data yet).
         *          The UE stays in CM-CONNECTED meanwhile: no NGAP signalling is expected. If the gNB nevertheless
         *          asks for the release of the UE context (UE CONTEXT RELEASE REQUEST, e.g. user inactivity when the
         *          UE sends nothing), it is released (UE CONTEXT RELEASE COMMAND/COMPLETE) and the wait goes on:
         *          left unanswered, the request would end in an NG RESET from the gNB.
         * @note   The verdict is set by the UT dispatcher only (NGAP_UtDispatcher): inconc if the modem could not
         *         run the pings at all (e.g. the context of the data call is not usable by AT+QPING); lost
         *         replies are not a failure.
         * @return true if the modem ran the pings.
         * @note   Lost replies are not a failure. The UT dispatcher (NGAP_UtDispatcher) sets the verdict to inconc
         *         if the modem could not run the pings at all (e.g. the context of the data call is not usable by
         *         AT+QPING).
         * @return true if the modem ran the pings and, with PICS_USE_GTPU, the uplink user data was conformant.
         */
        function f_NGAP_gnb_UE_ping() runs on gNBNGAPComponent return boolean {
            var UT_COMMON_CNF v_cnf;
            var GtpuMessage v_gtpu;
            var integer v_echoRequests := 0; // Conformant G-PDUs carrying an echo request of the UE
            var boolean v_conformant := true;
            timer t_ping := int2float(PX_UT_PING_COUNT * PX_UT_PING_TIMEOUT) + 30.0;

            if (PX_UT_PING_HOST == "") {
@@ -898,15 +907,109 @@ module NGAP_Steps { // TODO FSCOM f_xxx_UE_SecurityMode to be mmoved into NAG_NG
                    }
                    repeat;
                }
                [PICS_USE_GTPU] N3_P.receive(mw_gtpu_any) -> value v_gtpu {
                    fl_count_uplink_gpdu(v_gtpu, v_echoRequests, v_conformant);
                    repeat;
                }
                [] t_ping.timeout {
                    log("*** " & __SCOPE__ & ": INFO: no ping result from the upper tester ***");
                    return false;
                }
            }
            log("*** " & __SCOPE__ & ": INFO: ping ", PX_UT_PING_HOST, " result: ", v_cnf, " ***");
            if (not PICS_USE_GTPU) {
                return v_cnf.Result;
            }
            // G-PDUs still in flight or queued when the result came
            t_ping.start(1.0);
            alt {
                [] N3_P.receive(mw_gtpu_any) -> value v_gtpu {
                    fl_count_uplink_gpdu(v_gtpu, v_echoRequests, v_conformant);
                    repeat;
                }
                [] t_ping.timeout {
                }
            }
            log("*** " & __SCOPE__ & ": INFO: ", v_echoRequests, " echo request(s) of the UE received on N3 ***");
            if (v_cnf.Result and v_conformant and (v_echoRequests == 0)) {
                log("*** " & __SCOPE__ & ": FAIL: the UE sent echo requests, but the gNB forwarded none on N3 ***");
                setverdict(fail, "no uplink user data forwarded by the gNB on N3");
                return false;
            }
            if (v_conformant and (v_echoRequests > 0)) {
                log("*** " & __SCOPE__ & ": PASS: uplink user data forwarded by the gNB on N3 ***");
            }
            return v_cnf.Result and v_conformant and (v_echoRequests > 0);
        } // End of function f_NGAP_gnb_UE_ping

        /**
         * @brief  Check an uplink G-PDU (f_NGAP_gnb_check_uplink_gpdu) and update the counters of f_NGAP_gnb_UE_ping.
         * @param  p_gtpu The received GTP-U message.
         * @param  p_echoRequests Incremented if it carries an echo request of the UE.
         * @param  p_conformant Set to false if its GTP-U encapsulation does not conform.
         */
        function fl_count_uplink_gpdu(in GtpuMessage p_gtpu, inout integer p_echoRequests, inout boolean p_conformant) runs on gNBNGAPComponent {
            var boolean v_echoRequest;
            if (not f_NGAP_gnb_check_uplink_gpdu(p_gtpu, v_echoRequest)) {
                p_conformant := false;
            } else if (v_echoRequest) {
                p_echoRequests := p_echoRequests + 1;
            }
        } // End of function fl_count_uplink_gpdu

        /**
         * @brief  Check an uplink G-PDU the gNB forwarded on N3 for the PDU session of the UE (TS 29.281, TS 38.415).
         * @details The gNB is responsible for the GTP-U encapsulation, which must conform: a G-PDU, to the uplink
         *          tunnel of the PDU session (PX_GTP_TEID), with a PDU Session Container of type UL PDU SESSION
         *          INFORMATION for the QoS flow PX_QOS_FLOW_IDENTIFIER (TS 38.415 clause 5.5.2.2). The verdict is
         *          set to fail otherwise.
         *          The T-PDU, the packet of the UE that the gNB forwards unchanged, is then examined: an IPv4 ICMP
         *          echo request from PX_UT_PDU_ADDRESS_IPV4 to PX_UT_PING_HOST is reported in p_echoRequest; any
         *          other packet is only logged.
         * @param  p_gtpu The received GTP-U message.
         * @param  p_echoRequest true if it carries an echo request of the ping of the UE.
         * @return false if the GTP-U encapsulation does not conform.
         */
        function f_NGAP_gnb_check_uplink_gpdu(in GtpuMessage p_gtpu, out boolean p_echoRequest) runs on gNBNGAPComponent return boolean {
            var integer v_pduType;
            var integer v_qfi;
            var octetstring v_source;
            var octetstring v_destination;
            var integer v_protocol;
            var octetstring v_payload;

            p_echoRequest := false;
            if (p_gtpu.header.messageType != c_gtpuGPdu) {
                log("f_NGAP_gnb_check_uplink_gpdu: INFO: GTP-U message ", p_gtpu.header.messageType, " ignored: ", p_gtpu);
                return true;
            }
            if (p_gtpu.header.teid != PX_GTP_TEID) {
                log("*** " & __SCOPE__ & ": FAIL: G-PDU to TEID ", p_gtpu.header.teid, ", expected ", PX_GTP_TEID, " ***");
                setverdict(fail, "G-PDU to an unexpected TEID");
                return false;
            }
            if (not f_gtpu_getPduSessionContainer(p_gtpu, v_pduType, v_qfi)) {
                log("*** " & __SCOPE__ & ": FAIL: G-PDU without PDU Session Container: ", p_gtpu.header, " ***");
                setverdict(fail, "G-PDU without PDU Session Container");
                return false;
            }
            if ((v_pduType != c_pduSessionUlInformation) or (v_qfi != PX_QOS_FLOW_IDENTIFIER)) {
                log("*** " & __SCOPE__ & ": FAIL: PDU Session Container with PDU type ", v_pduType, " and QFI ", v_qfi,
                    ", expected ", c_pduSessionUlInformation, " (UL) and ", PX_QOS_FLOW_IDENTIFIER, " ***");
                setverdict(fail, "unexpected PDU Session Container");
                return false;
            }
            if (not f_ipv4_getHeader(p_gtpu.payload, v_source, v_destination, v_protocol, v_payload)) {
                log("f_NGAP_gnb_check_uplink_gpdu: INFO: T-PDU is not an IPv4 packet: ", p_gtpu.payload);
                return true;
            }
            p_echoRequest := (v_source == PX_UT_PDU_ADDRESS_IPV4) and (v_destination == f_ipv4_fromString(PX_UT_PING_HOST))
                             and (v_protocol == 1) and (lengthof(v_payload) > 0) and (v_payload[0] == '08'O);
            log("f_NGAP_gnb_check_uplink_gpdu: G-PDU conforms, QFI ", v_qfi, ", IPv4 ", f_ipv4_toString(v_source), " -> ",
                f_ipv4_toString(v_destination), ", protocol ", v_protocol, ", echo request of the UE: ", p_echoRequest);
            return true;
        } // End of function f_NGAP_gnb_check_uplink_gpdu

        /**
         * @brief  Leave the real UE in a known state at the end of a test: deregistered, in flight mode.
         * @details Unless PX_UT_DEREGISTER_TIMEOUT is 0.0: asks the upper tester to switch the modem to flight
+4 −0
Changes for ttcn/AtsNGAP/NGAP_TestConfiguration.ttcn: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ module NGAP_TestConfiguration {
            connect(p_NGAPComponent_gnb:syncPort, self:syncPort) ;
            //Map
            map(p_NGAPComponent_gnb:N2_gNBaMF_P, system:NGAP_gNB_1);
            if (PICS_USE_GTPU) {
                // The UDP port (2152) is bound here, until the component terminates
                map(p_NGAPComponent_gnb:N3_P, system:N3_gNB_1);
            }
            f_cf_Ut_Up(p_NGAPComponent_gnb);

            activate(a_mtc_shutdown());
+2 −0
Changes for ttcn/AtsNGAP/NGAP_TestSystem.ttcn: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ module NGAP_TestSystem {

    // LibNGAP
    import from LibNGAP_Interface all;
    import from LibGtpu_Interface all;

    // UpperTester
    import from UpperTesterCommon all;
@@ -33,6 +34,7 @@ module NGAP_TestSystem {

                    port NGAPPort NGAP_AMF, NGAP_gNB_1, NGAP_gNB_2;
                    port MTC_System_Ut utPort;
                    port GtpuPort N3_gNB_1; // N3 user plane with the gNB under test (GTP-U), see PICS_USE_GTPU
                } // End of type TestAdapter

        } // End of group TestSystemInterfaces
+5 −4
Changes for ttcn/AtsNGAP/module.mk: 5 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ modules := \
  ../LibCommon                                                  \
  ../Lib3GPP                                                    \
  ../UpperTester                                                \
  ../LibGtpv2                                                   \
  ../LibGtpu                                                    \
  ../../titan-test-system-framework/ttcn/LibHelpers             \
  ../../titan-test-system-framework/ttcn/LibSecurity            \
  ../../titan-test-system-framework/ttcn/LibXsd                 \
@@ -30,6 +30,7 @@ modules := \
  ../../titan-test-system-framework/ccsrc/Protocols/IP          \
  ../../titan-test-system-framework/ccsrc/Protocols/Sctp        \
  ../../titan-test-system-framework/ccsrc/Protocols/Tcp         \
  ../../titan-test-system-framework/ccsrc/Protocols/UDP         \
  ../../titan-test-system-framework/ccsrc/Protocols/Xml         \
  ../../titan-test-system-framework/ccsrc/Framework             \
  ../../titan-test-system-framework/ccsrc/Helpers               \
@@ -39,15 +40,15 @@ modules := \
  ../../ccsrc/Externals                                         \
  ../../ccsrc/Ports/LibNAS                                      \
  ../../ccsrc/Ports/LibNGAP                                     \
  ../../ccsrc/Ports/LibGtpv2                                    \
  ../../ccsrc/Ports/LibGtpu                                     \
  ../../ccsrc/Ports/UpperTester                                 \
  ../../ccsrc/framework                                         \
  ../../ccsrc/Protocols/NGAP_layer                              \
  ../../ccsrc/Protocols/NGAP                                    \
  ../../ccsrc/Protocols/NG_NAS                                  \
  ../../ccsrc/Protocols/FiveG_AKA                               \
  ../../ccsrc/Protocols/Gtpv2_layer                             \
  ../../ccsrc/Protocols/Gtpv2                                   \
  ../../ccsrc/Protocols/Gtpu_layer                              \
  ../../ccsrc/Protocols/Gtpu                                    \
  ../../ccsrc/Protocols/UT_layer                                \
  ../../ccsrc/Protocols/UT                                      \
  ../modules/titan.TestPorts.Common_Components.Abstract_Socket
Loading