Category Archives: 5G SA

Reflective QoS in 5G

Reflective QoS is a clever new concept introduced in 5G SA networks.

The concept is rather simple, apply QoS in the downlink, and let the UE reply using the QoS in the uplink.

So what is Reflective QoS?
If I send an ICMP ping request to a UE with a particular QoS Flow setup on the downlink, if Reflective QoS is enabled, the ICMP reply will have the same QoS applied on the uplink. Simple as that.

The UE looks at the QoS applied on the downlink traffic, and applies the same to the uplink traffic.

Let’s take another example, if a user starts playing an online game, and the traffic to the user (Downlink) has certain QoS parameters set, if Reflective QoS is enabled, the UE builds rules based on the incoming traffic based on the source IP / port / protocol of the traffic received, and the QoS used on the downlink, and applies the same on the uplink.

But actually getting Reflective QoS enabled requires a few more steps…

Reflective QoS is enabled on a per-packet basis, and is indicated by the UPF setting the Reflective QoS Indication (RQI) bit in the encapsulation header next to the QFI (This is set in the GTP header, as an extension header, used on the N3 and N9 reference points).

But before this is honored, a few other parameters have to be setup.

  • A Reflective QoS Timer (RQ Timer) has to be set, this can be done during the PDU Session Establishment, PDU Session Modification procedure, or set to a default value.
  • SMF has to set Reflective QoS Attribute (RQA) on the QoS profile for this traffic on the N2 reference point towards gNodeB
  • SMF must instruct UPF to use uplink reflective QoS by generating a new UL PDR for this SDF via the N4 reference point

When these requirements have been met, the traffic from the UPF to the gNodeB (N3 reference point) has the Reflective QoS Indication (RQI) bit in the encapsulation header, which is encapsulated and signaled down to the UE, which builds a rule based on the received IP source / port / protocol, and sends responses using the same QoS attributes.

N20 5G SBI for Nsmsf for SMS over 5GC

SMS in 5GC

Like in EPS / LTE, there are two ways to send SMS in Standalone 5G Core networks.

SMS over IMS or SMS over NAS – Both can be used on the same network, or just one, depending on operator preferences.

SMS over IMS in 5G

SMS over IMS uses the IMS network to send SMS. SIP MESSAGE methods are used to deliver SMS between users. While most operators have deployed IMS for 4G/LTE subscribers to use VoLTE some time ago, there are some changes required to the IMS architecture to support VoNR (Voice over New Radio) on the carrier side, and support for VoNR in commercial devices is currently in its early stages. Because of this many 5G devices and networks do not yet support SMS over IMS.

I’ve read in some places that RCS – The GSMA’s Rich Communications Service will replace SMS in 5GC. If this is the case, it reflected in any of the 3GPP standards.

SMS over NAS

To make a voice call on a device or network that does not support VoNR, EPS (VoLTE) fallback is used.
This means when making or receiving a call, the UE drops from the 5G RAN to using a 4G (LTE) basd RAN, and then uses VoLTE to make the call the same as it would when connected to 4G (LTE) networks, because it is connected to a 4G network.
This works technically, but is not the prefered option as it adds extra signaling and complexity to the network, and delays in the call setup, and it’s expected operators will eventually move to VoNR,but works as a stop-gap measure.

But mobile networks see a lot of SMS traffic. If every time an SMS was sent the UE had to rely on EPS fallback to access IMS, this would see users ping-ponging between 4G and 5G every time they sent or received an SMS.

This isn’t a new problem, in fact SMS-over-NAS was initially added to 4G (LTE) to allow devices to stay connected to the EPC (4G Core network) but still send and receive SMS, even if the network or device relied on “Circuit-Switched fallback” (A mechanism to drop from 4G to 2G / 3G for voice calls).

5GC reintroduces the SMS-over-NAS feature, allowing the SMS messages to be carried over NAS messaging on the N1 interface. Voice calls may still require fallback to EPS (4G) to make calls over VoLTE, but SMS can be carried over NAS messaging, minimizing the amount of Inter-RAT handovers required.

The Nsmsf_SMService

For this a new Service Based Interface is introduced between the AMF and the SMSF (SMS Function, typically built into an SMSc), via the N20 / Nsmsf SBI to offer the Nsmsf_SMService service.

There are 3 operations supported for the Nsmsf_SMService:

  • Active – Initiated by the AMF – Used to active the SMS service for a given subscriber,
  • Deactivate – Initiated by the AMF – Used to deactivate the SMS over NAS service for a given subscriber.
  • UplinkSMS – Initiated by the AMF to transfer the SMS payload towards the SMSF.

The UplinkSMS is a HTTP post from the AMF with the SUPI in the Request URI and the request body containing a JSON encoded SmsRecordData.

Astute readers may notice that’s all well and good, but that only covers Mobile Originated (MO) SMS, what about Mobile Terminated (MT) SMS?

Well that’s actually handled by a totally different SBI, the Namf_Communication action “N1N2MessageTransfer” is resused for sending MT SMS, as that interface already exists for use by SMF, LMF and PCF, and 5GC attempts to reuse interfaces as much as possible.

5G Online Charging with the Nchf_ConvergedCharging SBI

There’s no such thing as a free lunch, and 5G is the same – services running through a 5G Standalone core need to be billed.

In 5G Core Networks, the SMF (Session Management Function) reaches out to the CHF (Charging Function) to perform online charging, via the Nchf_ConvergedCharging Service Based Interface (aka reference point).

Like in other generations of core mobile networks, Credit Control in 5G networks is based on 3 functions:
Requesting a quota for a subscriber from an online charging service, which if granted permits the subscriber to use a certain number of units (in this case data transferred in/out).
Just before those units are exhausted sending an update to request more units from the online charging service to allow the service to continue.
When the session has ended or or subscriber has disconnected, a termination to inform the online charging service to stop billing and refund any unused credit / units (data).

Initial Service Creation (ConvergedCharging_Create)

When the SMF needs to setup a session, (For example when the AMF sends the SMF a Nsmf_PDU_SessionCreate request), the CTF (Charging Trigger Function) built into the SMF sends a Nchf_ ConvergedCharging_Create (Initial, Quota Requested) to the Charging Function (CHF).

Because the Nchf_ConvergedCharging interface is a Service Based Interface this is carried over HTTP, in practice, this means the SMF sends a HTTP post to http://yourchargingfunction/Nchf_ConvergedCharging/v1/chargingdata/

Obviously there’s some additional information to be shared rather than just a HTTP post, so the HTTP post includes the ChargingDataRequest as the Request Body. If you’ve dealt with Diameter Credit Control you may be expecting the ChargingDataRequest information to be a huge jumble of nested AVPs, but it’s actually a fairly short list:

  • The subscriberIdentifier (SUPI) is included to identify the subscriber so the CHF knows which subscriber to charge
  • The nfConsumerIdentification identifies the SMF generating the request (The SBI Consumer)
  • The invocationTimeStamp and invocationSequenceNumber are both pretty self explanatory; the time the request is sent and the sequence number from the SBI consumer
  • The notifyUri identifies which URI should receive subsequent notifications from the CHF (For example if the CHF wants to terminate the session, the SMF to send that to)
  • The multipleUnitUsage defines the service-specific parameters for the quota being requested.
  • The triggers identifies the events that trigger the request

Of those each of the fields should be pretty self explanatory as to their purpose.
The multipleUnitUsage data is used like the Service Information AVP in Diameter based Credit Control, in that it defines the specifics of the service we’re requesting a quota for. Inside it contains a mandatory ratingGroup specifying which rating group the CHF should use, and optionally requestedUnit which can define either the amount of service units being requested (For us this is data in/out), or to tell the CHF units are needed. Typically this is used to define the amount of units to be requested.

On the amount of units requested we have a bit of a chicken-and-egg scenario; we don’t know how many units (In our case the units is transferred data in/out) to request, if we request too much we’ll take up all the customer’s credit, potentially prohibiting them from accessing other services, and not enough requested and we’ll constantly slam the CHF with requests for more credit.
In practice this value is somewhere between the two, and will vary quite a bit.

Based on the service details the SMF has put in the Nchf_ ConvergedCharging_Create request, the Charging Function (CHF) takes into account the subscriber’s current balance, credit control policies, etc, and uses this to determine if the Subscriber has the required balances to be granted a service, and if so, sends back a 201 CREATED response back to the Nchf_ConvergedCharging_Create request sent by the CTF inside the SMF.

This 201 CREATED response is again fairly clean and simple, the key information is in the multipleQuotaInformation which is nested within the ChargingDataResponse, which contains the finalUnitIndication defining the maximum units to be granted for the session, and the triggers to define when to check in with CHF again, for time, volume and quota thresholds.

And with that, the service is granted, the SMF can instruct the UPF to start allowing traffic through.

Update (ConvergedCharging_Update)

Once the granted units / quota has been exhausted, the Update (ConvergedCharging_Update) request is used for requesting subsequent usage / quota units. For example our Subscriber has used up all the data initially allocated but is still consuming data, so the SMF sends a Nchf_ConvergedCharging_Update request to request more units, via another HTTP post, to the CHF, with the requested service unit in the request body in the form of ChargingDataRequest as we saw in the initial ConvergedCharging_Create.

If the subscriber still has credit and the CHF is OK to allow their service to continue, the CHF returns a 200 OK with the ChargingDataResponse, again, detailing the units to be granted.

This procedure repeats over and over as the subscriber uses their allocated units.

Release (ConvergedCharging_Release)

Eventually when our subscriber disconnects, the SMF will generate a Nchf_ConvergedCharging_Release request, detailing the data the subscriber used in the ChargingDataRequest in the body, to the CHF, so it can refund any unused credits.

The CHF sends back a 204 No Content response, and the procedure is completed.

More Info

If you’ve had experience in Diameter credit control, this simple procedure will be a breath of fresh air, it’s clean and easy to comprehend,
If you’d like to learn more the 3GPP specification docs on the topic are clear and comprehensible, I’d suggest:

  • TS 132 290 – Short overview of charging mechanisms
  • TS 132 291 – Specifics of the Nchf_ConvergedCharging interface
  • The common 3GPP charging architecture is specified in TS 32.240
  • TS 132 291 – Overview of components and SBIs inc Operations

EIR in 5G Networks (N5g-eir_EquipmentIdentityCheck)

Today, we’re going to look at one of the simplest Service Based Interfaces in the 5G Core, the Equipment Identity Register (EIR).

The purpose of the EIR is very simple – When a subscriber connects to the network it’s Permanent Equipment Identifier (PEI) can be queried against an EIR to determine if that device should be allowed onto the network or not.

The PEI is the IMEI of a phone / device, with the idea being that stolen phones IMEIs are added to a forbidden list on the EIR, and prohibited from connecting to the network, making them useless, in turn making stolen phones harder to resell, deterring mobile phone theft.

In reality these forbidden-lists are typically either country specific or carrier specific, meaning if the phone is used in a different country, or in some cases a different carrier, the phone’s IMEI is not in the forbidden-list of the overseas operator and can be freely used.

The dialog goes something like this:

AMF: Hey EIR, can PEI 49-015420-323751-8 connect to the network?
EIR: (checks if 49-015420-323751-8 in forbidden list - It's not) Yes.


AMF: Hey EIR, can PEI 58-241992-991142-3 connect to the network?
EIR: (checks if 58-241992-991142-3 is in forbidden list - It is) No.

(Optionally the SUPI can be included in the query as well, to lock an IMSI to an IMEI, which is a requirement in some jurisdictions)

As we saw in the above script, the AMF queries the EIR using the N5g-eir_EquipmentIdentityCheck service.

The N5g-eir_EquipmentIdentityCheck service only offers one operation – CheckEquipmentIdentity.

It’s called by sending an HTTP GET to:


Obviously we’ll need to include the PEI (IMEI) in the HTTP GET, which means if you remember back to basic HTTP GET, you may remember means you have to add ?attribute=value&attribute=value… for each attribute / value you want to share.

For the CheckEquipmentIdentity operation, the PEI is a mandatory parameter, and optionally the SUPI can be included, this means to query our PEI (The IMSI of the phone) against our EIR we’d simply send an HTTP GET to:

AMF: HTTP GET http://{apiRoot}/n5g-eir-eic/v1/equipment-status?pei=490154203237518
EIR: 200 (Body EirResponseData: status "WHITELISTED")

And how it would look for a blacklisted IMEI:

AMF: HTTP GET http://{apiRoot}/n5g-eir-eic/v1/equipment-status?pei=490154203237518
EIR: 404 (Body EirResponseData: status "BLACKLISTED")

Because it’s so simple, the N5g-eir_EquipmentIdentityCheck service is a great starting point for learning about 5G’s Service Based Interfaces.

You can find all the specifics in 3GPP TS 29.511 – Equipment Identity Register Services; Stage 3

Open5GS without NAT

While most users of Open5GS EPC will use NAT on the UPF / P-GW-U but you don’t have to.

While you can do NAT on the machine that hosts the PGW-U / UPF, you may find you want to do the NAT somewhere else in the network, like on a router, or something specifically for CG-NAT, or you may want to provide public addresses to your UEs, either way the default config assumes you want NAT, and in this post, we’ll cover setting up Open5GS EPC / 5GC without NAT on the P-GW-U / UPF.

Before we get started on that, let’s keep in mind what’s going to happen if we don’t have NAT in place,

Traffic originating from users on our network (UEs / Subscribers) will have the from IP Address set to that of the UE IP Pool set on the SMF / P-GW-C, or statically in our HSS.

This will be the IP address that’s sent as the IP Source for all traffic from the UE if we don’t have NAT enabled in our Core, so all external networks will see that as the IP Address for our UEs / Subscribers.

The above example shows the flow of a packet from UE with IP Address sending something to

This is all well and good for traffic originating from our 4G/5G network, but what about traffic destined to our 4G/5G core?

Well, the traffic path is backwards. This means that our router, and external networks, need to know how to reach the subnet containing our UEs. This means we’ve got to add static routes to point to the IP Address of the UPF / P-GW-U, so it can encapsulate the traffic and get the GTP encapsulated traffic to the UE / Subscriber.

For our example packet destined for, as that is a globally routable IP (Not an internal IP) the router will need to perform NAT Translation, but for internal traffic within the network (On the router) the static route on the router should be able to route traffic to the UE Subnets to the UPF / P-GW-U’s IP Address, so it can encapsulate the traffic and get the GTP encapsulated traffic to the UE / Subscriber.

Setting up static routes on your router is going to be different on what you use, in my case I’m using a Mikrotik in my lab, so here’s a screenshot from that showing the static route point at my UPF/P-GW-U. I’ve got BGP setup to share routes around, so all the neighboring routers will also have this information about how to reach the subscriber.

Next up we’ve got to setup IPtables on the server itself running our UPF/P-GW-U, to route traffic addressed to the UE and encapsulate it.

sudo ip route add dev ogstun
sudo echo 1 > /proc/sys/net/ipv4/ip_forward
sudo iptables -A FORWARD -i ogstun -o osgtun -s -d -j ACCEPT

And that’s it, now traffic coming from UEs on our UPF/P-GW will leave the NIC with their source address set to the UE Address, and so long as your router is happily configured with those static routes, you’ll be set.

If you want access to the Internet, it then just becomes a matter of configuring traffic from that subnet on the router to be NATed out your external interface on the router, rather than performing the NAT on the machine.

In an upcoming post we’ll look at doing this with OSPF and BGP, so you don’t need to statically assign routes in your routers.

The PLMN Problem for Private LTE / 5G

So it’s the not to distant future and the pundits vision of private LTE and 5G Networks was proved correct, and private networks are plentiful.

But what PLMN do they use?

The PLMN (Public Land Mobile Network) ID is made up of a Mobile Country Code + Mobile Network Code. MCCs are 3 digits and MNCs are 2-3 digits. It’s how your phone knows to connect to a tower belonging to your carrier, and not one of their competitors.

For example in Australia (Mobile Country Code 505) the three operators each have their own MCC. Telstra as the first licenced Mobile Network were assigned 505/01, Optus got 505/02 and VHA / TPG got 505/03.

Each carrier was assigned a PLMN when they started operating their network. But the problem is, there’s not much space in this range.

The PLMN can be thought of as the SSID in WiFi terms, but with a restriction as to the size of the pool available for PLMNs, we’re facing an IPv4 exhaustion problem from the start if we’re facing an explosion of growth in the space.

Let’s look at some ways this could be approached.

Everyone gets a PLMN

If every private network were to be assigned a PLMN, we’d very quickly run out of space in the range. Best case you’ve got 3 digits, so only space for 1,000 networks.

In certain countries this might work, but in other areas these PLMNs may get gobbled up fast, and when they do, there’s no more. New operators will be locked out of the market.

Loaner PLMNs

Carriers already have their own PLMNs, they’ve been using for years, some kit vendors have been assigned their own as well.

If you’re buying a private network from an existing carrier, they may permit you to use their PLMN,

Or if you’re buying kit from an existing vendor you may be able to use their PLMN too.

But what happens then if you want to move to a different kit vendor or another service provider? Do you have to rebuild your towers, reconfigure your SIMs?

Are you contractually allowed to continue using the PLMN of a third party like a hardware vendor, even if you’re no longer purchasing hardware from them? What happens if they change their mind and no longer want others to use their PLMN?

Everyone uses 999 / 99

The ITU have tried to preempt this problem by reallocating 999/99 for use in Private Networks.

The problem here is if you’ve got multiple private networks in close proximity, especially if you’re using CBRS or in close proximity to other networks, you may find your devices attempting to attach to another network with the same PLMN but that isn’t part of your network,

Mobile Country or Geographical Area Codes
Note from TSB
Following the agreement on the Appendix to Recommendation ITU-T E.212 on “shared E.212 MCC 999 for internal use within a private network” at the closing plenary of ITU-T SG2 meeting of 4 to 13 July 2018, upon the advice of ITU-T Study Group 2, the Director of TSB has assigned the Mobile Country Code (MCC) “999” for internal use within a private network. 

Mobile Network Codes (MNCs) under this MCC are not subject to assignment and therefore may not be globally unique. No interaction with ITU is required for using a MNC value under this MCC for internal use within a private network. Any MNC value under this MCC used in a network has
significance only within that network. 

The MNCs under this MCC are not routable between networks. The MNCs under this MCC shall not be used for roaming. For purposes of testing and examples using this MCC, it is encouraged to use MNC value 99 or 999. MNCs under this MCC cannot be used outside of the network for which they apply. MNCs under this MCC may be 2- or 3-digit.

(Recommendation ITU-T E.212 (09/2016))

The Crystal Ball?

My bet is we’ll see the ITU allocate an MCC – or a range of MCCs – for private networks, allowing for a pool of PLMNs to use.

When deploying networks, Private network operators can try and pick something that’s not in use at the area from a pool of a few thousand options.

The major problem here is that there still won’t be an easy way to identify the operator of a particular network; the SPN is local only to the SIM and the Network Name is only present in the NAS messaging on an attach, and only after authentication.

If you’ve got a problem network, there’s no easy way to identify who’s operating it.

But as eSIMs become more prevalent and BIP / RFM on SIMs will hopefully allow operators to shift PLMNs without too much headache.

IMS Routing with iFCs

SIP routing is complicated, there’s edge cases, traffic that can be switched locally and other traffic that needs to be proxied off to another Proxy or Application server. How can you define these rules and logic in a flexible way, that allows these rules to be distributed out to multiple different network elements and adjusted on a per-subscriber basis?

Enter iFCs – The Initial Filter Criteria.

iFCs are XML encoded rules to define which servers should handle traffic matching a set of rules.

Let’s look at some example rules we might want to handle through iFCs:

  • Send all SIP NOTIFY, SUBSCRIBE and PUBLISH requests to a presence server
  • Any Mobile Originated SMS to an SMSc
  • Calls to a specific destination to a MGC
  • Route any SIP INVITE requests with video codecs present to a VC bridge
  • Send calls to Subscribers who aren’t registered to a Voicemail server
  • Use 3rd party registration to alert a server that a Subscriber has registered

All of these can be defined and executed through iFCs, so let’s take a look,

iFC Structure

iFCs are encoded in XML and typically contained in the Cx-user-data AVP presented in a Cx Server Assignment Answer response.

Let’s take a look at an example iFC and then break down the details as to what we’re specifying.


Each rule in an iFC is made up of a Priority, TriggerPoint and ApplicationServer.

So for starters we’ll look at the Priority tag.
The Priority tag allows us to have multiple-tiers of priority and multiple levels of matching,
For example if we had traffic matching the conditions outlined in this rule (TriggerPoint) but also matching another rule with a lower priority, the lower priority rule would take precedence.

Inside our <TriggerPoint> tag contains the specifics of the rules and how the rules will be joined / matched, which is what we’ll focus on predominantly, and is followed by the <ApplicationServer> which is where we will route the traffic to if the TriggerPoint is matched / triggered.

So let’s look a bit more about what’s going on inside the TriggerPoint.

Each TriggerPoint is made up of Service Point Trigger (SPTs) which are individual rules that are matched or not matched, that are either combined as logical AND or logical OR statements when evaluated.

By using fairly simple building blocks of SPTs we can create a complex set of rules by joining them together.

Service Point Triggers (SPTs)

Let’s take a closer look at what goes on in an SPT.
Below is a simple SPT that will match all SIP requests using the SIP MESSAGE method request type:


So as you may have guessed, the <Method> tag inside the SPT defines what SIP request method we’re going to match.

But Method is only one example of the matching mechanism we can use, but we can also match on other attributes, such as Request URI, SIP Header, Session Case (Mobile Originated vs Mobile Terminated) and Session Description such as SDP.

Or an example of a SPT for anything Originating from the Subscriber utilizing the <SessionCase> tag inside the SPT.


Below is another SPT that’s matching any requests where the request URI is sip:[email protected] by setting the <RequestURI> tag inside the SPT:

            <RequestURI>sip:[email protected]</RequestURI>

We can match SIP headers, either looking for the existence of a header or the value it is set too,


Having <Header> will match if the header is present, while the optional Content tag can be used to match

In terms of the Content this is matched using Regular Expressions, but in this case, not so regular regular expressions. 3GPP selected Extended Regular Expressions (ERE) to be used (IEEE POSIX) which are similar to the de facto standard PCRE Regex, but with a few fewer parameters.

Condition Negated

The <ConditionNegated> tag inside the SPT allows us to do an inverse match.

In short it will match anything other than what is specified in the SPT.

For example if we wanted to match any SIP Methods other than MESSAGE, setting <ConditionNegated>1</ConditionNegated> would do just that, as shown below:


And another example of ConditionNegated in use, this time we’re matching anything where the Request URI is not sip:[email protected]:

            <RequestURI>sip:[email protected]</RequestURI>

Finally the <Group> tag allows us to group together a group of rules for the purpose of evaluating.
We’ll go into it more in in the below section.

ConditionTypeCNF / ConditionTypeDNF

As we touched on earlier, <TriggerPoints> contain all the SPTs, but also, very importantly, specify how they will be interpreted.

SPTs can be joined in AND or OR conditions.

For some scenarios we may want to match where METHOD is MESSAGE and RequestURI is sip:[email protected], which is different to matching where the METHOD is MESSAGE or RequestURI is sip:[email protected].

This behaviour is set by the presence of one of the ConditionTypeCNF (Conjunctive Normal Form) or ConditionTypeDNF (Disjunctive Normal Form) tags.

If each SPT has a unique number in the GroupTag and ConditionTypeCNF is set then we evaluate as AND.

If each SPT has a unique number in the GroupTag and ConditionTypeDNF is set then we evaluate as OR.

Let’s look at how the below rule is evaluated as AND as ConditionTypeCNF is set:


This means we will match if the method is MESSAGE and Session Case is 0 (Mobile Originated) as each SPT is in a different Group which leads to “and” behaviour.

If we were to flip to ConditionTypeDNF each of the SPTs are evaluated as OR.


This means we will match if the method is MESSAGE and Session Case is 0 (Mobile Originated).

Where this gets a little bit more complex is when we have multiple entries in the same Group tag.

Let’s say we have a trigger point made up of:



How would this be evaluated?

If we use ConditionTypeDNF every SPT inside the same Group are matched as AND, and SPTs with distinct are matched as OR.

Let’s look at our example rule evaluated as ConditionTypeDNF:



This means the two entries in Group 1 are evaluated as AND – So Method is message and Session Case is 0, OR the header “P-Some-Header” is present.

Let’s do another one, this time as ConditionTypeCNF:



This means the two entries in Group 1 are evaluated as OR – So Method is message OR Session Case is 0, AND the header “P-Some-Header” is present.

Pre-5G Network Slicing

Network Slicing, is a new 5G Technology. Or is it?

Pre 3GPP Release 16 the capability to “Slice” a network already existed, in fact the functionality was introduced way back at the advent of GPRS, so what is so new about 5G’s Network Slicing?

Network Slice: A logical network that provides specific network capabilities and network characteristics

3GPP TS 123 501 / 3 Definitions and Abbreviations

Let’s look at the old and the new ways, of slicing up networks, pre release 16, on LTE, UMTS and GSM.

Old Ways: APN Separation

The APN or “Access Point Name” is used so the SGSN / MME knows which gateway to that subscriber’s traffic should be terminated on when setting up the session.

APN separation is used heavily by MVNOs where the MVNO operates their own P-GW / GGSN.
This allows the MNVO can handle their own rating / billing / subscriber management when it comes to data.
A network operator just needs to setup their SGSN / MME to point all requests to setup a bearer on the MVNO’s APN to the MNVO’s gateways, and presoto, it’s no longer their problem.

Later as customers wanted MPLS solutions extended over mobile (Typically LTE), MNOs were able to offer “private APNs”.
An enterprise could be allocated an APN by the MNO that would ensure traffic on that APN would be routed into the enterprise’s MPLS VRF.
The MNO handles the P-GW / GGSN side of things, adding the APN configuration onto it and ensuring the traffic on that APN is routed into the enterprise’s VRF.

Different QCI values can be assigned to each APN, to allow some to have higher priority than others, but by slicing at an APN level you lock all traffic to those QoS characteristics (Typically mobile devices only support one primary APN used for routing all traffic), and don’t have the flexibility to steer which networks which traffic from a subscriber goes to.

It’s not really practical for everyone to have their own APNs, due in part to the namespace limitations, the architecture of how this is usually done limits this, and the simple fact of everyone having to populate an APN unique to them would be a real headache.

5G replaces APNs with “DNNs” – Data Network Names, but the functionality is otherwise the same.

In Summary:
APN separation slices all traffic from a subscriber using a special APN and provide a bearer with QoS/QCI values set for that APN, but does not allow granular slicing of individual traffic flows, it’s an all-or-nothing approach and all traffic in the APN is treated equally.

The old Ways: Dedicated Bearers

Dedicated bearers allow traffic matching a set rule to be provided a lower QCI value than the default bearer. This allows certain traffic to/from a UE to use GBR or Non-GBR bearers for traffic matching the rule.

The rule itself is known as a “TFT” (Traffic Flow Template) and is made up of a 5 value Tuple consisting of IP Source, IP Destination, Source Port, Destination Port & Protocol Number. Both the UE and core network need to be aware of these TFTs, so the traffic matching the TFT can get the QCI allocated to it.

This can be done a variety of different ways, in LTE this ranges from rules defined in a PCRF or an external interface like those of an IMS network using the Rx interface to request a dedicated bearers matching the specified TFTs via the PCRF.

Unlike with 5G network slicing, dedicated bearers still traverse the same network elements, the same MME, S-GW & P-GW is used for this traffic. This means you can’t “locally break out” certain traffic.

In Summary:
Dedicated bearers allow you to treat certain traffic to/from subscribers with different precedence & priority, but the traffic still takes the same path to it’s ultimate destination.

Old Ways: MOCN

Multi-Operator Core Network (MOCN) allows multiple MNOs to share the same active (tower) infrastructure.

This means one eNodeB can broadcast more than one PLMN and server more than one mobile network.

This slicing is very coarse – it allows two operators to share the same eNodeBs, but going beyond a handful of PLMNs on one eNB isn’t practical, and the PLMN space is quite limited (1000 PLMNs per country code max).

In Summary:
MOCN allows slicing of the RAN on a very coarse level, to slice traffic from different operators/PLMNs sharing the same RAN.

Its use is focused on sharing RAN rather than slicing traffic for users.

5Gethernet? – Transporting Non-IP data in 5G

I wrote not too long ago about how LTE access is not liked WiFi, after a lot of confusion amongst new Open5Gs users coming to LTE for the first time and expecting it to act like a Layer 2 network.

But 5G brings a new feature that changes that;

PDU Session Type: The type of PDU Session which can be IPv4, IPv6, IPv4v6, Ethernet or Unstructured

ETSI TS 123 501 – System Architecture for the 5G System

No longer are we limited to just IP transport, meaning at long last I can transport my Token Ring traffic over 5G, or in reality, customers can extend Layer 2 networks (Ethernet) over 3GPP technologies, without resorting to overlay networking, and much more importantly, fixed line networks, typically run at Layer 2, can leverage the 5G core architecture.

How does this work?

With TFTs and the N6 interfaces relying on the 5 value tuple with IPs/Ports/Protocol #s to make decisions, transporting Ethernet or Non-IP Data over 5G networks presents a problem.

But with fixed (aka Wireline) networks being able to leverage the 5G core (“Wireline Convergence”), we need a mechanism to handle Ethernet.

For starters in the PDU Session Establishment Request the UE indicates which PDN types, historically this was IPv4/6, but now if supported by the UE, Ethernet or Unstructured are available as PDU types.

We’ll focus on Ethernet as that’s the most defined so far,

Once an Ethernet PDU session has been setup, the N6 interface looks a bit different, for starters how does it know where, or how, to route unstructured traffic?

As far as 3GPP is concerned, that’s your problem:

Regardless of addressing scheme used from the UPF to the DN, the UPF shall be able to map the address used between the UPF and the DN to the PDU Session. Support of Unstructured PDU Session type

In short, the UPF will need to be able to make the routing decisions to support this, and that’s up to the implementer of the UPF.

In the Ethernet scenario, the UPF would need to learn the MAC addresses behind the UE, handle ARP and use this to determine which traffic to send to which UE, encapsulate it into trusty old GTP, fill in the correct TEID and then send it to the gNodeB serving that user (if they are indeed on a RAN not a fixed network).

So where does this leave QoS? Without IPs to apply with TFTs and Packet Filter Sets to, how is this handled? In short, it’s not – Only the default QoS rule exist for a PDU Session of Type Unstructured. The QoS control for Unstructured PDUs is performed at the PDU Session level, meaning you can set the QFI when the PDU session is set up, but not based on traffic through that bearer.

Does this mean 5G RAN can transport Ethernet?

Well, it remains to be seen.

The specifications don’t cover if this is just for wireline scenarios or if it can be used on RAN.

The 5G PDU Creation signaling has a field to indicate if the traffic is Ethernet, but to work over a RAN we would need UE support as well as support on the Core.

And for E-UTRAN?

For the foreseeable future we’re going to be relying on LTE/E-UTRAN as well as 5G. So if you’re mobile with a non-IP PDU, and you enter an area only served by LTE, what happens?

PDU Session types “Ethernet” and “Unstructured” are transferred to EPC as “non-IP” PDN type (when supported by UE and network).

It is assumed that if a UE supports Ethernet PDU Session type and/or Unstructured PDU Session type in 5GS it will also support non-IP PDN type in EPS.

5.17.2 Interworking with EPC

If you were not aware of support in the EPC for Non-IP PDNs, I don’t blame you – So far support the CIoT EPS optimizations were initially for Non-IP PDN type has been for NB-IoT to supporting Non-IP Data Delivery (NIDD) for lightweight LwM2M traffic.

So why is this? Well, it may have to do with WO 2017/032399 Al which is a patent held by Ericsson, regarding “COMMUNICATION OF NON-IP DATA OVER PACKET DATA NETWORKS” which may be restricting wide scale deployment of this,

Open5Gs Logo

Open5Gs Database Schema Change

As Open5Gs has introduced network slicing, which led to a change in the database used,

Alas many users had subscribers provisioned in the old DB schema and no way to migrate the SDM data between the old and new schema,

If you’ve created subscribers on the old schema, and now after the updates your Subscriber Authentication is failing, check out this tool I put together, to migrate your data over.

The Open5Gs Python library I wrote has also been updated to support the new schema.

And the call was coming from… INSIDE THE HOUSE. A look at finding UE Locations in LTE

Opening Tirade

Ok, admittedly I haven’t actually seen “When a Stranger Calls”, or the less popular sequel “When a stranger Redials” (Ok may have made the last one up).

But the premise (as I read Wikipedia) is that the babysitter gets the call on the landline, and the police trace the call as originating from the landline.

But you can’t phone yourself, that’s not how local loops work – When the murderer goes off hook it loops the circuit, which busys it. You could apply ring current to the line I guess externally but unless our murder has a Ring generator or has setup a PBX inside the house, the call probably isn’t coming from inside the house.

On Topic – The GMLC

The GMLC (Gateway Mobile Location Centre) is a central server that’s used to locate subscribers within the network on different RATs (GSM/UMTS/LTE/NR).

The GMLC typically has interfaces to each of the radio access technologies, there is a link between the GMLC and the CS network elements (used for GSM/UMTS) such as the HLR, MSC & SGSN via Lh & Lg interfaces, and a link to the PS network elements (LTE/NR) via Diameter based SLh and SLg interfaces with the MME and HSS.

The GMLC’s tentacles run out to each of these network elements so it can query them as to a subscriber’s location,

LTE Call Flow

To find a subscriber’s location in LTE Diameter based signaling is used, to query the MME which in turn queries, the eNodeB to find the location.

But which MME to query?

The SLh Diameter interface is used to query the HSS to find out which MME is serving a particular Subscriber (identified by IMSI or MSISDN).

The LCS-Routing-Info-Request is sent by the GMLC to the HSS with the subscriber identifier, and the LCS-Routing-Info-Response is returned by the HSS to the GMLC with the details of the MME serving the subscriber.

Now we’ve got the serving MME, we can use the SLg Diameter interface to query the MME to the location of that particular subscriber.

The MME can report locations to the GMLC periodically, or the GMLC can request the MME provide a location at that point.
For the GMLC to request a subscriber’s current location a Provide-Location-Request is set by the GMLC to the MME with the subscriber’s IMSI, and the MME responds after querying the eNodeB and optionally the UE, with the location info in the Provide-Location-Response.

(I’m in the process of adding support for these interfaces to PyHSS and all going well will release some software shortly to act at a GMLC so people can use this.)

Finding the actual Location

There are a few different ways the actual location of the UE is determined,

At the most basic level, Cell Global Identity (CGI) gives the identity of the eNodeB serving a user.
If you’ve got a 3 sector site each sector typically has its own Cell Global Identity, so you can determine to a certain extent, with the known radiation pattern, bearing and location of the sector, in which direction a subscriber is. This happens on the network side and doesn’t require any input from the UE.
But if we query the UE’s signal strength, this can then be combined with existing RF models and the signal strength reported by the UE to further pinpoint the user with a bit more accuracy. (Uplink and downlink cell coverage based positioning methods)
Barometric pressure and humidity can also be reported by the base station as these factors will impact resulting signal strengths.

Timing Advance (TA) and Time of Arrival (TOA) both rely on timing signals to/from a UE to determine it’s distance from the eNodeB. If the UE is only served by a single cell this gives you a distance from the cell and potentially an angle inside which the subscriber is. This becomes far more useful with 3 or more eNodeBs in working range of the UE, where you can “triangulate” the UE’s location. This part happens on the network side with no interaction with the UE.
If the UE supports it, EUTRAN can uses Enhanced Observed Time Difference (E-OTD) positioning method, which does TOD calcuation does this in conjunction with the UE.

GPS Assisted (A-GPS) positioning gives good accuracy but requires the devices to get it’s current location using the GPS, which isn’t part of the baseband typically, so isn’t commonly implimented.

Uplink Time Difference of Arrival (UTDOA) can also be used, which is done by the network.

So why do we need to get Subscriber Locations?

The first (and most noble) use case that springs to mind is finding the location of a subscriber making a call to emergency services. Often upon calling an emergency services number the GMLC is triggered to get the subscriber’s location in case the call is cut off, battery dies, etc.

But GMLCs can also be used for lots of other purposes, marketing purposes (track a user’s location and send targeted ads), surveillance (track movements of people) and network analytics (look at subscriber movement / behavior in a specific area for capacity planning).

Different countries have different laws regulating access to the subscriber location functions.

Hack to disable Location Reporting on Mobile Networks

If you’re wondering how you can disable this functionality, you can try the below hack to ensure that your phone does not report your location.

  1. Press the power button on your phone
  2. Turn it off

In reality, no magic super stealth SIM cards, special phones or fancy firmware will prevent the GMLC from finding your location.
So far none of the “privacy” products I’ve looked at have actually done anything special at the Baseband level. Most are just snakeoil.

For as long as your device is connected to the network, the passive ways of determining location, such as Uplink Time Difference of Arrival (UTDOA) and the CGI are going to report your location.

PyHSS New Features

Thanks to some recent developments, PyHSS has had a major overhaul recently, and is getting better than ever,

Some features that are almost ready for public release are:

Config File

Instead of having everything defined all over the place a single YAML config file is used to define how the HSS should function.

SCTP Support

No longer just limited to TCP, PyHSS now supports SCTP as well for transport,

SLh Interface for Location Services

So the GMLC can query the HSS as to the serving MME of a subscriber.

Additional Database Backends (MSSQL & MySQL)

No longer limited to just MongoDB, simple functions to add additional backends too and flexible enough to meet your existing database schema.

All these features will be merged into the mainline soon, and documented even sooner. I’ll share some posts on each of these features as I go.

MTU in LTE & 5G Transmission Networks – Part 1

Every now and then when looking into a problem I have to really stop and think about how things work low down, that I haven’t thought about for a long time, and MTU is one of those things.

I faced with an LTE MTU issue recently I thought I’d go back and brush up on my MTU knowhow and do some experimenting.

Note: This is an IPv4 discussion, IPv6 does not support fragmentation.

The very, very basics

MTU is the Maximum Transmission Unit.

In practice this is the largest datagram the layer can handle, and more often than not, this is based on a physical layer constraint, in that different physical layers can only stuff so much into a frame.

“The Internet” from a consumer perspective typically has an MTU of 1500 bytes or perhaps a bit under depending on their carrier, such as 1472 bytes.
SANs in data centers typically use an MTU of around 9000 bytes,
Out of the box, most devices if you don’t specify, will use an MTU of 1500 bytes.

As a general rule, service providers typically try to offer an MTU as close to 1500 as possible.

Messages that are longer than the Maximum Transmission Unit need to be broken up in a process known as “Fragmenting”.
Fragmenting allows large frames to be split into smaller frames to make their way across hops with a lower MTU.

All about Fragmentation

So we can break up larger packets into smaller ones by Fragmenting them, so case closed on MTU right? Sadly not.

Fragmentation leads to reduced efficiency – Fragmenting frames takes up precious CPU cycles on the router performing it, and each time a frame is broken up, additional overhead is added by the device breaking it up, and by the receiver to reassemble it.

Fragmentation can happen multiple times across a path (Multi-Stage Fragmentation).
For example if a frame is sent with a length of 9000 bytes, and needs to traverse a hop with an MTU of 4000, it would need to be fragmented (broken up) into 3 frames (Frame 1 and Frame 2 would be ~4000 bytes long and frame 3 would be ~1000 bytes long).
If it then needs to traverse another hop with an MTU of 1500, then the 3 fragmented frame would each need to be further fragmented, with the first frame of ~4000 bytes being split up into 3 more fragmented frames.
Lost track of what just happened? Spare a thought for the routers having to to do the fragmentation and the recipient having to reassemble their packets.

Fragmented frames are reassembled by the end recipient, other devices along the transmission path don’t reassemble packets.

In the end it boils down to this trade off:
The larger the packet can be, the more user data we can stuff into each one as a percentage of the overall data. We want the percentage of user data for each packet to be as high as can be.
This means we want to use the largest MTU possible, without having to fragment packets.

Overhead eats into our MTU

A 1500 byte MTU that has to be encapsulated in IPsec, GTP or PPP, is no longer a 1500 byte MTU as far as the customer is concerned.

Any of these encapsulation techniques add overhead, which shrinks the MTU available to the end customer.

Keep in mind we’re going to be encapsulating our subscriber’s data in GTP before it’s transmitted across LTE/NR, and this means we’ll be adding:

  • 8 bytes for the GTP header
  • 8 bytes for the transport UDP header
  • 20 bytes for the transport IPv4 header
  • 14 bytes if our transport is using Ethernet

This means we’ve got 50 bytes of transmission / transport overhead. This will be important later on!

How do subscribers know what to use as MTU?

Typically when a subscriber buys a DSL service or HFC connection, they’ll either get a preconfigured router from their carrier, or they will be given a list of values to use that includes MTU.

LTE and 5G on the other hand tell us the value we should use.

Inside the Protocol Configuration Options in the NAS PDU, the UE requests the MTU and DNS server to be used, and is provided back from the network.

This MTU value is actually set on the MME, not the P-GW. As the MME doesn’t actually know the maximum MTU of the network, it’s up to the operator to configure this to be a value that represents the network.

Why this Matters for LTE & 5G Transmission

As we covered earlier, fragmentation is costly. If we’re fragmenting packets we are:

  • Wasting resources on our transmission network / core networks – as we fragment Subscriber packets it’s taking up compute resources and therefore limiting throughput
  • Wasting radio resources as additional overhead is introduced for fragmented packets, and additional RBs need to be scheduled to handle the fragmented packets

To test this I’ve setup a scenario in the lab, and we’ll look at the packet captures to see how the MTU is advertised, and see how big we can make our MTU on the subscriber side.

Information stored on USIM / SIM Card for LTE / EUTRAN / EPC - K key, OP/OPc key and SQN Sequence Number

Confidentiality Algorithms in 3GPP Networks: MILENAGE, XOR & Comp128

We’ve covered a fair bit on authentication in 3GPP networks, SIM cards, HSS / AuC, etc, but never actually looked at the Confidentiality Algorithms in use,

LTE USIM Authentication - Mutual Authentication of the Network and Subscriber

While we’ve already covered the inputs required by the authentication elements of the core network (The HSS in LTE/4G, the AuC in UMTS/3G and the AUSF in 5G) to generate an output, it’s worth noting that the Confidentiality Algorithms used in the process determines the output.

This means the Authentication Vector (Also known as an F1 and F1*) generated for a subscriber using Milenage Confidentiality Algorithms will generate a different output to that of Confidentiality Algorithms XOR or Comp128.

To put it another way – given the same input of K key, OPc Key (or OP key), SQN & RAND (Random) a run with Milenage (F1 and F1* algorithm) would yield totally different result (AUTN & XRES) to the same inputs run with a simple XOR.

Technically, as operators control the network element that generates the challenges, and the USIM that responds to them, it is an option for an operator to implement their own Confidentiality Algorithms (Beyond just Milenage or XOR) so long as it produced the same number of outputs. But rolling your own cryptographic anything is almost always a terrible idea.

So what are the differences between the Confidentiality Algorithms and which one to use?
Spoiler alert, the answer is Milenage.


Milenage is based on AES (Originally called Rijndael) and is (compared to a lot of other crypto implimentations) fairly easy to understand,

AES is very well studied and understood and unlike Comp128 variants, is open for anyone to study/analyse/break, although AES is not without shortcomings, it’s problems are at this stage, fairly well understood and mitigated.

There are a few clean open source examples of Milenage implementations, such as this C example from FreeBSD.


It took me a while to find the specifications for the XOR algorithm – it turns out XOR is available as an alternate to Milenage available on some SIM cards for testing only, and the mechanism for XOR Confidentiality Algorithm is only employed in testing scenarios, not designed for production.

Instead of using AES under the hood like Milenage, it’s just plan old XOR of the keys.

Osmocom have an implementation of this in their CN code, you can find here.

Defined under 3GPP TS 34.108


Comp128 was originally a closed source algorithm, with the maths behind it not publicly available to scrutinise. It is used in GSM A3 and A5 functions, akin to the F1 and F1* in later releases.

Due to its secretive nature it wasn’t able to be studied or analysed prior to deployment, with the idea that if you never said how your crypto worked no one would be able to break it. Spoiler alert; public weaknesses became exposed as far back as 1998, which led to Toll Fraud, SIM cloning and eventually the development of two additional variants, with the original Comp128 renamed Comp128-1, and Comp128-2 (stronger algorithm than the original addressing a few of its flaws) and Comp128-3 (Same as Comp128-2 but with a 64 bit long key generated).

Into the Future & 5G later releases

As options beyond just USIM authentication become available for authentication in 5G SA networks, additional algorithms can be used beyond EAP and AKA, but at the time of writing only TLS has been added. 5G adds SUCI and SUPI which provide a mechanism to keep the private identifier (IMSI) away from prying eyes (or antenna), which I’ve detailed in this post.

5G Subscriber Identifiers – SUCI & SUPI

The SUPI (Subscription Permanent Identifier) replaces the IMSI as the unique identifier for each Subscriber in 5G.

One of the issues with using IMSI in LTE/EUTRAN is there were a few occasions where the IMSI was sent over the clear – meaning the IMSIs of subscribers nearby could be revealed to anyone listening.

So what is a SUPI and what does it look like? Well, most likely it’ll look like an IMSI – 15 or 16 digits long, with the MCC/MNC as the prefix.

If you’re using a non-3GPP RAT it could be a RFC 4282 Network Access Identifier, but if it’s on a SIM card or in a Mobile Device, it’s probably exactly the same as the IMSI.

SUCI Subscription Concealed Identifier

Our SUPI is never sent over the air in the clear / plaintext, instead we rely on the SUCI (Subscription Concealed Identifier) for this, which replaces the GUTI/TMSI/IMSI for all plaintext transactions over the air.

Either the UE or the SIM generate the SUCI (if it’s done by the SIM it’s much slower), based on a set of parameters defined on the SIM.

The SUCI has to be generated by the UE or SIM in a way the Network can identify the SUPI behind the SUCI, but no one else can.

In LTE/EUTRAN this was done by the network randomly assigning a value (T-MSI / GUTI) and the network keeping track of which randomly assigned value mapped to which user, but initial attach and certain handovers revealed the real IMSI in the clear, so for 5G this isn’t an option.

So let’s take a look at how SUCI is calculated in a way that only the network can reveal the SUPI belonging to a SUCI.

The Crypto behind SUCI Calculation

As we’ll see further down, SUCI is actually made up of several values concatenated together. The most complicated of these values is the Protection Scheme Output, the cryptographically generated part of the SUCI that can be used to determine the SUPI by the network.

Currently 3GPP defines 3 “Protection Scheme Profiles” for calculating the SUCI.

Protection Scheme Identifier 1 – null-scheme

Does nothing. Doesn’t conceal the SUPI at all. If this scheme is used then the Protection Scheme Output is going to just be the SUPI, for anyone to sniff off the air.

Protection Scheme Identifier 2 & 3 – ECIES scheme profile A & B

The other two Protection Scheme Identifiers both rely on Elliptic Curve Integrated Encryption Scheme (ECIES) for generation.

This is better known as Elliptic Curve Encryption Scheme, it’s primarily used for Cryptography. Crypto is crazy complex, and I’m a mere mathematical mortal, but there’s a great post on the Cloudflare blog on the topic that touches on Elliptic Curve Encryption.

So if both Profile A & Profile B rely on Elliptic Curve Integrated Encryption Scheme, then what’s the difference between the two?

Well dear reader, the answer is semantics! There’s lots of parameters and variables that go into generating a resulting value from a cryptographic function, and Profile A & Profile B are just different parameters being used to generate the results.

For crypto nerds you can find the specifics in C.3.4.1 Profile A and C.3.4.1 Profile B outlined in 3GPP TS 33.501.

For non crypto nerds we just need to know this;

When the SIM is generating the SUCI the UE just asks for an identity by executing the GET IDENTITY command ADF against the SIM and uses the response as the SUCI.

When the UE is generating the SUCI, the UE gets the SUCI_Calc_Info EF contents from the SIM and extracts the Home Network Public Key from it’s reply. It uses this Home Network Public Key and a freshly created ephemeral public/private key pair to generate a SUCI value to use.

Creating the SUCI

After generating a Protection Scheme Output, we’ll need to add some extra info into it to make it useful.

The first digit of the SUCI is the SUPI type, a value of 0 denotes the value contained in the Protection Scheme Output is an IMSI, while 1 is used for Network Access Indicator for Non 3GPP access.

Next up we have the Home Network Identifier, which in a mobile environment is our PLMN (MCC/MCC).

Then a Routing Indicator, 1-4 digits long, is used with the Home Network Identifier to route the Authentication traffic to the UDM that contains that subscriber’s information, ie you may have MVNOs with their own UDM. If the routing indicator of 10 is assigned to the MVNOs SIMs then the AMF can be set to route traffic with a routing indicator of 10 to the UDM of the VMNO.

The Protection Scheme we covered earlier, with the 3 types of protection scheme (Null & two relying on Elliptic Curve Integrated Encryption Scheme).

Home Network Public Key Identifier identifies which Public Key was used to generate the Protection Scheme Output.

Finally we have the Protection Scheme Output which we covered generating in the previous session.

Usage in Signaling

The SUPI is actually rarely used beyond the initial attach to the network.

After authenticating to the network using AKA and the SUCI, in 5GC, like in LTE/EUTRAN, a shorter GUTI is used which further protects the subscriber’s identity and changes frequently.

My first 5G Core: Open5Gs and UERANSIM

Note: As this space develops so quickly I’ve refreshed the original post from November 2021 in March 2021 with updated instructions.

While 5G SA devices are still in their early stages, and 5G RAN hardware / gNodeBs are hard to come by, so today we’ll cover using UERANSIM to simulate UEs and 5G RAN, to put test calls through our 5GC.

Bringing your 5G Core Online

We’ll use Open5Gs for all the 5GC components, and install on any recent Ubuntu distribution.

Installation is nice and easy;

$ sudo apt update 
$ sudo apt install software-properties-common 
$ sudo add-apt-repository ppa:open5gs/latest 
$ sudo apt update 
$ sudo apt install open5gs

The first point of contact we’ll need to talk about is the AMF,

The AMF – the Access and Mobility Function is reached by the gNodeB over the N2 interface. The AMF handles our 5G NAS messaging, which is the messaging used by the UEs / Devices to request data services, manage handovers between gNodeBs when moving around the network, and authenticate to the network.

By default the AMF binds to a loopback IP, which is fine if everything is running on the same box, but becomes an issue for real gNodeBs or if we’re running UERANSIM on a different machine.

This means we’ll need to configure our AMF to bind to the IP of the machine it’s running on, by configuring the AMF in /etc/open5gs/amf.yaml, so we’ll change the ngap addr to bind the AMF to the machine’s IP, for me this is,

  - addr:

In the amf.conf there’s a number of things we can change and configure; such as the PLMN and network name, the NRF parameters, however for now we’ll keep it simple and leave everything else as default.

To allow the changes to take effect, we’ll restart the Open5GS AMF service to make our changes take effect;

$ sudo systemcl restart open5gs-amfd

Setting up the Simulator

We’re using UERANSIM as our UE & RAN Simulator, so we’ll need to get it installed. I’m doing this on an Ubuntu system as we’re using Snaps.

$ sudo apt update 
$ sudo apt upgrade 
$ sudo apt install make g++ libsctp-dev lksctp-tools 
$ iproute2 sudo snap install cmake --classic

With all the prerequisites installed we’ll clone the Git repository and make everything from source;

We’ll clone the Github repository, move into it and make from source.

$ git clone
$ make

Now we wait for everything to compile,

XKCD – Compiling

Once we’ve got the software installed we’ll need to put together the basic settings.

You should see these files in the /build/ directory and they should be executable.

Running the Simulator (UERANSIM)

UERANSIM has two key parts, like any RAN,

The first is the gNodeB, that connects to our AMF and handles subscriber traffic over our (simulated) radio link,

The other is our subscribers themselves – the UEs.

Both are defined and setup through config files in the config/ directory,

Configuring & Starting the gNodeB

While we’re not actually going to bring anything “on air” in the RF sense, we’ll still need to configure and start our gNodeB.

All the parameters for our gNodeB are set in the config/open5gs-gnb.yaml file,

Inside here we’ll need to set the the parameters of our simulated gNodeB, for us this means (unless you’ve changed the PLMN etc) just changing the Link IPs that the gNodeB binds to, and the IP of the AMFs (for me it’s – you’ll need to substitute these IPs with your own of course.

Now we should be able to start the gNodeB service and see the connection, let’s take a look,

We’ll start the gNodeB service from the UERANSIM directory by running the nr-gnb service with the config file we just configured in config/open5gs-gnb.yaml

$ build/nr-gnb -c config/open5gs-gnb.yaml

All going well you’ll see something like:

[2021-03-08 12:33:46.433] [ngap] [info] NG Setup procedure is successful

And if you’re running Wireshark you should see the NG-AP (N2) traffic as well;

If we tail the logs on the Open5GS AMF we should also see the connection too:

Configuring the UE Simulator

So with our gNodeB “On the air” next up we’ll connect a simulated UE to our simulated gNodeB.

We’ll leave the nr-gnb service running and open up a new terminal to start the UE with:

$ build/nr-gnb -c config/open5gs-gnb.yaml

But if you run it now, you’ll just see errors regarding the PLMN search failing,

So why is this? We need to tell our UE the IP of the gNodeB (In reality the UE would scan the bands to find a gNB to serve it, but we’re simulating hre).

So let’s correct this by updating the config file to point to the IP of our gNodeB, and trying again,

So better but not working, we see the RRC was released with error “FIVEG_SERVICES_NOT_ALLOWED”, so why is this?

A quick look at the logs on Open5Gs provides the answer,

Of course, we haven’t configured the subscriber in Open5Gs’s UDM/UDR.

So we’ll browse to the web interface for Open5GS HSS/UDR and add a subscriber,

We’ll enter the IMSI, K key and OP key (make sure you’ve selected OPc and not OP), and save. You may notice the values match the defaults in the Open5GS Web UI, just without the spaces.

Running the UE Simulator

So now we’ve got all this configured we can run the UE simulator again, this time as Sudo, and we should get a very different ouput;

$ build/nr-gnb -c config/open5gs-gnb.yaml

Now when we run it we should see the session come up, and a new NIC is present on the machine, uesimtun0,

We can now run commands like Ping and Curl and by specifying our special uesimtun0 interface, and the traffic will be encapsulated in GTP and pop out the other end.

Supporting UERANSIM

More advanced functionality is in the works though, so keep an eye on the UERANSIM GitHub page and contribute code if you can, and consider supporting them on Patreon if you can’t, they’re doing great work.

Open5GS – NRF Setup

We covered NRFs last week, but I thought I’d cover actually configuring the NRF on Open5GS,

We’ll first off need to install the NRF,

$ sudo apt update 
$ sudo apt install software-properties-common 
$ sudo add-apt-repository ppa:open5gs/latest 
$ sudo apt update 
$ sudo apt install open5gs

Next up we’ll need to configure the NRF on the domain “”, for this we’ll edit /etc/open5gs/nrf.conf and set the binding IP.

    - addr:
      port: 7777

Now for each Network Element we’re bringing online we’ll need to point it at our NRF’s address (or IP).

    - addr:
      port: 7777

But there’s another very similar section inside the definition file, but this defines which IP the NRF client will listen on,

And that’s it,

From the log in /var/log/open5gs/nrf.log you see connections coming in,

5GC: The Network Function Repository Function

The Problem

Mobile networks are designed to be redundant and resilient, with N+1 for everything.

Every network element connects to multiple other network elements.

The idea being the network is architected so a failure of any one network element will not impact service.

To take an LTE/EPC example, your eNodeBs connect to multiple MMEs, which in turn connect to multiple HSSs, multiple S-GWs, multiple EIRs, etc.
The problem is when each eNodeB connects to 3 MMEs, and you want to add a 4th MME, you have to go and reconfigure all the eNodeBs to point to the new MME, and all the HSSs to accept that MME as a new Diameter Peer, for example.

The more redundant you make the network, the harder it becomes to change.

This led to development of network elements like Diameter Routing Agents (DRAs) and DNS SRV for service discovery, but ultimately adding and removing network elements in previous generations of mobile core, involved changing a lot of config on a lot of different boxes.

The Solution

The NRF – Network Repository Function serves as a central repository for Network Functions (NFs) on the network.

In practice this means when you bring a new Network Function / Network Element online, you only need to point it at the NRF, which will tell it about other Network Functions on the network, register the new Network Function and let every other interested Network Function know about the new guy.

Take for example adding a new AMF to the network, after bringing it online the only bit of information the AMF really needs to start placing itself in the network, is the details of the NRF, so it can find everything it needs to know.

Our new AMF will register itself to the NRF, advertising what Network Functions it can offer (ie AMF service), and it’ll in turn be able to learn about what Network Functions it can consume – for example our AMF would need to know about the UDMs it can query data from.

It is one of the really cool design patterns usually seen in modern software, that 3GPP have adopted as part of the 5GC.

In Practice

Let’s go into a bit more detail and look at how it looks.

The NRF uses HTTP and JSON to communicate (anything not using ASN.1 is a winner), and looks familiar to anyone used to dealing with RESTful APIs.

Let’s take a look at how an AMF looks when registering to a NRF,

NF Register – Providing the NRF a profile for each NF

In order for the NRF to function it has to know about the presence of all the Network Functions on the network, and what they support. So when a new Network Function comes online, it’s got to introduce itself to the NRF.

It does this by providing a “Profile” containing information about the Network Functions it supports, IP Addresses, versions, etc.

Going back to our AMF example, the AMF sends a HTTP PUT request to our NRF, with a JSON payload describing the functions and capabilities of the AMF, so other Network Functions will be able to find it.

Let’s take a look at what’s in the JSON payload used for the NF Profile.

  • Each Network Function is identified by a UUID – nfInstanceId, in this example it’s value is “f2b2a934-1b06-41eb-8b8b-cb1a09f099af”
  • The nfType (Network Function type) is an AMF, and it’s IP Address is
  • The heartBeatTimer sets how often the network function (in this case AMF) sends messages to the NRF to indicate it’s still alive. This prevents a device registering to an NRF and then going offline, and the NRF not knowing.

The nfServices key contains an array of services and details of those services, in the below example the key feature is the serviceName which is namf-comm which means the Namf_Communication Service offered by the AMF.

The NRF files this info away for anyone who requests it (more on that later) and in response to this our NRF will indicate (hopefully) that it’s successfully created the entry in its internal database of Network Functions for our AMF, resulting in a HTTP 201 “Created” response back from the NRF to the AMF.

NRF StatusSubscribe – Subscribe & Notify

Simply telling the NRF about the presence of NFs is one thing, but it’s not much use if nothing is done with that data.

A Network Function can subscribe to the NRF to get updates when certain types of NFs enter/leave the network.

Subscribing is done by sending a HTTP POST with a JSON payload indicating which NFs we’re interested in.

Contents of a Subscription message to be notified of all AMFs joining the network

Whenever a Network Function registers on the NRF that related to the type that has been subscribed to, a HTTP POST is sent to each subscriber to let them know.

For example when a UDM registers to the network, our AMF gets a Notification with information about the UDM that’s just joined.

NRF Update – Updating NRF Profiles & Heartbeat

If our AMF wants to update its profile in the NRF – for example a new IP is added to our AMF, a HTTP PATCH request is sent with a JSON payload with the updated details, to the NRF.

The same mechanism is used as the Heartbeat / keepalive mechanism, to indicate the NRF is still there and working.


The NRF acts as a central repository used for discovery of neighboring network functions.

5GC for EPC Folks – Control Plane Signalling

As the standardisation for 5G-SA has been completed and the first roll outs are happening, I thought I’d cover the basic architecture of the 5G Core Network, for people with a background in EPC/SAE networks for 4G/LTE, covering the key differences, what’s the same and what’s new.

The AMFAuthentication & Mobility Function, serves much the same role as the MME in LTE/EPC/SAE networks.

Like the MME, the AMF only handles Control Plane traffic, and serves as the gatekeeper to the services on the network, connecting the RAN to the core, authenticating subscribers and starting data / PDN connections for the UEs.

While the MME connects to eNodeBs for RAN connectivity, the AMF connects to gNodeBs for RAN.

The Authentication Functions

In EPC the HSS had two functions; it was a database of all subscribers’ profile information and also the authentication centre for generating authentication vectors.

5GC splits this back into two network elements (Akin to the AuC and HLR in 2G/3G).

The UDM (Unified Data Management) provides the AMF with the subscriber profile information (allowed / barred services / networks, etc),

The AUSF (Authentication Server Function) provides the AMF with the authentication vectors for authenticating subscribers.

Like in UMTS/LTE USIMs are used to authenticate subscribers when connecting to the network, again using AKA (Authentication and Key Agreement) for mutual subscriber & network authentication.

Other authentication methods may be implemented, R16 defines 3 suporrted methods, 5G-AKA, EAP-AKA’, and EAP-TLS.

This opens the door for the 5GC to be used for non-mobile usage. There has been early talk of using the 5G architecture for fixed line connectivity as well as mobile, hence supporting a variety of authentication methods beyond classic AKA & USIMs. (For more info about Non-3GPP Access interworking look into the N3IWF)

The Mobility Functions

When a user connects to the network the AMF selects a SMF (Session Management Function) akin to a P-GW-C in EPC CUPS architecture and requests the SMF setup a connection for the UE.

This is similar to the S11 interface in EPC, however there is no S-GW used in 5GC, so would be more like if S11 were instead sent to the P-GW-C.

The SMF selects a UPF (Akin to the P-GW-C selecting a P-GW-U in EPC), which will handle this user’s traffic, as the UPF bridges external data networks (DNs) to the gNodeB serving the UE.

More info on how the UPF functions compared to it’s EPC counterparts can be found in this post.

Moving between cells / gNodeBs is handled in much the same way as done previously, with the path the UPF sends traffic to (N3 interface) updated to point to the IP of the new gNodeB.

Mobility between EPC & 5GC is covered in this post.

Connection Overview

When a UE attempts to connect to the network their signalling traffic (Using the N1 reference point between the UE and the AMF), is sent to the AMF.

an authentication challenge is issued as in previous generations.

Upon successful authentication the AMF signals the SMF to setup a session for the UE. The SMF selects a UPF to handle the user plane forwarding to the gNodeB serving the UE.

Key Differences

  • Functions handled by the MME in EPC now handled by AMF in 5GC
  • Functions of HSS now in two Network Functions – The UDM (Unified Data Management) and AUSF (Authentication Server Function)
  • Setting up data connections “flatter” (more info on the User Plane differences can be found here)
  • Non 3GPP access (Potentially used for fixed-line / non mobile networks)

See also: 5GC for EPC Folks – User Plane Traffic

5GC for EPC Folks – User Plane Traffic

As the standardisation for 5G-SA has been completed and the first roll outs are happening, I thought I’d cover the basic architecture of the 5G Core Network, for people with a background in EPC/SAE networks for 4G/LTE, covering the key differences, what’s the same and what’s new.

This posts focuses on the User Plane side of things, there’s a similar post I’ve written here on the Control Plane side of things.

UPF – User Plane Forwarding

The UPF bridges the external networks (DNs) to the gNodeB serving the UE by encapsulating the traffic into GTP, which has been used in every network since GSM.

Like the P-GW the UPF takes traffic destined to/from external networks and passes it to/from subscribers.

In 5GC these external networks are now referred to as “DN” – Data Networks, instead of by the SGi reference point.

In EPC the Serving-Gateway’s intermediate function of routing traffic to the correct eNB is removed and instead this is all handled by the UPF, along with buffering packets for a subscriber in idle mode.

The idea behind this, is that by removing the S-GW removes extra hops / latency in the network, and allows users to be connected to the best UPF for their needs, typically one located close to the user.

However, there are often scenarios where an intermediate function is required – for example wanting to anchor a session to keep an IP Address allocated to one UPF associated with a user, while they move around the network. In this scenario a UPF can act as an “Session Anchor” (Akin to a P-GW), and pass through “Intermediate UPFs” (Like S-GWs).

Unlike the EPCs architecture, there is no limit to how many I-UPFs can be chained together between the Session Anchoring UPF and the gNB, and this chaining of UPFs allows for some funky routing options.

The UPF is dumb by design. The primary purpose is just to encapsulate traffic destined from external networks to subscribers into GTP-U packets and forward them onto the gNodeB serving that subscriber, and the same in reverse. Do one thing and do it well.

SMF – Session Management Function

So with dumb UPFs we need something smarter to tell them what to do.

Control of the UPFs is handled by the SMF – Session Management Function, which signals using PFCP down to the UPFs to tell them what to do in terms of setting up connections.

While GTP-U is used for handling user traffic, control plane traffic no longer uses GTPv2-C. Instead 5GC uses PFCP – Packet Forwarding Control Protocol. To get everyone warmed up to Control & User Plane separation 3GPP introduced as seen in CUPS into the EPC architecture in Release 14.

This means the interface between the SMF and UPF (the N4 interface) is more or less the same as the interface between a P-GW-C and a P-GW-U seen in CUPS.

When a subscriber connects to the network and has been authenticated, the AMF (For more info on the AMF see the sister post to this topic covering Control Plane traffic) requests the SMF to setup a connection for the subscriber.

Interworking with EPC

For deployments with an EPC and 5GC interworking between the two is of course required.

This is achieved first through the implementation of CUPS (Control & User Plane Separation) on the EPC, specifically splitting the P-GW into a P-GW-C for handing the Control Plane signalling (GTPv2c) and a P-GW-U for the User Plane traffic encapsulated into GTP.

The P-GW-C and P-GW-U communications using PFCP are essentially the same as the N4 interface (between the SMF and the UPF) so the P-GW-U is able to act as a UPF.

This means handovers between the two RATs / Cores is seamless as when moving from an LTE RAT and EPC to a 5G RAT and 5G Core, the same UPF/P-GW-U is used, and only the Control Plane signalling around it changes.

When moving from LTE to 5G RAT, the P-GW-C is replaced by the SMF,
When moving from 5G RAT to LTE, the SMF is replaced by the P-GW-C.
In both scenarios user plane traffic takes the same exit point to external Data Networks (SGi interface in EPC / N6 interface in 5GC).

Interfaces / Reference Points

N3 Interface

N3 interface connects the gNodeB user plane to the UPF, to transport GTP-U packets.

This is a User Plane interface, and only transports user plane traffic.

This is akin to the S1-UP interface in EPC.

N4 Interface

N4 interface connects the Session Management Function (SMF) control plane to the UPF, to setup, modify and delete UPF sessions.

It is a control plane interface, and does not transport User Plane traffic.

This interface relies on PFCP – Packet Forwarding Control Protocol.

This is akin to the SxB interface in EPC with CUPS.

N6 Interface

N6 interface connects the UPF to External Data Networks (DNs), taking packets destined for Subscribers and encapsulating them into GTP-U packets.

This is a User Plane interface, and only transports user plane traffic.

This is akin to the SGi interface in EPC.

N9 Interface

When Session Anchoring is used, and Intermediate-UPFs are used, the connection between these UPFs uses the N9 interface.

This is only used in certain scenarios – the preference is generally to avoid unnecessary hops, so Intermediate-UPF usage is to be avoided where possible.

As this is a User Plane interface, it only transports user plane traffic.

When used this would be akin to the S5 interface in EPC.

N11 Interface

SMFs need to be told when to setup / tear down connections, this information comes from the AMF via the N11 interface.

As this is a Control Plane interface, it only transports control plane traffic.

This is similar to the S11 interface between the MME and the S-GW in EPC, however it would be more like the S11 if the S11 terminated on the P-GW.