diff --git a/context/upf.go b/context/upf.go index 0aed83d8..11fa9ae2 100644 --- a/context/upf.go +++ b/context/upf.go @@ -13,6 +13,7 @@ import ( "net" "reflect" "strconv" + "strings" "sync" "time" @@ -90,9 +91,9 @@ type UPF struct { // UPFSelectionParams ... parameters for upf selection type UPFSelectionParams struct { - Dnn string - SNssai *SNssai - Dnai string + DnnList []string + SNssai *SNssai + Dnai string } // UPFInterfaceInfo store the UPF interface information @@ -163,12 +164,20 @@ func (i *UPFInterfaceInfo) IP(pduSessType uint8) (net.IP, error) { } func (upfSelectionParams *UPFSelectionParams) String() string { + if upfSelectionParams == nil { + return "UPFSelectionParams is nil" + } str := "" - Dnn := upfSelectionParams.Dnn - if Dnn != "" { - str += fmt.Sprintf("Dnn: %s\n", Dnn) + // Handle the DnnList + if len(upfSelectionParams.DnnList) > 0 { + str += "Dnn List: " + for _, dnn := range upfSelectionParams.DnnList { + str += fmt.Sprintf("%s ", dnn) + } + str += "\n" + } else { + str += "Dnn List is empty\n" } - SNssai := upfSelectionParams.SNssai if SNssai != nil { str += fmt.Sprintf("Sst: %d, Sd: %s\n", int(SNssai.Sst), SNssai.Sd) @@ -249,14 +258,26 @@ func (upf *UPF) GetInterface(interfaceType models.UpInterfaceType, dnn string) * switch interfaceType { case models.UpInterfaceType_N3: for i, iface := range upf.N3Interfaces { - if iface.NetworkInstance == dnn { - return &upf.N3Interfaces[i] + logger.CtxLog.Infof("Checking UPF N3 Interface: %v", iface.NetworkInstance) + + // Split multiple DNNs and check if dnn exists + dnnList := strings.Split(iface.NetworkInstance, ",") + for _, d := range dnnList { + if strings.TrimSpace(d) == strings.TrimSpace(dnn) { + return &upf.N3Interfaces[i] + } } } case models.UpInterfaceType_N9: for i, iface := range upf.N9Interfaces { - if iface.NetworkInstance == dnn { - return &upf.N9Interfaces[i] + logger.CtxLog.Infof("Checking UPF N9 Interface: %v", iface.NetworkInstance) + + // Split multiple DNNs and check if dnn exists + dnnList := strings.Split(iface.NetworkInstance, ",") + for _, d := range dnnList { + if strings.TrimSpace(d) == strings.TrimSpace(dnn) { + return &upf.N9Interfaces[i] + } } } } diff --git a/context/user_plane_information.go b/context/user_plane_information.go index 79de5ffc..521f90ba 100644 --- a/context/user_plane_information.go +++ b/context/user_plane_information.go @@ -184,12 +184,16 @@ func (upi *UserPlaneInformation) GenerateDefaultPath(selection *UPFSelectionPara destinations = upi.selectMatchUPF(selection) if len(destinations) == 0 { - logger.CtxLog.Errorf("can not find UPF with DNN[%s] S-NSSAI[sst: %d sd: %s] DNAI[%s]", selection.Dnn, - selection.SNssai.Sst, selection.SNssai.Sd, selection.Dnai) + for _, dnn := range selection.DnnList { + logger.CtxLog.Errorf("Can't find UPF with DNN[%s] S-NSSAI[sst: %d sd: %s] DNAI[%s]\n", dnn, + selection.SNssai.Sst, selection.SNssai.Sd, selection.Dnai) + } return false } else { - logger.CtxLog.Debugf("found UPF with DNN[%s] S-NSSAI[sst: %d sd: %s] DNAI[%s]", selection.Dnn, - selection.SNssai.Sst, selection.SNssai.Sd, selection.Dnai) + for _, dnn := range selection.DnnList { + logger.CtxLog.Infof("Found UPF with DNN[%s] S-NSSAI[sst: %d sd: %s] DNAI[%s]\n", dnn, + selection.SNssai.Sst, selection.SNssai.Sd, selection.Dnai) + } } // Run DFS @@ -223,7 +227,7 @@ func (upi *UserPlaneInformation) GenerateDefaultPath(selection *UPFSelectionPara func (upi *UserPlaneInformation) selectMatchUPF(selection *UPFSelectionParams) []*UPNode { upList := make([]*UPNode, 0) - + logger.CtxLog.Infof("Selecting matching UPFs for DNNs[%v] and S-NSSAI[sst: %d, sd: %s]", selection.DnnList, selection.SNssai.Sst, selection.SNssai.Sd) for _, upNode := range upi.UPFs { for _, snssaiInfo := range upNode.UPF.SNssaiInfos { currentSnssai := &snssaiInfo.SNssai @@ -231,9 +235,12 @@ func (upi *UserPlaneInformation) selectMatchUPF(selection *UPFSelectionParams) [ if currentSnssai.Equal(targetSnssai) { for _, dnnInfo := range snssaiInfo.DnnList { - if dnnInfo.Dnn == selection.Dnn && dnnInfo.ContainsDNAI(selection.Dnai) { - upList = append(upList, upNode) - break + for _, dnn := range selection.DnnList { + if dnnInfo.Dnn == dnn && dnnInfo.ContainsDNAI(selection.Dnai) { + upList = append(upList, upNode) + logger.CtxLog.Infof("Matching UPF found: %v for DNN[%s] and DNAI[%s]", upNode, dnn, selection.Dnai) + break + } } } } diff --git a/context/user_plane_information_test.go b/context/user_plane_information_test.go index 406ba7e7..0477cc5b 100644 --- a/context/user_plane_information_test.go +++ b/context/user_plane_information_test.go @@ -160,7 +160,7 @@ func TestGenerateDefaultPath(t *testing.T) { Sst: 1, Sd: "112232", }, - Dnn: "internet", + DnnList: []string{"internet"}, }, expected: true, }, @@ -171,7 +171,7 @@ func TestGenerateDefaultPath(t *testing.T) { Sst: 2, Sd: "112233", }, - Dnn: "internet", + DnnList: []string{"internet"}, }, expected: true, }, @@ -182,7 +182,7 @@ func TestGenerateDefaultPath(t *testing.T) { Sst: 3, Sd: "112234", }, - Dnn: "internet", + DnnList: []string{"internet"}, }, expected: true, }, @@ -193,7 +193,7 @@ func TestGenerateDefaultPath(t *testing.T) { Sst: 1, Sd: "112235", }, - Dnn: "internet", + DnnList: []string{"internet"}, }, expected: true, }, @@ -204,7 +204,7 @@ func TestGenerateDefaultPath(t *testing.T) { Sst: 1, Sd: "010203", }, - Dnn: "internet", + DnnList: []string{"internet"}, }, expected: false, }, diff --git a/factory/config.go b/factory/config.go index d10e6c00..cbb48a3c 100644 --- a/factory/config.go +++ b/factory/config.go @@ -18,7 +18,7 @@ import ( "strings" "time" - protos "github.com/omec-project/config5g/proto/sdcoreConfig" + protos "github.com/5GC-DEV/config5g-cdac/proto/sdcoreConfig" "github.com/omec-project/openapi/models" "github.com/omec-project/smf/logger" utilLogger "github.com/omec-project/util/logger" @@ -325,14 +325,16 @@ func (c *Configuration) parseRocConfig(rsp *protos.NetworkSliceResponse) error { // make DNN Info structure sNssaiInfoItem.DnnInfos = make([]SnssaiDnnInfoItem, 0) for _, devGrp := range ns.DeviceGroup { - var dnnInfo SnssaiDnnInfoItem - dnnInfo.Dnn = devGrp.IpDomainDetails.DnnName - dnnInfo.DNS.IPv4Addr = devGrp.IpDomainDetails.DnsPrimary - dnnInfo.UESubnet = devGrp.IpDomainDetails.UePool - dnnInfo.MTU = uint16(devGrp.IpDomainDetails.Mtu) - - // update to Slice structure - sNssaiInfoItem.DnnInfos = append(sNssaiInfoItem.DnnInfos, dnnInfo) + for _, ipDomain := range devGrp.IpDomainDetails { // Iterate over IpDomainDetails slice + var dnnInfo SnssaiDnnInfoItem + dnnInfo.Dnn = ipDomain.DnnName + dnnInfo.DNS.IPv4Addr = ipDomain.DnsPrimary + dnnInfo.UESubnet = ipDomain.UePool + dnnInfo.MTU = uint16(ipDomain.Mtu) + + // Update to Slice structure + sNssaiInfoItem.DnnInfos = append(sNssaiInfoItem.DnnInfos, dnnInfo) + } } // Update to SMF config structure @@ -376,18 +378,21 @@ func (c *Configuration) parseRocConfig(rsp *protos.NetworkSliceResponse) error { // Popoulate DNN names per UPF slice Info for _, devGrp := range ns.DeviceGroup { - // DNN Info in UPF per Slice - var dnnUpfInfo models.DnnUpfInfoItem - dnnUpfInfo.Dnn = devGrp.IpDomainDetails.DnnName - snsUpfInfoItem.DnnUpfInfoList = append(snsUpfInfoItem.DnnUpfInfoList, dnnUpfInfo) - - // Populate UPF Interface Info and DNN info in UPF per Interface - intfUpfInfoItem := InterfaceUpfInfoItem{ - InterfaceType: models.UpInterfaceType_N3, - Endpoints: make([]string, 0), NetworkInstance: devGrp.IpDomainDetails.DnnName, + for _, ipDomain := range devGrp.IpDomainDetails { // Iterate over IpDomainDetails slice + // DNN Info in UPF per Slice + var dnnUpfInfo models.DnnUpfInfoItem + dnnUpfInfo.Dnn = ipDomain.DnnName + snsUpfInfoItem.DnnUpfInfoList = append(snsUpfInfoItem.DnnUpfInfoList, dnnUpfInfo) + + // Populate UPF Interface Info and DNN info in UPF per Interface + intfUpfInfoItem := InterfaceUpfInfoItem{ + InterfaceType: models.UpInterfaceType_N3, + Endpoints: make([]string, 0), + NetworkInstance: ipDomain.DnnName, + } + intfUpfInfoItem.Endpoints = append(intfUpfInfoItem.Endpoints, ns.Site.Upf.UpfName) + upf.InterfaceUpfInfoList = append(upf.InterfaceUpfInfoList, intfUpfInfoItem) } - intfUpfInfoItem.Endpoints = append(intfUpfInfoItem.Endpoints, ns.Site.Upf.UpfName) - upf.InterfaceUpfInfoList = append(upf.InterfaceUpfInfoList, intfUpfInfoItem) } upf.SNssaiInfos = append(upf.SNssaiInfos, snsUpfInfoItem) diff --git a/factory/config_test.go b/factory/config_test.go index 4cfda4dd..24a1201b 100644 --- a/factory/config_test.go +++ b/factory/config_test.go @@ -8,7 +8,7 @@ package factory import ( "testing" - protos "github.com/omec-project/config5g/proto/sdcoreConfig" + protos "github.com/5GC-DEV/config5g-cdac/proto/sdcoreConfig" "github.com/omec-project/openapi/models" "github.com/stretchr/testify/assert" ) @@ -50,7 +50,7 @@ func makeDummyConfig(sst, sd string) *protos.NetworkSliceResponse { ns.DeviceGroup = make([]*protos.DeviceGroup, 0) ipDomain := protos.IpDomain{DnnName: "internet", UePool: "60.60.0.0/16", DnsPrimary: "8.8.8.8", Mtu: 1400} - devGrp := protos.DeviceGroup{IpDomainDetails: &ipDomain} + devGrp := protos.DeviceGroup{IpDomainDetails: []*protos.IpDomain{&ipDomain}} ns.DeviceGroup = append(ns.DeviceGroup, &devGrp) rsp.NetworkSlice = append(rsp.NetworkSlice, &ns) diff --git a/go.mod b/go.mod index 69dae719..24bffcf6 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/google/uuid v1.6.0 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/omec-project/aper v1.3.1 - github.com/omec-project/config5g v1.6.2 github.com/omec-project/nas v1.6.0 github.com/omec-project/ngap v1.5.0 github.com/omec-project/openapi v1.5.0 @@ -23,6 +22,8 @@ require ( gopkg.in/yaml.v2 v2.4.0 ) +require github.com/5GC-DEV/config5g-cdac v0.2.1 // indirect + require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect diff --git a/go.sum b/go.sum index ec8e618b..77ec7099 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/5GC-DEV/config5g-cdac v0.2.1 h1:7Cqwmqh5jqeWtwYTrITflrGotglIRBIb1P3EF2f85OA= +github.com/5GC-DEV/config5g-cdac v0.2.1/go.mod h1:0OEL6UoNKKlx2tlNSoKpRtzckwxR2SL+pRBDAOCT4BU= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -175,8 +177,6 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/omec-project/aper v1.3.1 h1:3Vyqn2xQEulzsQ9JganXqxbR1E2IM7oUm4IW1HiPnr0= github.com/omec-project/aper v1.3.1/go.mod h1:W0i+XhbXHeeLQ4BhMmAS8h83yZ5pnD3w0sdIlnuPS70= -github.com/omec-project/config5g v1.6.2 h1:bfLxwVSt6LAWCQtBmjUuks5CO3qambvcy3VjSVAMHdk= -github.com/omec-project/config5g v1.6.2/go.mod h1:LuaRiJTCJXCkQF7nKB5fOcz6oVMF/8oid+EKCYFAy0E= github.com/omec-project/nas v1.6.0 h1:Bar13cFszi8l4AStLGRLbznFx93OYNV9n/Ba4A2RN1Y= github.com/omec-project/nas v1.6.0/go.mod h1:C5mXN3MiZZBF0YRiPkxB2RWc8RvTFb0xWGcUTZ6efng= github.com/omec-project/ngap v1.5.0 h1:Fu0JIDxDxuNnlz9iomehxn2ZSryqwcY0YS8a73cSIsM= diff --git a/producer/pdu_session.go b/producer/pdu_session.go index 86f701fa..3159bce9 100644 --- a/producer/pdu_session.go +++ b/producer/pdu_session.go @@ -226,7 +226,7 @@ func HandlePDUSessionSMContextCreate(eventData interface{}) error { smContext.Tunnel = smf_context.NewUPTunnel() var defaultPath *smf_context.DataPath upfSelectionParams := &smf_context.UPFSelectionParams{ - Dnn: createData.Dnn, + DnnList: []string{createData.Dnn}, SNssai: &smf_context.SNssai{ Sst: createData.SNssai.Sst, Sd: createData.SNssai.Sd, diff --git a/qos/qos_flow.go b/qos/qos_flow.go index 65497073..d7b400fa 100644 --- a/qos/qos_flow.go +++ b/qos/qos_flow.go @@ -5,6 +5,7 @@ package qos import ( + "reflect" "strconv" "strings" @@ -351,7 +352,21 @@ func GetQosDataChanges(qf1, qf2 *models.QosData) bool { } func GetQoSDataFromPolicyDecision(smPolicyDecision *models.SmPolicyDecision, refQosData string) *models.QosData { - return smPolicyDecision.QosDecs[refQosData] + if smPolicyDecision == nil { + logger.PduSessLog.Errorln("smPolicyDecision is nil") + return nil + } + if smPolicyDecision.QosDecs == nil { + logger.PduSessLog.Errorln("QosDecs map is nil") + return nil + } + qos, exists := smPolicyDecision.QosDecs[refQosData] + if !exists { + logger.PduSessLog.Errorf("QoS Data [%s] not found in QosDecs. Available keys: %v", refQosData, reflect.ValueOf(smPolicyDecision.QosDecs).MapKeys()) + return nil + } + + return qos } func (d *QosFlowDescriptionsAuthorized) AddDefaultQosFlowDescription(sessRule *models.SessionRule) { diff --git a/service/init.go b/service/init.go index 9a8e5a22..05c8f545 100644 --- a/service/init.go +++ b/service/init.go @@ -18,9 +18,9 @@ import ( "syscall" "time" + grpcClient "github.com/5GC-DEV/config5g-cdac/proto/client" + protos "github.com/5GC-DEV/config5g-cdac/proto/sdcoreConfig" aperLogger "github.com/omec-project/aper/logger" - grpcClient "github.com/omec-project/config5g/proto/client" - protos "github.com/omec-project/config5g/proto/sdcoreConfig" nasLogger "github.com/omec-project/nas/logger" ngapLogger "github.com/omec-project/ngap/logger" openapiLogger "github.com/omec-project/openapi/logger"