-
Notifications
You must be signed in to change notification settings - Fork 117
Support for Multiple DNNs per Device Group with a Single UPF #929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -155,7 +155,12 @@ | |
| "cpiface": { | ||
| "peers": ["148.162.12.214"], | ||
| // [Optional] Below parameters | ||
| "dnn": "internet", | ||
| "dnn_list": [ | ||
| { | ||
| "dnn": "internet", | ||
| "ue_ip_pool": "10.250.0.0/16" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that now you have the // "hostname": "upf-0",
"ue_ip_pool": "10.250.0.0/16"
},There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, can we please update this to use a private IP range/pool? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gab-arrobo Isn't it like 10.0.0.0/8 is complete Class A private IP address range. So 10.250.0.0/16 is part of private IP address range. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
My bad. I misread this... for some reason I thought it was |
||
| } | ||
| ], | ||
| "http_port": "8080", | ||
| "enable_ue_ip_alloc": false, | ||
| // "use_fqdn": "true", | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -86,13 +86,18 @@ type SimModeInfo struct { | |||
|
|
||||
| // CPIfaceInfo : CPIface interface settings. | ||||
| type CPIfaceInfo struct { | ||||
| Peers []string `json:"peers"` | ||||
| UseFQDN bool `json:"use_fqdn"` | ||||
| NodeID string `json:"hostname"` | ||||
| HTTPPort string `json:"http_port"` | ||||
| Dnn string `json:"dnn"` | ||||
| EnableUeIPAlloc bool `json:"enable_ue_ip_alloc"` | ||||
| UEIPPool string `json:"ue_ip_pool"` | ||||
| Peers []string `json:"peers"` | ||||
| UseFQDN bool `json:"use_fqdn"` | ||||
| NodeID string `json:"hostname"` | ||||
| HTTPPort string `json:"http_port"` | ||||
| DnnList []DNNInfo `json:"dnn_list"` | ||||
| EnableUeIPAlloc bool `json:"enable_ue_ip_alloc"` | ||||
| UEIPPool string `json:"ue_ip_pool"` | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that you are moving the
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we should remove UEIPPool config from here and also look at the functionality of enable_ue_ip_alloc flag. |
||||
| } | ||||
|
|
||||
| type DNNInfo struct { | ||||
| DNN string `json:"dnn"` | ||||
| UEIPPool string `json:"ue_ip_pool"` | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add enable_ue_ip_alloc flag in this structure and see the flow around this flag. |
||||
| } | ||||
|
|
||||
| // IfaceType : Gateway interface struct. | ||||
|
|
@@ -118,12 +123,12 @@ func validateConf(conf Conf) error { | |||
| if err != nil { | ||||
| return ErrInvalidArgumentWithReason("conf.P4rtcIface.AccessIP", conf.P4rtcIface.AccessIP, err.Error()) | ||||
| } | ||||
|
|
||||
| _, _, err = net.ParseCIDR(conf.CPIface.UEIPPool) | ||||
| if err != nil { | ||||
| return ErrInvalidArgumentWithReason("conf.UEIPPool", conf.CPIface.UEIPPool, err.Error()) | ||||
| for _, dnn := range conf.CPIface.DnnList { | ||||
| _, _, err := net.ParseCIDR(dnn.UEIPPool) | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we check that dnn is not an empty string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm. It seems good idea to check the pool validity. But see we have error handling as well. so that will indirectly handle the configuration error? |
||||
| if err != nil { | ||||
| return ErrInvalidArgumentWithReason("conf.CPIface.DnnList.UEIPPool", dnn.UEIPPool, err.Error()) | ||||
| } | ||||
| } | ||||
|
|
||||
| if conf.Mode != "" { | ||||
| return ErrInvalidArgumentWithReason("conf.Mode", conf.Mode, "mode must not be set for UP4") | ||||
| } | ||||
|
|
@@ -140,14 +145,14 @@ func validateConf(conf Conf) error { | |||
| return ErrInvalidArgumentWithReason("conf.Mode", conf.Mode, "invalid mode") | ||||
| } | ||||
| } | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in this function there are 2 checks over the |
||||
|
|
||||
| if conf.CPIface.EnableUeIPAlloc { | ||||
| _, _, err := net.ParseCIDR(conf.CPIface.UEIPPool) | ||||
| if err != nil { | ||||
| return ErrInvalidArgumentWithReason("conf.UEIPPool", conf.CPIface.UEIPPool, err.Error()) | ||||
| for _, dnn := range conf.CPIface.DnnList { | ||||
| _, _, err := net.ParseCIDR(dnn.UEIPPool) | ||||
| if err != nil { | ||||
| return ErrInvalidArgumentWithReason("conf.CPIface.DnnList.UEIPPool", dnn.UEIPPool, err.Error()) | ||||
| } | ||||
| } | ||||
| } | ||||
|
|
||||
| for _, peer := range conf.CPIface.Peers { | ||||
| ip := net.ParseIP(peer) | ||||
| if ip == nil { | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,9 @@ func NewFTEIDGenerator() *FTEIDGenerator { | |
|
|
||
| // Allocate and return an id in range [minValue, maxValue] | ||
| func (idGenerator *FTEIDGenerator) Allocate() (uint32, error) { | ||
| if idGenerator == nil { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is redundant. Everytime we create upf object we assign/create FTEID Generator block. Perhaps you saw crash and that is the reason you want to add this nil check. But remember there is likely chance that we are masking some other bug by adding this nil check. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anaswarac-dac - please confirm why this change is needed. As I said this is likely not required. Issue could be something else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right β ideally the FTEIDGenerator should never be nil, as it's initialized during UPF object creation. However, I added this nil check because during testing I encountered a crash due to a nil dereference in this function. |
||
| return 0, errors.New("FTEIDGenerator is not initialized") | ||
| } | ||
| idGenerator.lock.Lock() | ||
| defer idGenerator.lock.Unlock() | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ package pfcpiface | |
|
|
||
| import ( | ||
| "errors" | ||
| "strings" | ||
|
|
||
| "github.com/omec-project/upf-epc/logger" | ||
| "github.com/wmnsk/go-pfcp/ie" | ||
|
|
@@ -92,7 +93,7 @@ func (pConn *PFCPConn) handleIncomingResponse(msg message.Message) { | |
|
|
||
| func (pConn *PFCPConn) associationIEs() []*ie.IE { | ||
| upf := pConn.upf | ||
| networkInstance := string(ie.NewNetworkInstanceFQDN(upf.dnn).Payload) | ||
| networkInstance := string(ie.NewNetworkInstanceFQDN(strings.Join(upf.dnn, ",")).Payload) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please help me understand why this change is needed. It seems you are trying to add more DNNs in single message? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thakurajayL ,Currently, the PFCP Association Setup Request is initiated by the SMF. The UPF responds with only one DNN. After that, no further PFCP Association Setup Request is triggered by the SMF, which means there's no opportunity to send additional DNNs separately. Because of this limitation, we include all required DNNs in a single PFCP Association Setup Request to ensure that the SMF receives the full list in one go. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to know which version of 29.244 you are referring to. As specification around this area has changed drastically in release 15/16/17. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thakurajayL ,We are following 3GPP TS 29.244 v16.5.0 (Release 16), and as per this version, User Plane IP Resource Information (IE Type 116) was removed. Instead, we are required to use UE IP Address Pool Information (IE Type 123) in the PFCP Association Setup Response. As Per Section 7.2.2.2 of the spec, this IE allows the UPF to report multiple DNN and IP pool mappings to the SMF in a single response by including multiple UE IP Address Pool Information IEs, each containing: DNN (Network Instance), UE IP Pool Identity, and IP version. This change is necessary because: The PFCP Association Setup Request is sent only once by the SMF to the UPF. The UPF must respond once with all supported DNNs and corresponding UE IP pools. If we send only one DNN in the PFCP Association Setup Response, the SMF wonβt be aware of other available DNNs/pools, and there's no further opportunity to send them due to the single-shot nature of the PFCP association procedure. Spec Reference: TS 29.244 v16.5.0, Section 6.2.6.2.2: DNN | Pool | IP Versionims | ims-pool | IPv4 Will Update the code based on this? |
||
| flags := uint8(0x41) | ||
|
|
||
| if len(upf.dnn) != 0 { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -94,6 +94,10 @@ func (pConn *PFCPConn) handleSessionEstablishmentRequest(msg message.Message) (m | |||||
|
|
||||||
| if p.UPAllocateFteid { | ||||||
| var fteid uint32 | ||||||
| if pConn.upf.fteidGenerator == nil { | ||||||
| logger.PfcpLog.Warnf("fteid is nill") | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| pConn.upf.fteidGenerator = NewFTEIDGenerator() | ||||||
| } | ||||||
| fteid, err = pConn.upf.fteidGenerator.Allocate() | ||||||
| if err != nil { | ||||||
| return errProcessReply(err, ie.CauseNoResourcesAvailable) | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -404,7 +404,11 @@ func (up4 *UP4) SetUpfInfo(u *upf, conf *Conf) { | |
|
|
||
| logger.PfcpLog.Infof("AccessIP: %v", up4.accessIP) | ||
|
|
||
| up4.ueIPPool = MustParseStrIP(conf.CPIface.UEIPPool) | ||
| if len(conf.CPIface.DnnList) > 0 { | ||
| up4.ueIPPool = MustParseStrIP(conf.CPIface.DnnList[0].UEIPPool) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that a device group can support multiple DNNs (which includes dnn itself and UE IP pool) but only the IP pool for the first dnn is actually used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it seems like up4 should support multiple IP pools now ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @patriciareinoso as far as I see we do not have any active user for UP4. @gab-arrobo are you aware about any users? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, we need to decide what to do with that code (whether maintain it or remove it) because, as far as I know, we are not supporting UP4 anymore. So, I would say that we should remove it. Probably this is something we should bring to the TST meeting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gab-arrobo When we added multiple DNNs, the integration test for UP4 failed. |
||
| } else { | ||
| logger.PfcpLog.Fatalln("No UE IP pool configured in DnnList") | ||
| } | ||
|
|
||
| logger.PfcpLog.Infof("UE IP pool: %v", up4.ueIPPool) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -48,7 +48,7 @@ type upf struct { | |||||
| nodeID string | ||||||
| ippool *IPPool | ||||||
| peers []string | ||||||
| dnn string | ||||||
| dnn []string | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
i think that making it plural would represent the multiple dnns better |
||||||
| reportNotifyChan chan uint64 | ||||||
| sliceInfo *SliceInfo | ||||||
| readTimeout time.Duration | ||||||
|
|
@@ -116,17 +116,28 @@ func NewUPF(conf *Conf, fp datapath) *upf { | |||||
| nodeID = hosts[0] | ||||||
| } | ||||||
|
|
||||||
| var dnns []string | ||||||
| var ippoolCidr string | ||||||
|
|
||||||
| // Extract DNN names and UEIPPool from the new DnnList structure | ||||||
| for _, dnnInfo := range conf.CPIface.DnnList { | ||||||
| dnns = append(dnns, dnnInfo.DNN) | ||||||
| if ippoolCidr == "" { | ||||||
| ippoolCidr = dnnInfo.UEIPPool | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In relation to my previous comment, here it actually looks like the UE IP pool for the last DNN is used, correct? or am I overlooking something? |
||||||
| } | ||||||
| } | ||||||
|
|
||||||
| u := &upf{ | ||||||
| enableUeIPAlloc: conf.CPIface.EnableUeIPAlloc, | ||||||
| enableEndMarker: conf.EnableEndMarker, | ||||||
| enableFlowMeasure: conf.EnableFlowMeasure, | ||||||
| enableGtpuMonitor: conf.EnableGtpuPathMonitoring, | ||||||
| accessIface: conf.AccessIface.IfName, | ||||||
| coreIface: conf.CoreIface.IfName, | ||||||
| ippoolCidr: conf.CPIface.UEIPPool, | ||||||
| ippoolCidr: ippoolCidr, | ||||||
| nodeID: nodeID, | ||||||
| datapath: fp, | ||||||
| dnn: conf.CPIface.Dnn, | ||||||
| dnn: dnns, | ||||||
| peers: conf.CPIface.Peers, | ||||||
| reportNotifyChan: make(chan uint64, 1024), | ||||||
| maxReqRetries: conf.MaxReqRetries, | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -155,7 +155,12 @@ | |
| "cpiface": { | ||
| "peers": ["148.162.12.214"], | ||
| // [Optional] Below parameters | ||
| "dnn": "internet", | ||
| "dnn_list": [ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these parameter are marked as optionals but in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we set the dnn_list, should we make sure that both the dnn and ip pool are set ? |
||
| { | ||
| "dnn": "internet", | ||
| "ue_ip_pool": "10.250.0.0/16" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as in the other jsonc file. Should not the |
||
| } | ||
| ], | ||
| "http_port": "8080", | ||
| "enable_ue_ip_alloc": false, | ||
| // "use_fqdn": "true", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,9 +57,12 @@ func BESSConfigUPFBasedIPAllocation() pfcpiface.Conf { | |
| config := BESSConfigDefault() | ||
| config.CPIface = pfcpiface.CPIfaceInfo{ | ||
| EnableUeIPAlloc: true, | ||
| UEIPPool: UEPoolUPF, | ||
| DnnList: []pfcpiface.DNNInfo{ | ||
| { | ||
| UEIPPool: UEPoolUPF, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why you are not setting the |
||
| }, | ||
| }, | ||
| } | ||
|
|
||
| return config | ||
| } | ||
|
|
||
|
|
@@ -87,7 +90,11 @@ func UP4ConfigDefault() pfcpiface.Conf { | |
| } | ||
|
|
||
| config.CPIface = pfcpiface.CPIfaceInfo{ | ||
| UEIPPool: UEPoolCP, | ||
| DnnList: []pfcpiface.DNNInfo{ | ||
| { | ||
| UEIPPool: UEPoolCP, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why you are not setting the |
||
| }, | ||
| }, | ||
| } | ||
|
|
||
| return config | ||
|
|
@@ -97,7 +104,11 @@ func UP4ConfigUPFBasedIPAllocation() pfcpiface.Conf { | |
| config := UP4ConfigDefault() | ||
| config.CPIface = pfcpiface.CPIfaceInfo{ | ||
| EnableUeIPAlloc: true, | ||
| UEIPPool: UEPoolUPF, | ||
| DnnList: []pfcpiface.DNNInfo{ | ||
| { | ||
| UEIPPool: UEPoolUPF, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why you are not setting the |
||
| }, | ||
| }, | ||
| } | ||
|
|
||
| return config | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as in
ptf/config/upf.jsonc