pgw: Add support for PCRF emulation (CCR/CCA)
If mp_pcrf_local_ip is set to a non-empty string, the PGW testsuite now emulates a PCRF and expects the PGW to perform the related transactions - so far Credit-Control-Request INITIAL_REQUEST at session creation, and TERMINATION_REQUST at session deletion. Change-Id: I5f0c7a66d38e5c8b5f36b45717d49648a14ed7b2changes/50/17950/2
parent
d01b5d0af0
commit
f400151003
|
@ -326,6 +326,51 @@ template (value) GenericAVP ts_AVP_AuthAppId(template (value) OCTET4 auth_app_id
|
|||
}
|
||||
}
|
||||
}
|
||||
template (present) GenericAVP tr_AVP_AuthAppId(template (present) OCTET4 auth_app_id := ?) := {
|
||||
avp := {
|
||||
avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Auth_Application_Id),
|
||||
avp_data := {
|
||||
avp_BASE_NONE_Auth_Application_Id := auth_app_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template (value) GenericAVP ts_AVP_CcReqType(template (value) DCC_NONE_CC_Request_Type r) := {
|
||||
avp := {
|
||||
avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_CC_Request_Type),
|
||||
avp_data := {
|
||||
avp_DCC_NONE_CC_Request_Type := r
|
||||
}
|
||||
}
|
||||
}
|
||||
template (present) GenericAVP tr_AVP_CcReqType(template (present) DCC_NONE_CC_Request_Type r := ?) := {
|
||||
avp := {
|
||||
avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_CC_Request_Type),
|
||||
avp_data := {
|
||||
avp_DCC_NONE_CC_Request_Type := r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template (value) GenericAVP ts_AVP_CcReqNum(template (value) AVP_Unsigned32 n) := {
|
||||
avp := {
|
||||
avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_CC_Request_Number),
|
||||
avp_data := {
|
||||
avp_DCC_NONE_CC_Request_Number := n
|
||||
}
|
||||
}
|
||||
}
|
||||
template (present) GenericAVP tr_AVP_CcReqNum(template (present) AVP_Unsigned32 n := ?) := {
|
||||
avp := {
|
||||
avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_CC_Request_Number),
|
||||
avp_data := {
|
||||
avp_DCC_NONE_CC_Request_Number := n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template (value) GenericAVP ts_AVP_SuppVendorIdRaw(uint32_t vendor_id) := {
|
||||
avp := {
|
||||
|
@ -879,4 +924,43 @@ ts_DIA_ULA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
|
|||
|
||||
|
||||
|
||||
/* RFC 4006 3.1. Credit-Control-Request (CCR) Command */
|
||||
template (present) PDU_DIAMETER
|
||||
tr_DIA_CCR(template (present) DCC_NONE_CC_Request_Type req_type := INITIAL_REQUEST)
|
||||
:= tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
|
||||
app_id:=int2oct(c_DIAMETER_3GPP_Gx_AID, 4),
|
||||
avps := superset(
|
||||
tr_AVP_SessionId,
|
||||
tr_AVP_OriginHost,
|
||||
tr_AVP_OriginRealm,
|
||||
tr_AVP_DestinationRealm,
|
||||
tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_Gx_AID, 4)),
|
||||
tr_AVP_CcReqType(req_type),
|
||||
tr_AVP_CcReqNum(?)
|
||||
));
|
||||
|
||||
|
||||
/* RFC 4006 3.2. Credit-Control-Answer (CCA) Command */
|
||||
template (value) PDU_DIAMETER
|
||||
ts_DIA_CCA(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)
|
||||
|
||||
:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
|
||||
app_id:=int2oct(c_DIAMETER_3GPP_Gx_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
|
||||
avps := {
|
||||
ts_AVP_SessionId(sess_id),
|
||||
ts_AVP_ResultCode(DIAMETER_SUCCESS),
|
||||
ts_AVP_OriginHost("pcrf.localdomain"),
|
||||
ts_AVP_OriginRealm("localdomain"),
|
||||
ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_Gx_AID, 4)),
|
||||
ts_AVP_CcReqType(req_type),
|
||||
ts_AVP_CcReqNum(req_num)//,
|
||||
// qos
|
||||
// default eps bearer qos
|
||||
// supported features
|
||||
// origin
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -12,22 +12,37 @@ import from UECUPS_Types all;
|
|||
|
||||
import from DNS_Helpers all;
|
||||
|
||||
|
||||
import from DIAMETER_Types all;
|
||||
import from DIAMETER_Templates all;
|
||||
import from DIAMETER_Emulation all;
|
||||
|
||||
|
||||
modulepar {
|
||||
charstring mp_pgw_hostname := "127.0.0.3";
|
||||
charstring mp_local_hostname_c := "127.0.0.1";
|
||||
charstring mp_local_hostname_u := "127.0.0.1";
|
||||
|
||||
charstring mp_run_prog_as_user := "laforge";
|
||||
charstring mp_ping_hostname := "10.45.0.1";
|
||||
|
||||
charstring mp_pcrf_local_ip := "127.0.0.5";
|
||||
integer mp_pcrf_local_port := 3868;
|
||||
}
|
||||
|
||||
/* main component, we typically have one per testcase */
|
||||
type component PGW_Test_CT {
|
||||
var GTPv2_Emulation_CT vc_GTP2;
|
||||
port GTP2EM_PT TEID0;
|
||||
|
||||
/* emulated PCRF */
|
||||
var DIAMETER_Emulation_CT vc_DIAMETER;
|
||||
port DIAMETER_PT DIAMETER_UNIT;
|
||||
port DIAMETEREM_PROC_PT DIAMETER_PROC;
|
||||
}
|
||||
|
||||
/* per-session component; we typically have 1..N per testcase */
|
||||
type component PGW_Session_CT extends GTP2_ConnHdlr {
|
||||
type component PGW_Session_CT extends GTP2_ConnHdlr, DIAMETER_ConnHdlr {
|
||||
var SessionPars g_pars;
|
||||
|
||||
/* TEI (Data) local side */
|
||||
|
@ -91,6 +106,35 @@ type record BearerConfig {
|
|||
|
||||
type function void_fn() runs on PGW_Session_CT;
|
||||
|
||||
friend function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
|
||||
runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
|
||||
DIAMETER_UNIT.send(msg);
|
||||
return omit;
|
||||
}
|
||||
|
||||
friend function f_init_diameter(charstring id) runs on PGW_Test_CT {
|
||||
var DIAMETEROps ops := {
|
||||
create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
|
||||
unitdata_cb := refers(DiameterForwardUnitdataCallback)
|
||||
};
|
||||
var DIAMETER_conn_parameters pars := {
|
||||
remote_ip := mp_pgw_hostname,
|
||||
remote_sctp_port := -1,
|
||||
local_ip := mp_pcrf_local_ip,
|
||||
local_sctp_port := mp_pcrf_local_port,
|
||||
origin_host := "pcrf.localdomain",
|
||||
origin_realm := "localdomain",
|
||||
vendor_app_id := c_DIAMETER_3GPP_Gx_AID
|
||||
};
|
||||
vc_DIAMETER := DIAMETER_Emulation_CT.create(id);
|
||||
map(vc_DIAMETER:DIAMETER, system:DIAMETER_CODEC_PT);
|
||||
connect(vc_DIAMETER:DIAMETER_UNIT, self:DIAMETER_UNIT);
|
||||
connect(vc_DIAMETER:DIAMETER_PROC, self:DIAMETER_PROC);
|
||||
vc_DIAMETER.start(DIAMETER_Emulation.main(ops, pars, id));
|
||||
|
||||
f_diameter_wait_capability(DIAMETER_UNIT);
|
||||
}
|
||||
|
||||
private function f_init() runs on PGW_Test_CT {
|
||||
var Gtp2EmulationCfg cfg := {
|
||||
gtpc_bind_ip := mp_local_hostname_c,
|
||||
|
@ -105,6 +149,10 @@ private function f_init() runs on PGW_Test_CT {
|
|||
map(vc_GTP2:GTP2C, system:GTP2C);
|
||||
connect(vc_GTP2:TEID0, self:TEID0);
|
||||
vc_GTP2.start(GTPv2_Emulation.main(cfg));
|
||||
|
||||
if (mp_pcrf_local_ip != "") {
|
||||
f_init_diameter(testcasename());
|
||||
}
|
||||
}
|
||||
|
||||
function f_start_handler(void_fn fn, template (omit) SessionPars pars := omit)
|
||||
|
@ -114,6 +162,12 @@ runs on PGW_Test_CT return PGW_Session_CT {
|
|||
vc_conn := PGW_Session_CT.create(id);
|
||||
connect(vc_conn:GTP2, vc_GTP2:CLIENT);
|
||||
connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC);
|
||||
|
||||
if (isbound(vc_DIAMETER)) {
|
||||
connect(vc_conn:DIAMETER, vc_DIAMETER:DIAMETER_CLIENT);
|
||||
connect(vc_conn:DIAMETER_PROC, vc_DIAMETER:DIAMETER_PROC);
|
||||
}
|
||||
|
||||
vc_conn.start(f_handler_init(fn, pars));
|
||||
return vc_conn;
|
||||
}
|
||||
|
@ -123,6 +177,9 @@ runs on PGW_Session_CT {
|
|||
if (isvalue(pars)) {
|
||||
g_pars := valueof(pars);
|
||||
}
|
||||
if (DIAMETER_PROC.checkstate("Connected")) {
|
||||
f_diameter_expect(g_pars.imsi);
|
||||
}
|
||||
fn.apply();
|
||||
}
|
||||
|
||||
|
@ -146,6 +203,28 @@ function f_gen_msisdn(integer suffix) return hexstring {
|
|||
return f_concat_pad(12, '49123'H, suffix);
|
||||
}
|
||||
|
||||
private altstep as_DIA_CCR(DCC_NONE_CC_Request_Type req_type) runs on PGW_Session_CT {
|
||||
var PDU_DIAMETER rx_dia;
|
||||
[] DIAMETER.receive(tr_DIA_CCR(req_type := req_type)) -> value rx_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);
|
||||
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);
|
||||
req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
|
||||
|
||||
DIAMETER.send(ts_DIA_CCA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
|
||||
req_type, req_num));
|
||||
}
|
||||
[] DIAMETER.receive(PDU_DIAMETER:?) -> value rx_dia {
|
||||
setverdict(fail, "Received unexpected DIAMETER ", rx_dia);
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* find TEID of given interface type (and optionally instance) */
|
||||
private function f_find_teid(FullyQualifiedTEID_List list,
|
||||
|
@ -228,6 +307,9 @@ private function f_create_session() runs on PGW_Session_CT {
|
|||
g2c.gtpcv2_pdu.createSessionRequest.userLocationInfo := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi);
|
||||
|
||||
GTP2.send(g2c);
|
||||
if (DIAMETER_PROC.checkstate("Connected")) {
|
||||
as_DIA_CCR(INITIAL_REQUEST);
|
||||
}
|
||||
alt {
|
||||
[] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid:=g_teic, cause:='10'O)) -> value rx {
|
||||
/* extract TEIDs */
|
||||
|
@ -283,6 +365,9 @@ private function f_delete_session(template (omit) OCT1 tx_cause := omit,
|
|||
teid_list := {}, bearer_id := 1);
|
||||
|
||||
GTP2.send(g2c);
|
||||
if (DIAMETER_PROC.checkstate("Connected")) {
|
||||
as_DIA_CCR(TERMINATION_REQUEST);
|
||||
}
|
||||
alt {
|
||||
[] GTP2.receive(tr_GTP2C_DeleteSessionResp(d_teid := exp_teid, cause := exp_cause)) {
|
||||
setverdict(pass);
|
||||
|
|
|
@ -44,12 +44,17 @@ DIR=$BASEDIR/osmo-uecups/ttcn3
|
|||
FILES="UECUPS_CodecPort.ttcn UECUPS_CodecPort_CtrlFunct.ttcn UECUPS_CodecPort_CtrlFunctDef.cc UECUPS_Types.ttcn "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator/src
|
||||
FILES="DIAMETER_EncDec.cc"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=../library
|
||||
FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPCP_Types.ttcn PAP_Types.ttcn "
|
||||
FILES+="GTP_CodecPort.ttcn GTP_CodecPort_CtrlFunct.ttcn GTP_CodecPort_CtrlFunctDef.cc GTP_Templates.ttcn "
|
||||
FILES+="GTPv2_PrivateExtensions.ttcn GTPv2_Templates.ttcn "
|
||||
FILES+="GTPv2_CodecPort.ttcn GTPv2_CodecPort_CtrlFunctDef.cc GTPv2_CodecPort_CtrlFunct.ttcn GTPv2_Emulation.ttcn "
|
||||
FILES+="DNS_Helpers.ttcn "
|
||||
FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn DIAMETER_Templates.ttcn "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
ignore_pp_results
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
|
||||
FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc GTPv2_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc UDP_EncDec.cc ICMP_EncDec.cc "
|
||||
FILES+="UECUPS_CodecPort_CtrlFunctDef.cc "
|
||||
FILES+="DIAMETER_EncDec.cc DIAMETER_CodecPort_CtrlFunctDef.cc "
|
||||
|
||||
../regen-makefile.sh PGW_Tests.ttcn $FILES
|
||||
|
|
Loading…
Reference in New Issue