ggsn: Validate charging reported values
Change-Id: I497309bb0b30c61bdb00e0c08f18294ecd4dd485
diff --git a/ggsn_tests/GGSN_Tests.ttcn b/ggsn_tests/GGSN_Tests.ttcn
index 4a5f0ba..4e6581c 100644
--- a/ggsn_tests/GGSN_Tests.ttcn
+++ b/ggsn_tests/GGSN_Tests.ttcn
@@ -141,6 +141,7 @@
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 PDU_DIAMETER g_rx_gy; /* Store last received Gy message */
}
private function f_init_vty() runs on GT_CT {
@@ -653,30 +654,29 @@
}
private altstep as_DIA_Gy_CCR(template (omit) PdpContext ctx, DCC_NONE_CC_Request_Type req_type) runs on GT_CT {
- var PDU_DIAMETER rx_dia;
- [] Gy_UNIT.receive(f_tr_DIA_Gy_CCR(ctx, req_type := req_type)) -> value rx_dia {
+ [] Gy_UNIT.receive(f_tr_DIA_Gy_CCR(ctx, req_type := req_type)) -> value g_rx_gy {
var template (value) PDU_DIAMETER tx_dia;
var template (omit) AVP avp;
var octetstring sess_id;
var AVP_Unsigned32 req_num;
- avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
+ avp := f_DIAMETER_get_avp(g_rx_gy, c_AVP_Code_BASE_NONE_Session_Id);
sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
- avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_DCC_NONE_CC_Request_Number);
+ 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(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
+ 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(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
+ 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);
}
Gy_UNIT.send(tx_dia);
}
- [] Gy_UNIT.receive(PDU_DIAMETER:?) -> value rx_dia {
+ [] Gy_UNIT.receive(PDU_DIAMETER:?) -> value g_rx_gy {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Received unexpected DIAMETER Gy", rx_dia));
+ log2str("Received unexpected DIAMETER Gy", g_rx_gy));
}
}
@@ -2397,9 +2397,11 @@
g_gy_validity_time := 2;
/* First update reports octests/pkt on both UL/DL (see icmp ping-pong above) */
as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (3..4), 28, 28);
/* 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, (2..3), 0, 0);
/* Third update: make sure report contains again octets/pkts for both UL/DL: */
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
@@ -2407,6 +2409,7 @@
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
f_wait_icmp4_echo_reply(ctx);
as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (2..3), 56, 56);
/* Let the CCA reach the GGSN */
f_sleep(0.5);
@@ -2419,6 +2422,7 @@
f_wait_icmp4_echo_reply(ctx);
f_pdp_ctx_del(ctx, '1'B);
+ f_validate_gy_cc_report(g_rx_gy, FINAL, (0..2), 28, 28);
f_shutdown_helper();
diff --git a/library/DIAMETER_Emulation.ttcn b/library/DIAMETER_Emulation.ttcn
index 748b452..09f92be 100644
--- a/library/DIAMETER_Emulation.ttcn
+++ b/library/DIAMETER_Emulation.ttcn
@@ -211,23 +211,6 @@
}
}
-function f_DIAMETER_get_avp(PDU_DIAMETER pdu, template (present) AVP_Code avp_code)
-return template (omit) AVP
-{
- var integer i;
-
- for (i := 0; i < lengthof(pdu.avps); i := i+1) {
- if (not ispresent(pdu.avps[i].avp)) {
- continue;
- }
- var AVP_Header hdr := pdu.avps[i].avp.avp_header;
- if (match(hdr.avp_code, avp_code)) {
- return pdu.avps[i].avp;
- }
- }
- return omit;
-}
-
function f_DIAMETER_get_imsi(PDU_DIAMETER pdu) return template (omit) IMSI
{
var template (omit) AVP imsi_avp;
diff --git a/library/DIAMETER_Templates.ttcn b/library/DIAMETER_Templates.ttcn
index 855358d..4b17ac5 100644
--- a/library/DIAMETER_Templates.ttcn
+++ b/library/DIAMETER_Templates.ttcn
@@ -11,6 +11,7 @@
import from DIAMETER_Types all;
import from Osmocom_Types all;
+import from Misc_Helpers all;
/* https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xhtml#aaa-parameters-4 */
type enumerated DIAMETER_Resultcode {
@@ -1611,4 +1612,100 @@
tr_AVP_OriginStateId(state_id)
));
+function f_DIAMETER_get_avp(PDU_DIAMETER pdu, template (present) AVP_Code avp_code)
+return template (omit) AVP
+{
+ var integer i;
+
+ for (i := 0; i < lengthof(pdu.avps); i := i+1) {
+ if (not ispresent(pdu.avps[i].avp)) {
+ continue;
+ }
+ var AVP_Header hdr := pdu.avps[i].avp.avp_header;
+ if (match(hdr.avp_code, avp_code)) {
+ return pdu.avps[i].avp;
+ }
+ }
+ return omit;
+}
+function f_DIAMETER_get_avp_or_fail(PDU_DIAMETER pdu, template (present) AVP_Code avp_code)
+return AVP
+{
+ var template (omit) AVP avp;
+ avp := f_DIAMETER_get_avp(pdu, avp_code);
+ if (istemplatekind(avp, "omit")) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("AVP ", avp_code, " not found in ", pdu));
+ }
+ return valueof(avp);
+}
+
+function f_AVP_Grouped_get_avp(AVP_Grouped avp_grp, template (present) AVP_Code avp_code)
+return template (omit) AVP
+{
+ var integer i;
+
+ for (i := 0; i < lengthof(avp_grp); i := i+1) {
+ if (not ispresent(avp_grp[i].avp)) {
+ continue;
+ }
+ var AVP_Header hdr := avp_grp[i].avp.avp_header;
+ if (match(hdr.avp_code, avp_code)) {
+ return avp_grp[i].avp;
+ }
+ }
+ return omit;
+}
+function f_AVP_Grouped_get_avp_or_fail(AVP_Grouped avp_grp, template (present) AVP_Code avp_code)
+return AVP
+{
+ var template (omit) AVP avp;
+ avp := f_AVP_Grouped_get_avp(avp_grp, avp_code);
+ if (istemplatekind(avp, "omit")) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("AVP ", avp_code, " not found in ", avp_grp));
+ }
+ return valueof(avp);
+}
+
+function f_validate_gy_cc_report(PDU_DIAMETER rx_dia, template (present) DCA_3GPP_Reporting_Reason repreason_exp := ?,
+ template (present) integer cc_time_exp := ?,
+ template (present) integer cc_in_oct_exp := ?,
+ template (present) integer cc_out_oct_exp := ?)
+{
+ var AVP multi_services_cc, used_service_unit;
+ var AVP_Grouped multi_services_cc_data, used_service_unit_data;
+ var AVP repreason, cc_time, cc_in_oct, cc_out_oct;
+
+ multi_services_cc := f_DIAMETER_get_avp_or_fail(rx_dia, c_AVP_Code_DCC_NONE_Multiple_Services_Credit_Control);
+ multi_services_cc_data := valueof(multi_services_cc.avp_data.avp_DCC_NONE_Multiple_Services_Credit_Control);
+
+ repreason := f_AVP_Grouped_get_avp_or_fail(multi_services_cc_data, c_AVP_Code_DCA_3GPP_Reporting_Reason);
+ if (not match(repreason.avp_data.avp_DCA_3GPP_Reporting_Reason, repreason_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-Reporting-Reason mismatch ", repreason, " vs exp ", repreason_exp));
+ }
+
+ used_service_unit := f_AVP_Grouped_get_avp_or_fail(multi_services_cc_data, c_AVP_Code_DCC_NONE_Used_Service_Unit);
+ used_service_unit_data := valueof(used_service_unit.avp_data.avp_DCC_NONE_Used_Service_Unit);
+
+ cc_time := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Time);
+ if (not match(oct2int(cc_time.avp_data.avp_DCC_NONE_CC_Time), cc_time_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-CC-Time mismatch ", cc_time, " vs exp ", cc_time_exp));
+ }
+
+ cc_in_oct := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Input_Octets);
+ if (not match(oct2int(cc_in_oct.avp_data.avp_DCC_NONE_CC_Input_Octets), cc_in_oct_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-CC-Input-Octets mismatch ", cc_in_oct, " vs exp ", cc_in_oct_exp));
+ }
+
+ cc_out_oct := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Output_Octets);
+ if (not match(oct2int(cc_out_oct.avp_data.avp_DCC_NONE_CC_Output_Octets), cc_out_oct_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-CC-Output-Octets mismatch ", cc_out_oct, " vs exp ", cc_out_oct_exp));
+ }
+}
+
}