Skip to content

Conversation

anaswarac-dac
Copy link

📌 Description:
This PR introduces support for associating multiple DNNs to a single device group in the 5G Core, enabling flexible and scalable configurations in deployments with a single UPF.

✅ Key Highlights:
Introduced configuration support for multiple DNNs per IMSI range in the sdcore-5g-values.yml file.

Each DNN can have its own:

IP pool

MTU

DNS

UE QoS profile (including MBR uplink/downlink and traffic class)

Validated end-to-end traffic flow for both ims and internet DNNs over the same UPF.

📂 Configuration Changes (in sdcore-5g-values.yml):

✅ device-groups Section:

ip-domains list now includes multiple DNNs (ims, internet) under a single group (gnbsim-user-group1).
ip-domain-expanded changed to ip-domains
Each DNN is mapped to a different ue-ip-pool and ue-dnn-qos.
device-groups:
- name: "gnbsim-user-group1"
imsis:
- "208930100007487"
- "208930100007488"
- "208930100007489"
- "208930100007490"
- "208930100007491"
- "208930100007492"
- "208930100007493"
- "208930100007494"
- "208930100007495"
- "208930100007496"
ip-domain-name: "pool1"
ip-domains:
- dnn: ims
dns-primary: "8.8.8.8"
mtu: 1400
ue-ip-pool: "172.252.0.0/16"
ue-dnn-qos:
dnn-mbr-downlink: 2400
dnn-mbr-uplink: 1200
bitrate-unit: Kbps
traffic-class:
name: "platinum"
qci: 5
arp: 1
pdb: 100
pelr: 6
- dnn: internet
dns-primary: "10.176.0.11"
mtu: 1460
ue-ip-pool: {{ core.upf.default_upf.ue_ip_pool }}
ue-dnn-qos:
dnn-mbr-downlink: 1000
dnn-mbr-uplink: 1000
bitrate-unit: Mbps
traffic-class:
name: "platinum"
qci: 9
arp: 6
pdb: 300
pelr: 6
site-info: "enterprise"

✅ Userplane Section:
Defined dnn_list with individual DNNs and their respective ue_ip_pool.
cpiface:
dnn_list:
- dnn: "ims"
ue_ip_pool: "172.252.0.0/16"
- dnn: "internet"
ue_ip_pool: "172.250.0.0/16" # Must match slice DNN
hostname: "upf"
enable_ue_ip_alloc: false

Signed-off-by: anaswara <anaswara.n@cdac.in>
Copy link
Contributor

@gab-arrobo gab-arrobo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on my preliminary testing and the changes, this PR should be independent of the other PRs you opened, correct? If so, we could proceed to merge it after the comments/suggestions have been addressed

