From 738a6621396774b077c09b674a94e77c9415ba5b Mon Sep 17 00:00:00 2001 From: Michele Segata Date: Tue, 5 Nov 2024 16:00:22 +0100 Subject: [PATCH 1/5] multi UE MEC app: enable the possibility of instantiating shared MEC apps by using pre-defined device application ids --- src/apps/mec/DeviceApp/DeviceApp.cc | 22 +++++++- src/apps/mec/DeviceApp/DeviceApp.h | 2 + .../DeviceAppMessages/DeviceAppPacket.msg | 4 ++ .../mec/MECOrchestrator/MecOrchestrator.cc | 19 +++++-- .../mec/MECOrchestrator/MecOrchestrator.h | 1 + src/nodes/mec/MECPlatform/MultiUEMECApp.cc | 27 +++++++++ src/nodes/mec/MECPlatform/MultiUEMECApp.h | 48 ++++++++++++++++ src/nodes/mec/MECPlatform/MultiUEMECApp.ned | 56 +++++++++++++++++++ .../VirtualisationInfrastructureManager.cc | 1 + .../VirtualisationInfrastructureManager.h | 1 + 10 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 src/nodes/mec/MECPlatform/MultiUEMECApp.cc create mode 100644 src/nodes/mec/MECPlatform/MultiUEMECApp.h create mode 100644 src/nodes/mec/MECPlatform/MultiUEMECApp.ned diff --git a/src/apps/mec/DeviceApp/DeviceApp.cc b/src/apps/mec/DeviceApp/DeviceApp.cc index 604b0dec6..85fe33c38 100644 --- a/src/apps/mec/DeviceApp/DeviceApp.cc +++ b/src/apps/mec/DeviceApp/DeviceApp.cc @@ -68,7 +68,14 @@ void DeviceApp::handleUALCMPMessage() nlohmann::json appInfo = jsonResponseBody["appList"]; if(appName.compare(appInfo.at(i)["appName"]) == 0) { - jsonRequestBody["associateDevAppId"] = std::to_string(getId()); + // search fo the app name in the list of shared apps. if found, use the stored dev app id + auto sharedDevAppId = devAppIds.find(std::string(appName)); + int associateDevAppId; + if (sharedDevAppId != devAppIds.end()) + associateDevAppId = sharedDevAppId->second; + else + associateDevAppId = getId(); + jsonRequestBody["associateDevAppId"] = std::to_string(associateDevAppId); jsonRequestBody["appInfo"]["appDId"] = appInfo.at(i)["appDId"];// "WAMECAPP_External"; //startPk->getMecAppDId() // jsonBody["appInfo"]["appPackageSource"] = "ApplicationDescriptors/WarningAlertApp.json"; @@ -82,7 +89,14 @@ void DeviceApp::handleUALCMPMessage() if(found == false) { EV << "DeviceApp::handleUALCMPMessage: application descriptor for appName: " << appName << " not found." << endl; - jsonRequestBody["associateDevAppId"] = std::to_string(getId()); + // search fo the app name in the list of shared apps. if found, use the stored dev app id + auto sharedDevAppId = devAppIds.find(std::string(appName)); + int associateDevAppId; + if (sharedDevAppId != devAppIds.end()) + associateDevAppId = sharedDevAppId->second; + else + associateDevAppId = getId(); + jsonRequestBody["associateDevAppId"] = std::to_string(associateDevAppId); jsonRequestBody["appInfo"]["appPackageSource"] = appPackageSource; //"ApplicationDescriptors/WarningAlertApp.json"; jsonRequestBody["appInfo"]["appName"] = appName;//"MEWarningAlertApp_rest"; @@ -383,6 +397,10 @@ void DeviceApp::sendStartAppContext(inet::Ptr pk) * ask the proxy for the requested app, by appName */ appName = startPk->getMecAppName(); + if (startPk->getShared()) { + // if this is a shared app, store the dev app id to be associated when sending the start request + devAppIds[std::string(appName)] = startPk->getAssociateDevAppId(); + } std::string uri("/example/dev_app/v1/app_list"); std::stringstream params; diff --git a/src/apps/mec/DeviceApp/DeviceApp.h b/src/apps/mec/DeviceApp/DeviceApp.h index 25be0f5c8..a06b80a12 100644 --- a/src/apps/mec/DeviceApp/DeviceApp.h +++ b/src/apps/mec/DeviceApp/DeviceApp.h @@ -73,6 +73,8 @@ class DeviceApp : public omnetpp::cSimpleModule, public inet::TcpSocket::ICallba State appState; std::string appName; + // mapping from app names to app dev id to use (only used for shared apps) + std::map devAppIds; // variable set in ned, if the appDescriptor is not in the MEC orchestrator // std::string appProvider; not used diff --git a/src/apps/mec/DeviceApp/DeviceAppMessages/DeviceAppPacket.msg b/src/apps/mec/DeviceApp/DeviceAppMessages/DeviceAppPacket.msg index ef378e14d..645314560 100644 --- a/src/apps/mec/DeviceApp/DeviceAppMessages/DeviceAppPacket.msg +++ b/src/apps/mec/DeviceApp/DeviceAppMessages/DeviceAppPacket.msg @@ -36,6 +36,10 @@ class DeviceAppStartPacket extends DeviceAppPacket string mecAppName; string mecAppProvider; string appPackageSource; + // determines whether the instantiated app should be unique for every UE or shared among them + bool shared = false; + // if the MEC app is shared, determines which DevAppId should be used + int associateDevAppId = -1; } class DeviceAppStopPacket extends DeviceAppPacket diff --git a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc index d73c5839e..a7f98b57e 100644 --- a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc +++ b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc @@ -15,6 +15,7 @@ #include "nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.h" #include "nodes/mec/MECPlatform/ServiceRegistry/ServiceRegistry.h" +#include "nodes/mec/MECPlatform/MultiUEMECApp.h" #include "nodes/mec/MECOrchestrator/MECOMessages/MECOrchestratorMessages_m.h" @@ -133,11 +134,6 @@ void MecOrchestrator::startMECApp(UALCMPMessage* msg) for(const auto& contextApp : meAppMap) { - /* - * TODO - * set the check to provide multi UE to one mec application scenario. - * For now the scenario is one to one, since the device application ID is used - */ if(contextApp.second.mecUeAppID == ueAppID && contextApp.second.appDId.compare(contAppMsg->getAppDId()) == 0) { // meAppMap[ueAppID].lastAckStartSeqNum = pkt->getSno(); @@ -147,7 +143,17 @@ void MecOrchestrator::startMECApp(UALCMPMessage* msg) EV << "MecOrchestrator::startMECApp - \tWARNING: required MEC App instance ALREADY STARTED on MEC host: " << contextApp.second.mecHost->getName() << endl; EV << "MecOrchestrator::startMECApp - sending ackMEAppPacket with "<< ACK_CREATE_CONTEXT_APP << endl; sendCreateAppContextAck(true, contAppMsg->getRequestId(), contextApp.first); - return; + auto* existingMECApp = dynamic_cast(contextApp.second.reference); + if (existingMECApp) { + // if the app already exist and it is an app supporting multiple UEs, then notify the app about the new UE + struct UE_MEC_CLIENT newUE; + newUE.address = inet::L3Address(contAppMsg->getUeIpAddress()); + // the UE port is not known at this stage + newUE.port = -1; + existingMECApp->addNewUE(newUE); + } + else + return; } } @@ -266,6 +272,7 @@ void MecOrchestrator::startMECApp(UALCMPMessage* msg) newMecApp.mecAppPort = appInfo->endPoint.port; newMecApp.mecAppIsntanceId = appInfo->instanceId; newMecApp.contextId = contextIdCounter; + newMecApp.reference = appInfo->reference; meAppMap[contextIdCounter] = newMecApp; MECOrchestratorMessage *msg = new MECOrchestratorMessage("MECOrchestratorMessage"); diff --git a/src/nodes/mec/MECOrchestrator/MecOrchestrator.h b/src/nodes/mec/MECOrchestrator/MecOrchestrator.h index 6df22db48..29ade71ad 100644 --- a/src/nodes/mec/MECOrchestrator/MecOrchestrator.h +++ b/src/nodes/mec/MECOrchestrator/MecOrchestrator.h @@ -42,6 +42,7 @@ struct mecAppMapEntry cModule* mecHost; // reference to the mecHost where the mec app has been deployed cModule* vim; // for virtualisationInfrastructureManager methods cModule* mecpm; // for mecPlatformManager methods + cModule* reference; // direct reference to mec app instance (omnet module) std::string ueSymbolicAddres; inet::L3Address ueAddress; //for downstream using UDP Socket diff --git a/src/nodes/mec/MECPlatform/MultiUEMECApp.cc b/src/nodes/mec/MECPlatform/MultiUEMECApp.cc new file mode 100644 index 000000000..b7e808b73 --- /dev/null +++ b/src/nodes/mec/MECPlatform/MultiUEMECApp.cc @@ -0,0 +1,27 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#include "MultiUEMECApp.h" + +namespace simu5g { + +Define_Module(MultiUEMECApp); + +void MultiUEMECApp::addNewUE(struct UE_MEC_CLIENT ueData) +{ + throw cRuntimeError("Every MEC app inheriting from MultiUEMECApp must override and implement the addNewUE method"); +} + +} diff --git a/src/nodes/mec/MECPlatform/MultiUEMECApp.h b/src/nodes/mec/MECPlatform/MultiUEMECApp.h new file mode 100644 index 000000000..b65953cd9 --- /dev/null +++ b/src/nodes/mec/MECPlatform/MultiUEMECApp.h @@ -0,0 +1,48 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#pragma once + +#include +#include "inet/networklayer/common/L3Address.h" +#include "apps/mec/MecApps/MecAppBase.h" + +using namespace omnetpp; + +namespace simu5g { + +struct UE_MEC_CLIENT { + inet::L3Address address; + int port; +}; + +class MultiUEMECApp : public MecAppBase +{ +protected: + virtual void handleSelfMessage(omnetpp::cMessage *msg) {}; + virtual void handleServiceMessage(int connId) {}; + virtual void handleMp1Message(int connId) {}; + virtual void handleHttpMessage(int connId) {}; + virtual void handleUeMessage(omnetpp::cMessage *msg) {}; + virtual void established(int connId) {}; +public: + /** + * Method used to notify the MEC app that a new UE would like to associate with that + * Every MEC app inheriting from this class, must implement this method + */ + virtual void addNewUE(struct UE_MEC_CLIENT ueData); +}; + +} diff --git a/src/nodes/mec/MECPlatform/MultiUEMECApp.ned b/src/nodes/mec/MECPlatform/MultiUEMECApp.ned new file mode 100644 index 000000000..cee94c232 --- /dev/null +++ b/src/nodes/mec/MECPlatform/MultiUEMECApp.ned @@ -0,0 +1,56 @@ +// +// Simu5G +// +// Authors: Giovanni Nardini, Giovanni Stea, Antonio Virdis (University of Pisa) +// +// This file is part of a software released under the license included in file +// "license.pdf". Please read LICENSE and README files before using it. +// The above files and the present reference are part of the software itself, +// and cannot be removed from it. +// + +package simu5g.nodes.mec.MECPlatform; + +import inet.applications.contract.IApp; +import simu5g.nodes.mec.MECPlatform.IMECApp; + +// +// This is an empty MEC app which is used as a model for MEC apps that should +// be shared among multiple UEs. Any shared MEC app that should extend this app +simple MultiUEMECApp like IMECApp, IApp +{ + parameters: + @class(simu5g::MultiUEMECApp); + @display("i=block/app;is=s"); + + int packetSize @unit(B) = default(10B); + string interfaceTableModule = default(""); + + int mecAppIndex; + int mecAppId; + int localUePort; + + string mp1Address = default(""); + int mp1Port = default(10021); + + //resource required info + double requiredRam @unit("B"); + double requiredDisk @unit("B"); + double requiredCpu; + + // IApp parameters + int timeToLive = default(-1); // if not -1, set the TTL (IPv4) or Hop Limit (IPv6) field of sent packets to this value + int dscp = default(-1); // if not -1, set the DSCP (IPv4/IPv6) field of sent packets to this value + int tos = default(-1); // if not -1, set the Type Of Service (IPv4) / Traffic Class (IPv6) field of sent packets to this value + + bool logger = default(false); + + gates: + input mePlatformIn; + output mePlatformOut; + + input socketIn; + output socketOut; + +} + diff --git a/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.cc b/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.cc index 35b7d62a9..59fa9936a 100644 --- a/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.cc +++ b/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.cc @@ -370,6 +370,7 @@ MecAppInstanceInfo* VirtualisationInfrastructureManager::instantiateMEApp(Create EV << "VirtualisationInfrastructureManager::instantiateMEApp - currentMEApps: " << currentMEApps << " / " << maxMECApps << endl; instanceInfo->status = true; + instanceInfo->reference = module; return instanceInfo; } else diff --git a/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.h b/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.h index 67a13067f..8f6503d1d 100644 --- a/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.h +++ b/src/nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.h @@ -50,6 +50,7 @@ struct MecAppInstanceInfo bool status; std::string instanceId; SockAddr endPoint; + cModule *reference; }; // used to calculate processing time needed to execute a number of instructions From 127917762feb5e6a31e4c3995c351c05c1193185 Mon Sep 17 00:00:00 2001 From: Michele Segata Date: Fri, 8 Nov 2024 12:01:01 +0100 Subject: [PATCH 2/5] move MultiUEMEApp to a more appropriate folder --- .../mec/MECPlatform => apps/mec/MecApps}/MultiUEMECApp.cc | 0 src/{nodes/mec/MECPlatform => apps/mec/MecApps}/MultiUEMECApp.h | 0 .../mec/MECPlatform => apps/mec/MecApps}/MultiUEMECApp.ned | 2 +- src/nodes/mec/MECOrchestrator/MecOrchestrator.cc | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename src/{nodes/mec/MECPlatform => apps/mec/MecApps}/MultiUEMECApp.cc (100%) rename src/{nodes/mec/MECPlatform => apps/mec/MecApps}/MultiUEMECApp.h (100%) rename src/{nodes/mec/MECPlatform => apps/mec/MecApps}/MultiUEMECApp.ned (97%) diff --git a/src/nodes/mec/MECPlatform/MultiUEMECApp.cc b/src/apps/mec/MecApps/MultiUEMECApp.cc similarity index 100% rename from src/nodes/mec/MECPlatform/MultiUEMECApp.cc rename to src/apps/mec/MecApps/MultiUEMECApp.cc diff --git a/src/nodes/mec/MECPlatform/MultiUEMECApp.h b/src/apps/mec/MecApps/MultiUEMECApp.h similarity index 100% rename from src/nodes/mec/MECPlatform/MultiUEMECApp.h rename to src/apps/mec/MecApps/MultiUEMECApp.h diff --git a/src/nodes/mec/MECPlatform/MultiUEMECApp.ned b/src/apps/mec/MecApps/MultiUEMECApp.ned similarity index 97% rename from src/nodes/mec/MECPlatform/MultiUEMECApp.ned rename to src/apps/mec/MecApps/MultiUEMECApp.ned index cee94c232..a6f7643be 100644 --- a/src/nodes/mec/MECPlatform/MultiUEMECApp.ned +++ b/src/apps/mec/MecApps/MultiUEMECApp.ned @@ -9,7 +9,7 @@ // and cannot be removed from it. // -package simu5g.nodes.mec.MECPlatform; +package simu5g.apps.mec.MecApps; import inet.applications.contract.IApp; import simu5g.nodes.mec.MECPlatform.IMECApp; diff --git a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc index a7f98b57e..bec61c2b1 100644 --- a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc +++ b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc @@ -15,7 +15,7 @@ #include "nodes/mec/VirtualisationInfrastructureManager/VirtualisationInfrastructureManager.h" #include "nodes/mec/MECPlatform/ServiceRegistry/ServiceRegistry.h" -#include "nodes/mec/MECPlatform/MultiUEMECApp.h" +#include "apps/mec/MecApps/MultiUEMECApp.h" #include "nodes/mec/MECOrchestrator/MECOMessages/MECOrchestratorMessages_m.h" From fbfbfd140b36234b11def670e5d663c6f68256a6 Mon Sep 17 00:00:00 2001 From: Michele Segata Date: Thu, 19 Dec 2024 14:37:57 +0100 Subject: [PATCH 3/5] add missing call to addNewUE for the first UE client --- src/nodes/mec/MECOrchestrator/MecOrchestrator.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc index bec61c2b1..ed7f2da51 100644 --- a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc +++ b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc @@ -273,6 +273,14 @@ void MecOrchestrator::startMECApp(UALCMPMessage* msg) newMecApp.mecAppIsntanceId = appInfo->instanceId; newMecApp.contextId = contextIdCounter; newMecApp.reference = appInfo->reference; + auto multiUEMECApp = dynamic_cast(newMecApp.reference); + if (multiUEMECApp) { + struct UE_MEC_CLIENT newUE; + newUE.address = inet::L3Address(contAppMsg->getUeIpAddress()); + // the UE port is not known at this stage + newUE.port = -1; + multiUEMECApp->addNewUE(newUE); + } meAppMap[contextIdCounter] = newMecApp; MECOrchestratorMessage *msg = new MECOrchestratorMessage("MECOrchestratorMessage"); From a8bc398297f9e92cc20a8843c845e281523d0ff7 Mon Sep 17 00:00:00 2001 From: Michele Segata Date: Thu, 19 Dec 2024 11:40:38 +0100 Subject: [PATCH 4/5] add signal for handover within NR PHY --- src/stack/phy/NRPhyUe.ned | 2 ++ src/stack/phy/layer/NRPhyUe.cc | 6 ++++++ src/stack/phy/layer/NRPhyUe.h | 3 +++ 3 files changed, 11 insertions(+) diff --git a/src/stack/phy/NRPhyUe.ned b/src/stack/phy/NRPhyUe.ned index 03889eb7d..d29dfc252 100644 --- a/src/stack/phy/NRPhyUe.ned +++ b/src/stack/phy/NRPhyUe.ned @@ -18,6 +18,8 @@ simple NRPhyUe extends LtePhyUeD2D { parameters: @class("NRPhyUe"); + // indicates when an handover starts (false) and when it ends (true) + @signal[lte_stack_phy_handover](type=bool); } diff --git a/src/stack/phy/layer/NRPhyUe.cc b/src/stack/phy/layer/NRPhyUe.cc index 767314db2..f41714fbd 100644 --- a/src/stack/phy/layer/NRPhyUe.cc +++ b/src/stack/phy/layer/NRPhyUe.cc @@ -19,6 +19,7 @@ namespace simu5g { Define_Module(NRPhyUe); +const simsignal_t NRPhyUe::lte_stack_phy_handover = registerSignal("lte_stack_phy_handover"); NRPhyUe::NRPhyUe() { handoverStarter_ = NULL; @@ -356,6 +357,8 @@ void NRPhyUe::triggerHandover() handoverTrigger_ = new cMessage("handoverTrigger"); scheduleAt(simTime() + handoverLatency, handoverTrigger_); + // signal handover begin + emit(lte_stack_phy_handover, false); } void NRPhyUe::doHandover() @@ -475,6 +478,9 @@ void NRPhyUe::doHandover() IP2Nic* enbIp2nic = check_and_cast(getSimulation()->getModule(binder_->getOmnetId(masterId_))->getSubmodule("cellularNic")->getSubmodule("ip2nic")); enbIp2nic->signalHandoverCompleteTarget(nodeId_,oldMaster); } + + // signal end handover + emit(lte_stack_phy_handover, true); } void NRPhyUe::forceHandover(MacNodeId targetMasterNode, double targetMasterRssi) diff --git a/src/stack/phy/layer/NRPhyUe.h b/src/stack/phy/layer/NRPhyUe.h index 1b7f0cb4f..a2bcc9153 100644 --- a/src/stack/phy/layer/NRPhyUe.h +++ b/src/stack/phy/layer/NRPhyUe.h @@ -36,6 +36,9 @@ class NRPhyUe : public LtePhyUeD2D public: NRPhyUe(); virtual ~NRPhyUe(); + + // indicates when an handover starts (0) and when it ends (1) + static const simsignal_t lte_stack_phy_handover; }; } //namespace From de45ab5a9d7b800ed7b872e59c802ea2f25e487e Mon Sep 17 00:00:00 2001 From: Michele Segata Date: Wed, 21 May 2025 17:02:52 +0200 Subject: [PATCH 5/5] MecOrchestrator: add return statement in case an instance of the requested shared app is found to avoid instantiating a new one TODO: currently, the way shared apps are implemented do not enable the possibility of instantiating different ones using different devAppIds. Core of the issue is DeviceApp.cc:402 --- src/nodes/mec/MECOrchestrator/MecOrchestrator.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc index ed7f2da51..5a3782c47 100644 --- a/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc +++ b/src/nodes/mec/MECOrchestrator/MecOrchestrator.cc @@ -151,6 +151,7 @@ void MecOrchestrator::startMECApp(UALCMPMessage* msg) // the UE port is not known at this stage newUE.port = -1; existingMECApp->addNewUE(newUE); + return; } else return;