From 8513dd8523eef50dab54e310ab24bf3d2afa76d3 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 12 Mar 2020 10:58:10 +0100 Subject: [PATCH] Enhance AtsRSUsSimulator --- .../ConfigRsuSimulatorLayer.cc | 323 ++++++++++++++- .../ConfigRsuSimulatorLayer.hh | 8 +- .../ConfigRsuSimulatorPort.cc | 53 ++- .../ConfigRsuSimulatorPort.hh | 5 + .../GeoNetworking/geonetworking_codec.cc | 8 +- .../GeoNetworking/geonetworking_layer.cc | 10 +- ccsrc/Protocols/Security/security_services.cc | 32 +- ccsrc/Protocols/UDP/udp_layer.cc | 11 +- ccsrc/Protocols/UDP/udp_layer.hh | 2 + etc/AtsPki/AtsPki_Idnomic.cfg_ | 4 +- etc/AtsRSUsSimulator/AtsRSUSimulator.cfg | 42 +- .../ItsRSUsSimulator_Functions.ttcn | 377 +++++++++++++++--- .../ItsRSUsSimulator_Pics.ttcn | 5 + .../ItsRSUsSimulator_Templates.ttcn | 56 ++- .../ItsRSUsSimulator_TestCases.ttcn | 37 +- .../ItsRSUsSimulator_TestSystem.ttcn | 32 +- .../ItsRSUsSimulator_TypesAndValues.ttcn | 14 +- ttcn/LibIts | 2 +- 18 files changed, 867 insertions(+), 154 deletions(-) diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc index 7df72e2df..1893d972e 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc @@ -7,9 +7,11 @@ #include "LibCommon_BasicTypesAndValues.hh" #include "uppertester_cam_codec.hh" +#include "uppertester_denm_codec.hh" #include "uppertester_geonetworking_codec.hh" #include "LibItsCam_EncdecDeclarations.hh" +#include "LibItsDenm_EncdecDeclarations.hh" ConfigRsuSimulatorLayer::ConfigRsuSimulatorLayer(const std::string & p_type, const std::string & param) : t_layer(p_type), _params(), _codec(), _codec_cam() { loggers::get_instance().log(">>> ConfigRsuSimulatorLayer::ConfigRsuSimulatorLayer: %s, %s", to_string().c_str(), param.c_str()); @@ -19,7 +21,7 @@ ConfigRsuSimulatorLayer::ConfigRsuSimulatorLayer(const std::string & p_type, con void ConfigRsuSimulatorLayer::sendMsg(const ItsRSUsSimulator__TestSystem::CfInitialize& send_par, params& params){ loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); - + // Encode ConfigRsuSimulator PDU OCTETSTRING data; if (_codec.encode(static_cast(send_par), data) == -1) { @@ -49,6 +51,18 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsGeoNetworking__TypesAndValues: send_data(os, _params); } +void ConfigRsuSimulatorLayer::sendMsg(const LibItsGeoNetworking__TypesAndValues::UtGnEventInd& send_par, params& params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); + + TTCN_Buffer encoding_buffer; + encoding_buffer.put_c(0x55/*static_cast(uppertester_geonetworking_codec::c_utGnEventInd)*/); + OCTETSTRING l = int2oct(send_par.rawPayload().lengthof(), 2); + encoding_buffer.put_s(l.lengthof(), static_cast(l)); + encoding_buffer.put_s(send_par.rawPayload().lengthof(), static_cast(send_par.rawPayload())); + OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data()); + send_data(data, _params); +} + void ConfigRsuSimulatorLayer::sendMsg(const LibItsCam__TypesAndValues::UtCamResults& send_par, params& params) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); @@ -74,9 +88,12 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsCam__TypesAndValues::UtCamEven TTCN_Buffer encoding_buffer; encoding_buffer.put_c(0x23/*static_cast(uppertester_cam_codec::c_utCamEventInd)*/); BITSTRING bs = LibItsCam__EncdecDeclarations::fx__enc__CAM(send_par.camMsg()); - encoding_buffer.put_s(bs.lengthof(), static_cast(bs)); - OCTETSTRING os(encoding_buffer.get_len(), encoding_buffer.get_data()); - send_data(os, _params); + OCTETSTRING os = bit2oct(bs); + OCTETSTRING l = int2oct(os.lengthof(), 2); + encoding_buffer.put_s(l.lengthof(), static_cast(l)); + encoding_buffer.put_s(os.lengthof(), static_cast(os)); + OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data()); + send_data(data, _params); } void ConfigRsuSimulatorLayer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmResults& send_par, params& params) { @@ -86,6 +103,25 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmRe if (send_par.ischosen(LibItsDenm__TypesAndValues::UtDenmResults::ALT_utDenmInitializeResult)) { encoding_buffer.put_c(0x01/*static_cast(uppertester_denm_codec::c_utDenmInitializeResult)*/); encoding_buffer.put_c((unsigned char)static_cast(send_par.utDenmInitializeResult())); + } else if (send_par.ischosen(LibItsDenm__TypesAndValues::UtDenmResults::ALT_utDenmTriggerResult)) { + encoding_buffer.put_c(0x11/*static_cast(uppertester_denm_codec::c_utDenmTriggerResult)*/); + const LibItsDenm__TypesAndValues::UtDenmTriggerResult& r = send_par.utDenmTriggerResult(); + encoding_buffer.put_c((unsigned char)static_cast(r.result())); + OCTETSTRING os = int2oct(r.actionId().originatingStationID(), 4); + encoding_buffer.put_s(os.lengthof(), static_cast(os)); + os = int2oct(r.actionId().sequenceNumber(), 2); + encoding_buffer.put_s(os.lengthof(), static_cast(os)); + } else if (send_par.ischosen(LibItsDenm__TypesAndValues::UtDenmResults::ALT_utDenmUpdateResult)) { + encoding_buffer.put_c(0x13/*static_cast(uppertester_denm_codec::c_utDenmUpdateResult)*/); + const LibItsDenm__TypesAndValues::UtDenmUpdateResult& r = send_par.utDenmUpdateResult(); + encoding_buffer.put_c((unsigned char)static_cast(r.result())); + OCTETSTRING os = int2oct(r.actionId().originatingStationID(), 4); + encoding_buffer.put_s(os.lengthof(), static_cast(os)); + os = int2oct(r.actionId().sequenceNumber(), 2); + encoding_buffer.put_s(os.lengthof(), static_cast(os)); + } else if (send_par.ischosen(LibItsDenm__TypesAndValues::UtDenmResults::ALT_utDenmTerminationResult)) { + encoding_buffer.put_c(0x15/*static_cast(uppertester_denm_codec::c_utDenmInitializeResult)*/); + encoding_buffer.put_c((unsigned char)static_cast(send_par.utDenmTerminationResult())); } else { loggers::get_instance().warning("ConfigRsuSimulatorLayer::sendMsg: Unsupported UtDenmResults variant"); return; @@ -95,6 +131,20 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmRe send_data(os, _params); } +void ConfigRsuSimulatorLayer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmEventInd& send_par, params& params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); + + TTCN_Buffer encoding_buffer; + encoding_buffer.put_c(0x17/*static_cast(uppertester_cam_codec::c_utDenmEventInd)*/); + BITSTRING bs = LibItsDenm__EncdecDeclarations::fx__enc__DENM(send_par.denMsg()); + OCTETSTRING os = bit2oct(bs); + OCTETSTRING l = int2oct(os.lengthof(), 2); + encoding_buffer.put_s(l.lengthof(), static_cast(l)); + encoding_buffer.put_s(os.lengthof(), static_cast(os)); + OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data()); + send_data(data, _params); +} + void ConfigRsuSimulatorLayer::sendMsg(const LibItsPki__TypesAndValues::UtPkiResults& send_par, params& params) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); @@ -133,6 +183,14 @@ void ConfigRsuSimulatorLayer::receive_data(OCTETSTRING& data, params& params) process_ut_cam_changespeed_data(data, params); } else if (id == 0x34/*uppertester_cam_codec::c_utCamChangeHeading*/) { process_ut_cam_changeheading_data(data, params); + } else if (id == 0x3a/*uppertester_cam_codec::c_utCamSetVehicleRole*/) { + process_ut_cam_setvehiclerole_data(data, params); + } else if (id == 0x10/*uppertester_denm_codec::c_utDenmTrigger*/) { + process_ut_denm_trigger(data, params); + } else if (id == 0x12/*uppertester_denm_codec::c_utDenmUpdate*/) { + process_ut_denm_update(data, params); + } else if (id == 0x14/*uppertester_denm_codec::c_utDenmTermination*/) { + process_ut_denm_termination(data, params); } else if ((id >= 0x50) && (id <= 0x54)) { // Receive an UtGnTrigger process_ut_geonetworking_trigger(data, params); } else if ((id >= 0xBB) && (id <= 0xBF)) { // Receive an UtPkiTrigger @@ -140,12 +198,12 @@ void ConfigRsuSimulatorLayer::receive_data(OCTETSTRING& data, params& params) } else { loggers::get_instance().warning("ConfigRsuSimulatorLayer::receive_data: Unsupported tag %02x", id); } - + } int ConfigRsuSimulatorLayer::process_utinitialize_data(const OCTETSTRING& data, params& params) { loggers::get_instance().log(">>> ConfigRsuSimulatorLayer::process_utinitialize_data"); - + params::const_iterator it = _params.find("ut"); if (it == _params.cend()) { loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_utinitialize_data: CF layer's ut parameter is missing"); @@ -249,6 +307,220 @@ int ConfigRsuSimulatorLayer::process_ut_cam_changeheading_data(const OCTETSTRING return 0; } +int ConfigRsuSimulatorLayer::process_ut_cam_setvehiclerole_data(const OCTETSTRING& data, params& params) { + loggers::get_instance().log(">>> ConfigRsuSimulatorLayer::process_ut_cam_setvehiclerole_data"); + + params::const_iterator it = _params.find("ut"); + if (it == _params.cend()) { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_cam_setvehiclerole_data: CF layer's ut parameter is missing"); + return -1; + } + + if (_params[std::string("ut")].compare("cam") == 0) { + OCTETSTRING vehicle_role(data.lengthof() - 1, 1 + static_cast(data)); + LibItsCam__TypesAndValues::UtCamTrigger p; + p.setVehicleRole() = oct2int(vehicle_role); + // Pass it to the ports if any + to_all_upper_ports(p, params); + } else { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_cam_setvehiclerole_data: Unsupported protocol"); + return -1; + } + + return 0; +} + +int ConfigRsuSimulatorLayer::process_ut_denm_trigger(const OCTETSTRING& data, params& params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::process_ut_denm_trigger", data); + + params::const_iterator it = _params.find("ut"); + if (it == _params.cend()) { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_denm_trigger: CF layer's ut parameter is missing"); + return -1; + } + + if (_params[std::string("ut")].compare("denm") == 0) { + unsigned char* p = (unsigned char*)static_cast(data); + unsigned char msg_id = *p++; + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_trigger: msg_id=%02x", msg_id); + unsigned char flag = *p++; + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_trigger: flag=%02x", flag); + LibItsDenm__TypesAndValues::UtDenmTrigger trigger; // See ETSI TR 103 34 099 Cause C.4.1 GenerateDenmEvent + // Decode detectionTime + trigger.detectionTime() = oct2int(OCTETSTRING(6, p)); + p += 6; + // ValidityDuration + if ((flag & 0x80) == 0x80) { + trigger.validityDuration() = OPTIONAL(oct2int(OCTETSTRING(3, p))); + } else { + trigger.validityDuration().set_to_omit(); + } + p += 3; + if ((flag & 0x40) == 0x40) { + trigger.repetitionDuration() = OPTIONAL(oct2int(OCTETSTRING(3, p))); + } else { + trigger.repetitionDuration().set_to_omit(); + } + p += 3; + // Situation + trigger.situation().informationQuality() = oct2int(OCTETSTRING(1, p++)); + trigger.situation().eventType().causeCode() = oct2int(OCTETSTRING(1, p++)); + trigger.situation().eventType().subCauseCode() = oct2int(OCTETSTRING(1, p++)); + trigger.situation().linkedCause().set_to_omit(); + trigger.situation().eventHistory().set_to_omit(); + // RelevanceDistance + trigger.relevanceDistance() = oct2int(OCTETSTRING(1, p++)); + // RelevanceTrafficDirection + trigger.relevanceTrafficDirection() = oct2int(OCTETSTRING(1, p++)); + if ((flag & 0x04) == 0x04) { + trigger.transmissionInterval() = OPTIONAL(oct2int(OCTETSTRING(2, p))); + } else { + trigger.transmissionInterval().set_to_omit(); + } + p += 2; + if ((flag & 0x02) == 0x02) { + trigger.repetitionInterval() = OPTIONAL(oct2int(OCTETSTRING(2, p))); + } else { + trigger.repetitionInterval().set_to_omit(); + } + p += 2; + // alacarteLength + INTEGER alacarte_length = oct2int(OCTETSTRING(1, p)); + if (static_cast(alacarte_length) != 0) { + p += 1; + // FIXME AlacarteContainer alacarte optional + } else { + trigger.alacarte().set_to_omit(); + } + loggers::get_instance().log_msg("ConfigRsuSimulatorLayer::process_ut_denm_trigger: ", trigger); + + // Pass it to the ports if any + to_all_upper_ports(trigger, params); + } else { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_denm_trigger: Unsupported protocol"); + return -1; + } + + return 0; +} + +int ConfigRsuSimulatorLayer::process_ut_denm_update(const OCTETSTRING& data, params& params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::process_ut_denm_update", data); + + params::const_iterator it = _params.find("ut"); + if (it == _params.cend()) { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_denm_update: CF layer's ut parameter is missing"); + return -1; + } + + if (_params[std::string("ut")].compare("denm") == 0) { + unsigned char* p = (unsigned char*)static_cast(data); + unsigned char msg_id = *p++; + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_update: msg_id=%02x", msg_id); + unsigned char flag = *p++; + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_update: flag=%02x", flag); + LibItsDenm__TypesAndValues::UtDenmUpdate update; // See ETSI TR 103 34 099 Cause C.4.1 GenerateDenmEvent + // Statuion ID + update.actionId().originatingStationID() = oct2int(OCTETSTRING(4, p)); + p += 4; + // SequenceNumber + update.actionId().sequenceNumber() = oct2int(OCTETSTRING(2, p)); + p += 2; + // Decode detectionTime + update.detectionTime() = oct2int(OCTETSTRING(6, p)); + p += 6; + if ((flag & 0x80) == 0x80) { + update.validityDuration() = OPTIONAL(oct2int(OCTETSTRING(3, p))); + } else { + update.validityDuration().set_to_omit(); + } + p += 3; + // Situation + if ((flag & 0x40) == 0x40) { + DENM__PDU__Descriptions::SituationContainer& s = static_cast(*update.get_opt_value()); + s.informationQuality() = oct2int(OCTETSTRING(1, p++)); + s.eventType().causeCode() = oct2int(OCTETSTRING(1, p++)); + s.eventType().subCauseCode() = oct2int(OCTETSTRING(1, p++)); + s.linkedCause().set_to_omit(); + s.eventHistory().set_to_omit(); + update.situation() = OPTIONAL(s); + } else { + update.situation().set_to_omit(); + } + // Location + update.location().set_to_omit(); + // RelevanceDistance + if ((flag & 0x20) == 0x20) { + update.relevanceDistance() = oct2int(OCTETSTRING(1, p++)); + } else { + update.relevanceDistance().set_to_omit(); + } + // RelevanceTrafficDirection + if ((flag & 0x10) == 0x10) { + update.relevanceTrafficDirection() = oct2int(OCTETSTRING(1, p++)); + } else { + update.relevanceTrafficDirection().set_to_omit(); + } + if ((flag & 0x08) == 0x08) { + update.transmissionInterval() = OPTIONAL(oct2int(OCTETSTRING(2, p))); + } else { + update.transmissionInterval().set_to_omit(); + } + p += 2; + if ((flag & 0x04) == 0x04) { + update.repetitionInterval() = OPTIONAL(oct2int(OCTETSTRING(2, p))); + } else { + update.repetitionInterval().set_to_omit(); + } + p += 2; + // alacarteLength + INTEGER alacarte_length = oct2int(OCTETSTRING(1, p)); + if (static_cast(alacarte_length) != 0) { + p += 1; + // FIXME AlacarteContainer alacarte optional + } else { + update.alacarte().set_to_omit(); + } + loggers::get_instance().log_msg("ConfigRsuSimulatorLayer::process_ut_denm_update: ", update); + + // Pass it to the ports if any + to_all_upper_ports(update, params); + } else { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_denm_update: Unsupported protocol"); + return -1; + } + + return 0; +} + +int ConfigRsuSimulatorLayer::process_ut_denm_termination(const OCTETSTRING& data, params& params) { + loggers::get_instance().log(">>> ConfigRsuSimulatorLayer::process_ut_denm_termination"); + + params::const_iterator it = _params.find("ut"); + if (it == _params.cend()) { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_denm_termination: CF layer's ut parameter is missing"); + return -1; + } + + if (_params[std::string("ut")].compare("denm") == 0) { + unsigned char* p = (unsigned char*)static_cast(data); + unsigned char msg_id = *p++; + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_termination: msg_id=%02x", msg_id); + LibItsDenm__TypesAndValues::UtDenmTermination termination; + termination.actionId().originatingStationID() = oct2int(OCTETSTRING(4, p)); + p += 4; + termination.actionId().sequenceNumber() = oct2int(OCTETSTRING(2, p)); + + // Pass it to the ports if any + to_all_upper_ports(termination, params); + } else { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_denm_termination: Unsupported protocol"); + return -1; + } + + return 0; +} + int ConfigRsuSimulatorLayer::process_ut_geonetworking_trigger(const OCTETSTRING& data, params& params) { loggers::get_instance().log(">>> ConfigRsuSimulatorLayer::process_ut_geonetworking_trigger"); @@ -270,13 +542,48 @@ int ConfigRsuSimulatorLayer::process_ut_geonetworking_trigger(const OCTETSTRING& if (msg_id == 0x50/*uppertester_geonetworking_codec::c_utGnTrigger_GeoUnicast*/) { LibItsGeoNetworking__TypesAndValues::GenerateGeoUnicastMessage g; g.decode(*g.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_RAW); - g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + if(g.payload().lengthof() > 2) { + g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + } else { + g.payload() = OCTETSTRING(0, nullptr); + } p.geoUnicast() = g; } else if (msg_id == 0x51/*uppertester_geonetworking_codec::c_utGnTrigger_GeoBroadcast*/) { LibItsGeoNetworking__TypesAndValues::GenerateGeoBroadcastMessage g; g.decode(*g.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_RAW); - g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + if(g.payload().lengthof() > 2) { + g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + } else { + g.payload() = OCTETSTRING(0, nullptr); + } p.geoBroadcast() = g; + } else if (msg_id == 0x52/*uppertester_geonetworking_codec::c_utGnTrigger_GeoAnycast*/) { + LibItsGeoNetworking__TypesAndValues::GenerateGeoAnycastMessage g; + g.decode(*g.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_RAW); + if(g.payload().lengthof() > 2) { + g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + } else { + g.payload() = OCTETSTRING(0, nullptr); + } + p.geoAnycast() = g; + } else if (msg_id == 0x53/*uppertester_geonetworking_codec::c_utGnTrigger_Shb*/) { + LibItsGeoNetworking__TypesAndValues::GenerateSHBMessage g; + g.decode(*g.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_RAW); + if(g.payload().lengthof() > 2) { + g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + } else { + g.payload() = OCTETSTRING(0, nullptr); + } + p.shb() = g; + } else if (msg_id == 0x54/*uppertester_geonetworking_codec::c_utGnTrigger_Tsb*/) { + LibItsGeoNetworking__TypesAndValues::GenerateTSBMessage g; + g.decode(*g.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_RAW); + if(g.payload().lengthof() > 2) { + g.payload() = OCTETSTRING(g.payload().lengthof() - 2, static_cast(g.payload())); + } else { + g.payload() = OCTETSTRING(0, nullptr); + } + p.tsb() = g; } // Pass it to the ports if any to_all_upper_ports(p, params); diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh index c1b400918..89511ab13 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh @@ -34,11 +34,13 @@ public: void sendMsg(const ItsRSUsSimulator__TestSystem::CfInitialize&, params& params); void sendMsg(const LibItsGeoNetworking__TypesAndValues::UtGnResults& send_par, params& params); + void sendMsg(const LibItsGeoNetworking__TypesAndValues::UtGnEventInd& send_par, params& params); void sendMsg(const LibItsCam__TypesAndValues::UtCamResults& send_par, params& params); void sendMsg(const LibItsCam__TypesAndValues::UtCamEventInd& send_par, params& params); void sendMsg(const LibItsDenm__TypesAndValues::UtDenmResults& send_par, params& params); + void sendMsg(const LibItsDenm__TypesAndValues::UtDenmEventInd& send_par, params& params); void sendMsg(const LibItsPki__TypesAndValues::UtPkiResults& send_par, params& params); - + virtual void send_data(OCTETSTRING& data, params& params); virtual void receive_data(OCTETSTRING& data, params& params); @@ -47,6 +49,10 @@ private: int process_ut_cam_changespeed_data(const OCTETSTRING& data, params& params); int process_ut_cam_changecurvature_data(const OCTETSTRING& data, params& params); int process_ut_cam_changeheading_data(const OCTETSTRING& data, params& params); + int process_ut_cam_setvehiclerole_data(const OCTETSTRING& data, params& params); + int process_ut_denm_trigger(const OCTETSTRING& data, params& params); + int process_ut_denm_update(const OCTETSTRING& data, params& params); + int process_ut_denm_termination(const OCTETSTRING& data, params& params); int process_ut_geonetworking_trigger(const OCTETSTRING& data, params& params); int process_ut_pki_trigger(const OCTETSTRING& data, params& params); diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc index 491757362..9f6dba246 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc @@ -124,6 +124,15 @@ namespace ItsRSUsSimulator__TestSystem { loggers::get_instance().set_stop_time(_time_key, duration); } + void ConfigRsuSimulatorPort::outgoing_send(const LibItsGeoNetworking__TypesAndValues::UtGnEventInd& send_par) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); + + float duration; + loggers::get_instance().set_start_time(_time_key); + static_cast(_layer)->sendMsg(send_par, _layer_params); + loggers::get_instance().set_stop_time(_time_key, duration); + } + void ConfigRsuSimulatorPort::outgoing_send(const LibItsCam__TypesAndValues::UtCamEventInd& send_par) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); @@ -142,6 +151,16 @@ namespace ItsRSUsSimulator__TestSystem { loggers::get_instance().set_stop_time(_time_key, duration); } + void ConfigRsuSimulatorPort::outgoing_send(const LibItsDenm__TypesAndValues::UtDenmEventInd& send_par) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); + + float duration; + loggers::get_instance().set_start_time(_time_key); + static_cast(_layer)->sendMsg(send_par, _layer_params); + loggers::get_instance().set_stop_time(_time_key, duration); + } + + void ConfigRsuSimulatorPort::outgoing_send(const LibItsPki__TypesAndValues::UtPkiResults& send_par) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); @@ -190,7 +209,7 @@ namespace ItsRSUsSimulator__TestSystem { incoming_message(p_ind); } - + void ConfigRsuSimulatorPort::receiveMsg (const LibItsCam__TypesAndValues::UtCamTrigger& p_ind, const params& p_params) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); // Sanity check @@ -210,7 +229,37 @@ namespace ItsRSUsSimulator__TestSystem { incoming_message(p_ind); } - + + void ConfigRsuSimulatorPort::receiveMsg (const LibItsDenm__TypesAndValues::UtDenmTrigger& p_ind, const params& p_params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); + // Sanity check + if (!p_ind.is_bound()) { + return; + } + + incoming_message(p_ind); + } + + void ConfigRsuSimulatorPort::receiveMsg (const LibItsDenm__TypesAndValues::UtDenmUpdate& p_ind, const params& p_params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); + // Sanity check + if (!p_ind.is_bound()) { + return; + } + + incoming_message(p_ind); + } + + void ConfigRsuSimulatorPort::receiveMsg (const LibItsDenm__TypesAndValues::UtDenmTermination& p_ind, const params& p_params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); + // Sanity check + if (!p_ind.is_bound()) { + return; + } + + incoming_message(p_ind); + } + void ConfigRsuSimulatorPort::receiveMsg (const LibItsPki__TypesAndValues::UtPkiInitialize& p_ind, const params& p_params) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); // Sanity check diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh index 3d4451f23..6806d0ed2 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh @@ -24,6 +24,9 @@ namespace ItsRSUsSimulator__TestSystem { void receiveMsg (const LibItsCam__TypesAndValues::UtCamInitialize& p_ind, const params& p_params); void receiveMsg (const LibItsCam__TypesAndValues::UtCamTrigger& p_ind, const params& p_params); void receiveMsg (const LibItsDenm__TypesAndValues::UtDenmInitialize& p_ind, const params& p_params); + void receiveMsg (const LibItsDenm__TypesAndValues::UtDenmTrigger& p_ind, const params& p_params); + void receiveMsg (const LibItsDenm__TypesAndValues::UtDenmUpdate& p_ind, const params& p_params); + void receiveMsg (const LibItsDenm__TypesAndValues::UtDenmTermination& p_ind, const params& p_params); void receiveMsg (const LibItsPki__TypesAndValues::UtPkiInitialize& p_ind, const params& p_params); void receiveMsg (const LibItsPki__TypesAndValues::UtPkiTrigger& p_ind, const params& p_params); @@ -58,9 +61,11 @@ namespace ItsRSUsSimulator__TestSystem { void outgoing_send(const CfInitialize& send_par); void outgoing_send(const BOOLEAN& send_par); void outgoing_send(const LibItsGeoNetworking__TypesAndValues::UtGnResults& send_par); + void outgoing_send(const LibItsGeoNetworking__TypesAndValues::UtGnEventInd& send_par); void outgoing_send(const LibItsCam__TypesAndValues::UtCamResults& send_par); void outgoing_send(const LibItsCam__TypesAndValues::UtCamEventInd& send_par); void outgoing_send(const LibItsDenm__TypesAndValues::UtDenmResults& send_par); + void outgoing_send(const LibItsDenm__TypesAndValues::UtDenmEventInd& send_par); void outgoing_send(const LibItsPki__TypesAndValues::UtPkiResults& send_par); }; // End of class ConfigRsuSimulatorPort diff --git a/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc b/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc index a241cbe0b..129de3ab5 100644 --- a/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc +++ b/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc @@ -377,7 +377,7 @@ int geonetworking_codec::decode_extendedHeader(LibItsGeoNetworking__TypesAndValu } else if (_dc.get_header_sub_type() == LibItsGeoNetworking__TypesAndValues::HeaderSubTypeTSB::e__singleHop) { decode_(u.shbHeader(), *u.shbHeader().get_descriptor(), decoding_buffer); } else { - TTCN_error("geonetworking_codec::decode_headerTST: TSB subtype not processed"); + TTCN_error("geonetworking_codec::decode_headerTST: TSB subtype not processed, See ETSI EN 302 636-4-1 Clause 9.7.4 Encoding of the HT and HST fields"); } break; case LibItsGeoNetworking__TypesAndValues::HeaderType::e__geoBroadcast: @@ -395,7 +395,7 @@ int geonetworking_codec::decode_extendedHeader(LibItsGeoNetworking__TypesAndValu } else if (_dc.get_header_sub_type() == LibItsGeoNetworking__TypesAndValues::HeaderSubTypeLs::e__lsReply) { decode_(u.lsReplyHeader(), *u.lsReplyHeader().get_descriptor(), decoding_buffer); } else { - TTCN_error("geonetworking_codec::decode_headerTST: Location service subtype not processed"); + TTCN_error("geonetworking_codec::decode_headerTST: Location service subtype not processed, See ETSI EN 302 636-4-1 Clause 9.7.4 Encoding of the HT and HST fields"); } break; case LibItsGeoNetworking__TypesAndValues::HeaderType::e__any: @@ -408,11 +408,11 @@ int geonetworking_codec::decode_extendedHeader(LibItsGeoNetworking__TypesAndValu } else if (_dc.get_header_sub_type() == LibItsGeoNetworking__TypesAndValues::HeaderSubTypeSa::e__saEos) { decode_(u.saEosHeader(), *u.saEosHeader().get_descriptor(), decoding_buffer); } else { - TTCN_error("geonetworking_codec::decode_headerTST: Service Advertisement subtype not processed"); + TTCN_error("geonetworking_codec::decode_headerTST: Service Advertisement subtype not processed, See ETSI EN 302 636-4-1 Clause 9.7.4 Encoding of the HT and HST fields"); } break; default: - TTCN_error("geonetworking_codec::decode_headerTST: Not processed, _dc.header_type = %d - _dc.header_sub_type = %d", _dc.get_header_type(), _dc.get_header_sub_type()); + TTCN_error("geonetworking_codec::decode_headerTST: Not processed, _dc.header_type = %d - _dc.header_sub_type = %d, See ETSI EN 302 636-4-1 Clause 9.7.4 Encoding of the HT and HST fields", _dc.get_header_type(), _dc.get_header_sub_type()); } // End of 'switch' statement return 0; diff --git a/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc b/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc index 6de44725c..847ab6e0c 100644 --- a/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc +++ b/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc @@ -213,6 +213,10 @@ void geonetworking_layer::receive_data(OCTETSTRING& data, params& params) { /////////////////// // FIXME Check what to do with this! if (*static_cast(secured_data) == 0x02) { // This is the old Security version format, discard it + loggers::get_instance().warning("geonetworking_layer::receive_data: Security error"); + if (_enable_security_checks) { + return; + } INTEGER n; int r; TTCN_Buffer buf(secured_data); loggers::get_instance().warning("geonetworking_layer::receive_data: Old security format, parse manualy"); @@ -237,7 +241,7 @@ void geonetworking_layer::receive_data(OCTETSTRING& data, params& params) { } unsecured_gn_payload = OCTETSTRING(n, buf.get_read_data()); } - }else{ + } else { /////////////////// if (security_services::get_instance().verify_and_extract_gn_payload(secured_data, _enable_security_checks, ieee_1609dot2_data, unsecured_gn_payload, params) != 0) { loggers::get_instance().warning("geonetworking_layer::receive_data: Security error"); @@ -342,7 +346,7 @@ void geonetworking_layer::receive_data(OCTETSTRING& data, params& params) { // By default incoming beacons are filtered by the test adapter if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { - loggers::get_instance().log_msg("geonetworking_layer::receive_data: Pass beaconing filtering", sopv->gnAddr().mid()); + loggers::get_instance().log_msg("geonetworking_layer::receive_data: Pass beaconing filtering: ", sopv->gnAddr().mid()); if (_pass_beacon_table.empty()) { // Discard beacon loggers::get_instance().log("geonetworking_layer::receive_data: Pass beaconing table empty, discard it"); return; @@ -616,7 +620,7 @@ void geonetworking_layer::fill_beacon(const OCTETSTRING& p_ll_address, const INT 0, h, TrafficClass( - SCF(SCF::e__scfDisabled), + SCF(SCF::e__scfEnabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0 ), diff --git a/ccsrc/Protocols/Security/security_services.cc b/ccsrc/Protocols/Security/security_services.cc index 76e031073..a227e089f 100644 --- a/ccsrc/Protocols/Security/security_services.cc +++ b/ccsrc/Protocols/Security/security_services.cc @@ -160,8 +160,8 @@ int security_services::process_ieee_1609_dot2_signed_data(const IEEE1609dot2::Si unsigned long long gt = ((INTEGER&)(*v.get_opt_value())).get_long_long_val(); // Get current time timestamp unsigned long long us = base_time::get_instance().get_its_current_time_us(); // in microsecond - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: generation time check %ld / %ld, delta = %f", header_info.generationTime(), us, abs((double)gt - (double)us)); - if (abs((double)gt - (double)us) >= 500000.0) { // TODO Use a params for generation_time_epsilon, 500ms differences + loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: generation time check %ld / %ld, delta = %f", gt, us, abs((double)gt - (double)us)); + if (abs((double)gt - (double)us) >= 5000000.0) { // TODO Use a params for generation_time_epsilon, 5s differences loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Invalid generation time, discard it"); if (p_verify) { return -1; @@ -169,9 +169,22 @@ int security_services::process_ieee_1609_dot2_signed_data(const IEEE1609dot2::Si } } + // Check p2pcdLearningRequest keys if present + if (header_info.p2pcdLearningRequest().is_present()) { + loggers::get_instance().error("security_services::process_ieee_1609_dot2_signed_data: p2pcdLearningRequest not supported yet"); + // TODO Not supported by C-ITS Protocol + } + + // Check missingCrlIdentifier keys if present + if (header_info.missingCrlIdentifier().is_present()) { + loggers::get_instance().error("security_services::process_ieee_1609_dot2_signed_data: missingCrlIdentifier not supported yet"); + // TODO Not supported by C-ITS Protocol + } + // Check encryption keys if present if (header_info.encryptionKey().is_present()) { - // TODO + loggers::get_instance().error("security_services::process_ieee_1609_dot2_signed_data: encryptionKey not supported yet"); + // TODO Not supported by C-ITS Protocol } // Check request certificate @@ -188,7 +201,7 @@ int security_services::process_ieee_1609_dot2_signed_data(const IEEE1609dot2::Si // Check requested certificate if (header_info.requestedCertificate().is_present()) { loggers::get_instance().error("security_services::process_ieee_1609_dot2_signed_data: requestedCertificate not supported yet"); - // TODO + // TODO Not supported by C-ITS Protocol } // Check and extract unsecured payload @@ -248,14 +261,16 @@ int security_services::process_ieee_1609_dot2_signed_data(const IEEE1609dot2::Si // Check in the cache if (_security_cache.get()->get_certificate_id(p_signed_data.signer().digest(), certificate_id) == -1) { // Unknown certificate, request it - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: Unknown certificate, request it"); const OCTETSTRING& os = p_signed_data.signer().digest(); _unknown_certificate = OCTETSTRING(3, static_cast(os) + os.lengthof() - 3); + loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Unknown certificate, request it"); loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: HashedId3: ", _unknown_certificate); } // Reset certificate timer loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: Set Certificate re-transmission flag and reset timer"); _last_generation_time = 0; + + return -1; } } else if (p_signed_data.signer().ischosen(IEEE1609dot2::SignerIdentifier::ALT_certificate) && (p_signed_data.signer().certificate().size_of() != 0)) { // Extract the certificates @@ -509,7 +524,7 @@ int security_services::sign_payload(const OCTETSTRING& p_unsecured_gn_payload, O header_info.generationTime() = OPTIONAL(i); loggers::get_instance().log("security_services::sign_payload: Final HeaderInfo timestamp: %ld", us); // Check if a certificate shall be requested - if (_unknown_certificate.lengthof() == 3) { // HashedId3 + if (_unknown_certificate.lengthof() == 3) { // HashedId3 of a requested certificate IEEE1609dot2BaseTypes::SequenceOfHashedId3 s; s[0] = _unknown_certificate; header_info.inlineP2pcdRequest() = OPTIONAL(s); @@ -583,7 +598,7 @@ int security_services::sign_payload(const OCTETSTRING& p_unsecured_gn_payload, O loggers::get_instance().warning("security_services::sign_payload: Failed to encode Ieee1609Dot2Data"); return -1; } - + return 0; } @@ -1120,6 +1135,9 @@ int security_services::extract_verification_keys(const IEEE1609dot2::Certificate p_public_key_y = ecc.public_key_y(); p_public_comp_key_mode = INTEGER(1); } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen(IEEE1609dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + security_ecc ecc(ec_elliptic_curves::nist_p_256, p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().x(), p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().y()); + p_public_comp_key = ecc.public_key_compressed(); + p_public_comp_key_mode = INTEGER((int)ecc.public_key_compressed_mode()); p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().x(); p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().y(); } else { diff --git a/ccsrc/Protocols/UDP/udp_layer.cc b/ccsrc/Protocols/UDP/udp_layer.cc index 1339474d0..abd0a29ba 100644 --- a/ccsrc/Protocols/UDP/udp_layer.cc +++ b/ccsrc/Protocols/UDP/udp_layer.cc @@ -11,7 +11,7 @@ #include #include -udp_layer::udp_layer(const std::string & p_type, const std::string & param) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { +udp_layer::udp_layer(const std::string & p_type, const std::string & param) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> udp_layer::udp_layer: %s, %s", to_string().c_str(), param.c_str()); // Setup parameters @@ -32,6 +32,11 @@ udp_layer::udp_layer(const std::string & p_type, const std::string & param) : la if (it == _params.cend()) { _params.insert(std::pair(std::string("dst_port"), "12345")); } + it = _params.find("reuse_incoming_source_adddress"); + if (it != _params.cend()) { + _reuse_incoming_source_adddress = (boolean)(it->second.compare("1") == 0); + } + loggers::get_instance().log("udp_layer::udp_layer: _reuse_incoming_source_adddress: %d", _reuse_incoming_source_adddress); // Initialize the socket _saddr.sin_family = AF_INET; @@ -119,6 +124,10 @@ void udp_layer::Handle_Fd_Event_Readable(int fd) { return; } else { std::copy((unsigned char*)buffer, (unsigned char*)((unsigned char*)buffer + result), std::back_inserter(acc)); + if (_reuse_incoming_source_adddress) { // Reuse the incoming address/port for sending + memcpy((void*)&_daddr, (const void*)&from, sizeof(struct sockaddr_in)); + loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: New _daddr: %s:%d", ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); + } } params.insert(std::pair(std::string("timestamp"), std::to_string(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()))); diff --git a/ccsrc/Protocols/UDP/udp_layer.hh b/ccsrc/Protocols/UDP/udp_layer.hh index f589675d7..6e2f57d3f 100644 --- a/ccsrc/Protocols/UDP/udp_layer.hh +++ b/ccsrc/Protocols/UDP/udp_layer.hh @@ -28,6 +28,8 @@ class udp_layer : public layer, public PORT { params _params; //! Layer parameters struct sockaddr_in _saddr; //! Source socket address description struct sockaddr_in _daddr; //! Destination socket address description + boolean _reuse_incoming_source_adddress; + //! This flag must be set to true if the UpperTester/UDP layer must act as an IUT, not as a Test System. Default value: Test System int _fd; // Socket file descriptor std::string _time_key; //! \todo diff --git a/etc/AtsPki/AtsPki_Idnomic.cfg_ b/etc/AtsPki/AtsPki_Idnomic.cfg_ index d19bcc6de..85127ceae 100644 --- a/etc/AtsPki/AtsPki_Idnomic.cfg_ +++ b/etc/AtsPki/AtsPki_Idnomic.cfg_ @@ -70,7 +70,7 @@ system.httpAtPort.params := "HTTP(codecs=http_its:http_etsi_ieee1609dot2_codec)/ #ItsPki_TestCases.TC_SECPKI_EA_ENR_RCV_01_BV # Check that EA doesn't accept Enrolment rekeying request when enrolment is not permitted by signing certificate (not containing an item of type PsidSsp) -#ItsPki_TestCases.TC_SECPKI_EA_ENR_RCV_02_BI_01 +ItsPki_TestCases.TC_SECPKI_EA_ENR_RCV_02_BI_01 # Check that EA doesn't accept Enrolment rekeying request when enrolment is not permitted by signing certificate (containing opaque[0] (version) indicating other value than 1) #ItsPki_TestCases.TC_SECPKI_EA_ENR_RCV_02_BI_02 # Check that EA doesn't accept Enrolment rekeying request when enrolment is not permitted by signing certificate (containing opaque[1] (value) indicating "Enrolment Request" (bit 1) set to 0) @@ -172,7 +172,7 @@ system.httpAtPort.params := "HTTP(codecs=http_its:http_etsi_ieee1609dot2_codec)/ #ItsPki_TestCases.TC_SECPKI_AA_AUTH_RCV_16_BI # Check that the AA sends AuthorizationValidationRequest after receiving of the AuthorizationRequest -ItsPki_TestCases.TC_SECPKI_AA_AUTHVAL_01_BV +#ItsPki_TestCases.TC_SECPKI_AA_AUTHVAL_01_BV [MAIN_CONTROLLER] # The options herein control the behavior of MC. diff --git a/etc/AtsRSUsSimulator/AtsRSUSimulator.cfg b/etc/AtsRSUsSimulator/AtsRSUSimulator.cfg index e4fd4d860..d880bec7f 100644 --- a/etc/AtsRSUsSimulator/AtsRSUSimulator.cfg +++ b/etc/AtsRSUsSimulator/AtsRSUSimulator.cfg @@ -5,14 +5,17 @@ LibItsGeoNetworking_Pics.PICS_GN_LOCAL_GN_ADDR := { typeOfAddress := e_manual, stationType := e_passengerCar, #e_unknown stationCountryCode := 0, - mid := '4C5E0C14D2EA'O + mid := '4C5E0C14D2EA'O #'00000000000B'O } -# GeoNetwoking only, no facility layer +# GeoNetwoking only, no facility layer, used for AtsGenNetworking and AtsSecurity with other profile #LibItsGeoNetworking_Pixits.PX_GN_UPPER_LAYER := e_any # With facility layer LibItsGeoNetworking_Pixits.PX_GN_UPPER_LAYER := e_btpB +# Use this certificate if the RSU simulator act as IUT +LibItsCommon_Pixits.PX_CERT_FOR_TS := "CERT_IUT_A_AT" + # Indicate which RSU to simulate ItsRSUsSimulator_Pixits.PX_RSU_ID := 1; # Indicate which Use Case to simulate @@ -24,7 +27,7 @@ ItsRSUsSimulator_Pixits.PX_RSU_ID := 1; # UC7 (CAM only): PX_ETSI_USE_CASE_ID := 7 # UC8 (EVCSN only): PX_ETSI_USE_CASE_ID := 8 # UC9 (CAM only): PX_ETSI_USE_CASE_ID := 9 -ItsRSUsSimulator_Pixits.PX_ETSI_USE_CASE_ID := 1 # 7 PX_RSU_ID := 8 ==> LCWW +ItsRSUsSimulator_Pixits.PX_ETSI_USE_CASE_ID := 6 # 7 PX_RSU_ID := 8 ==> LCWW # 1 PX_RSU_ID := 1 ==> RWW # 2 PX_RSU_ID := 1 ==> RHW # Indicate which zone to simulate @@ -33,8 +36,8 @@ ItsRSUsSimulator_Pixits.PX_ETSI_ZONE_ID := 1 ItsRSUsSimulator_Pixits.PX_DENM_PARAM_UC2 := 1; # ==> RHW (1..5) ItsRSUsSimulator_Pics.PICS_GENERATE_BEACON := false # Change also its_aid in geoNetworking port setting -ItsRSUsSimulator_Pics.PICS_GENERATE_CAM := false # Change also its_aid in geoNetworking port setting -ItsRSUsSimulator_Pics.PICS_GENERATE_DENM := true # Change also its_aid in geoNetworking port setting +ItsRSUsSimulator_Pics.PICS_GENERATE_CAM := true # Change also its_aid in geoNetworking port setting +ItsRSUsSimulator_Pics.PICS_GENERATE_DENM := false # Change also its_aid in geoNetworking port setting ItsRSUsSimulator_Pics.PICS_GENERATE_IVIM := false ItsRSUsSimulator_Pics.PICS_GENERATE_MAPEM := false ItsRSUsSimulator_Pics.PICS_GENERATE_SPATEM := false @@ -46,7 +49,9 @@ ItsRSUsSimulator_Pics.PICS_BEACON_FREQUENCY := 1.0 ItsRSUsSimulator_Pics.PICS_CAM_FREQUENCY := 1.0 ItsRSUsSimulator_Pics.PICS_DENM_FREQUENCY := 1.0 -ItsRSUsSimulator_Pics.PICS_SEND_CAM_INDICATION := false +ItsRSUsSimulator_Pics.PICS_SEND_BEACON_INDICATION := false +ItsRSUsSimulator_Pics.PICS_SEND_CAM_INDICATION := true +ItsRSUsSimulator_Pics.PICS_SEND_DENM_INDICATION := true # Enable Security support LibItsGeoNetworking_Pics.PICS_GN_SECURITY := true @@ -73,10 +78,10 @@ LibItsPki_Pics.PICS_TS_AA_CERTIFICATE_ID := "CERT_TS_A_AA" # In this section you can specify the name of the log file and the classes of events # you want to log into the file or display on console (standard error). LogFile := "../logs/%e.%h-%r.%s" -#FileMask := LOG_ALL | USER | DEBUG | MATCHING -#ConsoleMask := LOG_ALL | USER | DEBUG | MATCHING -FileMask := ERROR | WARNING | USER | MATCHING | EXECUTOR_RUNTIME | VERDICTOP -ConsoleMask := ERROR | WARNING | USER | MATCHING | EXECUTOR_RUNTIME | VERDICTOP +FileMask := LOG_ALL | USER | DEBUG | MATCHING +ConsoleMask := LOG_ALL | USER | DEBUG | MATCHING +#FileMask := ERROR | WARNING | USER | MATCHING | EXECUTOR_RUNTIME | VERDICTOP +#ConsoleMask := ERROR | WARNING | USER | MATCHING | EXECUTOR_RUNTIME | VERDICTOP LogSourceInfo := Stack LogEntityName:= Yes LogEventTypes:= Yes @@ -151,21 +156,24 @@ LogEventTypes:= Yes # save_mode : Set to 1 to save sent packet, 0 otherwise # Single GeoNetworking component port -# its_aid=36: CAM -# its_aid=37: DENM -#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,its_aid=37,secured_mode=0,encrypted_mode=0,certificate=CERT_IUT_A_AT,peer_certifIcate=CERT_TS_A_AT,sec_db_path=/home/vagrant/tmp/asn1c_cert)/ETH(mac_src=080027128a53)/PCAP(mac_src=080027128a53,nic=eth0,filter=and ether proto 0x8947)" - +# its_aid=36: CAM +# its_aid=37: DENM +# its_aid=141: GeoMet +system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,its_aid=37,secured_mode=1,certificate=CERT_IUT_A_AT,sec_db_path=/home/vagrant/tmp/asn1c_cert)/ETH(mac_src=080027128a53)/PCAP(mac_src=080027128a53,nic=eth1,filter=and ether proto 0x8947)" # Commsignia -#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,its_aid=37,secured_mode=0,encrypted_mode=0,certificate=CERT_IUT_A_AT,peer_certifIcate=CERT_TS_A_AT,sec_db_path=/home/vagrant/tmp/asn1c_cert)/COMMSIGNIA(xport_mode=LTE-V2X,mac_src=080027F44E7D,interface_id=2,target_host=192.168.0.54)/UDP(dst_ip=192.168.0.54,src_port=9091,dst_port=7946)" +#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,its_aid=37,secured_mode=0,encrypted_mode=0,certificate=CERT_IUT_A_AT,peer_certificate=CERT_TS_A_AT,sec_db_path=/home/vagrant/tmp/asn1c_cert)/COMMSIGNIA(xport_mode=LTE-V2X,mac_src=080027F44E7D,interface_id=2,target_host=192.168.0.54)/UDP(dst_ip=192.168.0.54,src_port=9091,dst_port=7946)" # Qualcom -system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=36747486,longitude=-4556772,distanceA=25,distanceB=25,its_aid=37,secured_mode=1,encrypted_mode=0,certificate=CERT_MICROSEC_AT_01,peer_certifIcate=CERT_TS_A_AT,sec_db_path=/home/vagrant/tmp/asn1c_cert)/QUALCOMM/UDP(dst_ip=10.200.1.113,src_port=9091,dst_port=4041)" +#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=36747486,longitude=-4556772,distanceA=25,distanceB=25,its_aid=37,secured_mode=1,encrypted_mode=0,certificate=CERT_MICROSEC_AT_01,peer_certificate=CERT_TS_A_AT,sec_db_path=/home/vagrant/tmp/asn1c_cert)/QUALCOMM/UDP(dst_ip=10.200.1.113,src_port=9091,dst_port=4041)" #system.httpPort.params := "HTTP(codecs=http_its:http_etsi_ieee1609dot2_codec)/TCP(debug=1,server=192.168.42.252,port=80)" system.httpPort.params := "HTTP(codecs=http_its:http_etsi_ieee1609dot2_codec)/TCP(debug=1,server=192.168.1.252,port=80)" # Config port based on UDP #system.cfPort.params := "CF(ut=pki)/UDP(dst_ip=192.168.42.252,src_port=12345)" -system.cfPort.params := "CF(ut=cam)/UDP(dst_ip=192.168.1.252,src_port=12345)" +#system.cfPort.params := "CF(ut=cam)/UDP(dst_ip=192.168.1.39,src_port=12345)" +#system.cfPort.params := "CF(ut=cam)/UDP(dst_ip=172.28.4.87,src_port=12345,reuse_incoming_source_adddress=1)" +system.cfPort.params := "CF(ut=denm)/UDP(dst_ip=172.28.4.87,src_port=12345,reuse_incoming_source_adddress=1)" +#system.cfPort.params := "CF(ut=gn)/UDP(dst_ip=172.28.4.87,src_port=12345,reuse_incoming_source_adddress=1)" [EXECUTE] ItsRSUsSimulator_TestCases.TC_RSUSIMU_BV_01 diff --git a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Functions.ttcn b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Functions.ttcn index b2ea4de4d..d524994e2 100644 --- a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Functions.ttcn +++ b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Functions.ttcn @@ -212,7 +212,7 @@ module ItsRSUsSimulator_Functions { // Local variables var template (value) DenmParmContainers v_denmParmContainers; - var template (omit) octetstring v_beacon := omit; + var template (omit) GeoNetworkingPdu v_beacon := omit; var template (omit) DENMs v_denms := omit; var template (omit) CAM v_cam := omit; var template (omit) MAPEM v_mapem := omit; @@ -452,9 +452,18 @@ module ItsRSUsSimulator_Functions { } } if (vc_beacon == true) { - // Build the list of the BeACON events - v_beacon := 'AAAAAAAA'O; // TODO Use a PICS - } + // Build the list of the Beacon events + v_beacon := valueof(m_geoNwPdu( + m_geoNwBeaconPacket( + vc_longPosVectorRsu + ), + m_defaultLifetime, + 1 + ) + ); + v_beacon.gnPacket.packet.commonHeader.flags := f_isMobile(); + f_acTriggerEvent(m_startPassBeaconing(m_beaconHeader(m_longPosVector(PX_TS_NODE_B_LOCAL_GN_ADDR, 0)).beaconHeader)); + } // Build the messages value list for this RSU vc_rsuMessagesValueList[p_rsu_id] := m_rsuProfile( @@ -467,7 +476,6 @@ module ItsRSUsSimulator_Functions { // v_evcsn, v_ssem ); - //log("vc_rsuMessagesValueList[p_rsu_id] = ", vc_rsuMessagesValueList[p_rsu_id]); if (PICS_RSU_PARAMS[p_rsu_id].geoShape == e_geoCircle) { vc_geoArea := { shape := e_geoCircle, @@ -522,21 +530,6 @@ module ItsRSUsSimulator_Functions { return true; } // End of function f_process_cf_event - function f_prepare_beacon( - out template (value) GnRawPayload p_payload - ) runs on ItsRSUsSimulator { - - p_payload := valueof( - f_adaptPayload( - vc_rsuMessagesValueList[vc_rsu_id].beacon, - 0, - -, - e_any - ) - ); - log("f_prepare_beacon: ", p_payload); - } // End of function f_prepare_beacon - function f_prepare_cam( out template (value) GnRawPayload p_payload ) runs on ItsRSUsSimulator { @@ -553,6 +546,7 @@ module ItsRSUsSimulator_Functions { PICS_CAM_BTP_SOURCE_PORT ) ); + //log("f_prepare_cam: ", p_payload); } // End of function f_prepare_cam function f_prepare_denm( @@ -576,6 +570,8 @@ module ItsRSUsSimulator_Functions { ) ); vc_denmEventCounter := (vc_denmEventCounter + 1) mod lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); + + log("f_prepare_denm: ", p_payload); } // End of function f_prepare_denm function f_prepare_mapem( @@ -878,32 +874,34 @@ module ItsRSUsSimulator_Functions { }, c_hopLimit1 )); - } else { - v_geoNetworkingPdu := valueof(m_geoNwPdu( // FIXME Use PIXIT parameter to get a fully configurable template - m_geoNwBroadcastPacket_payload( // TODO modifes 'template (value) GnNonSecuredPacket m_geoNwBroadcastPacket' to set the field - vc_longPosVectorRsu, - f_incLocalSeqNumber(), - f_geoArea2GeoBroadcastArea(vc_geoArea), - -, - -, - valueof(p_payload) - ), - Lifetime:{ - multiplier := c_defaultLifetime, - ltBase := e_100s - }, - c_hopLimit1 - )); - v_geoNetworkingPdu.gnPacket.packet.commonHeader.nextHeader := e_any; + } else { // Beacon + v_geoNetworkingPdu := valueof(vc_rsuMessagesValueList[vc_rsu_id].beacon); } f_sendGeoNetMessage(valueof(m_geoNwReq_linkLayerBroadcast(v_geoNetworkingPdu, p_its_aid))); } // End of function f_send + function f_processBeacon( + in GeoNetworkingPdu p_geoNetworkingPdu + ) runs on ItsRSUsSimulator { + var bitstring v_enc_msg; + log("f_processBeacon: Beacon=", p_geoNetworkingPdu); + if (PICS_SEND_BEACON_INDICATION) { + var UtGnEventInd v_utGnEventInd; + var integer v_result; + // Extract BEACON message + var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; + // Send UtGnEventInd + log("f_processBeacon: v_payload=", v_payload); + v_utGnEventInd.rawPayload := v_payload; + cfPort.send(v_utGnEventInd); + } + } + function f_processCam( - in GeoNetworkingPdu p_geoNetworkingPdu + in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { var bitstring v_enc_msg; - log("CAM=", p_geoNetworkingPdu); + log("f_processCam: CAM=", p_geoNetworkingPdu.gnPacket.packet.payload); if (PICS_SEND_CAM_INDICATION) { var UtCamEventInd v_utCamEventInd; var integer v_result; @@ -911,14 +909,36 @@ module ItsRSUsSimulator_Functions { var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; // Remove BTP layer v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); - // Send UtEventCamIndication + // Send UtCamEventInd + log("f_processCam: v_payload=", v_payload); v_enc_msg := oct2bit(v_payload); if (decvalue(v_enc_msg, v_utCamEventInd.camMsg) == 0) { cfPort.send(v_utCamEventInd); } } } - + + function f_processDenm( + in GeoNetworkingPdu p_geoNetworkingPdu + ) runs on ItsRSUsSimulator { + var bitstring v_enc_msg; + log("f_processDenm: DENM=", p_geoNetworkingPdu.gnPacket.packet.payload); + if (PICS_SEND_DENM_INDICATION) { + var UtDenmEventInd v_utDenmEventInd; + var integer v_result; + // Extract DENM message + var octetstring v_payload := p_geoNetworkingPdu.gnPacket.packet.payload; + // Remove BTP layer + v_payload := substr(v_payload, 4, lengthof(v_payload) - 4); + // Send UtDenmEventInd + log("f_processDenm: v_payload=", v_payload); + v_enc_msg := oct2bit(v_payload); + if (decvalue(v_enc_msg, v_utDenmEventInd.denMsg) == 0) { + cfPort.send(v_utDenmEventInd); + } + } + } + function f_processSrem( in GeoNetworkingPdu p_geoNetworkingPdu ) runs on ItsRSUsSimulator { @@ -977,31 +997,49 @@ module ItsRSUsSimulator_Functions { } function f_payload_template( - in integer p_dest_port, + in integer p_dest_port, in integer p_src_port ) return template (present) octetstring { - log(">>> f_payload_template: ", p_dest_port, " - ", p_src_port); - var template (present) Oct2 v_t1 := int2oct(PICS_SREM_BTP_DESTINATION_PORT, 2); - var template (present) Oct2 v_t2 := int2oct(PICS_SREM_BTP_SOURCE_PORT, 2); - var template (present) octetstring v_t3 := ? length (5 .. 65535); - var template (present) octetstring v_out := valueof(v_t1) & valueof(v_t2) & valueof(v_t3); - return v_out + //log(">>> f_payload_template: ", p_dest_port, " - ", p_src_port); + var template (value) Oct2 v_t1 := int2oct(p_dest_port, 2); + var template (value) Oct2 v_t2 := int2oct(p_src_port, 2); + var template (present) octetstring v_t3 := ? /*? length (5 .. 65535)*/; + var template (present) octetstring v_out := valueof(v_t1) & valueof(v_t2) & v_t3; + //log("<<< f_payload_template: v_out=", v_out); + return v_out } altstep a_process_cf_ut_command() runs on ItsRSUsSimulator { var UtGnInitialize v_utGnInitialize; + var UtCamInitialize v_utCamInitialize; + var UtDenmInitialize v_utDenmInitialize; var UtPkiInitialize v_utPkiInitialize; var UtGnTrigger v_utGnTrigger; var UtCamTrigger v_utCamTrigger; + var UtDenmTrigger v_utDenmTrigger; + var UtDenmUpdate v_utDenmUpdate; + var UtDenmTermination v_utDenmTermination; var UtPkiTrigger v_utPkiTrigger; - + [] cfPort.receive(UtGnInitialize:?) -> value v_utGnInitialize { + var GeoNetworkingPdu v_geoNwPdu; + log("v_utGnInitialize = ", v_utGnInitialize); + v_geoNwPdu :=valueof( + m_geoNwPdu( + m_geoNwBeaconPacket( + vc_longPosVectorRsu + ), + m_defaultLifetime, + 1 + ) + ); + v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); + vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; cfPort.send(UtGnResults: { utGnInitializeResult := true } ); repeat; } [] cfPort.receive(UtGnTrigger:?) -> value v_utGnTrigger { - cfPort.send(UtGnResults: { utGnTriggerResult := true } ); log("v_utGnTrigger = ", v_utGnTrigger); if (ischosen(v_utGnTrigger.geoUnicast)) { var GnNonSecuredPacket v_geoNwUnicastPacket := valueof( @@ -1012,17 +1050,19 @@ module ItsRSUsSimulator_Functions { c_defaultHopLimit, v_utGnTrigger.geoUnicast.trafficClass, v_utGnTrigger.geoUnicast.payload - )); + )); var GeoNetworkingPdu v_geoNwPdu := valueof( m_geoNwPdu( v_geoNwUnicastPacket, - m_lifetimeBase1s(v_utGnTrigger.geoUnicast.lifetime), + m_lifetimeBase1s(v_utGnTrigger.geoUnicast.lifetime / 1000), c_defaultHopLimit - ) - ); + ) + ); v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; + v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); v_geoNwPdu.gnPacket.packet.extendedHeader.geoUnicastHeader.dstPosVector.gnAddr := v_utGnTrigger.geoUnicast.gnAddress; - geoNetworkingPort.send(m_geoNwReq_linkLayerBroadcast(v_geoNwPdu)); + vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; + cfPort.send(UtGnResults: { utGnTriggerResult := true } ); } else if (ischosen(v_utGnTrigger.geoBroadcast)) { var GeoBroadcastArea v_broadcastArea; var GnNonSecuredPacket v_geoNwBroadcastPacket; @@ -1047,20 +1087,118 @@ module ItsRSUsSimulator_Functions { v_utGnTrigger.geoBroadcast.trafficClass, v_utGnTrigger.geoBroadcast.payload )); + v_geoNwBroadcastPacket.commonHeader.flags := f_isMobile(); v_geoNwPdu := valueof( m_geoNwPdu( v_geoNwBroadcastPacket, - m_lifetimeBase1s(v_utGnTrigger.geoBroadcast.lifetime), + m_lifetimeBase1s(v_utGnTrigger.geoBroadcast.lifetime / 1000), c_defaultHopLimit )); + v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; + v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); + vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; + cfPort.send(UtGnResults: { utGnTriggerResult := true } ); + } else if (ischosen(v_utGnTrigger.geoAnycast)) { + var GeoAnycastArea v_anycastArea; + var GnNonSecuredPacket v_geoNwAnycastPacket; + var GeoNetworkingPdu v_geoNwPdu; + + if (v_utGnTrigger.geoAnycast.shape == e_geoCircle) { + v_anycastArea.geoAnycastSubType := e_geoAnycastCircle; + } else if (v_utGnTrigger.geoAnycast.shape == e_geoRect) { + v_anycastArea.geoAnycastSubType := e_geoAnycastRect; + } else if (v_utGnTrigger.geoAnycast.shape == e_geoElip) { + v_anycastArea.geoAnycastSubType := e_geoAnycastElip; + } else { + v_anycastArea.geoAnycastSubType := e_reserved; + } + v_anycastArea.geoAnycastArea := v_utGnTrigger.geoAnycast.area; + v_geoNwAnycastPacket := valueof( + m_geoNwAnycastPacket_payload( + vc_longPosVectorRsu, + f_incLocalSeqNumber(), + v_anycastArea, + c_defaultHopLimit, + v_utGnTrigger.geoAnycast.trafficClass, + v_utGnTrigger.geoAnycast.payload + )); + v_geoNwPdu := valueof( + m_geoNwPdu( + v_geoNwAnycastPacket, + m_lifetimeBase1s(v_utGnTrigger.geoAnycast.lifetime / 1000), + c_defaultHopLimit + )); + v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); + v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; + vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; + cfPort.send(UtGnResults: { utGnTriggerResult := true } ); + } else if (ischosen(v_utGnTrigger.shb)) { + var GnNonSecuredPacket v_geoShbPacket; + var GeoNetworkingPdu v_geoNwPdu; + + v_geoShbPacket := valueof( + m_geoNwShbPacket_payload( + vc_longPosVectorRsu, + v_utGnTrigger.shb.payload + )); + v_geoShbPacket.commonHeader.maxHopLimit := 1; + v_geoShbPacket.commonHeader.trafficClass.scf := v_utGnTrigger.shb.trafficClass.scf; + v_geoShbPacket.commonHeader.trafficClass.channelOffload := v_utGnTrigger.shb.trafficClass.channelOffload; + v_geoShbPacket.commonHeader.trafficClass.tcId := v_utGnTrigger.shb.trafficClass.tcId; + v_geoNwPdu := valueof( + m_geoNwPdu( + v_geoShbPacket, + m_defaultLifetime, + 1 + )); + v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); + v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; + vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; + cfPort.send(UtGnResults: { utGnTriggerResult := true } ); + } else if (ischosen(v_utGnTrigger.tsb)) { + var GnNonSecuredPacket v_geoTsbPacket; + var GeoNetworkingPdu v_geoNwPdu; + + v_geoTsbPacket := valueof( + m_geoNwTsbPacket_payload( + f_incLocalSeqNumber(), + vc_longPosVectorRsu, + -, + -, + v_utGnTrigger.tsb.payload + )); + v_geoTsbPacket.commonHeader.trafficClass.scf := v_utGnTrigger.tsb.trafficClass.scf; + v_geoTsbPacket.commonHeader.trafficClass.channelOffload := v_utGnTrigger.tsb.trafficClass.channelOffload; + v_geoTsbPacket.commonHeader.trafficClass.tcId := v_utGnTrigger.tsb.trafficClass.tcId; + v_geoNwPdu := valueof( + m_geoNwPdu( + v_geoTsbPacket, + m_defaultLifetime, + c_defaultHopLimit + )); + v_geoNwPdu.gnPacket.packet.commonHeader.nextHeader := e_any; + v_geoNwPdu.gnPacket.packet.commonHeader.flags := f_isMobile(); + vc_rsuMessagesValueList[vc_rsu_id].beacon := v_geoNwPdu; + cfPort.send(UtGnResults: { utGnTriggerResult := true } ); + } else { + cfPort.send(UtGnResults: { utGnTriggerResult := false } ); } repeat; } - [vc_cam == true] cfPort.receive(UtCamInitialize:?) { + [vc_cam == true] cfPort.receive(UtCamInitialize:?) -> value v_utCamInitialize { + log("v_utCamInitialize = ", v_utCamInitialize); + /*if (v_utCamInitialize.hashedId8 != int2oct(0, 8)) { + }*/ + vc_cam_timer_value := 1.0; // Reset CAM timer + vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.curvature.curvatureValue := 0 + vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.highFrequencyContainer.basicVehicleContainerHighFrequency.heading.headingValue := 0; + vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.lowFrequencyContainer.basicVehicleContainerLowFrequency.vehicleRole := default_; + vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.specialVehicleContainer := omit; cfPort.send(UtCamResults: { utCamInitializeResult := true } ); repeat; } - [vc_cam == true] cfPort.receive(UtCamTrigger: { changeSpeed := ? }) { + [vc_cam == true] cfPort.receive(UtCamTrigger: { changeSpeed := ? }) -> value v_utCamTrigger { + log("v_utCamTrigger = ", v_utCamTrigger); cfPort.send(UtCamResults: { utCamTriggerResult := true } ); vc_cam_timer_value := vc_cam_timer_value / 2.0; repeat; @@ -1085,15 +1223,128 @@ module ItsRSUsSimulator_Functions { } repeat; } - /*[vc_cam == true] cfPort.receive(UtCamTrigger: { changePosition := ? }) { + [vc_cam == true] cfPort.receive(UtCamTrigger: { setVehicleRole := ? }) -> value v_utCamTrigger { + log("v_utCamTrigger = ", v_utCamTrigger); + vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.lowFrequencyContainer.basicVehicleContainerLowFrequency.vehicleRole := v_utCamTrigger.setVehicleRole; + vc_rsuMessagesValueList[vc_rsu_id].cam.cam.camParameters.specialVehicleContainer := { publicTransportContainer := { embarkationStatus := true, ptActivation := omit } }; cfPort.send(UtCamResults: { utCamTriggerResult := true } ); - //TODO vc_cam_timer_value := vc_cam_timer_value / 4.0; repeat; - }*/ - [vc_denm == true] cfPort.receive(UtDenmInitialize:?) { + } + [] cfPort.receive(UtDenmInitialize:?) -> value v_utDenmInitialize { + log("v_utDenmInitialize = ", v_utDenmInitialize); + vc_rsuMessagesValueList[vc_rsu_id].denms := {}; + vc_denmEventCounter := 0; + vc_denm := true; cfPort.send(UtDenmResults: { utDenmInitializeResult := true } ); repeat; } + [vc_denm == true] cfPort.receive(UtDenmTrigger:?) -> value v_utDenmTrigger { + var template (value) DenmParmContainers v_denmParmContainers; + var DenmEventsParmsPerZone v_denmEventsParmsPerZone := PICS_DENM_EVENTS_RSU_UC1[vc_rsu_id][PX_ETSI_ZONE_ID - 1]; + var integer seq_number := f_incDenmSequenceNumber(); + + log("v_utDenmTrigger: ", v_utDenmTrigger); + v_denmParmContainers := m_denmParmContainers( + PICS_RSU_PARAMS[vc_rsu_id].stationID, + seq_number, + v_utDenmTrigger.repetitionInterval, + v_denmEventsParmsPerZone[0].eventPosition, + v_utDenmTrigger.situation.eventType.causeCode, + v_denmEventsParmsPerZone[0].eventHistory, + v_denmEventsParmsPerZone[0].traces, + v_utDenmTrigger.validityDuration, + v_utDenmTrigger.relevanceDistance, + v_utDenmTrigger.relevanceTrafficDirection + ); + v_denmParmContainers.managementContainer.detectionTime := v_utDenmTrigger.detectionTime; + vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms)] := valueof( + m_denmPdu_rsu( + PICS_RSU_PARAMS[vc_rsu_id].stationID, + m_denm( + v_denmParmContainers.managementContainer, + v_denmParmContainers.situationContainer, + v_denmParmContainers.locationContainer + ))); + log("utDenmTrigger: denm=[" & int2char(lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1) & "]=", vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1]); + //denm={ { header := { protocolVersion := 2, messageID := 1, stationID := 1111101 }, denm := { management := { actionID := { originatingStationID := 1111101, sequenceNumber := 1 }, detectionTime := 510819417810, referenceTime := 510819420809, termination := omit, eventPosition := { latitude := 367467556, longitude := -45552381, positionConfidenceEllipse := { semiMajorConfidence := 100, semiMinorConfidence := 100, semiMajorOrientation := 0 }, altitude := { altitudeValue := 0, altitudeConfidence := alt_000_01 (0) } }, relevanceDistance := lessThan50m (0), relevanceTrafficDirection := upstreamTraffic (1), validityDuration := 2, transmissionInterval := omit, stationType := 15 }, situation := { informationQuality := 0, eventType := { causeCode := 91, subCauseCode := 0 }, linkedCause := omit, eventHistory := { { eventPosition := { deltaLatitude := 135, deltaLongitude := -147, deltaAltitude := 0 }, eventDeltaTime := omit, informationQuality := 0 }, { eventPosition := { deltaLatitude := -68, deltaLongitude := 74, deltaAltitude := 0 }, eventDeltaTime := omit, informationQuality := 0 } } }, location := { eventSpeed := omit, eventPositionHeading := omit, traces := { { { pathPosition := { deltaLatitude := -1086, deltaLongitude := 2551, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -450, deltaLongitude := 1010, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -460, deltaLongitude := 1000, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -440, deltaLongitude := 1000, deltaAltitude := 0 }, pathDeltaTime := omit }, { pathPosition := { deltaLatitude := -440, deltaLongitude := 990, deltaAltitude := 0 }, pathDeltaTime := omit } } }, roadType := omit }, alacarte := omit } } } + if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) == 1) { + tc_denm.start; + } + cfPort.send(UtDenmResults: { utDenmTriggerResult := { result := true, actionId := vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1].denm.management.actionID } } ); + repeat; + } + [vc_denm == true] cfPort.receive(UtDenmUpdate:?) -> value v_utDenmUpdate { + var integer v_i := 0; + var boolean v_found := false; + + log("v_utDenmUpdate = ", v_utDenmUpdate); + for (v_i := 0; v_i < lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); v_i := v_i + 1) { + if (v_utDenmUpdate.actionId.sequenceNumber == valueof(vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.actionID.sequenceNumber)) { + v_found := true; + break; + } + } // End of 'for' statement + if (v_found == true) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.detectionTime := v_utDenmUpdate.detectionTime; + if (ispresent(v_utDenmUpdate.validityDuration)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.validityDuration := v_utDenmUpdate.validityDuration; + } + if (ispresent(v_utDenmUpdate.situation)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.situation := v_utDenmUpdate.situation; + } + if (ispresent(v_utDenmUpdate.relevanceDistance)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.relevanceDistance := v_utDenmUpdate.relevanceDistance; + } + if (ispresent(v_utDenmUpdate.relevanceTrafficDirection)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.relevanceTrafficDirection := v_utDenmUpdate.relevanceTrafficDirection; + } + if (ispresent(v_utDenmUpdate.transmissionInterval)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.transmissionInterval := v_utDenmUpdate.transmissionInterval; + } + if (ispresent(v_utDenmUpdate.transmissionInterval)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.transmissionInterval := v_utDenmUpdate.transmissionInterval; + } + if (ispresent(v_utDenmUpdate.alacarte)) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.alacarte := v_utDenmUpdate.alacarte; + } + } + cfPort.send(UtDenmResults: { utDenmUpdateResult := { result := true, actionId := vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.actionID } } ); + repeat; + } + [vc_denm == true] cfPort.receive(UtDenmTermination:?) -> value v_utDenmTermination { + var integer v_i := 0; + var boolean v_found := false; + + log("v_utDenmTermination: ", v_utDenmTermination); + for (v_i := 0; v_i < lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); v_i := v_i + 1) { + if (v_utDenmTermination.actionId.sequenceNumber == valueof(vc_rsuMessagesValueList[vc_rsu_id].denms[v_i].denm.management.actionID.sequenceNumber)) { + v_found := true; + break; + } + } // End of 'for' statement + if (v_found == true) { + log("v_utDenmTermination: v_i=", v_i); + log("v_utDenmTermination: l=", lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms)); + if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) > 1) { //Shift elements + for (var integer v_j := v_i + 1; v_i < lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms); v_i := v_i + 1) { + vc_rsuMessagesValueList[vc_rsu_id].denms[v_i] := vc_rsuMessagesValueList[vc_rsu_id].denms[v_j]; + v_j := v_j + 1; + } // End of 'for' statement + vc_rsuMessagesValueList[vc_rsu_id].denms[lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) - 1] := {} + } else { + vc_rsuMessagesValueList[vc_rsu_id].denms := {}; + vc_denmEventCounter := 0; + } + log("v_utDenmTermination: New l=", lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms)); + if (lengthof(vc_rsuMessagesValueList[vc_rsu_id].denms) == 0) { + tc_denm.stop; + f_sleep(1.0); + vc_denm := false; + } + cfPort.send(UtDenmResults: { utDenmTerminationResult := true } ); + } + repeat; + } [vc_pki == true] cfPort.receive(UtPkiInitialize:?) -> value v_utPkiInitialize { log("v_utPkiInitialize = ", v_utPkiInitialize); cfPort.send(UtPkiResults: { utPkiInitializeResult := true } ); @@ -1101,7 +1352,7 @@ module ItsRSUsSimulator_Functions { } [vc_pki == true] cfPort.receive(UtPkiTrigger: { triggerEnrolmentRequest := ? }) -> value v_utPkiTrigger { var ItsPkiHttp v_pki; - + cfPort.send(UtPkiResults: { utPkiTriggerResult := true } ); v_pki := ItsPkiHttp.create("TriggeredEc") alive; v_pki.start(f_trigger_enrolment_request_await_response( diff --git a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Pics.ttcn b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Pics.ttcn index 088708167..9bde552bc 100644 --- a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Pics.ttcn +++ b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Pics.ttcn @@ -5765,6 +5765,11 @@ module ItsRSUsSimulator_Pics { */ modulepar boolean PICS_SEND_CAM_INDICATION := false; + /** + * @desc Set to true to send DENM UT event indication + */ + modulepar boolean PICS_SEND_DENM_INDICATION := false; + } // End of group indications group generationFrequencies { diff --git a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Templates.ttcn b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Templates.ttcn index 2983a9fc0..375d109e5 100644 --- a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Templates.ttcn +++ b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_Templates.ttcn @@ -47,7 +47,7 @@ module ItsRSUsSimulator_Templates { import from ItsRSUsSimulator_Pics all; template (omit) RsuMessagesValue m_rsuProfile( - in template (omit) octetstring p_beacon := omit, + in template (omit) GeoNetworkingPdu p_beacon := omit, in template (omit) CAM p_cam := omit, in template (omit) DENMs p_denms := omit, in template (omit) MAPEM p_mapem := omit, @@ -67,7 +67,37 @@ module ItsRSUsSimulator_Templates { } // End of template RsuMessagesValue group geoNetworkingTemplates { + + /** + * @desc Send template for long position vector with specific GN_Address + * @param p_gnAddress GN_Address to be contained in the long position vector + */ + template (value) LongPosVector m_longPosVector( + in template (value) GN_Address p_gnAddress, + in UInt32 p_timestamp_, + in Int32 p_latitude := 0, + in Int32 p_longitude := 0, + in Bit1 p_pai := '0'B, + in Int15 p_speed := 0, + in UInt16 p_heading := 0 + + ) := { + gnAddr := p_gnAddress, + timestamp_ := p_timestamp_, + latitude := p_latitude, + longitude := p_longitude, + pai := p_pai, + speed := p_speed, + heading := p_heading + } + template (value) GnNonSecuredPacket m_geoNwBeaconPacket_payload( + in template (value) LongPosVector p_sourceLongPosVec, + in template (value) GnRawPayload p_gnRawPayload + ) modifies m_geoNwBeaconPacket := { + payload := p_gnRawPayload + } + template (value) GnNonSecuredPacket m_geoNwBroadcastPacket_payload( in template (value) LongPosVector p_sourceLongPosVec, in template (value) UInt16 p_seqNumber, @@ -79,6 +109,17 @@ module ItsRSUsSimulator_Templates { payload := p_payload } // End of template m_geoNwBroadcastPacket_payload + template (value) GnNonSecuredPacket m_geoNwAnycastPacket_payload( + in template (value) LongPosVector p_sourceLongPosVec, + in template (value) UInt16 p_seqNumber, + in template (value) GeoAnycastArea p_anycastArea, + in template (value) UInt8 p_hopLimit := c_defaultHopLimit, + in template (value) TrafficClass p_trafficClass := m_trafficClass, + in template (value) GnRawPayload p_payload + ) modifies m_geoNwAnycastPacket := { + payload := p_payload + } // End of template m_geoNwAnycastPacket_payload + /** * @desc Send template for GeoNetworking TSB Packet * @param p_seqNumber Sequence number of TSB packet @@ -152,6 +193,19 @@ module ItsRSUsSimulator_Templates { payload := f_payload_template(PICS_DENM_BTP_DESTINATION_PORT, PICS_DENM_BTP_SOURCE_PORT) } // End of template mw_geoNwTsbPacketWithNextHeader_denm + /** + * @desc Receive template for GeoNetworking DENM Packet + * @param p_destinationShortPosVec Short position vector of destination + * @param p_seqNumber Sequence number of GeoUnicast packet + * @param p_nextHeader Id of next header + */ + template (present) GnNonSecuredPacket mw_geoNwBroadcastPacketWithNextHeader_denm( + in template (present) LongPosVector p_sourceLongPosVec := ?, + in template (present) UInt16 p_seqNumber := ? + ) modifies mw_geoNwBroadcastPacket := { + payload := f_payload_template(PICS_DENM_BTP_DESTINATION_PORT, PICS_DENM_BTP_SOURCE_PORT) + } // End of template mw_geoNwBroadcastPacketWithNextHeader_denm + /** * @desc Receive template for GeoNetworking CAM Packet * @param p_destinationShortPosVec Short position vector of destination diff --git a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestCases.ttcn b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestCases.ttcn index df97180fc..6f91cd1fb 100644 --- a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestCases.ttcn +++ b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestCases.ttcn @@ -80,42 +80,38 @@ module ItsRSUsSimulator_TestCases { geoNetworkingPort.clear; alt { - /*[] geoNetworkingPort.receive( + [PICS_SEND_BEACON_INDICATION == true] geoNetworkingPort.receive( mw_geoNwInd( mw_geoNwPdu( - mw_geoNwTsbPacketWithNextHeader_srem( - ?, - ?, - e_btpB - )))) -> value v_gnInd { // Receive a SREM message - //log("*** " & testcasename() & ": DEBUG: Processing SREM ***"); - f_processSrem(v_gnInd.msgIn); + mw_geoNwShbPacket + ))) -> value v_gnInd { // Receive a BEACON + log("*** " & testcasename() & ": DEBUG: Processing Beacon ***"); + f_processBeacon(v_gnInd.msgIn); repeat; - } - [] geoNetworkingPort.receive( + } + [PICS_SEND_DENM_INDICATION == true] geoNetworkingPort.receive( mw_geoNwInd( mw_geoNwPdu( - mw_geoNwTsbPacketWithNextHeader_denm( + mw_geoNwBroadcastPacketWithNextHeader_denm( //mw_geoNwTsbPacketWithNextHeader_denm( ?, - ?, - e_btpB // TODO Refined to exclude RSU StationID + ? )))) -> value v_gnInd { // Receive a DENM message - //log("*** " & testcasename() & ": DEBUG: Processing DENM ***"); - // Nothing to do, just for logging purposes + log("*** " & testcasename() & ": DEBUG: Processing DENM ***"); + f_processDenm(v_gnInd.msgIn); repeat; - }*/ - /*[] geoNetworkingPort.receive( + } + [PICS_SEND_CAM_INDICATION == true] geoNetworkingPort.receive( mw_geoNwInd( mw_geoNwPdu( mw_geoNwShbPacketWithNextHeader_cam( ?, ?, e_btpB - )))) -> value v_gnInd { // Receive a SREM message + )))) -> value v_gnInd { // Receive a CAM message log("*** " & testcasename() & ": DEBUG: Processing CAM ***"); f_processCam(v_gnInd.msgIn); repeat; - }*/ + } [] geoNetworkingPort.receive(mw_geoNwInd(?)) -> value v_gnInd { // Receive a message log("*** " & testcasename() & ": DEBUG: Recieving unsollicited message ***"); // Nothing to do, just for logging purposes @@ -128,8 +124,7 @@ module ItsRSUsSimulator_TestCases { } } [vc_beacon == true] tc_beacon.timeout { - log("*** " & testcasename() & ": DEBUG: Processing BEACON ***"); - f_prepare_beacon(v_payload); + //log("*** " & testcasename() & ": DEBUG: Processing BEACON ***"); f_send(v_payload, PICS_BEACON_ITS_AID); tc_beacon.start; repeat; diff --git a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestSystem.ttcn b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestSystem.ttcn index ba08fc41c..e7687d63c 100644 --- a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestSystem.ttcn +++ b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TestSystem.ttcn @@ -138,7 +138,7 @@ module ItsRSUsSimulator_TestSystem { var integer vc_at_counter := 0; var SequenceOfAtData vc_at_certificates := {}; } // End of component ItsRSUsSimulator - + /** * @desc Test system component for ITS Network and Transport layer */ @@ -147,44 +147,44 @@ module ItsRSUsSimulator_TestSystem { port HttpPort httpPort; port HttpPort httpPort_notif; } - + type record of record { boolean detected, ItsRSUsSimulator component_, integer stationId, integer detectionCounter - } VehiclesSimulator; - + } VehiclesSimulator; + group configRsuSimulatorTypes { - + type record CfInitialize { integer i } with { variant "FIELDORDER(msb)" } - + type charstring CfEvent; - + type boolean CfResult; - + type union CfEventInd { anytype empty } - + } with { variant "" - } // End of group configRsuSimulatorTypes - + } // End of group configRsuSimulatorTypes + group configRsuSimulatorPort { - + /** * @desc Configuration RSUsimulator port */ type port ConfigRsuSimulatorPort message { - out - CfInitialize, CfResult, UtGnResults, UtCamResults, UtDenmResults, UtCamEventInd, UtPkiResults; - in - CfEvent, CfEventInd, UtGnInitialize, UtCamInitialize, UtDenmInitialize, UtGnTrigger, UtCamTrigger, UtPkiInitialize, UtPkiTrigger + out + CfInitialize, CfResult, UtGnResults, UtCamResults, UtDenmResults, UtGnEventInd, UtCamEventInd, UtDenmEventInd, UtPkiResults; + in + CfEvent, CfEventInd, UtGnInitialize, UtCamInitialize, UtDenmInitialize, UtGnTrigger, UtCamTrigger, UtDenmTrigger, UtDenmUpdate, UtDenmTermination, UtPkiInitialize, UtPkiTrigger } // End of ConfigRsuSimulatorPort } // End of group configRsuSimulatorPort diff --git a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TypesAndValues.ttcn b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TypesAndValues.ttcn index 18e3ec1a4..064463a44 100644 --- a/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TypesAndValues.ttcn +++ b/ttcn/AtsRSUsSimulator/ItsRSUsSimulator_TypesAndValues.ttcn @@ -49,14 +49,14 @@ module ItsRSUsSimulator_TypesAndValues { * @member denms List of DENM events that a RSU shall send */ type record RsuMessagesValue { - octetstring beacon optional, - CAM cam optional, - DENMs denms optional, - MAPEM mapem optional, - SPATEMs spatems optional, - IVIM ivim optional, + GeoNetworkingPdu beacon optional, + CAM cam optional, + DENMs denms optional, + MAPEM mapem optional, + SPATEMs spatems optional, + IVIM ivim optional, // EvcsnPdu evcsn optional, - SSEM ssem optional + SSEM ssem optional } // End of type RsuMessagesValue /** diff --git a/ttcn/LibIts b/ttcn/LibIts index 9ccad87d3..afb30ae08 160000 --- a/ttcn/LibIts +++ b/ttcn/LibIts @@ -1 +1 @@ -Subproject commit 9ccad87d3e34ec870bf80c5991bf73757f998340 +Subproject commit afb30ae0801caaf3c3190e5eacdb31921f5b2631 -- GitLab