From 52562c9ca1c9d18442d3e28096ccc7c06e798fc7 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 23 May 2022 15:45:46 +0200 Subject: [PATCH] ggsn: test Gy Volume-Quote-Threshold feature Change-Id: If10171589e915db8e78278d2d802e38c66b37687 --- ggsn_tests/GGSN_Tests.ttcn | 73 ++++++++++++++++++++++++++++++--- library/DIAMETER_Templates.ttcn | 39 ++++++++++++++++++ 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/ggsn_tests/GGSN_Tests.ttcn b/ggsn_tests/GGSN_Tests.ttcn index 875a9d618..ddc651c33 100644 --- a/ggsn_tests/GGSN_Tests.ttcn +++ b/ggsn_tests/GGSN_Tests.ttcn @@ -141,6 +141,7 @@ module GGSN_Tests { port DIAMETER_PT Gy_UNIT; port DIAMETEREM_PROC_PT Gy_PROC; var integer g_gy_validity_time := 0; /* In seconds. 0 => disabled, !0 => grant over CC-Time period */ + var integer g_gy_volume_threshold := 0; /* In octets. 0 => disabled, !0 => request IUT to revalidate after N octets */ var PDU_DIAMETER g_rx_gy; /* Store last received Gy message */ } @@ -667,8 +668,13 @@ module GGSN_Tests { avp := f_DIAMETER_get_avp(g_rx_gy, c_AVP_Code_DCC_NONE_CC_Request_Number); req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number); if (g_gy_validity_time > 0) { - tx_dia := ts_DIA_Gy_CCA_ValidityTime(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id, - req_type, req_num, g_gy_validity_time); + if (g_gy_volume_threshold > 0) { + tx_dia := ts_DIA_Gy_CCA_ValidityTimeVolumeThreshold(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id, + req_type, req_num, g_gy_validity_time, g_gy_volume_threshold); + } else { + tx_dia := ts_DIA_Gy_CCA_ValidityTime(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id, + req_type, req_num, g_gy_validity_time); + } } else { tx_dia := ts_DIA_Gy_CCA(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id, req_type, req_num); @@ -812,14 +818,14 @@ module GGSN_Tests { const octetstring c_neigh_solicit:= '6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff00000287009f9600000000fe80000000000000000000000000000201010288b51f2559'O; /* template for sending an ICMPv4 echo request */ - template PDU_ICMP ts_ICMPv4_ERQ := { + template PDU_ICMP ts_ICMPv4_ERQ(octetstring data := ''O) := { echo := { type_field := 8, code := 0, checksum := '0000'O, identifier := '0345'O, sequence_number := '0001'O, - data := ''O + data := data } } @@ -1112,8 +1118,8 @@ module GGSN_Tests { } /* Send an ICMPv4 echo msg through GTP given pdp ctx, and ip src and dst addr */ - function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr) return octetstring { - var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ)); + function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr, octetstring pl := ''O) return octetstring { + var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ(pl))); var IPv4_packet ip4 := valueof(ts_IP4(saddr, daddr, 1, 50, tmp)); var octetstring data := f_IPv4_enc(ip4); var OCT2 cksum := f_IPv4_checksum(data); @@ -2429,6 +2435,60 @@ module GGSN_Tests { f_shutdown_helper(); } + /* Test Volume-Quota-Thresold AVP triggers request before Validity-Time */ + testcase TC_gy_charging_volume_quota_threshold() runs on GT_CT { + var default d; + timer Tout; + g_gy_volume_threshold := 1000; /* Will make a trigger when we send bigger payload below */ + g_gy_validity_time := 8; /* Grant access for 8 seconds, needs to be re-validated afterwards */ + f_init(); + var float tout_sec := int2float(g_gy_validity_time) / 2.0; + var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn))); + ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT); + f_pdp_ctx_act(ctx); + + var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O); + + T_default.start(40.0); + d := activate(pingpong()); + + /* Send some UL traffic: */ + var octetstring payload := f_rnd_octstring(1200); + var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address; + f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr, payload)); + f_wait_icmp4_echo_reply(ctx); + + /* ICMP Req generates one report: */ + Tout.start(tout_sec); + alt { + [] as_DIA_Gy_CCR(ctx, UPDATE_REQUEST); + [] Tout.timeout { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + "TImeout waiting for Gy UPDATE triggered by Volume-Quota-Threshold"); + } + } + f_validate_gy_cc_report(g_rx_gy, THRESHOLD, (0..6), 0, (1200..1400)); + + /* ICMP Resp (echo back) generates one report: */ + as_DIA_Gy_CCR(ctx, UPDATE_REQUEST); + f_validate_gy_cc_report(g_rx_gy, THRESHOLD, (0..1), (1200..1400), 0); + + /* Second update: 0 ul/dl pkt/octet should be reported, since nothing was sent */ + as_DIA_Gy_CCR(ctx, UPDATE_REQUEST); + f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (8..9), 0, 0); + + /* Let the CCA reach the GGSN */ + f_sleep(0.5); + deactivate(d); + T_default.stop; + + f_pdp_ctx_del(ctx, '1'B); + f_validate_gy_cc_report(g_rx_gy, FINAL, (0..2), 0, 0); + + + f_shutdown_helper(); + } + control { execute(TC_pdp4_act_deact()); execute(TC_pdp4_act_deact_ipcp()); @@ -2479,6 +2539,7 @@ module GGSN_Tests { /* open5gs specific tests: */ if (m_ggsn_impl == GGSN_IMPL_OPEN5GS) { execute(TC_gy_charging_cc_time()); + execute(TC_gy_charging_volume_quota_threshold()); } } } diff --git a/library/DIAMETER_Templates.ttcn b/library/DIAMETER_Templates.ttcn index 03fec7c86..2bc9e7732 100644 --- a/library/DIAMETER_Templates.ttcn +++ b/library/DIAMETER_Templates.ttcn @@ -1195,6 +1195,15 @@ template (value) GenericAVP ts_AVP_Validity_Time(uint32_t validity_time_val) := } } +template (value) GenericAVP ts_AVP_3GPP_VolumeQuotaThreshold(uint32_t volume_quota_thresh_val) := { + avp := { + avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_Volume_Quota_Threshold), + avp_data := { + avp_DCA_3GPP_Volume_Quota_Threshold := int2oct(volume_quota_thresh_val, 4) + } + } +} + template (present) GenericAVP tr_AVP_3GPP_CalledStationId(template (present) DNAS_NONE_Called_Station_Id id := ?) := { avp := { avp_header := tr_DIA_Hdr(c_AVP_Code_DNAS_NONE_Called_Station_Id), @@ -1541,6 +1550,36 @@ ts_DIA_Gy_CCA_ValidityTime(template (value) UINT32 hbh_id, template (value) UINT // supported features // origin }); +/* Same as ts_DIA_Gy_CCA_ValidityTime, but with extra AVP to grant access for limited amount of octets */ +template (value) PDU_DIAMETER +ts_DIA_Gy_CCA_ValidityTimeVolumeThreshold(template (value) UINT32 hbh_id, template (value) UINT32 ete_id, + template (value) octetstring sess_id, + template (value) DCC_NONE_CC_Request_Type req_type, + template (value) AVP_Unsigned32 req_num, + uint32_t validity_time, uint32_t volume_threhsold) +:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control, + app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id, + avps := { + ts_AVP_SessionId(sess_id), + ts_AVP_ResultCode(DIAMETER_SUCCESS), + ts_AVP_OriginHost("ocs.localdomain"), + ts_AVP_OriginRealm("localdomain"), + ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)), + ts_AVP_CcReqType(req_type), + ts_AVP_CcReqNum(req_num), + ts_AVP_Multiple_Services_Credit_Control({ + ts_AVP_Validity_Time(validity_time), + ts_AVP_Granted_Service_Unit({ + ts_AVP_CC_Total_Octets(volume_threhsold*100) + }), + ts_AVP_3GPP_VolumeQuotaThreshold(volume_threhsold) + }) + //, + // qos + // default eps bearer qos + // supported features + // origin + }); /* RFC 6733, section 5.5.1 "Device-Watchdog-Request" */ template (value) PDU_DIAMETER