diff --git a/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_CommonIE_Types.ttcn b/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_CommonIE_Types.ttcn index 9d890281e..99e90efb7 100644 --- a/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_CommonIE_Types.ttcn +++ b/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_CommonIE_Types.ttcn @@ -100,7 +100,7 @@ type record ML3_NotifySS_Arg //============================================================================ // 10.5.1.1 Cell Identity -type record CellIdentity +type record CellIdentityTV { OCT1 elementIdentifier, OCT2 cIvalue diff --git a/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_Types.ttcn b/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_Types.ttcn index 0165481d9..6e28c0ebc 100644 --- a/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_Types.ttcn +++ b/MobileL3_v13.4.0_CNL113832_LATEST/src/MobileL3_Types.ttcn @@ -25,7 +25,7 @@ import from MobileL3_MM_Types all; import from MobileL3_CC_Types all; import from MobileL3_RRM_Types all; import from MobileL3_SMS_Types all; -import from MobileL3_SS_Types all; +//import from MobileL3_SS_Types all; external function enc_PDU_L3_MS_SGSN(in PDU_L3_MS_SGSN pdu) return octetstring with { extension "prototype(convert)" extension "encode(RAW)" } @@ -283,7 +283,7 @@ type union ML3_Discr_NW_MS //<-24.011, imported from L3_SMS_Types octetstring gprs_sm, // GPRS session management messages <- not required in MSC // but impl. as L3_GMM_MS_SGSN in L3_GSM_SGSN_MS_Types - PDU_ML3_SS_NW_MS ss, // non call related SS messages + octetstring ss, // non call related SS messages //<- 24.080 ASN1 or implemented by ethgbh octetstring loc, // Location services(LCS) <- 24.030 octetstring reserved @@ -347,7 +347,7 @@ type union ML3_Discr_MS_NW octetstring gprs_mm, // GPRS mobility management messages L3_SMS_MS_SGSN sms, // SMS messages octetstring gprs_sm, // GPRS session management messages - PDU_ML3_SS_MS_NW ss, // non call related SS messages + octetstring ss, // non call related SS messages octetstring loc, // Location services octetstring reserved }; diff --git a/ggsn_tests/GGSN_Tests.cfg b/ggsn_tests/GGSN_Tests.cfg index a7f4681f0..6954e1df1 100644 --- a/ggsn_tests/GGSN_Tests.cfg +++ b/ggsn_tests/GGSN_Tests.cfg @@ -11,13 +11,14 @@ LoggerPlugins := { JUnitLogger := "libjunitlogger2" } system.*.lazy_conn_id_handling := "YES" [MODULE_PARAMETERS] -GGSN_Tests.m_bind_ip_gtpc := "127.0.42.1" -GGSN_Tests.m_bind_ip_gtpu := "127.0.42.1" -GGSN_Tests.m_ggsn_ip_gtpc := "127.0.23.1" -GGSN_Tests.m_ggsn_ip_gtpu := "127.0.23.1" +GGSN_Tests.m_bind_ip_gtpc := "172.18.0.202" +GGSN_Tests.m_bind_ip_gtpu := "172.18.0.202" +GGSN_Tests.m_ggsn_ip_gtpc := "172.18.0.201" +GGSN_Tests.m_ggsn_ip_gtpu := "172.18.0.201" +GGSN_Tests.m_pdn_sock_host_v4 = "172.17.0.2" [EXECUTE] -#GGSN_Tests.TC_dummy +GGSN_Tests.TC_dummy GGSN_Tests.TC_pdp4_act_deact GGSN_Tests.TC_pdp4_act_deact_ipcp GGSN_Tests.TC_pdp4_act_deact_pcodns @@ -27,3 +28,6 @@ GGSN_Tests.TC_pdp6_act_deact_pcodns GGSN_Tests.TC_pdp6_act_deact_icmp6 GGSN_Tests.TC_echo_req_resp + +GGSN_Tests.TC_pdp4_act_deact_ipcp_udp + diff --git a/ggsn_tests/GGSN_Tests.ttcn b/ggsn_tests/GGSN_Tests.ttcn index 358945a95..eea7058a8 100644 --- a/ggsn_tests/GGSN_Tests.ttcn +++ b/ggsn_tests/GGSN_Tests.ttcn @@ -11,6 +11,7 @@ module GGSN_Tests { import from IP_Types all; import from ICMPv6_Types all; import from Native_Functions all; + import from UDP_Types all; const integer GTP0_PORT := 3386; const integer GTP1C_PORT := 2123; @@ -22,6 +23,10 @@ module GGSN_Tests { charstring m_ggsn_ip_gtpc := "127.0.0.6"; charstring m_ggsn_ip_gtpu := "127.0.0.6"; + + /* IPv4 address on the external PDN for testing user plane */ + charstring m_pdn_sock_host_v4 := "192.168.0.1"; + integer m_pdn_sock_port_v4 := 5555; } type set PdpContext { @@ -32,6 +37,7 @@ module GGSN_Tests { ProtConfigOptions pco_neg optional, EndUserAddress eua, OCT16 ip6_prefix optional, + OCT4 ip4_addr optional, BIT4 nsapi, /* TEI (Data) local side */ OCT4 teid, @@ -46,6 +52,7 @@ module GGSN_Tests { type component GT_CT { port GTPC_PT GTPC; port GTPU_PT GTPU; + port IPL4asp_PT UDP; var boolean g_initialized := false; @@ -53,11 +60,16 @@ module GGSN_Tests { /* FIXME: unify with g_bind_ip + parse from config file */ var OCT4 g_sgsn_ip_c; var OCT4 g_sgsn_ip_u; + var OCT4 g_pdn_sock_ip; /* FIXME: parse remName from config file */ var GtpPeer g_peer_c := { connId := 0, remName := m_ggsn_ip_gtpc, remPort := GTP1C_PORT }; var GtpPeer g_peer_u := { connId := 0, remName := m_ggsn_ip_gtpu, remPort := GTP1U_PORT }; + /* address to which we can bind an IP socket to simulate an internet host */ timer T_default := 3.0; + /* UDP connection ID for UDP test port */ + var integer g_udp_connId; + /* next to-be-sent GTP-C sequence number */ var uint16_t g_c_seq_nr; /* next to-be-sent GTP-U sequence number */ @@ -72,6 +84,7 @@ module GGSN_Tests { g_sgsn_ip_c := f_inet_addr(m_bind_ip_gtpc); g_sgsn_ip_u := f_inet_addr(m_bind_ip_gtpu); + g_pdn_sock_ip := f_inet_haddr(m_pdn_sock_host_v4); var Result res; map(self:GTPC, system:GTPC); @@ -83,6 +96,10 @@ module GGSN_Tests { res := GTP_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, m_bind_ip_gtpu, GTP1U_PORT, {udp:={}}); g_peer_u.connId:= res.connId; + map(self:UDP, system:IPL4); + res := IPL4asp_PortType.f_IPL4_listen(UDP, m_pdn_sock_host_v4, m_pdn_sock_port_v4, {udp:={}}); + g_udp_connId := res.connId; + g_restart_ctr := f_rnd_octstring(1); g_c_seq_nr := f_rnd_int(65535); g_d_seq_nr := f_rnd_int(65535); @@ -204,7 +221,7 @@ module GGSN_Tests { template EndUserAddress tr_EuaIPv4(template OCT4 ip_addr) modifies t_EuaIPv4 := { endUserAddress := { endUserAddressIPv4 := { - lengthf := 2+lengthof(ip_addr) + lengthf := 2+4 } } } @@ -667,6 +684,9 @@ module GGSN_Tests { ctx.teid_remote := cpr.teidDataI.teidDataI; ctx.teic_remote := cpr.teidControlPlane.teidControlPlane; ctx.eua := cpr.endUserAddress; + if (match(ctx.eua, tr_EuaIPv4(?))) { + ctx.ip4_addr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address; + } ctx.pco_neg := cpr.protConfigOptions; setverdict(pass); } else { @@ -813,6 +833,28 @@ module GGSN_Tests { payload := payload } + /* template to construct IPv4_packet from input arguments, ready to use in f_IPv4_enc() */ + template IPv4_packet ts_IP4(OCT4 srcaddr, OCT4 dstaddr, LIN1 proto, octetstring payload, LIN1 ttl := 255) := { + header := { + ver := 4, + hlen := 5, + tos := 0, + tlen := 0, + id := f_rnd_int(65535), + res := '0'B, + dfrag := '1'B, + mfrag := '0'B, + foffset := 0, + ttl := ttl, + proto := proto, + cksum := 0, /* overwritten in encoder */ + srcaddr := srcaddr, + dstaddr := dstaddr + }, + ext_headers := omit, + payload := payload + } + function f_ipv6_link_local(in OCT16 link_id) return OCT16 { return 'FE80000000000000'O & substr(link_id, 8, 8); } @@ -883,6 +925,103 @@ module GGSN_Tests { T_default.stop; } + template ASP_RecvFrom tr_UdpRecvFrom(template ConnectionId id, template HostName remName, template PortNumber remPort, + template HostName locName, template PortNumber locPort, template octetstring payload) := { + connId := id, + remName := remName, + remPort := remPort, + locName := locName, + locPort := locPort, + proto := { udp := {} }, + userData := ?, + msg := payload + } + function f_gen_UdpRT(template HostName remName, template PortNumber remPort, + template octetstring payload) runs on GT_CT return template ASP_RecvFrom { + return tr_UdpRecvFrom(g_udp_connId, remName, remPort, m_pdn_sock_host_v4, m_pdn_sock_port_v4, payload); + } + + template ASP_SendTo ts_UdpSendTo(ConnectionId id, HostName remName, PortNumber remPort, octetstring payload) := { + connId := id, + remName := remName, + remPort := remPort, + proto := { udp := {} }, + msg := payload + } + function f_gen_UdpST(HostName remName, PortNumber remPort, octetstring payload) runs on GT_CT return ASP_SendTo { + return valueof(ts_UdpSendTo(g_udp_connId, remName, remPort, payload)); + } + + template UDP_packet ts_UDP(uint16_t srcport, uint16_t dstport, octetstring payload) := { + header := { + srcport := srcport, + dstport := dstport, + len := lengthof(payload), + cksum := 0 + }, + payload := payload + } + + function f_gen_UDP4(OCT4 saddr, uint16_t sport, OCT4 daddr, uint16_t dport, octetstring payload) return octetstring { + var octetstring udp := f_UDP_enc(valueof(ts_UDP(sport, dport, payload))); + var UDP_pseudo_header phdr := { + ipv4 := { + srcaddr := saddr, dstaddr := daddr, zero := 0, + proto := 17, plen := 0 + } + }; + /* compute UDP checksum and patch into UDP binary */ + var OCT2 udpcksum := f_UDP_checksum(f_UDP_pseudo_header_enc(phdr) & udp); + udp[6] := udpcksum[0]; + udp[7] := udpcksum[1]; + return f_IPv4_enc(valueof(ts_IP4(saddr, daddr, 17, udp))); + } + + function f_gen_UDP6(OCT16 saddr, uint16_t sport, OCT16 daddr, uint16_t dport, octetstring payload) return octetstring { + var octetstring udp := f_UDP_enc(valueof(ts_UDP(sport, dport, payload))); + var UDP_pseudo_header phdr := { + ipv6 := { + srcaddr := saddr, dstaddr := daddr, plen := 0, + zero := 0, nextheader := 17 + } + }; + /* compute UDP checksum and patch into UDP binary */ + var OCT2 udpcksum := f_UDP_checksum(f_UDP_pseudo_header_enc(phdr) & udp); + udp[6] := udpcksum[0]; + udp[7] := udpcksum[1]; + return f_IPv6_enc(valueof(ts_IP6(saddr, daddr, 17, udp))); + } + + /* Send a packet via GTP (SGSN->GGSN) and confirm it arrives on UDP socket */ + function f_transceive_udp_mo(PdpContext ctx, octetstring udp_payload) runs on GT_CT { + var uint16_t src_port := 8888; + /* build packet with UDP and IP header */ + var octetstring ip_packet := f_gen_UDP4(ctx.ip4_addr, src_port, g_pdn_sock_ip, m_pdn_sock_port_v4, udp_payload); + /* send IP packet wrapped in GTP for given PDP context */ + f_send_gtpu(ctx, ip_packet) + /* wait for it to arrive on UDP socket */ + T_default.start; + alt { + [] UDP.receive(f_gen_UdpRT(f_inet_hntoa(ctx.ip4_addr), src_port, udp_payload)) { setverdict(pass); } + [] UDP.receive { setverdict(fail); } + [] T_default.timeout { setverdict(fail); } + } + T_default.stop; + } + + function f_transceive_udp_mt(PdpContext ctx, octetstring udp_payload) runs on GT_CT { + var uint16_t dst_port := 7777; + var octetstring ip_packet := f_gen_UDP4(g_pdn_sock_ip, m_pdn_sock_port_v4, ctx.ip4_addr, dst_port, udp_payload); + /* Send IP packet in GGSN -> MS direction */ + UDP.send(f_gen_UdpST(f_inet_hntoa(ctx.ip4_addr), dst_port, udp_payload)); + T_default.start; + alt { + [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ctx.teid, ?)) { /* FIXME: check for ip_packet */} + [] T_default.timeout { setverdict(fail); } + } + T_default.stop; + } + /* Test IPv6 context activation for dynamic IPv6 EUA without request of IPv6 DNS */ testcase TC_pdp6_act_deact() runs on GT_CT { f_init(); @@ -946,6 +1085,19 @@ module GGSN_Tests { f_pdp_ctx_del(ctx, '1'B); } + /* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in IPCP + UDP user data */ + testcase TC_pdp4_act_deact_ipcp_udp() runs on GT_CT { + f_init(); + var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn))); + ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP); + f_pdp_ctx_act(ctx); + for (var integer i := 0; i < 10; i := i + i) { + var octetstring payload := f_rnd_octstring(512); + f_transceive_udp_mo(ctx, payload); + } + f_pdp_ctx_del(ctx, '1'B); + } + testcase TC_echo_req_resp() runs on GT_CT { f_init(); f_send_gtpc(ts_GTPC_PING(g_peer_c, g_c_seq_nr)); diff --git a/ggsn_tests/gen_links.sh b/ggsn_tests/gen_links.sh index 573e26331..1297938b8 100755 --- a/ggsn_tests/gen_links.sh +++ b/ggsn_tests/gen_links.sh @@ -35,6 +35,10 @@ DIR=$BASEDIR/titan.ProtocolModules.IP/src FILES="IP_EncDec.cc IP_Types.ttcn" gen_links $DIR $FILES +DIR=$BASEDIR/titan.ProtocolModules.UDP/src +FILES="UDP_EncDec.cc UDP_Types.ttcn" +gen_links $DIR $FILES + DIR=../GTP_v13.5.0_CNL113843_LATEST/src FILES="GTPC_EncDec.cc GTPC_Types.ttcn GTPU_EncDec.cc GTPU_Types.ttcn" gen_links $DIR $FILES diff --git a/ggsn_tests/regen_makefile.sh b/ggsn_tests/regen_makefile.sh index f9c1bcfd6..ad4f5a9d6 100755 --- a/ggsn_tests/regen_makefile.sh +++ b/ggsn_tests/regen_makefile.sh @@ -1,6 +1,6 @@ #!/bin/sh -FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc" +FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc UDP_EncDec.cc" ttcn3_makefilegen -l -f GGSN_Tests.ttcn $FILES sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile diff --git a/gprs_gb/BSSGP_Emulation.ttcn b/gprs_gb/BSSGP_Emulation.ttcn index 5937a278f..ac7beb87f 100644 --- a/gprs_gb/BSSGP_Emulation.ttcn +++ b/gprs_gb/BSSGP_Emulation.ttcn @@ -65,7 +65,7 @@ module BSSGP_Emulation { modulepar { Nsvci mp_nsei := 96; Nsvci mp_bvci := 196; - BssgpCellId mp_cellid := { ra_id := { lai := { mcc_mnc := '234F04'H, lac := 200}, rac := 0 }, cell_id := 20960 }; + BssgpCellId mp_cellid := { ra_id := { lai := { mcc_mnc := '262F42'H, lac := 13135}, rac := 0 }, cell_id := 20960 }; }; function f_BnsUdReq(template BssgpPdu pdu, BssgpBvci bvci := mp_bvci) return NsUnitdataRequest { diff --git a/gprs_gb/BSSGP_Types.ttcn b/gprs_gb/BSSGP_Types.ttcn index c97b78b65..1be98303b 100644 --- a/gprs_gb/BSSGP_Types.ttcn +++ b/gprs_gb/BSSGP_Types.ttcn @@ -3,6 +3,8 @@ module BSSGP_Types { import from General_Types all; import from Osmocom_Types all; import from GSM_Types all; + import from GSM_RR_Types all; + import from MobileL3_CommonIE_Types all; import from BSSGP_Helper_Functions all; type enumerated BssgpPduType { @@ -233,10 +235,10 @@ module BSSGP_Types { uint16_t bvc_measurement, /* 11.3.7 */ BssgpCause cause, /* 11.3.8 */ BssgpCellId cell_id, /* 11.3.9 */ - DrxParameter drx_parameter, /* 11.3.11 */ - MobileIdentity imsi, /* 11.3.14 */ + DrxParameter drx_parameter, /* 10.3.11 */ + MobileIdentityV imsi, /* 11.3.14 */ LocationAreaIdentification lai, /* 11.3.17 */ - MobileIdentity mobile_id, /* 11.3.20 */ + MobileIdentityV mobile_id, /* 11.3.20 */ BssgpPduLifetime pdu_lifetime, /* 11.3.25 */ BssgpPriority priority, /* 11.3.27 */ BssgpQosProfile qos_profile, /* 11.3.28 */ @@ -377,10 +379,13 @@ module BSSGP_Types { len := 4, u := { imsi := { - imsi := { - mi_type := MI_TYPE_IMSI, - odd := true, /* IMSI has 15 digits */ - digits := imsi + typeOfIdentity := '001'B, + oddEvenInd_identity := { + imsi := { + oddevenIndicator := '1'B, /* IMSI has 15 digits */ + digits := imsi, + fillerDigit := omit + } } } } diff --git a/gprs_gb/LLC_Types.ttcn b/gprs_gb/LLC_Types.ttcn index 61fc66449..8ca8f39d1 100644 --- a/gprs_gb/LLC_Types.ttcn +++ b/gprs_gb/LLC_Types.ttcn @@ -4,15 +4,31 @@ module LLC_Types { /* TS 44.064 Chapter 6.2 */ type record LlcAddressField { - boolean pd, + BIT1 pd ('0'B), boolean c_r, BIT2 reserved, LlcSapi sapi } with { - variant (pd) "FIELDLENGTH(1)" variant (c_r) "FIELDLENGTH(1)" }; + template LlcAddressField t_LLC_Addr(template boolean c_r, template LlcSapi sapi) := { + pd := '0'B, + c_r := c_r, + reserved := '00'B, + sapi := sapi + }; + + const boolean LLC_CR_DL_CMD := true; + const boolean LLC_CR_DL_RSP := false; + const boolean LLC_CR_UL_CMD := false; + const boolean LLC_CR_UL_RSP := true; + + template LlcAddressField t_LLC_Addr_DlCmd(template LlcSapi sapi) := t_LLC_Addr(true, sapi); + template LlcAddressField t_LLC_Addr_DlRsp(template LlcSapi sapi) := t_LLC_Addr(false, sapi); + template LlcAddressField t_LLC_Addr_UlCmd(template LlcSapi sapi) := t_LLC_Addr(false, sapi); + template LlcAddressField t_LLC_Addr_UlRsp(template LlcSapi sapi) := t_LLC_Addr(true, sapi); + type enumerated LlcSapi { LLC_SAPI_RESERVED_0 ('0000'B), LLC_SAPI_GMM ('0001'B), @@ -68,6 +84,14 @@ module LLC_Types { variant (pm) "FIELDLENGTH(1)" }; + template LlcCtrlFieldUI t_LlcCtrlUI(template uint8_t n_u) := { + presence := '110'B, + spare := '00'B, + n_u := n_u, + e := false, + pm := true + }; + /* TS 44.064 Chapter 6.3 */ type record LlcCtrlFieldU { BIT3 presence ('111'B), @@ -120,8 +144,8 @@ module LLC_Types { type record LlcPdu { LlcAddressField addr, LlcCtrlUnion ctrl, - octetstring payload, - LlcFcs fcs + octetstring payload//, + //LlcFcs fcs } with { variant "" }; external function enc_LlcPdu(in LlcPdu pdu) return octetstring @@ -129,4 +153,13 @@ module LLC_Types { external function dec_LlcPdu(in octetstring stream) return LlcPdu with { extension "prototype(convert) decode(RAW)" }; + + template LlcPdu t_LLC_UI(template boolean c_r, template uint8_t n_u, template octetstring payload, + template LlcSapi sapi := LLC_SAPI_GMM) := { + addr := t_LLC_Addr(c_r, sapi), + ctrl := { + ui := t_LlcCtrlUI(n_u) + }, + payload := payload + }; } with { encode "RAW"; variant "FIELDORDER(msb)" } diff --git a/gprs_gb/NS_Emulation.ttcn b/gprs_gb/NS_Emulation.ttcn index 99607a02f..253c91e78 100644 --- a/gprs_gb/NS_Emulation.ttcn +++ b/gprs_gb/NS_Emulation.ttcn @@ -102,9 +102,9 @@ module NS_Emulation { } modulepar { - PortNumber mp_local_udp_port := 23001; + PortNumber mp_local_udp_port := 23000; charstring mp_local_ip := "127.0.0.1"; - PortNumber mp_remote_udp_port := 23000; + PortNumber mp_remote_udp_port := 21000; charstring mp_remote_ip := "127.0.0.1"; Nsvci mp_nsvci := 0; Nsvci mp_nsei := 2342; diff --git a/gprs_gb/Test.cfg b/gprs_gb/Test.cfg index 252704fb6..215562893 100644 --- a/gprs_gb/Test.cfg +++ b/gprs_gb/Test.cfg @@ -1,11 +1,14 @@ [LOGGING] +#*.FileMask := LOG_ALL +ConsoleMask := ERROR | WARNING | TESTCASE | TIMEROP_START | DEBUG_ENCDEC [MODULE_PARAMETERS] -mp_local_ip := "192.168.100.239" -mp_local_udp_port := 23000 -mp_remote_ip := "192.168.100.196" -mp_remote_udp_port := 21000 +#mp_local_ip := "192.168.100.239" +#mp_local_udp_port := 23000 +#mp_remote_ip := "192.168.100.196" +#mp_remote_udp_port := 21000 mp_nsei := 96 +mp_bvci := 196 [TESTPORT_PARAMETERS] #*.BSCVTY.CTRL_MODE := "client" @@ -24,4 +27,10 @@ mp_nsei := 96 [MAIN_CONTROLLER] [EXECUTE] -Test.TC_nsem +#Test.TC_selftest_llc +#Test.TC_selftest_rlcmac +#Test.TC_selftest_bssgp +#Test.TC_nsem +#Test.TC_paging +Test.TC_rach +#Test.TC_selftest_rr diff --git a/gprs_gb/Test.ttcn b/gprs_gb/Test.ttcn index 6e772dc08..759f23c4a 100644 --- a/gprs_gb/Test.ttcn +++ b/gprs_gb/Test.ttcn @@ -1,18 +1,47 @@ module Test { + import from General_Types all; + import from Osmocom_Types all; + import from GSM_Types all; + import from GSM_RR_Types all; import from BSSGP_Helper_Functions all; import from BSSGP_Types all; import from BSSGP_Emulation all; import from NS_Types all; import from NS_Emulation all; + import from LLC_Types all; + import from MobileL3_Types all; + import from RLCMAC_Types all; + import from RLCMAC_CSN1_Types all; + import from LAPDm_RAW_PT all; + + type record MmContext { + octetstring imsi optional, + BssgpTlli tlli, + uint9_t n_u + }; type component dummy_CT { + var lapdm_CT lapdm_component; + port LAPDm_PT L1; + port BSSGP_PT BSSGP; var NS_CT ns_component; var BSSGP_CT bssgp_component; + + var MmContext g_mmctx := { + tlli := 0, + n_u := 0 + }; + + var boolean g_initialized := false; } function f_init() runs on dummy_CT { + if (g_initialized == true) { + return; + } + g_initialized := true; /* create a new NS component */ ns_component := NS_CT.create; bssgp_component := BSSGP_CT.create; @@ -24,6 +53,11 @@ module Test { map(ns_component:NSCP, system:NS_CODEC_PORT); ns_component.start(NSStart()); bssgp_component.start(BssgpStart()); + + lapdm_component := lapdm_CT.create; + connect(self:L1, lapdm_component:LAPDM_SP); + map(lapdm_component:L1CTL, system:L1CTL); + lapdm_component.start(LAPDmStart()); } function f_bssgp_assert_prepr(in octetstring a, in octetstring b) { @@ -91,6 +125,8 @@ module Test { f_bssgp_dec_and_log(c_gmm_mt_att_acc); f_bssgp_dec_and_log(c_gmm_mt_det_req); f_bssgp_dec_and_log(c_gmm_mo_att_cpl); + + log(t_BSSGP_PS_PAGING_IMSI(196, '262420123456789'H)); } function f_ns_assert_prepr(in octetstring a, in octetstring b) { @@ -132,7 +168,76 @@ module Test { f_ns_dec_and_log(c_ns_reset_pcu); } - testcase TC_nsem() runs on dummy_CT { + const BssgpQosProfile c_DefaultQos := { r := 80, spare := '00'B, c_r := false, t := false, a := false, precedence := 0 }; + template BssgpTLV c_DefaultLifetimeTLV := t_BSSGP_IE_Lifetime(65535); + + template BssgpTLV t_BSSGP_IE_LLC_PDU(LlcPdu llc) := t_BssgpIE(LLC_PDU, { other := f_LLC_append_fcs(enc_LlcPdu(llc)) }); + + template BssgpPdu t_BSSGP_DL_UD(BssgpTlli tlli, LlcPdu llc, BssgpTLVs opt_tlvs := {}) := { + pdu_type := DL_UNITDATA, + u := { + dl_unitdata := { + tlli := tlli, + qos_profile := c_DefaultQos, + pdu_lifetime := c_DefaultLifetimeTLV, + //tlvs := opt_tlvs & { t_BSSGP_IE_LLC_PDU(llc) } + tlvs := { t_BSSGP_IE_LLC_PDU(llc) } + } + } + }; + + template BssgpPdu t_BSSGP_UL_UD(template BssgpTlli tlli, template BssgpCellId cell_id, template octetstring payload) := { + pdu_type := UL_UNITDATA, + u := { + ul_unitdata := { + tlli := tlli, + qos_profile := ?, + cell_id := { iei := CELL_ID, len := 8, u := { cell_id := cell_id } }, + tlvs := { + { iei := ALIGNMENT_OCTETS, len := ?, u := { other := ? } }, + { iei := LLC_PDU, len := ?, u := { other := payload } } + } + } + } + } + + template BssgpPdu t_BSSGP_PS_PAGING_IMSI(BssgpBvci bvci, hexstring imsi) := { + pdu_type := PAGING_PS, + u := { + other := { + tlvs := { t_BSSGP_IE_Imsi(imsi), t_BSSGP_IE_Bvci(bvci), t_BSSGP_IE_Qos(c_DefaultQos) } + } + } + }; + + template BssgpPdu t_BSSGP_PS_PAGING_PTMSI(BssgpBvci bvci, hexstring imsi, GsmTmsi ptmsi) := { + pdu_type := PAGING_PS, + u := { + other := { + tlvs := { t_BSSGP_IE_Imsi(imsi), t_BSSGP_IE_Bvci(bvci), t_BSSGP_IE_Qos(c_DefaultQos), t_BSSGP_IE_Tmsi(ptmsi) } + } + } + }; + + const octetstring gmm_auth_req := '081200102198c72477ea104895e8b959acc58b108182'O; + + function tx_gmm(boolean c_r, in octetstring gmm_pdu, LlcSapi sapi := LLC_SAPI_GMM) runs on dummy_CT { + var LlcPdu llc; + + log("GMM Tx: ", dec_PDU_L3_SGSN_MS(gmm_pdu)); + + log(c_r, g_mmctx.n_u, gmm_pdu, sapi); + log(t_LLC_UI(c_r, g_mmctx.n_u, gmm_pdu, sapi)); + llc := valueof(t_LLC_UI(c_r, g_mmctx.n_u, gmm_pdu, sapi)); + log(llc); + g_mmctx.n_u := g_mmctx.n_u + 1; + + log(t_BSSGP_DL_UD(g_mmctx.tlli, llc)); + + BSSGP.send(t_BSSGP_DL_UD(g_mmctx.tlli, llc)); + } + + function f_bssgp_establish() runs on dummy_CT { timer T:= 60.0; f_init(); @@ -144,6 +249,17 @@ module Test { } T.stop log("BSSGP successfully initialized"); + } + + testcase TC_paging() runs on dummy_CT { + var hexstring imsi := '262420123456789'H; + var BssgpBvci bvci := 196; + var GsmTmsi tmsi := hex2int('01234567'H); + + f_bssgp_establish(); + + BSSGP.send(t_BSSGP_PS_PAGING_IMSI(bvci, imsi)); + BSSGP.send(t_BSSGP_PS_PAGING_PTMSI(bvci, imsi, tmsi)); while (true) { var BssgpPdu pdu; @@ -157,9 +273,329 @@ module Test { } } + function f_establish_ul_tbf() runs on dummy_CT { + timer T := 5.0; + var BCCH_tune_req tune_req := { { false, 871 }, true }; + L1.send(tune_req); + /* FIXME: wait for confirm */ + + var TBF_establish_req est_req := { ra := hex2int('7B'H) }; + L1.send(est_req); + T.start; + /* FIXME: wait for confirm */ + alt { + [] L1.receive(TBF_establish_res:?) {} + [] L1.receive { repeat; } + [] T.timeout { setverdict(fail); } + } + T.stop; + } + + template RlcmacUlBlock t_RLCMAC_UL_DATA(template uint5_t tfi, template uint4_t cv, template uint7_t bsn, + template LlcBlocks blocks := {}, template boolean stall := false) := { + data := { + mac_hdr := { + payload_type := MAC_PT_RLC_DATA, + countdown := cv, + stall_ind := false, + retry := false, + spare := '0'B, + pfi_ind := false, + tfi := tfi, + tlli_ind := false, + bsn := bsn, + e := false + }, + tlli := omit, + pfi := omit, + blocks := blocks + } + } + template RlcmacUlBlock t_RLCMAC_UL_DATA_TLLI(template uint5_t tfi, template uint4_t cv, template uint7_t bsn, + template LlcBlocks blocks := {}, template boolean stall := false, template GprsTlli tlli) modifies t_RLCMAC_UL_DATA := { + data := { + tlli := tlli + } + } + + template DlMacHeader t_RLCMAC_DlMacH(template MacPayloadType pt, template MacRrbp rrbp, template +uint3_t usf) := { + payload_type := pt, + rrbp := rrbp, + rrbp_valid := fixme, + usf := usf + } + + template RlcmacDlBlock tr_RLCMAC_ACK_NACK(template uint5_t ul_tfi, template GprsTlli tlli := ?) := { + ctrl := { + mac_hdr := { + payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT), + rrbp:= ?, + rrbp_valid := true, + usf := ? + }, + opt := *, + payload := { + msg_type := PACKET_UL_ACK_NACK, + u := { + ul_ack_nack := { + page_mode := ?, + msg_excape := ?, + uplink_tfi := ul_tfi, + is_egprs := '0'B, + gprs := { + ch_coding_cmd := ?, + ack_nack_desc := ?, + cont_res_tlli_present := ?, + cont_res_tlli := tlli, + pkt_ta_present := ?, + pkt_ta := *, + pwr_ctrl_present := ?, + pwr_ctrl := * + } + } + } + } + } + } + + template UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template MacPayloadType pt, template boolean retry := false) := { + payload_type := pt, + spare := '00000'B, + retry := retry + } + + template RlcmacUlBlock ts_RLCMAC_CTRL_ACK(GprsTlli tlli, CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := { + ctrl := { + mac_hdr := t_RLCMAC_UlMacCtrlH(MAC_PT_RLCMAC_NO_OPT), + payload := { + msg_type := PACKET_CONTROL_ACK, + u := { + ctrl_ack := { + tlli := tlli, + ctrl_ack := ack + } + } + } + } + } + + template LlcBlock t_RLCMAC_LLCBLOCK(octetstring data, BIT1 more := '0'B, boolean e := true) := { + hdr := { + length_ind := lengthof(data), + more := more, + e := e + }, + payload := data + } + + function f_random_tlli() return GprsTlli { + var GprsTlli tlli := float2int(rnd()* 4294967295.0); + return tlli; + } + + function f_single_ul_block(GprsCodingScheme cs) runs on dummy_CT { + var GprsTlli tlli := f_random_tlli(); + var octetstring payload := '01020304'O; + + /* establish upling TBF */ + f_establish_ul_tbf(); + + /* Generate LLC PDU consisting of single RLC block and send it via simulated MS */ + var template RlcmacUlBlock blk := t_RLCMAC_UL_DATA_TLLI(0, 0, 0, {t_RLCMAC_LLCBLOCK(payload)}, false, tlli); + L1.send(RLCMAC_ph_data_req:{tbf_id := 0, cs := cs, block := blk}); + /* ensure that this LLC-PDU arrives from the right TLLI at the (simulated) SGSN */ + BSSGP.receive(t_BSSGP_UL_UD(tlli, ?, payload)); + + /* ensure the MS eceives an UL_ACK_NACK */ + alt { + [] L1.receive(RLCMAC_ph_data_ind:{cs:=?, block:=tr_RLCMAC_ACK_NACK(0, tlli)}) { }; + [] L1.receive { repeat; }; + } + log("found matching ACK/NACK"); + /* send CTRL ACK in uplink */ + //L1.send(FIXME); + } + + testcase TC_rach() runs on dummy_CT { + var hexstring imsi := '262420123456789'H; + var BssgpBvci bvci := 196; + var GsmTmsi tmsi := hex2int('01234567'H); + + f_init(); + + f_bssgp_establish(); + + f_single_ul_block(CS1); + + while (true) { + var BssgpPdu pdu; + var RLCMAC_ph_data_ind dl_msg; + alt { + + [] BSSGP.receive(BssgpPdu:?) -> value pdu { + log("BSSGP Rx: ", pdu); + } + [] BSSGP.receive(t_BssgpStsInd(?, ?, BVC_S_UNBLOCKED)) { repeat; } + [] BSSGP.receive { repeat; } + + [] L1.receive(RLCMAC_ph_data_ind:?) -> value dl_msg { + log("L1 DL: ", dl_msg); + } + } + } + } + + + testcase TC_nsem() runs on dummy_CT { + + f_bssgp_establish(); + + while (true) { + var BssgpPdu pdu; + alt { + [] BSSGP.receive(BssgpPdu:?) -> value pdu { + log("BSSGP Rx: ", pdu); + //log("GMM Rx: ", dec_PDU_L3_MS_SGSN(pdu.payload)); + g_mmctx.tlli := pdu.u.ul_unitdata.tlli; + tx_gmm(LLC_CR_DL_CMD, gmm_auth_req); + } + [] BSSGP.receive(t_BssgpStsInd(?, ?, BVC_S_UNBLOCKED)) { repeat; } + [] BSSGP.receive { repeat; } + } + } + } + + + function f_llc_dec_and_log(in octetstring inp) { + log("LLC Input: ", inp); + var LlcPdu dec := dec_LlcPdu(inp); + log("LLC Decoded: ", dec); + } + + function f_llc_assert(in octetstring a, in octetstring b) { + log("LLC Input: ", a); + log("LLC Expected: ", b); + + if (a != b) { + setverdict(fail); + } else { + setverdict(pass); + } + } + + + testcase TC_selftest_llc() runs on dummy_CT { + const octetstring c_gmm_att_pcu := '01c001080103e5e000210a0005f4fb146ddd32f44000c8001d1b53432b37159ef9090070000dd9c6321200e00019b32c642401c00020170580460b'O; + const octetstring c_gmm_att_pcu_nofcs := '01c001080103e5e000210a0005f4fb146ddd32f44000c8001d1b53432b37159ef9090070000dd9c6321200e00019b32c642401c000201705'O; + const octetstring c_ctrl_ui := 'c001'O; + + log(dec_LlcCtrlUnion(c_ctrl_ui)); + f_llc_assert(enc_LlcCtrlUnion({ ui := { presence := '110'B, spare := '00'B, n_u := 0, e := false, pm := true } }), c_ctrl_ui); + + f_llc_dec_and_log(c_gmm_att_pcu); + + f_llc_assert(f_LLC_append_fcs(c_gmm_att_pcu_nofcs), c_gmm_att_pcu); + + log(valueof(t_LLC_UI(LLC_CR_DL_CMD, g_mmctx.n_u, gmm_auth_req, LLC_SAPI_GMM))); + log(t_LLC_UI(LLC_CR_DL_CMD, g_mmctx.n_u, gmm_auth_req, LLC_SAPI_GMM)); + } + + testcase TC_selftest_rlcmac() runs on dummy_CT { + var RlcmacDlCtrlBlock dcb; + var RlcmacUlCtrlBlock ucb; + const octetstring c_dl_ul_ack_nack := '40240080400000000000000077628dbba14b2b2b2b2b2b'O; + const octetstring c_dl_data := '0f00007341c001081200102198c72477ea104895e8b959acc58b108182f4d0454300'O; + const octetstring c_dl_data2 := '070002165dc0012b2b2b43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b00'O; + const octetstring c_ul_ctrl_ack := '4006ec51b7772b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b'O; + const octetstring c_ul_dl_ack_nack := '4008004000000000000000701000edc0000b2b2b2b2b2b'O; + const octetstring c_dl_ul_assign := '482857628dbbaf0126e68800082b2b2b2b2b2b2b2b2b2b'O; + + log(c_dl_ul_ack_nack); + dcb := dec_RlcmacDlCtrlBlock(c_dl_ul_ack_nack); + log(dcb); + //log(dec_RlcmacDlCtrlMsg(dcb.payload)); + + f_rlcmac_dld_decenc(c_dl_data); + + f_rlcmac_dld_decenc(c_dl_data2); + + log(c_ul_ctrl_ack); + ucb := dec_RlcmacUlCtrlBlock(c_ul_ctrl_ack); + log(ucb); + //log(dec_RlcmacUlCtrlMsg(ucb.payload)); + + log(c_ul_dl_ack_nack); + ucb := dec_RlcmacUlCtrlBlock(c_ul_dl_ack_nack); + log(ucb); + //log(dec_RlcmacUlCtrlMsg(ucb.payload)); + + log(c_dl_ul_assign); + dcb := dec_RlcmacDlCtrlBlock(c_dl_ul_assign); + log(dcb); + //log(dec_RlcmacDlCtrlMsg(dcb.payload)); + + const octetstring c_uld_tlli_noext := '080101a61cab5201c001080103e5e000310a0005f4e61cab5232f44000c8001d1b00'O; + f_rlcmac_uld_decenc(c_uld_tlli_noext); + + const octetstring c_uld_tlli_ext7pad := '0001041da61cab5200201705a96e102b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b00'O; + log("ULD_decenc"); + f_rlcmac_uld_decenc(c_uld_tlli_ext7pad); + log("UL_decenc"); + f_rlcmac_ul_decenc(c_uld_tlli_ext7pad); + + f_rlcmac_ul_decenc(c_ul_dl_ack_nack); + } + + function f_rlcmac_ul_decenc(in octetstring buf) { + log("=================================="); + log("In: ", buf); + var RlcmacUlBlock udb := dec_RlcmacUlBlock(buf); + log("Dec: ", udb); + var octetstring enc := enc_RlcmacUlBlock(udb); + log("Enc: ", enc); + if (enc != buf) { setverdict(fail, "Re-encoded data doesn't equal input data"); } + } + + function f_rlcmac_uld_decenc(in octetstring buf) { + log("=================================="); + log("In: ", buf); + var RlcmacUlDataBlock udb := dec_RlcmacUlDataBlock(buf); + log("Dec: ", udb); + var octetstring enc := enc_RlcmacUlDataBlock(udb); + log("Enc: ", enc); + if (enc != buf) { setverdict(fail, "Re-encoded data doesn't equal input data"); } + } + + function f_rlcmac_dld_decenc(in octetstring buf) { + log("=================================="); + log("In: ", buf); + var RlcmacDlDataBlock udb := dec_RlcmacDlDataBlock(buf); + log("Dec: ", udb); + var octetstring enc := enc_RlcmacDlDataBlock(udb); + log("Enc: ", enc); + if (enc != buf) { setverdict(fail, "Re-encoded data doesn't equal input data"); } + } + + + testcase TC_selftest_rr() runs on dummy_CT { + //const octetstring c_paging_none := '06210001F02B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O + const octetstring c_paging_none := '1506210001F0'O; + const octetstring c_ia_tbf := '2d063f100fe3677bd8440000c800100b2b2b2b2b2b2b2b'O + log(c_paging_none); + log(dec_GsmRrMessage(c_paging_none)); + + log(c_ia_tbf); + log(dec_GsmRrMessage(c_ia_tbf)); + } + control { execute(TC_selftest_bssgp()); execute(TC_selftest_ns()); + execute(TC_selftest_llc()); + execute(TC_selftest_rr()); + execute(TC_selftest_rlcmac()); execute(TC_nsem()); + execute(TC_paging()); } }; diff --git a/gprs_gb/gen_links.sh b/gprs_gb/gen_links.sh index e93969050..bdfb24101 100755 --- a/gprs_gb/gen_links.sh +++ b/gprs_gb/gen_links.sh @@ -27,8 +27,14 @@ DIR=$BASEDIR/titan.TestPorts.IPL4asp/src FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh" gen_links $DIR $FILES +DIR=../MobileL3_v13.4.0_CNL113832_LATEST/src +FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn SS_DataTypes.asn SS_EncDec.cc SS_Errors.asn SS_Operations.asn SS_PDU_Defs.asn SS_Protocol.asn SS_Types.ttcn" +gen_links $DIR $FILES +DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src +FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn" +gen_links $DIR $FILES DIR=../library -FILES="General_Types.ttcn GSM_Types.ttcn GSM_RR_Types.ttcn Osmocom_Types.ttcn RLCMAC_Types.ttcn RLCMAC_EncDec.cc L1CTL_Types.ttcn L1CTL_PortType.ttcn" +FILES="General_Types.ttcn GSM_Types.ttcn GSM_RR_Types.ttcn Osmocom_Types.ttcn RLCMAC_Types.ttcn RLCMAC_EncDec.cc L1CTL_Types.ttcn L1CTL_PortType.ttcn LAPDm_RAW_PT.ttcn LAPDm_Types.ttcn" gen_links $DIR $FILES diff --git a/gprs_gb/regen_makefile.sh b/gprs_gb/regen_makefile.sh index a985592d3..812ff489e 100755 --- a/gprs_gb/regen_makefile.sh +++ b/gprs_gb/regen_makefile.sh @@ -1,9 +1,9 @@ #!/bin/sh -FILES="*.ttcn BSSGP_Helper.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc NS_CodecPort_CtrlFunctDef.cc" +FILES="*.ttcn BSSGP_Helper.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc NS_CodecPort_CtrlFunctDef.cc UD_PT.cc RLCMAC_EncDec.cc" ttcn3_makefilegen -f Test.ttcn $FILES sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile -sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan `pkg-config --libs libnetfilter_conntrack`/' Makefile +sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan/' Makefile #sed -i -e 's/TTCN3_LIB = ttcn3-parallel/TTCN3_LIB = ttcn3/' Makefile sed -i -e 's/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include -I\/usr\/include\/titan/' Makefile diff --git a/library/RLCMAC_EncDec.cc b/library/RLCMAC_EncDec.cc index 86fe7f325..4cdeae7e6 100644 --- a/library/RLCMAC_EncDec.cc +++ b/library/RLCMAC_EncDec.cc @@ -16,7 +16,8 @@ OCTETSTRING enc__RlcmacDlDataBlock(const RlcmacDlDataBlock& si) int i; /* Fix 'e' bit of initial header based on following blocks */ - if (!in.blocks().is_bound() || (in.blocks().size_of() == 1 && !in.blocks()[0].hdr().is_bound())) + if (!in.blocks().is_bound() || + (in.blocks().size_of() == 1 && !in.blocks()[0].hdr().is_bound())) in.mac__hdr().hdr__ext().e() = true; else in.mac__hdr().hdr__ext().e() = false; @@ -107,7 +108,8 @@ OCTETSTRING enc__RlcmacUlDataBlock(const RlcmacUlDataBlock& si) int i; /* Fix 'e' bit of initial header based on following blocks */ - if (!in.blocks().is_bound() || (in.blocks().size_of() == 1 && !in.blocks()[0].hdr().is_bound())) + if (!in.blocks().is_bound() || + (in.blocks().size_of() == 1 && !in.blocks()[0].hdr().is_bound())) in.mac__hdr().e() = true; else in.mac__hdr().e() = false; diff --git a/sysinfo/Test.ttcn b/sysinfo/Test.ttcn index 77e46fc3c..e7cdcfe58 100644 --- a/sysinfo/Test.ttcn +++ b/sysinfo/Test.ttcn @@ -691,8 +691,8 @@ module Test { testcase TC_telnet() runs on dummy_CT { f_init(); - f_vty_enter_config(BSCVTY); f_vty_transceive(BSCVTY, "show network") + f_vty_enter_config(BSCVTY); f_vty_transceive(BSCVTY, "network") f_vty_transceive(BSCVTY, "bts 0") f_vty_transceive(BSCVTY, "end")