blob: 5d88afed36418d5ae6b1ec85251ea4cb12beddc0 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2000-2019 Ericsson Telecom AB //
// //
// All rights reserved. This program and the accompanying materials //
// are made available under the terms of the Eclipse Public License v2.0 //
// which accompanies this distribution, and is available at //
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// Module: EPTF_LoadRegulator_demo
//
// Purpose:
// This module contains function definitions for testing EPTF Load Regulator
//
// Module Parameters:
// tsp_demoInterval - *float* - interval of testing, default: 30.0
// tsp_demoLoadGenerationPeriod - *float* - load generation period, default: 0.1
// tsp_demoSutLoadUpdatePeriod - *float* - update period for load measurement, default: 2.0
// tsp_demoLoadToReach - *float*
// tsp_demoCpsToReach - *float*
// tsp_NetInterfaceName - *charstring*
// tsp_bandwidthToReach - *float*
// Module depends on:
// <EPTF_CLL_Base_Definitions>
// <EPTF_CLL_Base_Functions>
// <EPTF_CLL_LoadRegulator_Definitions>
// <EPTF_CLL_LoadRegulator_Functions>
// <EPTF_CLL_HostAdmin_BaseDefinitions>
// <EPTF_CLL_HostAdmin_BaseFunctions>
// <EPTF_CLL_Scheduler_Definitions>
// <EPTF_CLL_RBTScheduler_Definitions>
// <EPTF_CLL_RBTScheduler_Functions>
// <LOADMEASasp_Types>
// <LOADMEASasp_PortType>
//
// Current Owner:
// Gabor Tatarka (egbotat)
//
// Last Review Date:
// -
//
// Detailed Comments:
// -
///////////////////////////////////////////////////////////
module EPTF_LoadRegulator_demo
{
import from EPTF_CLL_Base_Functions all;
import from EPTF_CLL_LoadRegulator_Definitions all;
import from EPTF_CLL_LoadRegulator_Functions all;
import from EPTF_CLL_HostAdmin_BaseDefinitions all;
import from EPTF_CLL_HostAdmin_BaseFunctions all;
import from EPTF_CLL_Scheduler_Definitions all;
import from EPTF_CLL_RBTScheduler_Definitions all;
import from EPTF_CLL_RBTScheduler_Functions all;
import from LOADMEASasp_Types all;
import from LOADMEASasp_PortType all;
modulepar float tsp_demoInterval := 300.0;
modulepar float tsp_demoLoadGenerationPeriod := 0.1;
modulepar float tsp_demoSutLoadUpdatePeriod := 2.0;
modulepar float tsp_demoLoadToReach := 25.0;
modulepar float tsp_demoCpsToReach := 10.0;
modulepar charstring tsp_NetInterfaceName := "eth0";
modulepar float tsp_bandwidthToReach := 150.0; // kB/s
type record WeightedCpsElem {
float cps,
float weight,
boolean lockCps
}
type record of WeightedCpsElem WeightedCpsList;
type port Demo_PT message
{
inout charstring;
} with { extension "internal" }
type component LoadRegulatorDemo_CT
extends EPTF_HostAdmin_Base_CT, EPTF_Scheduler_CT, EPTF_LoadRegulator_CT
{
var EPTF_Scheduler_ActionHandler v_myEventHandler;
port Demo_PT demo_PCO;
// for weighted CPS:
var WeightedCpsList v_weightedCpsList := {}
// for bandwidth limited traffic control:
port LOADMEASasp_PT loadMeas_PCO;
}
type component Repeater_CT
{
port Demo_PT demo_PCO;
}
////////////////////////////////////////////////////////////////////////////////////
// scheduling and event handling
const integer c_actionId_generateLoad := 0;
const integer c_actionId_updateSutLoad := 1;
function f_myEventHandler(in EPTF_ScheduledAction pl_action, in integer pl_eventIndex)
runs on LoadRegulatorDemo_CT return boolean
{
if (pl_action.actionId[0] == c_actionId_generateLoad) {
f_handleEvent_generateLoad(pl_action.when);
return true;
}
if (pl_action.actionId[0] == c_actionId_updateSutLoad) {
f_handleEvent_updateSutLoad(pl_action.when);
return true;
}
return false;
}
function f_scheduleEvent_generateLoad(in float pl_when)
runs on LoadRegulatorDemo_CT
{
var integer eventIdx := 0;
if(not f_EPTF_SchedulerComp_scheduleAction(
pl_when + tsp_demoLoadGenerationPeriod,v_myEventHandler,{c_actionId_generateLoad},
eventIdx
)) {
setverdict(fail, "f_EPTF_SchedulerComp_scheduleAction failed.");
stop;
}
}
function f_scheduleEvent_updateSutLoad(in float pl_when)
runs on LoadRegulatorDemo_CT
{
var integer eventIdx := 0;
if(not f_EPTF_SchedulerComp_scheduleAction(
pl_when + tsp_demoSutLoadUpdatePeriod,v_myEventHandler,{c_actionId_updateSutLoad},
eventIdx
)) {
setverdict(fail, "f_EPTF_SchedulerComp_scheduleAction failed.");
stop;
}
}
type octetstring SDP_Message;
function f_SDP_enc_Message(in SDP_Message pl_msg) return charstring {
return oct2char(pl_msg);
}
function f_SDP_dec_Message(in charstring pl_msg) return SDP_Message {
return char2oct(pl_msg);
}
function f_handleEvent_generateLoad(in float pl_when)
runs on LoadRegulatorDemo_CT
{
var SDP_Message vl_SDP_Message := '000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F'O;
// Note: this is not an accurate way of generating load.
var integer calls := float2int(f_EPTF_LoadRegulator_getCpsToReach() * tsp_demoLoadGenerationPeriod);
for(var integer i := 0; i < calls; i := i + 1) {
var charstring msg := f_SDP_enc_Message(vl_SDP_Message);
demo_PCO.send(msg);
}
f_scheduleEvent_generateLoad(pl_when);
}
function f_handleEvent_updateSutLoad(in float pl_when)
runs on LoadRegulatorDemo_CT
{
// log("f_handleEvent_updateSutLoad() called");
f_EPTF_HostAdmin_Base_update();
log("Tester host load: ", v_EPTF_HostAdmin_testerHostLoad);
f_scheduleEvent_updateSutLoad(pl_when);
}
// end of scheduling and event handling
////////////////////////////////////////////////////////////////////////////////////
function f_getSUTLoad() runs on LoadRegulatorDemo_CT return float
{
return v_EPTF_HostAdmin_testerHostLoad;
}
function f_repeater() runs on Repeater_CT
{
var charstring msg;
var SDP_Message SDP_msg;
alt {
[] demo_PCO.receive(charstring:?) -> value msg {
SDP_msg := f_SDP_dec_Message(msg);
msg := f_SDP_enc_Message(SDP_msg);
demo_PCO.send(msg);
repeat;
}
}
}
testcase tc_LoadRegulator_demo() runs on LoadRegulatorDemo_CT
{
timer T_interval := tsp_demoInterval;
log("**** creating repeater component");
var Repeater_CT rep := Repeater_CT.create;
connect(self:demo_PCO, rep:demo_PCO);
rep.start(f_repeater());
log("**** initializing HostAdmin_Base");
f_EPTF_HostAdmin_Base_init_CT("LoadRegulator");
log("**** initializing LoadRegulator");
f_EPTF_LoadRegulator_setLoadToReach(tsp_demoLoadToReach);
//v_EPTF_LoadRegulator_cpsToReach := tsp_demoCpsToReach;
f_EPTF_LoadRegulator_init_CT("LoadRegulator", refers(f_getSUTLoad));
log("**** initializing Scheduler");
f_EPTF_Scheduler_init_CT(f_EPTF_Base_selfName());
v_myEventHandler := refers(f_myEventHandler);
f_EPTF_SchedulerComp_refreshSnapshotTime();
f_scheduleEvent_generateLoad(f_EPTF_SchedulerComp_snapshotTime());
f_scheduleEvent_updateSutLoad(f_EPTF_SchedulerComp_snapshotTime());
log("**** entering main loop");
T_interval.start;
var charstring msg;
alt {
[] T_interval.timeout
{
setverdict(pass);
}
[]demo_PCO.receive(charstring:?) -> value msg
{
var SDP_Message SDP_msg := f_SDP_dec_Message(msg);
repeat;
}
}
log("**** performing cleanup");
rep.stop;
disconnect(self:demo_PCO, rep:demo_PCO);
f_EPTF_Base_cleanup_CT();
}
// Post-calculate function for weighted CPS calculation.
function f_calcWeightedCpsList()
runs on LoadRegulatorDemo_CT
{
log(%definitionId&" called");
if(sizeof(v_weightedCpsList) == 0) { return; }
var float weightSum := 0.0;
var float cpsSum := f_EPTF_LoadRegulator_getCpsToReach();
for(var integer i := 0; i < sizeof(v_weightedCpsList); i := i + 1) {
if(not v_weightedCpsList[i].lockCps) {
weightSum := weightSum + v_weightedCpsList[i].weight;
} else {
cpsSum := cpsSum - v_weightedCpsList[i].cps;
}
}
if(weightSum == 0.0) {
log("WARNING " & %definitionId & ": all CPS values are locked or the "&
"unlocked CPS values have a weight of 0.0.");
return;
}
if(cpsSum < 0.0) {
log("WARNING " & %definitionId & ": sum of locked CPS values already "&
"greater than CPS-to-reach.");
for(var integer i := 0; i < sizeof(v_weightedCpsList); i := i + 1) {
if(not v_weightedCpsList[i].lockCps) {
v_weightedCpsList[i].cps := 0.0;
}
}
return;
}
for(var integer i := 0; i < sizeof(v_weightedCpsList); i := i + 1) {
if(not v_weightedCpsList[i].lockCps) {
v_weightedCpsList[i].cps :=
(v_weightedCpsList[i].weight * cpsSum) / weightSum;
}
}
log(%definitionId&" finished. Weighted CPS list: ", v_weightedCpsList);
}
testcase tc_LoadRegulator_weightedCPS_demo() runs on LoadRegulatorDemo_CT
{
timer T_interval := tsp_demoInterval;
log("**** creating repeater component");
var Repeater_CT rep := Repeater_CT.create;
connect(self:demo_PCO, rep:demo_PCO);
rep.start(f_repeater());
log("**** initializing HostAdmin_Base");
f_EPTF_HostAdmin_Base_init_CT("LoadRegulator");
log("**** initializing LoadRegulator");
f_EPTF_LoadRegulator_setLoadToReach(tsp_demoLoadToReach);
//v_EPTF_LoadRegulator_cpsToReach := tsp_demoCpsToReach;
v_weightedCpsList := {
{
cps := 10.0,
weight := 19.0,
lockCps := true
},
{
cps := 10.0,
weight := 1.0,
lockCps := false
},
{
cps := 10.0,
weight := 2.0,
lockCps := false
},
{
cps := 10.0,
weight := 3.0,
lockCps := false
}
}
f_EPTF_LoadRegulator_init_CT("LoadRegulator",refers(f_getSUTLoad), null, refers(f_calcWeightedCpsList));
log("**** initializing Scheduler");
f_EPTF_Scheduler_init_CT(f_EPTF_Base_selfName());
v_myEventHandler := refers(f_myEventHandler);
f_EPTF_SchedulerComp_refreshSnapshotTime();
f_scheduleEvent_generateLoad(f_EPTF_SchedulerComp_snapshotTime());
f_scheduleEvent_updateSutLoad(f_EPTF_SchedulerComp_snapshotTime());
log("**** entering main loop");
T_interval.start;
var charstring msg;
alt {
[] T_interval.timeout
{
setverdict(pass);
}
[]demo_PCO.receive(charstring:?) -> value msg
{
var SDP_Message SDP_msg := f_SDP_dec_Message(msg);
repeat;
}
}
log("**** performing cleanup");
rep.stop;
disconnect(self:demo_PCO, rep:demo_PCO);
f_EPTF_Base_cleanup_CT();
}
function f_initNetMeas() runs on LoadRegulatorDemo_CT
{
map(self:loadMeas_PCO, system:loadMeas_PCO);
var ASP_LOADMEAS vl_ASP_LOADMEAS;
vl_ASP_LOADMEAS.loadType := NETWORK;
vl_ASP_LOADMEAS.msg := { setPeriod := { periodTime := tsp_EPTF_loadRegulator_updateTimeout/2.0 } };
loadMeas_PCO.send(vl_ASP_LOADMEAS);
vl_ASP_LOADMEAS := { loadType := NETWORK, msg := { setInterface:= { interface := tsp_NetInterfaceName } } };
loadMeas_PCO.send(vl_ASP_LOADMEAS);
vl_ASP_LOADMEAS.msg := { startMeas := {} };
loadMeas_PCO.send(vl_ASP_LOADMEAS);
}
function f_getBandwidthUsage() runs on LoadRegulatorDemo_CT return float
{
// var float upRate := getNetworkUploadSpeed(loadMeas_PCO);
var float downRate := getNetworkDownloadSpeed(loadMeas_PCO);
// return downRate + upRate;
return downRate;
}
function f_cleanupNetMeas() runs on LoadRegulatorDemo_CT
{
unmap(self:loadMeas_PCO, system:loadMeas_PCO);
}
/*function f_calcNextCps_BW(
in float loadToReach,
in float oldCps)
runs on LoadRegulatorDemo_CT
return float
{
if (loadToReach == 0.0) { return 0.0 }
var integer measWindowSize := sizeof(vc_loadRegMeasWindow);
var float loadNew := 0.0;
var float loadOld := 0.0;
//calculate last two load values
if(vc_measWinIdx == 0) {
loadNew := vc_loadRegMeasWindow[measWindowSize-1];
loadOld := vc_loadRegMeasWindow[measWindowSize-2];
}
else if(vc_measWinIdx == 1) {
loadNew := vc_loadRegMeasWindow[0];
loadOld := vc_loadRegMeasWindow[measWindowSize-1];
}
else {
loadNew := vc_loadRegMeasWindow[vc_measWinIdx-1];
loadOld := vc_loadRegMeasWindow[vc_measWinIdx-2];
}
var float cpsDelta := (1.0 - ((2.0*loadNew+loadOld)/(loadToReach*3.0))) * tsp_EPTF_loadregulator_cpsDelta;
if(cpsDelta > tsp_EPTF_loadregulator_cpsDelta) {
cpsDelta := tsp_EPTF_loadregulator_cpsDelta;
} else if(cpsDelta < -tsp_EPTF_loadregulator_cpsDelta) {
cpsDelta := -tsp_EPTF_loadregulator_cpsDelta;
}
var float newCps := oldCps + cpsDelta
if(newCps < 0.0) { newCps := 0.0; }
log(%definitionId&": Old cps: ", oldCps);
log(%definitionId&": LoadToReach: ", loadToReach);
log(%definitionId&": Load: ", loadNew);
log(%definitionId&": Cps delta: ", cpsDelta);
log(%definitionId&": New cps: ", newCps);
return newCps;
}*/
// note: this demo needs that the repeater and the demo component are running on different hosts!
// For this, start two host controllers on two hosts connecting to the same main controller.
// The first HC started will run the demo component and will regulate the load.
testcase tc_BandwidthLimitedTrafficControl_demo() runs on LoadRegulatorDemo_CT
{
timer T_interval := tsp_demoInterval;
timer T_startup := 2.0;
T_startup.start;
T_startup.timeout;
log("**** creating repeater component");
var Repeater_CT rep := Repeater_CT.create;
connect(self:demo_PCO, rep:demo_PCO);
rep.start(f_repeater());
log("**** initializing NET measure interface");
f_initNetMeas();
f_EPTF_Base_registerCleanup(refers(f_cleanupNetMeas));
log("**** initializing LoadRegulator");
f_EPTF_LoadRegulator_setLoadToReach(tsp_bandwidthToReach);
//v_EPTF_LoadRegulator_cpsToReach := tsp_demoCpsToReach;
// f_EPTF_LoadRegulator_init_CT(refers(f_getBandwidthUsage), refers(f_calcNextCps_BW));
f_EPTF_LoadRegulator_init_CT("LoadRegulator",refers(f_getBandwidthUsage));
log("**** initializing Scheduler");
f_EPTF_Scheduler_init_CT(f_EPTF_Base_selfName());
v_myEventHandler := refers(f_myEventHandler);
f_EPTF_SchedulerComp_refreshSnapshotTime();
f_scheduleEvent_generateLoad(f_EPTF_SchedulerComp_snapshotTime());
// f_scheduleEvent_updateSutLoad(f_EPTF_SchedulerComp_snapshotTime());
log("**** entering main loop");
T_interval.start;
var charstring msg;
alt {
[] T_interval.timeout
{
setverdict(pass);
}
[]demo_PCO.receive(charstring:?) -> value msg
{
var SDP_Message SDP_msg := f_SDP_dec_Message(msg);
repeat;
}
}
log("**** performing cleanup");
rep.stop;
disconnect(self:demo_PCO, rep:demo_PCO);
f_EPTF_Base_cleanup_CT();
}
} // module