Category Archives: LTE

3GPP Long Term Evolution (4G)

Diameter-User-Authorization-Request-Command-Code-300-Packet-Capture

Diameter and SIP: User-Authorization-Request/Answer

These posts focus on the use of Diameter and SIP in an IMS / VoLTE context, however these practices can be equally applied to other networks.

The Diameter User-Authorization-Request and User-Authorization-Answer commands are used as the first line of authorization of a user and to determine which Serving-CSCF to forward a request to.

Basics

When a SIP Proxy (I-CSCF) receives an incoming SIP REGISTER request, it sends a User-Authorization-Request to a Diameter server to confirm if the user exists on the network, and which S-CSCF to forward the request to.

When the Diameter server receives the User-Authorization-Request it looks at the User-Name (1) AVP to determine if the Domain / Realm is served by the Diameter server and the User specified exists.

Assuming the user & domain are valid, the Diameter server sends back a User-Authorization-Answer, containing a Server-Capabilities (603) AVP with the Server-Name of the S-CSCF the user will be served by.

I always find looking at the packets puts everything in context, so here’s a packet capture of both the User-Authorization-Request and the User-Authorization-Answer.

First Registration

If this is the first time this Username / Domain combination (Referred to in the RFC as an AOR – Address of Record) is seen by the Diameter server in the User-Authorization-Request it will allocate a S-CSCF address for the subscriber to use from it’s pool / internal logic.

The Diameter server will store the S-CSCF it allocated to that Username / Domain combination (AoR) for subsequent requests to ensure they’re routed to the same S-CSCF.

The Diameter server indicates this is the first time it’s seen it by adding the DIAMETER_FIRST_REGISTRATION (2001) AVP to the User-Authorization-Answer.

Subsequent Registration

If the Diameter server receives another User-Authorization-Request for the same Username / Domain (AoR) it has served before, the Diameter server returns the same S-CSCF address as it did in the first User-Authorization-Answer.

It indicates this is a subsequent registration in much the same way the first registration is indicated, by adding an DIAMETER_SUBSEQUENT_REGISTRATION (2002) AVP to the User-Authorization-Answer.

User-Authorization-Type (623) AVP

An optional User-Authorization-Type (623) AVP is available to indicate the reason for the User-Authorization-Request. The possible values / reasons are:

  • Creating / Updating / Renewing a SIP Registration (REGISTRATION (0))
  • Establishing Server Capabilities & Registering (CAPABILITIES (2))
  • Terminating a SIP Registration (DEREGISTRATION (1))

If the User-Authorization-Type is set to DEREGISTRATION (1) then the Diameter server returns the S-CSCF address in the User-Authorization-Answer and then removes the S-SCSF address it had associated with the AoR from it’s own records.

Other Diameter Cx (IMS) Calls

User-Authorization-Request / User-Authorization-Answer
Server-Assignment-Request / Server-Assignment-Answer
Location-Info-Request / Location-Info-Answer
Multimedia-Auth-Request / Multimedia-Auth-Answer
Registration-Termination-Request / Registration-Termination-Answer
Push-Profile-Request / Push-Profile-Answer

References:

3GPP Specification #: 29.229

RFC 4740 – Diameter Session Initiation Protocol (SIP) Application

Diameter - Server Assignment Answer - All

Diameter and SIP: Server-Assignment-Request/Answer

These posts focus on the use of Diameter and SIP in an IMS / VoLTE context, however these practices can be equally applied to other networks.

The Server-Assignment-Request/Answer commands are used so a SIP Server can indicate to a Diameter server that it is serving a subscriber and pull the profile information of the subscriber.

Basics:

The RFC’s definition is actually pretty succinct as to the function of the Server-Assignment Request/Answer:

The main functions of the Diameter SAR command are to inform the Diameter server of the URI of the SIP server allocated to the user, and to store or clear it from the Diameter server.

Additionally, the Diameter client can request to download the user profile or part of it.

RFC 4740 – 8.3

The Server-Assignment-Request/Answer commands are sent by a S-CSCF to indicate to the Diameter server that it is now serving a specific subscriber, (This information can then be queried using the Location-Info-Request commands) and get the subscriber’s profile, which contains the details and identities of the subscriber.

Typically upon completion of a successful SIP REGISTER dialog (Multimedia-Authentication Request), the SIP Server (S-CSCF) sends the Diameter server a Server-Assignment-Request containing the SIP Username / Domain (referred to as an Address on Record (SIP-AOR) in the RFC) and the SIP Server (S-CSCF)’s SIP-Server-URI.

The Diameter server looks at the SIP-AOR and ensures there are not currently any active SIP-Server-URIs associated with that AoR. If there are not any currently active it then stores the SIP-AOR and the SIP-Server-URI of the SIP Server (S-CSCF) serving that user & sends back a Server-Assignment-Answer.

For most request the Subscriber’s profile is also transfered to the S-SCSF in the Server-Assignment-Answer command.

SIP-Server-Assignment-Type AVP

The same Server-Assignment-Request command can be used to register, re-register, remove registration bindings and pull the user profile, through the information in the SIP-Server-Assignment-Type AVP (375),

Common values are:

  • NO_ASSIGNMENT (0) – Used to pull just the user profile
  • REGISTRATION (1) – Used for first registration
  • RE_REGISTRATION (2) – Updating / renewing registration
  • USER_DEREGISTRATION (5) – User has deregistered

Complete list of values available here.

Cx-User-Data AVP (User Profile)

The Cx-User-Data profile contains the subscriber’s profile from the Diameter server in an XML formatted dataset, that is contained as part of the Server-Assignment-Answer in the Cx-User-Data AVP (606).

The profile his tells the S-CSCF what services are offered to the subscriber, such as the allowed SIP Methods (ie INVITE, MESSAGE, etc), and how to handle calls to the user when the user is not registered (ie send calls to voicemail if the user is not there).

There’s a lot to cover on the user profile which we’ll touch on in a later post.

Other Diameter Cx (IMS) Calls

User-Authorization-Request / User-Authorization-Answer
Server-Assignment-Request / Server-Assignment-Answer
Location-Info-Request / Location-Info-Answer
Multimedia-Auth-Request / Multimedia-Auth-Answer
Registration-Termination-Request / Registration-Termination-Answer
Push-Profile-Request / Push-Profile-Answer