"dnn_list": [
{
"dnn": "internet",
"ue_ip_pool": "10.250.0.0/16"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that now you have the ue_ip_pool here, should not it be removed from below?

        // "hostname": "upf-0",
        "ue_ip_pool": "10.250.0.0/16"
    },

"dnn_list": [
{
"dnn": "internet",
"ue_ip_pool": "10.250.0.0/16"
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

My bad. I misread this... for some reason I thought it was 172.250.0.0/16 (as it was in OnRamp before). @anaswarac-dac please disregard this comment

HTTPPort string `json:"http_port"`
DnnList []DNNInfo `json:"dnn_list"`
EnableUeIPAlloc bool `json:"enable_ue_ip_alloc"`
UEIPPool string `json:"ue_ip_pool"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that you are moving the UEIPPool to inside DNNInfo, should not it be removed from here?

Suggested change
UEIPPool string `json:"ue_ip_pool"`

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

if p.UPAllocateFteid {
var fteid uint32
if pConn.upf.fteidGenerator == nil {
logger.PfcpLog.Warnf("fteid is nill")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.PfcpLog.Warnf("fteid is nill")
logger.PfcpLog.Warnf("fteid is nil")


up4.ueIPPool = MustParseStrIP(conf.CPIface.UEIPPool)
if len(conf.CPIface.DnnList) > 0 {
up4.ueIPPool = MustParseStrIP(conf.CPIface.DnnList[0].UEIPPool)
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems like up4 should support multiple IP pools now ?

Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Author

Choose a reason for hiding this comment

The 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.

for _, dnnInfo := range conf.CPIface.DnnList {
dnns = append(dnns, dnnInfo.DNN)
if ippoolCidr == "" {
ippoolCidr = dnnInfo.UEIPPool
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

"dnn_list": [
{
"dnn": "internet",
"ue_ip_pool": "10.250.0.0/16"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as in the other jsonc file. Should not the ue_ip_pool be removed from below (new line 168)

UEIPPool: UEPoolUPF,
DnnList: []pfcpiface.DNNInfo{
{
UEIPPool: UEPoolUPF,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you are not setting the DNN here?

UEIPPool: UEPoolCP,
DnnList: []pfcpiface.DNNInfo{
{
UEIPPool: UEPoolCP,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you are not setting the DNN here?

UEIPPool: UEPoolUPF,
DnnList: []pfcpiface.DNNInfo{
{
UEIPPool: UEPoolUPF,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you are not setting the DNN here?

ippool *IPPool
peers []string
dnn string
dnn []string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dnn []string
dnns []string

i think that making it plural would represent the multiple dnns better

if err != nil {
return ErrInvalidArgumentWithReason("conf.UEIPPool", conf.CPIface.UEIPPool, err.Error())
for _, dnn := range conf.CPIface.DnnList {
_, _, err := net.ParseCIDR(dnn.UEIPPool)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we check that dnn is not an empty string?

Copy link
Contributor

Choose a reason for hiding this comment

The 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?

"peers": ["148.162.12.214"],
// [Optional] Below parameters
"dnn": "internet",
"dnn_list": [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these parameter are marked as optionals but in pfcpiface/up4.go there is a fatal log if the IP pool is not present. Is the dnn_list mandatory?

Copy link
Contributor

Choose a reason for hiding this comment

The 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 ?

// Control plane controller settings
"cpiface": {
"peers": ["148.162.12.214"],
// [Optional] Below parameters
Copy link
Contributor

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

if _, ok := validModes[conf.Mode]; !ok {
return ErrInvalidArgumentWithReason("conf.Mode", conf.Mode, "invalid mode")
}
}
Copy link
Contributor

@patriciareinoso patriciareinoso Jul 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this function there are 2 checks over the DnnList that seem redundant. One is done if EnableUeIPAlloc is true and the other if EnableP4rt is true.
Later on in the code, the information in DnnList seems to be used regardless of these 2 conditions being true or false.
Should the checks be done once here in this function, even if the 2 conditions are false?

Copy link
Contributor

@patriciareinoso patriciareinoso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Please update https://github.com/omec-project/upf/blob/main/docs/configuration-guide.md
  2. I added some comments to better understand the approach that will be used. I have some concerns regarding the possibility of setting multiple IP pools but in fact only using one
  3. What happens if 2 device groups within the same network slice share the same DNN ? does it mean that they need to use the same IP pool?

@thakurajayL thakurajayL self-assigned this Jul 18, 2025
@thakurajayL thakurajayL added the enhancement New feature or request label Jul 18, 2025
@thakurajayL
Copy link
Contributor

2 Generic comments

  1. Consider updating README file with multi-dnn support
  2. It would be great if we start adding Tests to cover this change.

HTTPPort string `json:"http_port"`
DnnList []DNNInfo `json:"dnn_list"`
EnableUeIPAlloc bool `json:"enable_ue_ip_alloc"`
UEIPPool string `json:"ue_ip_pool"`
Copy link
Contributor

Choose a reason for hiding this comment

The 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"`
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

if err != nil {
return ErrInvalidArgumentWithReason("conf.UEIPPool", conf.CPIface.UEIPPool, err.Error())
for _, dnn := range conf.CPIface.DnnList {
_, _, err := net.ParseCIDR(dnn.UEIPPool)
Copy link
Contributor

Choose a reason for hiding this comment

The 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?


// Allocate and return an id in range [minValue, maxValue]
func (idGenerator *FTEIDGenerator) Allocate() (uint32, error) {
if idGenerator == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Author

Choose a reason for hiding this comment

The 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.

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)
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Author

@anaswarac-dac anaswarac-dac Jul 18, 2025

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Author

@anaswarac-dac anaswarac-dac Jul 21, 2025

Choose a reason for hiding this comment

The 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:
"Optionally one or more UE IP address Pool Information IE which contains a list of UE IP Address Pool Identities per Network Instance, S-NSSAI and IP version."

DNN | Pool | IP Version

ims | ims-pool | IPv4
internet | internet-pool | IPv4

Will Update the code based on this?

@anaswarac-dac
Copy link
Author

@gab-arrobo , @thakurajayL , @patriciareinoso I have made the changes based on your comments. However, I'm currently unable to build because the integration-test-up4 and integration-test-bess are failing. I'm debugging the issue and will proceed with testing using COTS UEs once it's resolved.

@gab-arrobo
Copy link
Contributor

@anaswarac-dac,
Please rebase your PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants