Loading go-apps/meep-sandbox-ctrl/server/sandbox-ctrl.go +28 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ const fieldSandboxName = "sandbox-name" const fieldScenarioName = "scenario-name" const fieldEventType = "event-type" const fieldNodeName = "node-name" const fieldPduSessionId = "pdu-id" // Event types const ( Loading Loading @@ -535,6 +536,9 @@ func ceTerminateScenario(w http.ResponseWriter, r *http.Request) { log.Error("Failed to send message. Error: ", err.Error()) } // Delete all PDU sessions sbxCtrl.pduSessionStore.DeleteAllPduSessions() // Use new model instance sbxCtrl.activeModel, err = mod.NewModel(sbxCtrl.modelCfg) if err != nil { Loading Loading @@ -1125,6 +1129,18 @@ func ceCreatePduSession(w http.ResponseWriter, r *http.Request) { return } // Send message to inform other modules of terminated PDU session msg := sbxCtrl.mqLocal.CreateMsg(mq.MsgPduSessionCreated, mq.TargetAll, mq.TargetAll) msg.Payload[fieldNodeName] = ueName msg.Payload[fieldPduSessionId] = pduSessionId log.Debug("TX MSG: ", mq.PrintMsg(msg)) err = sbxCtrl.mqLocal.SendMsg(msg) if err != nil { log.Error("Failed to send message. Error: ", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) } Loading @@ -1146,6 +1162,18 @@ func ceTerminatePduSession(w http.ResponseWriter, r *http.Request) { return } // Send message to inform other modules of terminated PDU session msg := sbxCtrl.mqLocal.CreateMsg(mq.MsgPduSessionTerminated, mq.TargetAll, mq.TargetAll) msg.Payload[fieldNodeName] = ueName msg.Payload[fieldPduSessionId] = pduSessionId log.Debug("TX MSG: ", mq.PrintMsg(msg)) err = sbxCtrl.mqLocal.SendMsg(msg) if err != nil { log.Error("Failed to send message. Error: ", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) } Loading go-apps/meep-tc-engine/go.mod +2 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-net-char-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-pdu-session-store v0.0.0 // indirect github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis v0.0.0 github.com/gogo/protobuf v1.2.1 // indirect github.com/google/btree v1.0.0 // indirect Loading Loading @@ -41,5 +42,6 @@ replace ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model => ../../go-packages/meep-model github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq => ../../go-packages/meep-mq github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-net-char-mgr => ../../go-packages/meep-net-char-mgr github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-pdu-session-store => ../../go-packages/meep-pdu-session-store github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis => ../../go-packages/meep-redis ) go-packages/meep-model/model.go +35 −13 Original line number Diff line number Diff line Loading @@ -69,6 +69,11 @@ const ( EventRemoveNode string = "EVENT-REMOVE-NODE" ) const ( ConnectivityModelOpen string = "OPEN" ConnectivityModelPdu string = "PDU" ) const Disconnected = "DISCONNECTED" // ModelCfg - Model Configuration Loading @@ -94,6 +99,7 @@ type Model struct { svcMap []dataModel.NodeServiceMaps nodeMap *NodeMap networkGraph *NetworkGraph connectivityModel string lock sync.RWMutex } Loading @@ -119,6 +125,7 @@ func NewModel(cfg ModelCfg) (m *Model, err error) { m.subscribed = false m.activeKey = dkm.GetKeyRoot(m.namespace) + activeKey m.scenario = new(dataModel.Scenario) m.connectivityModel = ConnectivityModelOpen // Process scenario err = m.parseNodes() Loading Loading @@ -944,6 +951,14 @@ func (m *Model) GetNetworkGraph() *dijkstra.Graph { return m.networkGraph.graph } // GetConnectivityModel - Get the connectivity model func (m *Model) GetConnectivityModel() string { m.lock.RLock() defer m.lock.RUnlock() return m.connectivityModel } //---Internal Funcs--- func (m *Model) parseNodes() (err error) { Loading @@ -958,6 +973,9 @@ func (m *Model) parseNodes() (err error) { ctx := NewNodeContext(m.scenario.Name, "", "", "", "") m.nodeMap.AddNode(NewNode(m.scenario.Name, "DEPLOYMENT", deployment, &deployment.Domains, m.scenario, ctx)) m.svcMap = make([]dataModel.NodeServiceMaps, 0) if deployment.Connectivity != nil { m.connectivityModel = deployment.Connectivity.Model } // Domains for iDomain := range m.scenario.Deployment.Domains { Loading Loading @@ -1199,6 +1217,10 @@ func IsProc(typ string) bool { return typ == NodeTypeCloudApp || typ == NodeTypeEdgeApp || typ == NodeTypeUEApp } func IsUe(typ string) bool { return typ == NodeTypeUE } func validateParentType(nodeType string, parentType string) bool { if IsScenario(nodeType) { return parentType == "" Loading go-packages/meep-mq/mq.go +4 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,10 @@ const ( MsgScenarioUpdate Message = "SCENARIO-UPDATE" MsgScenarioTerminate Message = "SCENARIO-TERMINATE" // PDU Session Management MsgPduSessionCreated Message = "PDU-SESSION-CREATED" MsgPduSessionTerminated Message = "PDU-SESSION-TERMINATED" // Mobility Groups MsgMgLbRulesUpdate Message = "MG-LB-RULES-UPDATE" Loading go-packages/meep-net-char-mgr/algo-segment.go +73 −14 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ type SegmentAlgorithm struct { BaseKey string FlowMap map[string]*SegAlgoFlow SegmentMap map[string]*SegAlgoSegment ConnectivityModel string Config SegAlgoConfig rc *redis.Connector } Loading @@ -132,6 +133,7 @@ func NewSegmentAlgorithm(name string, namespace string, redisAddr string) (*Segm algo.BaseKey = dkm.GetKeyRoot(namespace) + metricsKey algo.FlowMap = make(map[string]*SegAlgoFlow) algo.SegmentMap = make(map[string]*SegAlgoSegment) algo.ConnectivityModel = mod.ConnectivityModelOpen algo.Config.MaxBwPerInactiveFlow = 20.0 algo.Config.MaxBwPerInactiveFlowFloor = 6.0 algo.Config.MinActivityThreshold = 0.3 Loading @@ -154,7 +156,7 @@ func NewSegmentAlgorithm(name string, namespace string, redisAddr string) (*Segm } // ProcessScenario - func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model) error { func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model, pduSessions map[string]map[string]*dataModel.PduSessionInfo) error { var netElemList []SegAlgoNetElem // Process empty scenario Loading @@ -165,6 +167,9 @@ func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model) error { algo.FlowMap = make(map[string]*SegAlgoFlow) } // Get scenario connectivity model algo.ConnectivityModel = model.GetConnectivityModel() // Clear segment & flow maps algo.SegmentMap = make(map[string]*SegAlgoSegment) // Process active scenario Loading Loading @@ -235,7 +240,7 @@ func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model) error { for _, elemDest := range netElemList { if elemSrc.Name != elemDest.Name { // Create flow algo.populateFlow(elemSrc.Name+":"+elemDest.Name, &elemSrc, &elemDest, 0, model) algo.populateFlow(elemSrc.Name+":"+elemDest.Name, &elemSrc, &elemDest, 0, model, pduSessions) // Create DB entry to begin collecting metrics for this flow algo.createMetricsEntry(elemSrc.Name, elemDest.Name) Loading Loading @@ -399,7 +404,8 @@ func (algo *SegmentAlgorithm) deleteMetricsEntries() { } // populateFlow - Create/Update flow func (algo *SegmentAlgorithm) populateFlow(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, maxBw float64, model *mod.Model) { func (algo *SegmentAlgorithm) populateFlow(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, maxBw float64, model *mod.Model, pduSessions map[string]map[string]*dataModel.PduSessionInfo) { // Use existing flow if present or Create new flow flow := algo.FlowMap[flowName] Loading Loading @@ -430,7 +436,7 @@ func (algo *SegmentAlgorithm) populateFlow(flowName string, srcElement *SegAlgoN flow.ConfiguredNetChar.PacketLoss = 0 // Create a new path for this flow oldPath := flow.Path flow.Path = algo.createPath(flowName, srcElement, destElement, model) flow.Path = algo.createPath(flowName, srcElement, destElement, model, pduSessions) flow.UpdateRequired = algo.comparePath(oldPath, flow.Path) } Loading @@ -453,7 +459,8 @@ func (algo *SegmentAlgorithm) comparePath(oldPath *SegAlgoPath, newPath *SegAlgo } // createPath - func (algo *SegmentAlgorithm) createPath(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, model *mod.Model) *SegAlgoPath { func (algo *SegmentAlgorithm) createPath(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, model *mod.Model, pduSessions map[string]map[string]*dataModel.PduSessionInfo) *SegAlgoPath { direction := "" var segment *SegAlgoSegment Loading Loading @@ -485,19 +492,71 @@ func (algo *SegmentAlgorithm) createPath(flowName string, srcElement *SegAlgoNet // Check if src or dest Physical location is disconnected // NOTE: Does not apply to apps on same physical node var srcPhyLoc *dataModel.PhysicalLocation srcPhyLocNode := model.GetNode(srcElement.PhyLocName) if srcPhyLocNode != nil { if srcPhyLoc, ok := srcPhyLocNode.(*dataModel.PhysicalLocation); ok { var ok bool if srcPhyLoc, ok = srcPhyLocNode.(*dataModel.PhysicalLocation); ok { path.Disconnected = path.Disconnected || !srcPhyLoc.Connected } } var destPhyLoc *dataModel.PhysicalLocation destPhyLocNode := model.GetNode(destElement.PhyLocName) if destPhyLocNode != nil { if destPhyLoc, ok := destPhyLocNode.(*dataModel.PhysicalLocation); ok { var ok bool if destPhyLoc, ok = destPhyLocNode.(*dataModel.PhysicalLocation); ok { path.Disconnected = path.Disconnected || !destPhyLoc.Connected } } // If in PDU Connectivity mode, check if src or dest UE has PDU connectivity to DN // NOTE: For LADN, additionally verify that UE and edge app are in the same zone if !path.Disconnected && algo.ConnectivityModel == mod.ConnectivityModelPdu { if mod.IsUe(srcPhyLoc.Type_) { pduMap, ok := pduSessions[srcPhyLoc.Name] if !ok || mod.IsUe(destPhyLoc.Type_) || destPhyLoc.DataNetwork == nil { path.Disconnected = true } else if destPhyLoc.DataNetwork.Ladn && srcElement.ZoneName != destElement.ZoneName { // LADN & not in same zone path.Disconnected = true } else { // Find matching DNN var found bool for _, pdu := range pduMap { if pdu.Dnn == destPhyLoc.DataNetwork.Dnn { found = true break } } if !found { path.Disconnected = true } } } if mod.IsUe(destPhyLoc.Type_) { pduMap, ok := pduSessions[destPhyLoc.Name] if !ok || mod.IsUe(srcPhyLoc.Type_) || srcPhyLoc.DataNetwork == nil { path.Disconnected = true } else if srcPhyLoc.DataNetwork.Ladn && srcElement.ZoneName != destElement.ZoneName { // LADN & not in same zone path.Disconnected = true } else { // Find matching DNN var found bool for _, pdu := range pduMap { if pdu.Dnn == srcPhyLoc.DataNetwork.Dnn { found = true break } } if !found { path.Disconnected = true } } } } //network location ul, dl if srcElement.Type == "UE" { direction = "uplink" Loading Loading
go-apps/meep-sandbox-ctrl/server/sandbox-ctrl.go +28 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ const fieldSandboxName = "sandbox-name" const fieldScenarioName = "scenario-name" const fieldEventType = "event-type" const fieldNodeName = "node-name" const fieldPduSessionId = "pdu-id" // Event types const ( Loading Loading @@ -535,6 +536,9 @@ func ceTerminateScenario(w http.ResponseWriter, r *http.Request) { log.Error("Failed to send message. Error: ", err.Error()) } // Delete all PDU sessions sbxCtrl.pduSessionStore.DeleteAllPduSessions() // Use new model instance sbxCtrl.activeModel, err = mod.NewModel(sbxCtrl.modelCfg) if err != nil { Loading Loading @@ -1125,6 +1129,18 @@ func ceCreatePduSession(w http.ResponseWriter, r *http.Request) { return } // Send message to inform other modules of terminated PDU session msg := sbxCtrl.mqLocal.CreateMsg(mq.MsgPduSessionCreated, mq.TargetAll, mq.TargetAll) msg.Payload[fieldNodeName] = ueName msg.Payload[fieldPduSessionId] = pduSessionId log.Debug("TX MSG: ", mq.PrintMsg(msg)) err = sbxCtrl.mqLocal.SendMsg(msg) if err != nil { log.Error("Failed to send message. Error: ", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) } Loading @@ -1146,6 +1162,18 @@ func ceTerminatePduSession(w http.ResponseWriter, r *http.Request) { return } // Send message to inform other modules of terminated PDU session msg := sbxCtrl.mqLocal.CreateMsg(mq.MsgPduSessionTerminated, mq.TargetAll, mq.TargetAll) msg.Payload[fieldNodeName] = ueName msg.Payload[fieldPduSessionId] = pduSessionId log.Debug("TX MSG: ", mq.PrintMsg(msg)) err = sbxCtrl.mqLocal.SendMsg(msg) if err != nil { log.Error("Failed to send message. Error: ", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) } Loading
go-apps/meep-tc-engine/go.mod +2 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-net-char-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-pdu-session-store v0.0.0 // indirect github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis v0.0.0 github.com/gogo/protobuf v1.2.1 // indirect github.com/google/btree v1.0.0 // indirect Loading Loading @@ -41,5 +42,6 @@ replace ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model => ../../go-packages/meep-model github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq => ../../go-packages/meep-mq github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-net-char-mgr => ../../go-packages/meep-net-char-mgr github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-pdu-session-store => ../../go-packages/meep-pdu-session-store github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis => ../../go-packages/meep-redis )
go-packages/meep-model/model.go +35 −13 Original line number Diff line number Diff line Loading @@ -69,6 +69,11 @@ const ( EventRemoveNode string = "EVENT-REMOVE-NODE" ) const ( ConnectivityModelOpen string = "OPEN" ConnectivityModelPdu string = "PDU" ) const Disconnected = "DISCONNECTED" // ModelCfg - Model Configuration Loading @@ -94,6 +99,7 @@ type Model struct { svcMap []dataModel.NodeServiceMaps nodeMap *NodeMap networkGraph *NetworkGraph connectivityModel string lock sync.RWMutex } Loading @@ -119,6 +125,7 @@ func NewModel(cfg ModelCfg) (m *Model, err error) { m.subscribed = false m.activeKey = dkm.GetKeyRoot(m.namespace) + activeKey m.scenario = new(dataModel.Scenario) m.connectivityModel = ConnectivityModelOpen // Process scenario err = m.parseNodes() Loading Loading @@ -944,6 +951,14 @@ func (m *Model) GetNetworkGraph() *dijkstra.Graph { return m.networkGraph.graph } // GetConnectivityModel - Get the connectivity model func (m *Model) GetConnectivityModel() string { m.lock.RLock() defer m.lock.RUnlock() return m.connectivityModel } //---Internal Funcs--- func (m *Model) parseNodes() (err error) { Loading @@ -958,6 +973,9 @@ func (m *Model) parseNodes() (err error) { ctx := NewNodeContext(m.scenario.Name, "", "", "", "") m.nodeMap.AddNode(NewNode(m.scenario.Name, "DEPLOYMENT", deployment, &deployment.Domains, m.scenario, ctx)) m.svcMap = make([]dataModel.NodeServiceMaps, 0) if deployment.Connectivity != nil { m.connectivityModel = deployment.Connectivity.Model } // Domains for iDomain := range m.scenario.Deployment.Domains { Loading Loading @@ -1199,6 +1217,10 @@ func IsProc(typ string) bool { return typ == NodeTypeCloudApp || typ == NodeTypeEdgeApp || typ == NodeTypeUEApp } func IsUe(typ string) bool { return typ == NodeTypeUE } func validateParentType(nodeType string, parentType string) bool { if IsScenario(nodeType) { return parentType == "" Loading
go-packages/meep-mq/mq.go +4 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,10 @@ const ( MsgScenarioUpdate Message = "SCENARIO-UPDATE" MsgScenarioTerminate Message = "SCENARIO-TERMINATE" // PDU Session Management MsgPduSessionCreated Message = "PDU-SESSION-CREATED" MsgPduSessionTerminated Message = "PDU-SESSION-TERMINATED" // Mobility Groups MsgMgLbRulesUpdate Message = "MG-LB-RULES-UPDATE" Loading
go-packages/meep-net-char-mgr/algo-segment.go +73 −14 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ type SegmentAlgorithm struct { BaseKey string FlowMap map[string]*SegAlgoFlow SegmentMap map[string]*SegAlgoSegment ConnectivityModel string Config SegAlgoConfig rc *redis.Connector } Loading @@ -132,6 +133,7 @@ func NewSegmentAlgorithm(name string, namespace string, redisAddr string) (*Segm algo.BaseKey = dkm.GetKeyRoot(namespace) + metricsKey algo.FlowMap = make(map[string]*SegAlgoFlow) algo.SegmentMap = make(map[string]*SegAlgoSegment) algo.ConnectivityModel = mod.ConnectivityModelOpen algo.Config.MaxBwPerInactiveFlow = 20.0 algo.Config.MaxBwPerInactiveFlowFloor = 6.0 algo.Config.MinActivityThreshold = 0.3 Loading @@ -154,7 +156,7 @@ func NewSegmentAlgorithm(name string, namespace string, redisAddr string) (*Segm } // ProcessScenario - func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model) error { func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model, pduSessions map[string]map[string]*dataModel.PduSessionInfo) error { var netElemList []SegAlgoNetElem // Process empty scenario Loading @@ -165,6 +167,9 @@ func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model) error { algo.FlowMap = make(map[string]*SegAlgoFlow) } // Get scenario connectivity model algo.ConnectivityModel = model.GetConnectivityModel() // Clear segment & flow maps algo.SegmentMap = make(map[string]*SegAlgoSegment) // Process active scenario Loading Loading @@ -235,7 +240,7 @@ func (algo *SegmentAlgorithm) ProcessScenario(model *mod.Model) error { for _, elemDest := range netElemList { if elemSrc.Name != elemDest.Name { // Create flow algo.populateFlow(elemSrc.Name+":"+elemDest.Name, &elemSrc, &elemDest, 0, model) algo.populateFlow(elemSrc.Name+":"+elemDest.Name, &elemSrc, &elemDest, 0, model, pduSessions) // Create DB entry to begin collecting metrics for this flow algo.createMetricsEntry(elemSrc.Name, elemDest.Name) Loading Loading @@ -399,7 +404,8 @@ func (algo *SegmentAlgorithm) deleteMetricsEntries() { } // populateFlow - Create/Update flow func (algo *SegmentAlgorithm) populateFlow(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, maxBw float64, model *mod.Model) { func (algo *SegmentAlgorithm) populateFlow(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, maxBw float64, model *mod.Model, pduSessions map[string]map[string]*dataModel.PduSessionInfo) { // Use existing flow if present or Create new flow flow := algo.FlowMap[flowName] Loading Loading @@ -430,7 +436,7 @@ func (algo *SegmentAlgorithm) populateFlow(flowName string, srcElement *SegAlgoN flow.ConfiguredNetChar.PacketLoss = 0 // Create a new path for this flow oldPath := flow.Path flow.Path = algo.createPath(flowName, srcElement, destElement, model) flow.Path = algo.createPath(flowName, srcElement, destElement, model, pduSessions) flow.UpdateRequired = algo.comparePath(oldPath, flow.Path) } Loading @@ -453,7 +459,8 @@ func (algo *SegmentAlgorithm) comparePath(oldPath *SegAlgoPath, newPath *SegAlgo } // createPath - func (algo *SegmentAlgorithm) createPath(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, model *mod.Model) *SegAlgoPath { func (algo *SegmentAlgorithm) createPath(flowName string, srcElement *SegAlgoNetElem, destElement *SegAlgoNetElem, model *mod.Model, pduSessions map[string]map[string]*dataModel.PduSessionInfo) *SegAlgoPath { direction := "" var segment *SegAlgoSegment Loading Loading @@ -485,19 +492,71 @@ func (algo *SegmentAlgorithm) createPath(flowName string, srcElement *SegAlgoNet // Check if src or dest Physical location is disconnected // NOTE: Does not apply to apps on same physical node var srcPhyLoc *dataModel.PhysicalLocation srcPhyLocNode := model.GetNode(srcElement.PhyLocName) if srcPhyLocNode != nil { if srcPhyLoc, ok := srcPhyLocNode.(*dataModel.PhysicalLocation); ok { var ok bool if srcPhyLoc, ok = srcPhyLocNode.(*dataModel.PhysicalLocation); ok { path.Disconnected = path.Disconnected || !srcPhyLoc.Connected } } var destPhyLoc *dataModel.PhysicalLocation destPhyLocNode := model.GetNode(destElement.PhyLocName) if destPhyLocNode != nil { if destPhyLoc, ok := destPhyLocNode.(*dataModel.PhysicalLocation); ok { var ok bool if destPhyLoc, ok = destPhyLocNode.(*dataModel.PhysicalLocation); ok { path.Disconnected = path.Disconnected || !destPhyLoc.Connected } } // If in PDU Connectivity mode, check if src or dest UE has PDU connectivity to DN // NOTE: For LADN, additionally verify that UE and edge app are in the same zone if !path.Disconnected && algo.ConnectivityModel == mod.ConnectivityModelPdu { if mod.IsUe(srcPhyLoc.Type_) { pduMap, ok := pduSessions[srcPhyLoc.Name] if !ok || mod.IsUe(destPhyLoc.Type_) || destPhyLoc.DataNetwork == nil { path.Disconnected = true } else if destPhyLoc.DataNetwork.Ladn && srcElement.ZoneName != destElement.ZoneName { // LADN & not in same zone path.Disconnected = true } else { // Find matching DNN var found bool for _, pdu := range pduMap { if pdu.Dnn == destPhyLoc.DataNetwork.Dnn { found = true break } } if !found { path.Disconnected = true } } } if mod.IsUe(destPhyLoc.Type_) { pduMap, ok := pduSessions[destPhyLoc.Name] if !ok || mod.IsUe(srcPhyLoc.Type_) || srcPhyLoc.DataNetwork == nil { path.Disconnected = true } else if srcPhyLoc.DataNetwork.Ladn && srcElement.ZoneName != destElement.ZoneName { // LADN & not in same zone path.Disconnected = true } else { // Find matching DNN var found bool for _, pdu := range pduMap { if pdu.Dnn == srcPhyLoc.DataNetwork.Dnn { found = true break } } if !found { path.Disconnected = true } } } } //network location ul, dl if srcElement.Type == "UE" { direction = "uplink" Loading