References:

3GPP Specification #: 29.229

RFC 4740 – Diameter Session Initiation Protocol (SIP) Application

Diameter and SIP: Location-Info-Request / Answer

These posts focus on the use of Diameter and SIP in an IMS / VoLTE context, however these practices can be equally applied to other networks.

The Location-Information-Request/Answer commands are used so a SIP Server query a Diameter to find which P-CSCF a Subscriber is being served by

Basics:

The RFC’s definition is actually pretty succinct as to the function of the Server-Assignment Request/Answer:

The Location-Info-Request is sent by a Diameter Multimedia client to a Diameter Multimedia server in order to request name of the server that is currently serving the user.Reference: 29.229-

The Location-Info-Request is sent by a Diameter Multimedia client to a Diameter Multimedia server in order to request name of the server that is currently serving the user.

Reference: TS 29.229

The Location-Info-Request commands is sent by an I-CSCF to the HSS to find out from the Diameter server the FQDN of the S-CSCF serving that user.

The Public-Identity AVP (601) contains the Public Identity of the user being sought.

Here you can see the I-CSCF querying the HSS via Diameter to find the S-CSCF for public identity 12722123

The Diameter server sends back the Location-Info-Response containing the Server-Name AVP (602) with the FQDN of the S-CSCF.

Packet Capture

I’ve included a packet capture of these Diameter Commands from my lab network which you can find below.

Other Diameter Cx (IMS) Calls

User-Authorization-Request / User-Authorization-Answer
Server-Assignment-Request / Server-Assignment-Answer
Location-Info-Request / Location-Info-Answer
Multimedia-Auth-Request / Multimedia-Auth-Answer
Registration-Termination-Request / Registration-Termination-Answer
Push-Profile-Request / Push-Profile-Answer

References:

3GPP Specification #: 29.229

RFC 4740 – Diameter Session Initiation Protocol (SIP) Application

Screenshot of packet capture of Diameter Multimedia-Auth-Request (Diameter Command Code 303) used for IMS authentication

Diameter and SIP: Multimedia-Authentication-Request/Answer

These posts focus on the use of Diameter and SIP in an IMS / VoLTE context, however these practices can be equally applied to other networks.

The Multimedia-Authentication-Request/Answer commands are used to Authenticate subscribers / UAs using a variety of mechanisms such as straight MD5 and AKAv1-MD5.

Basics:

When a SIP Server (S-CSCF) receives a SIP INVITE, SIP REGISTER or any other SIP request, it needs a way to Authenticate the Subscriber / UA who sent the request.

We’ve already looked at the Diameter User-Authorization-Request/Answer commands used to Authorize a user for access, but the Multimedia-Authentication-Request / Multimedia-Authentication-Answer it used to authenticate the user.

The SIP Server (S-CSCF) sends a Multimedia-Authentication-Request to the Diameter server, containing the Username of the user attempting to authenticate and their Public Identity.

The Diameter server generates “Authentication Vectors” – these are Precomputed cryptographic challenges to challenge the user, and the correct (“expected”) responses to the challenges. The Diameter puts these Authentication Vectors in the 3GPP-SIP-Auth-Data (612) AVP, and sends them back to the SIP server in the Multimedia-Authentication-Answer command.

The SIP server sends the Subscriber / UA a SIP 401 Unauthorized response to the initial request, containing a WWW-Authenticate header containing the challenges.

SIP 401 Response with WWW-Authenticate header populated with values from Multimedia-Auth-Answer

The Subscriber / UA sends back the initial request with the WWW-Authenticate header populated to include a response to the challenges. If the response to the challenge matches the correct (“expected”) response, then the user is authenticated.

I always find it much easier to understand what’s going on through a packet capture, so here’s a packet capture showing the two Diameter commands,

Note: There is a variant of this process allows for stateless proxies to handle this by not storing the expected authentication values sent by the Diameter server on the SIP Proxy, but instead sending the received authentication values sent by the Subscriber/UA to the Diameter server to compare against the expected / correct values.

The Cryptography

The Cryptography for IMS Authentication relies on AKAv1-MD5 which I’ve written about before,

Essentially it’s mutual network authentication, meaning the network authenticates the subscriber, but the subscriber also authenticates the network.

LTE USIM Authentication - Mutual Authentication of the Network and Subscriber

Other Diameter Cx (IMS) Calls

User-Authorization-Request / User-Authorization-Answer
Server-Assignment-Request / Server-Assignment-Answer
Location-Info-Request / Location-Info-Answer
Multimedia-Auth-Request / Multimedia-Auth-Answer
Registration-Termination-Request / Registration-Termination-Answer
Push-Profile-Request / Push-Profile-Answer

References:

3GPP Specification #: 29.229

RFC 4740 – Diameter Session Initiation Protocol (SIP) Application

Connecting any 3rd Party HSS to Open5GS MME

You may want to connect Open5GS’ MME to a different Home Subscriber Server (HSS),

To do it we need a few bits of information:

  • The Domain Name of the HSS
  • The Realm of the HSS
  • The IP of the HSS
  • The Transport Used (TCP/SCTP)
  • If TLS is used

With these bits of information we can go about modifying the Open5GS MME config to talk to our different HSS.

Edit FreeDiameter Config

The config for the Open5GS MME’s Diameter peers is handled by the FreeDimaeter library,

You can find it’s config files in:

/etc/freediameter/mme.conf

We’ll start by changing the realm to match the realm of the HSS and the identity to match the identity configured as the MME peer on the HSS.

We’ll next set the ListenOn address to be a reachable IP address isntead of just a loopback address,

If you’re using TLS you’ll need to put your certificates and private key files into the TLS config,

Finally we’ll put our HSS details in the Peer Configuration;

Once all this is done we’ll need to restart our MME and you should see the Diameter Capabilities Exchange / Answer commands between the HSS and the MME if all was successful,

systemctl restart open5gs-mmed

In the /var/log/open5gs/mme.log I can now see:

05/11 23:25:46.896: [app] INFO: MME initialize…done (../src/mme/app-init.c:33)
05/11 23:25:46.898: [diam] INFO: CONNECTED TO 'hss.nickexamplenet' (SCTP,soc#15): (../lib/diameter/common/logger.c:108)

And that’s it! We’re connected to an external HSS.

Through the freeDiameter config file you can specify multiple ConnectPeer() entries to connect to multiple HSS (like a pool of them), and requests will be distributed evenly between them.

iPhone connecting to SRS LTE eNodeB SDR

srsLTE Install for BladeRF & LimeSDR on Debian / Ubuntu

Note: I’m running version 19.12.0 which I installed from the repos due to issues with 20.4.0 (latest when I wrote this) and stability on LimeSDR.

I wrote the other day about installing SRS LTE stack,

But installing it is one thing, meeting all the requirements to use it with your SDR hardware turns out to be another whole thing all together.

srsENB is a software defined eNodeB, allowing you to use a Software Defined Radio to serve as an eNodeB, UE and a few other utilities.

SRS’ implementation of the eNB is supposed to be 3GPP R10 compliant and supports eMBMS to boot.

Meeting Dependencies

Installing prerequisites

I’m using a LimeSDR, but these instructions also for for the BladeRF. I found the frequency stability of my BladeRF X40 wasn’t great, meaning when running SRS’s eNodeB the cell wasn’t visible to my UE.

sudo apt install tree vim git g++ make cmake pkg-config python-numpy swig libi2c-dev libusb-1.0-0-dev libfftw3-dev libmbedtls-dev libboost-program-options-dev libconfig++-dev libsctp-dev gnuradio

Install SoapySDR from Source

git clone https://github.com/pothosware/SoapySDR.git 
pushd SoapySDR
git checkout tags/soapy-sdr-0.7.2 -b soapy-sdr-0.7.2
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig
popd

Install LimeSuite

You can skip this if you’re using a BladeRF

git clone https://github.com/myriadrf/LimeSuite.git 
pushd LimeSuite
#git checkout tags/v19.04.0 -b v19.04.0
mkdir builddir
cd builddir
cmake ..
make
sudo make install
sudo ldconfig
cd ../udev-rules
sudo sh ./install.sh
popd

Install BladeRF

You can skip this if using a LimeSDR

git clone https://github.com/Nuand/bladeRF.git
pushd bladeRF/host/
mkdir build
cd build/
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DINSTALL_UDEV_RULES=ON -DBLADERF_GROUP=plugdev ..
make
sudo make install
sudo ldconfig
sudo mkdir -p /etc/Nuand/bladeRF/
sudo wget https://www.nuand.com/fpga/hostedx40-latest.rbf --output-document /etc/Nuand/bladeRF/hostedx40.rbf
popd


git clone https://github.com/pothosware/SoapyBladeRF.git
pushd SoapyBladeRF
mkdir build
cd build
cmake ..
make
sudo make install
popd

Install SRS GUI

(Optional but makes life easier and has to be done prior to installing SRSLTE)

sudo apt-get install libboost-system-dev libboost-test-dev libboost-thread-dev libqwt-qt5-dev qtbase5-dev
git clone https://github.com/srsLTE/srsGUI.git
pushd srsGUI
mkdir build
cd build
cmake ..
make
sudo make install
popd

Install SRSLTE (SRSenb & SRSue)

pushd srsLTE
mkdir build 
cd build 
cmake ../ 
make 
make test 
sudo make install 
sudo ldconfig 
sudo ./srslte_install_configs.sh service 
popd
SMS over SGi interface on Open5GS MME and OsmoMSC

Sending SMS in Open5GS LTE Networks using the SGs Interface and OsmoMSC with SMSoS

We recently covered Circuit Switched fallback between LTE EUTRAN and GSM GERAN, and the SGs interface between the MME and the MSC.

One nifty feature of this interface is that you can send SMS using the MSC to switch the SMS traffic and the LTE/EUTRAN to transfer the messaging.

This means you don’t need Circuit Switched Fallback to send or receive SMS on LTE.

I assume this functionality was added to avoid the signalling load of constantly changing RAN technologies each time a subscriber sent or received an SMS, but I couldn’t find much about it’s history.

In order to get this to work you’ll essentially need the exact same setup I outlined in my CSFB example (Osmo-MSC, Osmo-STP, Osmo-HLR populated with the IMSI and MSISDN values you want to use for SMS), although you won’t actually need a GERAN / GSM radio network.

Once that’s in place you can just send SMS between subscribers,

Plus from the VTY terminal of OsmoMSC you can send SMS too:

OsmoMSC# subscriber msisdn 61487654321 sms sender msisdn 61412341234 send Hello World
Using the SGs interface for Circuit Switched Fallback (CSFB) Calls from LTE falling back to GSM

OsmoMSC and Open5GS MME – SGs Interface for InterRAT Handover & SMS

I’ve talked about how LTE’s EUTRAN / EPC has no knowledge about voice calls or SMS and instead relies on IMS/VoLTE for these services.

Circuit Switched Fallback allows UEs to use a 2G or 3G network (Circuit Switched network) if their device isn’t connected to the IMS network to make calls as the 2G/3G network can handle the voice call or SMS routing via the Mobile Switching Center in the 2G/3G network.

However for incoming calls destined to the UE (Mobile Terminated) the MSC needs a way to keep track of which MME is serving the UE so it can get a message to the MME and the MME can relay it to the UE, to tell it to drop to a 2G or 3G network (Circuit Switched network).

The signalling between the MME (In the LTE EPC) and the MSC (In the GSM/UTRAN core) is done over the SGs interface.

While the SGs interface is primarily for managing user location state across multiple RAN types, it’s got a useful function for sending SMS over SGi, allowing users on an LTE RAN to send SMS via the MSC of the 2G/3G network (GSM/UTRAN core).

How it Works:

When a UE connects to the LTE RAN (EUTRAN) the MME signals the GSM/UMTS MSC with an SGsAP-LOCATION-UPDATE-REQUEST,

This request includes the IMSI of the subscriber that just attached and the FQDN of the MME serving that UE.

The MSC now knows that IMSI 001010000000003 is currently on LTE RAN served by MME mmec01.mmegi0002.mme.epc.mnc001.mcc001.3gppnetwork.org,

If a call or SMS comes into the MSC destined for the MSISDN of that IMSI, the MSC can page the UE on the LTE RAN to tell it to do an inter-RAN handover to GSM/UMTS.

Setting it Up

In order to get this working you’ll need OsmoMSC in place, your subscribers to exist on OsmoHLR and the LTE HSS – For example Open5GS-HSS.

If you’re not familiar with OsmoMSC or the Osmocom stack I did a series of posts covering them you can find here. If you want to get this setup I’d suggest following the posts on installing the Osmocom Software, setting up the MSC, the STP and the HLR.

Once you’ve done that the additional config on OsmoMSC is fairly simple, we just define a new SGs interface to listen on:

OsmoMSC Config:

sgs
  local-port 29118
  local-ip 0.0.0.0
  vlr-name vlr.msc001.mnc001.mcc001.3gppnetwork.org
end

On the Open5GS side we’ve got to include the SGs info the MME config. Keep in mind the Tracking Area Code (TAC) in LTE must exist as the Location Area code (LAC) in GSM, here’s an extract of the MME section of YAML config in the Open5GS MME config:

mme:
    freeDiameter: /etc/freeDiameter/mme.conf
    s1ap:
    gtpc:

    sgsap:
      addr: 10.0.1.9
      map:
        tai:
          plmn_id:
            mcc: 001
            mnc: 01
          tac: 7
        lai:
          plmn_id:
            mcc: 001
            mnc: 01
          lac: 7



    gummei: 
      plmn_id:
        mcc: 001
        mnc: 01
      mme_gid: 2
      mme_code: 1
    tai:
      plmn_id:
        mcc: 001
        mnc: 01
      tac: 7
    security:
        integrity_order : [ EIA1, EIA2, EIA0 ]
        ciphering_order : [ EEA0, EEA1, EEA2 ]
    network_name:
        full: Open5GS
sgw:
    gtpc:
      addr: 127.0.0.2
      addr: 10.0.1.252

pgw:
    gtpc:
      addr:
        - 127.0.0.3
        - ::1

Neighbours Configured

The EUTRAN will need to advertise the presence of it’s GERAN neighbours and vise-versa so the UE/terminals know what ARFCN to move to so they don’t need to scan for the presence of other RATs when performing the handover.

Setting this up will depend on your eNB / BSC and goes beyond the scope of this post.

I’ll cover setting up neighbours in a later post as it’s a big topic.

If you don’t have neighbours configured, the handover will still work but will be much slower as the UE will have to scan to find the serving cell it’s reselecting to.

Example Packet Capture

Decoding MAC LTE Frames in Wireshark

Working with LTE MAC traces in Wireshark

I recently pulled MAC layer traces off an eNB and wanted to view them,

In Wireshark this shows up as raw data, and there’s no option to decode as LTE MAC from the Decode As menu.

Instead you’ve got to go to Preferences -> Protocols and select DLT_USER and then edit the encapsulation table.

For DLT_147 enter:

mac-lte-framed

Now you’ll have your MAC frames decoded:

On top of this there’s also now the option to run analysis on these traces,

By selecting Telephony -> LTE -> MAC Statistics you’re able to view stats for each RNTI connected to the eNB.

I’ve attached a copy of my trace for reference.

Kamailio Proxy-CSCF Pull

I had a few headaches getting the example P-CSCF example configs from the Kamailio team to run, recent improvements with the IPsec support and code evolution meant that the example config just didn’t run.

So, after finally working out the changes I needed to make to get Kamailio to function as a P-CSCF, I took the plunge and made my first pull request on the Kamailio project.

And here it is!

https://github.com/kamailio/kamailio/pull/2203

It’s now in the master branch, so if you want to setup a P-CSCF using Kamailio, give it a shot, as the example config finally works!

Multi Operator Core-Networks (MOCN) for RAN Sharing

MOCN is one of those great concepts I’d not really come across,

Multi-tenancy on the RAN side of the network, allowing an eNB to broadcast multiple PLMN IDs (MCC/MNC) in the System Information Block (SIB).

It allows site sharing not just on the tower itself, but site sharing on the RAN side, allowing customers of MNO A to see themselves connected to MNO A, and customers from MNO B see themselves as connected to MNO B, but they’re both connected to the same RAN hardware.

Setup in my lab was a breeze; your RAN hardware will probably be different.

In terms of signaling it’s a standard S1AP Setup Request except with multiple broadcast PLMN keys:

Now when I run a manual cell selection on my UE I can see the PLMN 460/11 as well as the Open5gs 00101 PLMN:

Ansible for Scaling and Deployment of Evolved Packet Core NEs

There’s always lots of talk of Network Function Virtualization (NFV) in the Telco space, but replacing custom hardware with computing resources is only going to get you so far, if every machine has to be configured manually.

Ansible is a topic I’ve written a little bit about in terms of network automation / orchestration.

I wanted to test limits of Open5gs EPC, which led me to creating a lot of Packet Gateways, so I thought I’d share a little Ansible Playbook I wrote for deploying P-GWs.

It dynamically sets the binding address and DHCP servers, and points to each PCRF in the defined pool.

You can obviously build upon this too, creating another playbook to deploy PCRFs, MMEs and S-GWs will allow you to reference the hosts in each group to populate the references.

The Playbook

---
- name: Install & configure Open5GS EPC (P-GW)

  hosts: epc

  become: yes
  become_method: sudo

  vars:
    dns_servers: ['8.8.8.8','1.1.1.1']
    diameter_realm: 'nickvsnetworking.com'
    pcrf_hosts: ['pcrf1.nickvsnetworking.com', 'pcrf2.nickvsnetworking.com']
  tasks:
    - name: Set Hostname to {{inventory_hostname}}
      hostname:
        name: "{{inventory_hostname}}"
      register: rebootrequired

    - name: Updating hotnamectl
      command: "hostnamectl set-hostname {{inventory_hostname}}"
      become: True
      become: True
      when: rebootrequired.changed

    - name: Reboot VM due to Hostname Change
      reboot:
        reboot_timeout: 180
      when: rebootrequired.changed

    - name: Add Software common
      apt:
        name: software-properties-common

    - name: Add Repository
      apt_repository:
        repo: ppa:open5gs/latest

    - name: Install Open5gs P-GW
      apt:
        update_cache: true
        name: open5gs-pgw

    - name: Fill in GTP Addresses in Config
      template:
        src: pgw.yaml.j2
        dest: /etc/open5gs/pgw.yaml
        backup: true
      register: config_changed

    - name: Fill in P-GW Diameter Config
      template:
        src: pgw.conf.j2
        dest: /etc/freeDiameter/pgw.conf
        backup: true
      register: config_changed


    - name: Restart P-GW Service if Config Changed
      service:
        name: open5gs-pgwd
        state: restarted
      when: config_changed.changed

Jinja2 Template

P-GW Config (pgw.yaml.jn2)

logger:
    file: /var/log/open5gs/pgw.log

parameter:

pgw:
    freeDiameter: /etc/freeDiameter/pgw.conf
    gtpc:
      - addr: {{hostvars[inventory_hostname]['ansible_default_ipv4']['address']}}

    gtpu:
      - addr: {{hostvars[inventory_hostname]['ansible_default_ipv4']['address']}}

    ue_pool:
      - addr: 45.45.0.1/16
      - addr: cafe::1/64
    dns:
{% for dns in dns_servers %}
      - {{ dns }}
{% endfor %}

Diameter Config (pgw.conf.j2)

# This is a sample configuration file for freeDiameter daemon.

# Most of the options can be omitted, as they default to reasonable values.
# Only TLS-related options must be configured properly in usual setups.

# It is possible to use "include" keyword to import additional files
# e.g.: include "/etc/freeDiameter.d/*.conf"
# This is exactly equivalent as copy & paste the content of the included file(s)
# where the "include" keyword is found.


##############################################################
##  Peer identity and realm

# The Diameter Identity of this daemon.
# This must be a valid FQDN that resolves to the local host.
# Default: hostname's FQDN
#Identity = "aaa.koganei.freediameter.net";
Identity = "{{ inventory_hostname  }}.{{ diameter_realm }}";

# The Diameter Realm of this daemon.
# Default: the domain part of Identity (after the first dot).
#Realm = "koganei.freediameter.net";
Realm = "{{ diameter_realm }}";
##############################################################
##  Transport protocol configuration

# The port this peer is listening on for incoming connections (TCP and SCTP).
# Default: 3868. Use 0 to disable.
#Port = 3868;

# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP).
# See TLS_old_method for more information about TLS flavours.
# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter.
# Default: 5868. Use 0 to disable.
#SecPort = 5868;

# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed
# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the
# CER/CEA exchange on a dedicated secure port.
# This parameter only affects outgoing connections.
# The setting can be also defined per-peer (see Peers configuration section).
# Default: use RFC6733 method with separate port for TLS.
#TLS_old_method;

# Disable use of TCP protocol (only listen and connect over SCTP)
# Default : TCP enabled
#No_TCP;

# Disable use of SCTP protocol (only listen and connect over TCP)
# Default : SCTP enabled
#No_SCTP;
# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option.

# Prefer TCP instead of SCTP for establishing new connections.
# This setting may be overwritten per peer in peer configuration blocs.
# Default : SCTP is attempted first.
#Prefer_TCP;

# Default number of streams per SCTP associations.
# This setting may be overwritten per peer basis.
# Default : 30 streams
#SCTP_streams = 30;

##############################################################
##  Endpoint configuration

# Disable use of IP addresses (only IPv6)
# Default : IP enabled
#No_IP;

# Disable use of IPv6 addresses (only IP)
# Default : IPv6 enabled
#No_IPv6;

# Specify local addresses the server must bind to
# Default : listen on all addresses available.
#ListenOn = "202.249.37.5";
#ListenOn = "2001:200:903:2::202:1";
#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
ListenOn = "{{hostvars[inventory_hostname]['ansible_default_ipv4']['address']}}";


##############################################################
##  Server configuration

# How many Diameter peers are allowed to be connecting at the same time ?
# This parameter limits the number of incoming connections from the time
# the connection is accepted until the first CER is received.
# Default: 5 unidentified clients in paralel.
#ThreadsPerServer = 5;

##############################################################
##  TLS Configuration

# TLS is managed by the GNUTLS library in the freeDiameter daemon.
# You may find more information about parameters and special behaviors
# in the relevant documentation.
# http://www.gnu.org/software/gnutls/manual/

# Credentials of the local peer
# The X509 certificate and private key file to use for the local peer.
# The files must contain PKCS-1 encoded RSA key, in PEM format.
# (These parameters are passed to gnutls_certificate_set_x509_key_file function)
# Default : NO DEFAULT
#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
TLS_Cred = "/etc/freeDiameter/pgw.cert.pem", "/etc/freeDiameter/pgw.key.pem";

# Certificate authority / trust anchors
# The file containing the list of trusted Certificate Authorities (PEM list)
# (This parameter is passed to gnutls_certificate_set_x509_trust_file function)
# The directive can appear several times to specify several files.
# Default : GNUTLS default behavior
#TLS_CA = "<file.PEM>";
TLS_CA = "/etc/freeDiameter/cacert.pem";

# Certificate Revocation List file
# The information about revoked certificates.
# The file contains a list of trusted CRLs in PEM format. They should have been verified before.
# (This parameter is passed to gnutls_certificate_set_x509_crl_file function)
# Note: openssl CRL format might have interoperability issue with GNUTLS format.
# Default : GNUTLS default behavior
#TLS_CRL = "<file.PEM>";

# GNU TLS Priority string
# This string allows to configure the behavior of GNUTLS key exchanges
# algorithms. See gnutls_priority_init function documentation for information.
# You should also refer to the Diameter required TLS support here:
#   http://tools.ietf.org/html/rfc6733#section-13.1
# Default : "NORMAL"
# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL";
#TLS_Prio = "NORMAL";

# Diffie-Hellman parameters size
# Set the number of bits for generated DH parameters
# Valid value should be 768, 1024, 2048, 3072 or 4096.
# (This parameter is passed to gnutls_dh_params_generate2 function,
# it usually should match RSA key size)
# Default : 1024
#TLS_DH_Bits = 1024;

# Alternatively, you can specify a file to load the PKCS#3 encoded
# DH parameters directly from. This accelerates the daemon start
# but is slightly less secure. If this file is provided, the
# TLS_DH_Bits parameters has no effect.
# Default : no default.
#TLS_DH_File = "<file.PEM>";


##############################################################
##  Timers configuration

# The Tc timer of this peer.
# It is the delay before a new attempt is made to reconnect a disconnected peer.
# The value is expressed in seconds. The recommended value is 30 seconds.
# Default: 30
#TcTimer = 30;

# The Tw timer of this peer.
# It is the delay before a watchdog message is sent, as described in RFC 3539.
# The value is expressed in seconds. The default value is 30 seconds. Value must
# be greater or equal to 6 seconds. See details in the RFC.
# Default: 30
#TwTimer = 30;

##############################################################
##  Applications configuration

# Disable the relaying of Diameter messages?
# For messages not handled locally, the default behavior is to forward the
# message to another peer if any is available, according to the routing
# algorithms. In addition the "0xffffff" application is advertised in CER/CEA
# exchanges.
# Default: Relaying is enabled.
#NoRelay;

# Number of server threads that can handle incoming messages at the same time.
# Default: 4
#AppServThreads = 4;

# Other applications are configured by loaded extensions.

##############################################################
##  Extensions configuration

#  The freeDiameter framework merely provides support for
# Diameter Base Protocol. The specific application behaviors,
# as well as advanced functions, are provided
# by loadable extensions (plug-ins).
#  These extensions may in addition receive the name of a
# configuration file, the format of which is extension-specific.
#
# Format:
#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ;
#
# Examples:
#LoadExtension = "extensions/sample.fdx";
#LoadExtension = "extensions/sample.fdx":"conf/sample.conf";

# Extensions are named as follow:
# dict_* for extensions that add content to the dictionary definitions.
# dbg_*  for extensions useful only to retrieve more information on the framework execution.
# acl_*  : Access control list, to control which peers are allowed to connect.
# rt_*   : routing extensions that impact how messages are forwarded to other peers.
# app_*  : applications, these extensions usually register callbacks to handle specific messages.
# test_* : dummy extensions that are useful only in testing environments.


# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some
# information about some events. This extension does not actually use a configuration file
# but receives directly a parameter in the string passed to the extension. Here are some examples:
## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors.
## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details.
## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages.
# The four digits respectively control: connections, routing decisions, sent/received messages, errors.
# The values for each digit are:
#  0 - default - keep the default behavior
#  1 - quiet   - remove any specific log
#  2 - compact - display only a summary of the information
#  4 - full    - display the complete information on a single long line
#  8 - tree    - display the complete information in an easier to read format spanning several lines.

LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dbg_msg_dumps.fdx" : "0x8888";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_rfc5777.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_mip6i.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_nasreq.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_nas_mipv6.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_dcca.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_dcca_3gpp.fdx";


##############################################################
##  Peers configuration

#  The local server listens for incoming connections. By default,
# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl).
#
#  In addition to incoming connections, the local peer can
# be configured to establish and maintain connections to some
# Diameter nodes and allow connections from these nodes.
#  This is achieved with the ConnectPeer directive described below.
#
# Note that the configured Diameter Identity MUST match
# the information received inside CEA, or the connection will be aborted.
#
# Format:
#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ;
# Parameters that can be specified in the peer's parameter list:
#  No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method;
#  No_TLS;       # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions).
#  Port = 5868;  # The port to connect to
#  TcTimer = 30;
#  TwTimer = 30;
#  ConnectTo = "202.249.37.5";
#  ConnectTo = "2001:200:903:2::202:1";
#  TLS_Prio = "NORMAL";
#  Realm = "realm.net"; # Reject the peer if it does not advertise this realm.
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
{% for pcrf in pcrf_hosts %}
ConnectPeer = "{{ pcrf }}" { ConnectTo = "{{ pcrf }}"; No_TLS; };
{% endfor %}



##############################################################

GTPv2 – F-TEID Interface Types

I’ve been working on a ePDG for VoWiFi access to my IMS core.

This has led to a bit of a deep dive into GTP (easy enough) and GTPv2 (Bit harder).

The Fully Qualified Tunnel Endpoint Identifier includes an information element for the Interface Type, identified by a two digit number.

Here we see S2b is 32

In the end I found the answer in 3GPP TS 29.274, but thought I’d share it here.

0S1-U eNodeB GTP-U interface
1S1-U SGW GTP-U interface
2S12 RNC GTP-U interface
3S12 SGW GTP-U interface
4S5/S8 SGW GTP-U interface
5S5/S8 PGW GTP-U interface
6S5/S8 SGW GTP-C interface
7S5/S8 PGW GTP-C interface
8S5/S8 SGW PMIPv6 interface (the 32 bit GRE key is encoded in 32 bit TEID field and since alternate CoA is
not used the control plane and user plane addresses are the same for PMIPv6)
9S5/S8 PGW PMIPv6 interface (the 32 bit GRE key is encoded in 32 bit TEID field and the control plane and
user plane addresses are the same for PMIPv6)
10S11 MME GTP-C interface
11S11/S4 SGW GTP-C interface
12S10 MME GTP-C interface
13S3 MME GTP-C interface
14S3 SGSN GTP-C interface
15S4 SGSN GTP-U interface
16S4 SGW GTP-U interface
17S4 SGSN GTP-C interface
18S16 SGSN GTP-C interface
19eNodeB GTP-U interface for DL data forwarding
20eNodeB GTP-U interface for UL data forwarding
21RNC GTP-U interface for data forwarding
22SGSN GTP-U interface for data forwarding
23SGW GTP-U interface for DL data forwarding
24Sm MBMS GW GTP-C interface
25Sn MBMS GW GTP-C interface
26Sm MME GTP-C interface
27Sn SGSN GTP-C interface
28SGW GTP-U interface for UL data forwarding
29Sn SGSN GTP-U interface
30S2b ePDG GTP-C interface
31S2b-U ePDG GTP-U interface
32S2b PGW GTP-C interface
33S2b-U PGW GTP-U interface

I also found how this data is encoded on the wire is a bit strange,

In the example above the Interface Type is 7,

This is encoded in binary which give us 111.

This is then padded to 6 bits to give us 000111.

This is prefixed by two additional bits the first denotes if IPv4 address is present, the second bit is for if IPv6 address is present.

Bit 1Bit 2Bit 3-6
IPv4 Address Present IPv4 Address PresentInterface Type
11 000111

This is then encoded to hex to give us 87

Here’s my Python example;

interface_type = int(7)
interface_type = "{0:b}".format(interface_type).zfill(6)   #Produce binary bits
ipv4ipv6 = "10" #IPv4 only
interface_type = ipv4ipv6 + interface_type #concatenate the two
interface_type  = format(int(str(interface_type), 2),"x") #convert to hex

VoLTE Logo on Samsung Galaxy Handset

Things I wish I knew about setting up private VoLTE Networks

I’ve been working for some time on open source mobile network cores, and one feature that has been a real struggle for a lot of people (Myself included) is getting VoLTE / IMS working.

Here’s some of the issues I’ve faced, and the lessons I learned along the way,

Sadly on most UEs / handsets, there’s no “Make VoLTE work now” switch, you’ve got a satisfy a bunch of dependencies in the OS before the baseband will start sending SIP anywhere.

Get the right Hardware

Your eNB must support additional bearers (dedicated bearers I’ve managed to get away without in my testing) so the device can setup an APN for the IMS traffic.

Sadly at the moment this rules our Software Defined eNodeBs, like srsENB.

In the end I opted for a commercial eNB which has support for dedicated bearers.

ISIM – When you thought you understood USIMs – Guess again

According to the 3GPP IMS docs, an ISIM (IMS SIM) is not a requirement for IMS to work.

However in my testing I found Android didn’t have the option to enable VoLTE unless an ISIM was present the first time.

In a weird quirk I found once I’d inserted an ISIM and connected to the VoLTE network, I could put a USIM in the UE and also connect to the VoLTE network.

Obviously the parameters you can set on the USIM, such as Domain, IMPU, IMPI & AD, are kind of “guessed” but the AKAv1-MD5 algorithm does run.

Getting the APN Config Right

There’s a lot of things you’ll need to have correct on your UE before it’ll even start to think about sending SIP messaging.

I was using commercial UE (Samsung handsets) without engineering firmware so I had very limited info on what’s going on “under the hood”. There’s no “Make VoLTE do” tickbox, there’s VoLTE enable, but that won’t do anything by default.

In the end I found adding a new APN called ims with type ims and enabling VoLTE in the settings finally saw the UE setup an IMS dedicated bearer, and request the P-CSCF address in the Protocol Configuration Options.

Also keep in mind on Android at least, what you specify as your APN might be ignored if your UE thinks it knows best – Thanks to the Android Master APN Config – which guesses the best APN for you to use, which is a useful feature to almost any Android user, except the very small number who see fit to setup their own network.

Get the P-GW your P-CSCF Address

If your P-GW doesn’t know the IP of your P-CSCF, it’s not going to be able to respond to it in the Protocol Configuration Options (PCO) request sent by the UE with that nice new bearer for IMS we just setup.

There’s no way around Mutual Authentication

Coming from a voice background, and pretty much having RFC 3261 tattooed on my brain, when I finally got the SIP REGISTER request sent to the Proxy CSCF I knocked something up in Kamailio to send back a 200 OK, thinking that’d be the end of it.

For any other SIP endpoint this would have been fine, but IMS Clients, nope.

Reading the specs drove home the same lesson anyone attempting to setup their own LTE network quickly learns – Mutual authentication means both the network and the UE need to verify each other, while I (as the network) can say the UE is OK, the UE needs to check I’m on the level.

For anyone not familiar with the intricacies of 3GPP USIM Network Authentication, I’ve written about Mutual Network Authentication in this post.

In the end I added Multimedia Authentication support to PyHSS, and responded with a Crypto challenge using the AKAv1-MD5 auth,

For anyone curious about what goes on under the hood with this, I wrote about how the AKAv1-MD5 Authentication algorithm works in this post,

I saw my 401 response go back to the UE and then no response. Nada.

This led to my next lesson…

There’s no way around IPsec

According to the 3GPP docs, support for IPsec is optional, but I found this not to be the case on the handsets I’ve tested.

After sending back my 401 response the UE looks for the IPsec info in the 401 response, then tries to setup an IPsec SA and sends ESP packets back to the P-CSCF address.

Even with my valid AKAv1-MD5 auth, I found my UE wasn’t responding until I added IPsec support on the P-CSCF, hence why I couldn’t see the second REGISTER with the Authentication Info.

After setting up IPsec support, I finally saw the UE’s REGISTER with the AKAv1-MD5 authentication, and was able to send a 200 OK.

For some more info on ESP, IPsec SAs and how it works between the UE and the P-CSCF there’s a post on that too.

Get Good at Mind Reading (Or an Engineering Firmware)

To learn all these lessons took a long time,

One thing I worked out a bit late but would have been invaluable was cracking into the Engineering Debug options on the UEs I was testing with.

Samsung UEs feature a Sysdump utility that has an IMS Debugging tool, sadly it’s only their for carriers doing IMS interop testing.

After a bit of work I detailed in this post – Reverse Engineering Samsung Sysdump Utils to Unlock IMS Debug & TCPdump on Samsung Phones – I managed to create a One-Time-Password generator for this to generate valid Samsung OTP keys to unlock the IMS Debugging feature on these handsets.

I outlined turning on these features in this post.

This means without engineering firmware you’re able to pull a bunch of debugging info off the UE.

If you’ve recently gone through this, are going through this or thinking about it, I’d love to hear your experiences.

I’ll be continuing to share my adventures here and elsewhere to help others get their own VoLTE networks happening.

If you’re leaning about VoLTE & IMS networks, or building your own, I’d suggest checking out my other posts on the topic.

BaiCells Neutrino eNB Setup

For my LTE lab I got myself a BaiCells Neutrino, it operates on Band 3 (FDD ~1800Mhz) with only 24dBm of output power max and PoE powered it works well in a lab environment without needing -48vDC supply, BBUs, DUs feeders and antennas.

Setup can be done via TR-069 or via BaiCells management server, for smaller setups the web UI makes setup pretty easy,

Logging in with admin/admin to the web interface:

We’ll select Quick Settings, and load in our MME IP address, PLMN (MCC & MNC), Tracking Area Code, Cell ID and Absolute Radio Frequency No.

Once that’s done we’ll set our Sync settings to use GPS / GNSS (I’ve attached an external GPS Antenna purchased cheaply online).

Finally we’ll set the power levels, my RF blocking setup is quite small so I don’t want excess power messing around with it, so I’ve dialed the power right back:

And that’s it, it’ll now connect to my MME on 10.0.1.133 port 36412 on SCTP.

VoLTE / IMS – P-CSCF Assignment

The Proxy-Call Session Control Function is the first network element a UE sends it’s SIP REGISTER message to, but how does it get there?

To begin with our UE connects as it would normally, getting a default bearer, an IP address and connectivity.

Overview

If the USIM has an ISIM application on it (or IMS is enabled on the UE using USIM for auth) and an IMS APN exists on the UE for IMS, the UE will set up another bearer in addition to the default bearer.

This bearer will carry our IMS traffic and allow QoS to be managed through the QCI values set on the bearer.

While setting up the bearer the UE requests certain parameters from the network in the Protocol Configuration Options element, including the P-CSCF address.

When setting up the bearer the network responds with this information, which if supported includes the P-CSCF IPv4 &/or IPv6 addresses.

The Message Exchange

We’ll start assuming the default bearer is in place & our UE is configured with the APN for IMS and supports IMS functionality.

The first step is to begin the establishment of an additional bearer for the IMS traffic.

This is kicked off through the Uplink NAS Transport, PDN Connectivity Request from the UE to the network. This includes the IMS APN information, and the UE’s NAS Payload includes the Protocol Configuration Options element (PCO), with a series of fields the UE requires responses from the network. including DNS Server, MTU, etc.

In the PCO the UE also includes the P-CSCF address request, so the network can tell the UE the IP of the P-CSCF to use.

If this is missing it’s because either your APN settings for IMS are not valid, or your device doesn’t have IMS support or isn’t enabling it.(that could be for a few reasons).

Protocol Configuration Options (Unpopulated) used to request information from the Network by the UE

The MME gets this information from the P-GW, and the network responds in the E-RAB Setup Request, Activate default EPS bearer Context Request and includes the Protocol Configuration Options again, this time the fields are populated with their respective values, including the P-CSCF Address;

Once the UE has this setup, the eNB confirms it’s setup the radio resources through the E-RAB Setup Response.

One the eNB has put the radio side of things in place, the UE confirms the bearer assignment has completed successfully through the Uplink NAS Transport, Activate default EPS Bearer Accept, denoting the bearer is now in place.

Now the UE has the IP address(s) of the P-CSCF and a bearer to send it over, the UE establishes a TCP socket with the address specified in the P-CSCF IPv4 or IPv6 address, to start communicating with the P-CSCF.

The SIP REGISTER request can now be sent and the REGISTRATION procedure can begin.

I’ve attached a PCAP of the full exchange here.

I’ve written a bit about the Gm REGISTER procedure and how IPsec is implemented between the UE and the P-CSCF in this post.

If you’re leaning about VoLTE & IMS networks, or building your own, I’d suggest checking out my other posts on the topic.

SRS LTE – Software Defined LTE Stack with BladeRF x40

The team at Software Radio Systems in Ireland have been working on an open source LTE stack for some time, to be used with software defined radio (SDR) hardware like the USRP, BladeRF and LimeSDR.

They’ve released SRSUE and SRSENB their open source EUTRAN UE and eNodeB, which allow your SDR hardware to function as a LTE UE and connect to a commercial eNB like a standard UE while getting all the juicy logs and debug info, or as a LTE eNB and have commercial UEs connect to a network you’re running, all on COTS hardware.

The eNB supports S1AP to connect to a 3GPP compliant EPC, like Open5Gs, but also comes bundled with a barebones EPC for testing.

The UE allows you to do performance testing and gather packet captures on the MAC & PHY layers, something you can’t do on a commericial UE. It also supports software-USIMs (IMSI / K / OP variables stored in a text file) or physical USIMs using a card reader.

I’ve got a draw full of SDR hardware, from the first RTL-SDR dongle I got years ago, to a few HackRFs, a LimeSDR up to the BladeRF x40.

Really cool software to have a play with, I’ve been using SRSUE to get a better understanding of the lower layers of the Uu interface.

Installation

After mucking around trying to satisfy all the dependencies from source I found everything I needed could be found in Debian packages from the repos of the maintainers.

To begin with we need to install the BladeRF drivers and SopySDR modules to abstract it to UHD:

sudo add-apt-repository -y ppa:myriadrf/drivers
sudo add-apt-repository -y ppa:bladerf/bladerf
apt-get install *bladerf*
apt-get install libgnuradio-uhd3.7.11 libuhd-dev soapysdr-module-uhd uhd-soapysdr

Next up installing Software Radio System’s repo:

sudo add-apt-repository -y ppa:srslte/releases
sudo apt-get update
sudo apt-get install srslte -y 

And that’s it!

PyHSS Update – IMS Cx Support!

As I’ve been doing more and more work with IMS / VoLTE, the requirements / features on PyHSS has grown.

Some key features I’ve added recently:

IMS HSS Features

IMS Cx Server Assignment Request / Answer

IMS Cx Multimedia Authentication Request / Answer

IMS Cx User Authentication Request / Answer

IMS Cx Location Information Request / Answer

General HSS Features

Better logging (IPs instead of Diameter hostnames)

Better Resync Support (For USIMs with different sync windows)

ToDo

There’s still some functions in the 3GPP Cx interface description I need to implement:

IMS Cx Registration-Termination Request / Answer

IMS Cx Push-Profile-Request / Answer

Support for Resync in IMS Cx Multimedia Authentication Answer

Keep an eye on the GitLab repo where I’m pushing the changes.

If you’re leaning about VoLTE & IMS networks, or building your own, I’d suggest checking out my other posts on the topic.