Introduction
If you managed to land here without seeing part one, part two and part three in my series on setting up my own private LTE network, you may want to check those out first.
Continuing from where we left off, having programmed our SIM card. The next step involves configuring srsRAN and firing up the network. Before connecting our first mobile device to it.
This post therefore should if all goes well complete the initial series and leave us with our goal of a private and useful LTE network.
Configuration
In order to configure srsRAN we need to tweak the files found in ~/.config/srsran (which were added by the srsran_install_configs.sh script when building).
For example my directory currently looks like this:
user@deblaptop:~$ ls -l $HOME/.config/srsran/ total 72 -rw-r--r-- 1 user user 18362 Dec 22 15:28 enb.conf -rw-r--r-- 1 user user 3796 Dec 22 15:28 epc.conf -rw-r--r-- 1 user user 1688 Dec 22 15:28 mbms.conf -rw-r--r-- 1 user user 3386 Dec 22 15:28 rb.conf -rw-r--r-- 1 user user 2951 Dec 22 15:28 rr.conf -rw-r--r-- 1 user user 10584 Dec 22 15:28 sib.conf -rw-r--r-- 1 user user 19111 Dec 22 15:28 ue.conf -rw-r--r-- 1 user user 1275 Dec 22 15:28 user_db.csv
enb.conf
The enb.conf file configures the eNodeB component. In LTE terms the eNodeB is the hardware / software component responsible for communicating with the mobile devices. These live inside cellular base stations. It will manage the SDR radio, communicating with the mobile devices. While also communicating with the EPC (evolved packet core), described below.
In the “[enb]” section we need to update the MCC and MNC, with those selected during SIM card programming. My MCC is 999 and MNC is 69, therefore the section now contains:
[enb] enb_id = 0x19B mcc = 999 mnc = 69 ...
In the “[rf]” section we need to inform srsRAN that we’re using a LimeSDR, while selecting which antenna ports are in use. We use the device_name and device_args parameters for this.
We also need to set the transmit and receive gain which should be applied to the LimeSDR via the tx_gain and rx_gain paramters. I’ve set the gains here based on a LimeSDR forum post I happened across on my travels. It seems to work ok(ish) for me, although may need some tweaking.
My updated “[rf]” section is therefore as follows:
[rf] #dl_earfcn = 3350 tx_gain = 66 rx_gain = 47 device_name = soapy device_args = driver=lime,rxant=LNAH,txant=BAND2 ...
rr.conf
Finally we need to select the radio frequency to transmit and receive on, which can conveniently be expressed via a EARFCN (Evolved-UTRA Absolute Radio Frequency Number). srsRAN only supports FDD (frequency division duplexing), whereby the downlink and uplink from the mobile device occurs on different frequencies. By providing the downlink EARFCN number, srsRAN is able to calculate the downlink frequency. Before using its knowledge of the LTE bands and uplink / downlink offsets to calculate the uplink frequency. I used this neat calculator to select an EARFCN number at the start of LTE Band 7 which supports the full 20Mhz bandwidth, yielding a download EARFCN of 2850.
We could update the downlink EARFCN in the enb.conf
file using the dl_earfcn
which looks to be an override value. I believe the correct location to set the downlink channel is in the rr.conf
file.
Find the cell_list
section and update the dl_earfcn
parameter. The section of my updated file is as follows:
... cell_list = ( { // rf_port = 0; cell_id = 0x01; tac = 0x0007; pci = 1; // root_seq_idx = 204; dl_earfcn = 2850; //ul_earfcn = 21400; ho_active = false; ...
With that the eNodeB configuration is complete.
epc.conf
The epc.conf file configures the EPC. In a commercial network the EPC consists of several nodes, providing different services. Services for example to authenticate users, to track usage, to track which eNodeB a user is connected to as well as transferring data in and out of the network. srsRAN has neatly combined these services into a single binary, which for a small test setup makes things super simple.
In the “[mme]” section we need to update the MCC and MNC as above. My “[mme]” section therefore appears as follows:
[mme] mme_code = 0x1a mme_group = 0x0001 tac = 0x0007 mcc = 999 mnc = 69
With that the EPC configuration is complete.
user_data.csv
The user_data.csv file contains the different SIM card identities that we configured earlier. It’s used by the HSS (home subscriber service), which is part of the EPC binary described above.
The file contains a few example identities which we can update / remove as appropriate.
The details we programmed into the SIM card are now required, specifically the IMSI, Ki and OPc values. With the notes at the top of the file providing a useful description of what each field means.
My updated file, based on my SIM configuration is as follows:
# # .csv to store UE's information in HSS # Kept in the following format: "Name,Auth,IMSI,Key,OP_Type,OP/OPc,AMF,SQN,QCI,IP_alloc" # # Name: Human readable name to help distinguish UE's. Ignored by the HSS # Auth: Authentication algorithm used by the UE. Valid algorithms are XOR # (xor) and MILENAGE (mil) # IMSI: UE's IMSI value # Key: UE's key, where other keys are derived from. Stored in hexadecimal # OP_Type: Operator's code type, either OP or OPc # OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal # AMF: Authentication management field, stored in hexadecimal # SQN: UE's Sequence number for freshness of the authentication # QCI: QoS Class Identifier for the UE's default bearer. # IP_alloc: IP allocation stratagy for the SPGW. # With 'dynamic' the SPGW will automatically allocate IPs # With a valid IPv4 (e.g. '172.16.0.2') the UE will have a statically assigned IP. # # Note: Lines starting by '#' are ignored and will be overwritten ue1,mil,999690000000001,895fd70bd46fa42435ba1471665b0028,opc,9b9fb8dcae42ae23011abc20bb80796a,8000,000000000000,7,dynamic
The AMF number should be set to 8000 of above. From one of the 3GPP documents either the lowest order bit (or possibly highest order bit based on the examples above) is used to indicate that this device is connecting over LTE, rather than an alternative access technology such as Wi-Fi. The remaining bits are vendor specific and unused by srsRAN as far as I could tell.
The SQN is a sequence number which ensures the period before an authentication request for a device is repeated is sufficiently large to prevent replay attacks. We can set this to zero and it will be auto-incremented by the EPC.
QCI relates to the quality of service class for the user….given that we’d be happy with any service at present, leaving it at the example default of 7 seems reasonable.
With that all of the configuration is complete.
Startup
In order to start the network up ready for clients we need to launch the EPC followed by the eNodeB.
With the SDR connected and RF cables to the mobile device already in place.
Using the same prefix as was used when building and installing:
export SRSRAN_INSTALL=${HOME}/srsRAN
In one terminal launch the EPC:
sudo LD_LIBRARY_PATH=${SRSRAN_INSTALL}/lib sh -c "cd ${HOME}/.config/srsran; ${SRSRAN_INSTALL}/bin/srsepc epc.conf"
If all goes well it should output something similar to the following at startup:
Built in Release mode using commit 61059ecbc on branch release_23_04. --- Software Radio Systems EPC --- Reading configuration file epc.conf... HSS Initialized. MME S11 Initialized MME GTP-C Initialized MME Initialized. MCC: 0xf999, MNC: 0xff69 SPGW GTP-U Initialized. SPGW S11 Initialized. SP-GW Initialized.
In another terminal launch the eNodeB:
echo "performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor sudo LD_LIBRARY_PATH=${SRSRAN_INSTALL}/lib sh -c "cd ${HOME}/.config/srsran; ${SRSRAN_INSTALL}/bin/srsenb enb.conf"
If all goes well it should output something similar to the following at startup:
Active RF plugins: libsrsran_rf_soapy.so Inactive RF plugins: --- Software Radio Systems LTE eNodeB --- Reading configuration file enb_lime_soapy.conf... Built in Release mode using commit 61059ecbc on branch release_23_04. Opening 1 channels in RF device=soapy with args=driver=lime,rxant=LNAH,txant=BAND2 Supported RF device list: soapy limesdr file Soapy has found device #0: addr=1d50:6108, driver=lime, label=LimeSDR-USB [USB 3.0] 908340187372A, media=USB 3.0, module=FX3, name=LimeSDR-USB, serial=000908340187372A, Selecting Soapy device: 0 [INFO] Make connection: 'LimeSDR-USB [USB 3.0] 908340187372A' [INFO] Reference clock 30.72 MHz [INFO] Device name: LimeSDR-USB [INFO] Reference: 30.72 MHz [INFO] LMS7002M register cache: Disabled Setting up Rx stream with 1 channel(s) Setting up Tx stream with 1 channel(s) [INFO] RX LPF configured [INFO] Filter calibrated. Filter order-4th, filter bandwidth set to 5 MHz.Real pole 1st order filter set to 2.5 MHz. Preemphasis filter not active [INFO] TX LPF configured Available device sensors: - clock_locked - lms7_temp Available sensors for Rx channel 0: - lo_locked Setting Rx channel 0 antenna to LNAH Setting Tx channel 0 antenna to BAND2 State of gain elements for Rx channel 0 (AGC not supported): - TIA: 9.00 dB - LNA: 30.00 dB - PGA: -7.00 dB State of gain elements for Tx channel 0 (AGC not supported): - PAD: 0.00 dB - IAMP: 0.00 dB Rx antenna set to LNAH Tx antenna set to BAND2 ==== eNodeB started === Type <t> to view trace [INFO] RX LPF configured [INFO] Filter calibrated. Filter order-4th, filter bandwidth set to 11.52 MHz.Real pole 1st order filter set to 2.5 MHz. Preemphasis filter not active [INFO] TX LPF configured Setting frequency: DL=2630.0 Mhz, UL=2510.0 MHz for cc_idx=0 nof_prb=50 [INFO] Tx calibration finished [INFO] Rx calibration finished
Finally to allow clients onto the internet we need to enable IP forwarding and configure a NAT rule for the system. Clients will be assigned an IP in the range 172.16.0.0/255 with their traffic emerging from a Linux TUN interface. The IP forwarding and NAT configuration will allow them to access the internet via the host’s default route.
This has been neatly wrapped up by the srsRAN team in a small helper script, which we can execute as follows. Substituting enp3s0f2 for the name of your internet connected Ethernet interface.
sudo ${SRSRAN_INSTALL}/bin/srsepc_if_masq.sh enp3s0f2
If all goes well it should output the single line (with the appropriate interface name of course):
Masquerading Interface enp3s0f2
The network should be online and serving clients.
First Client
If you’ve got this far, I’d hazard a guess that you’ll be capable of configuring your mobile device. I thought this about myself….until what shall be referred to as “modem firmware and old configuration gate” occurred.
All you should need to connect is the network’s APN name which is “srsran”.
My test setup is using a Sierra Wireless MC7455, connected to an Ubuntu machine which is using ModemManager. I can therefore issue commands such as the following to scan for networks:
phil@ubuntu:~$ mmcli -m any --3gpp-scan --timeout=60 --------------------- 3GPP scan | networks: 99969 - Software Radio Systems (lte, current)
Woohoo, there it is!
Connecting should then just be a matter of executing something similar to the following:
phil@ubuntu:~$ mmcli -m any --simple-connect='apn=srsapn,ip-type=ipv4' successfully connected the modem phil@ubuntu:~$ journalctl -u ModemManager -n 10 -- Logs begin at Mon 2022-06-06 10:55:32 BST, end at Sun 2022-12-25 20:15:52 GMT. -- Dec 24 20:04:43 ubuntu ModemManager[181550]: [/dev/cdc-wdm0] Allocating new client ID... Dec 24 20:04:43 ubuntu ModemManager[181550]: [/dev/cdc-wdm0] Registered 'wds' (version 1.67) client with ID '36' Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14/bearer44] QMI IPv4 Settings: Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14/bearer44] address: 172.16.0.5/30 Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14/bearer44] gateway: 172.16.0.6 Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14/bearer44] DNS #1: 8.8.8.8 Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14/bearer44] DNS #2: failed (Field 'Secondary IPv4 DNS Address' was not found in the message) Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14/bearer44] MTU: 1500 Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14] state changed (connecting -> connected) Dec 24 20:04:44 ubuntu ModemManager[181550]: <info> [modem14] simple connect state (8/8): all done phil@ubuntu:~$ mmcli -m any --simple-disconnect successfully disconnected all bearers in the modem
While that got the modem connected, as could be seen in the journal log it didn’t assign the IP we were provided to the interface. For that network manager is required. We can create a connection as follows:
sudo nmcli c add con-name "TestNET" type gsm ifname "*" apn "srsapn" connection.autoconnect no
Which can then be connected as follows:
sudo nmcli c up TestNET
Which if all goes well, leads to ModemManager connecting the modem and NetworkManager configuring the interface with the details returned:
phil@ubuntu:~$ ip address show dev wwan0 41: wwan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000 link/none inet 172.16.0.5/30 brd 172.16.0.7 scope global noprefixroute wwan0 valid_lft forever preferred_lft forever
We should be able to ping the internet:
phil@ubuntu:~$ ping -I wwan0 8.8.8.8 PING 8.8.8.8 (8.8.8.8) from 172.16.0.5 wwan0: 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=115 time=34.4 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=115 time=31.7 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=115 time=29.8 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=115 time=28.6 ms 64 bytes from 8.8.8.8: icmp_seq=5 ttl=115 time=46.7 ms
And of course not forgetting the obligatory speed test, running iperf3 as a server on the SDR machine:
iperf3 -s
And on the machine with the modem. I add a specific route as the machine has an Ethernet card with a default route of its own which must be avoided. iPerf is run with the “-R” option for reverse, meaning the server sends and the client receives, aka the client is downloading from the server:
sudo ip route add 172.16.0.1 dev wwan0 iperf3 -c 172.16.0.1 -R -t 30
Here’s the result:
phil@ubuntu:~$ iperf3 -c 172.16.0.1 -R -t 30 Connecting to host 172.16.0.1, port 5201 Reverse mode, remote host 172.16.0.1 is sending [ 5] local 172.16.0.5 port 55018 connected to 172.16.0.1 port 5201 [ ID] Interval Transfer Bitrate [ 5] 0.00-1.00 sec 3.88 MBytes 32.5 Mbits/sec [ 5] 1.00-2.00 sec 3.36 MBytes 28.2 Mbits/sec [ 5] 2.00-3.00 sec 4.08 MBytes 34.3 Mbits/sec [ 5] 3.00-4.00 sec 3.20 MBytes 26.8 Mbits/sec [ 5] 4.00-5.00 sec 3.27 MBytes 27.4 Mbits/sec [ 5] 5.00-6.00 sec 4.06 MBytes 34.0 Mbits/sec [ 5] 6.00-7.00 sec 4.02 MBytes 33.7 Mbits/sec [ 5] 7.00-8.00 sec 4.09 MBytes 34.3 Mbits/sec [ 5] 8.00-9.00 sec 4.06 MBytes 34.1 Mbits/sec [ 5] 9.00-10.00 sec 3.61 MBytes 30.3 Mbits/sec [ 5] 10.00-11.00 sec 4.04 MBytes 33.9 Mbits/sec [ 5] 11.00-12.00 sec 4.03 MBytes 33.8 Mbits/sec [ 5] 12.00-13.00 sec 3.90 MBytes 32.7 Mbits/sec [ 5] 13.00-14.00 sec 3.96 MBytes 33.2 Mbits/sec [ 5] 14.00-15.00 sec 3.17 MBytes 26.6 Mbits/sec [ 5] 15.00-16.00 sec 3.95 MBytes 33.2 Mbits/sec [ 5] 16.00-17.00 sec 3.24 MBytes 27.1 Mbits/sec [ 5] 17.00-18.00 sec 4.08 MBytes 34.2 Mbits/sec [ 5] 18.00-19.00 sec 4.10 MBytes 34.4 Mbits/sec [ 5] 19.00-20.00 sec 4.00 MBytes 33.5 Mbits/sec [ 5] 20.00-21.00 sec 3.58 MBytes 30.0 Mbits/sec [ 5] 21.00-22.00 sec 3.16 MBytes 26.5 Mbits/sec [ 5] 22.00-23.00 sec 3.85 MBytes 32.3 Mbits/sec [ 5] 23.00-24.00 sec 3.99 MBytes 33.4 Mbits/sec [ 5] 24.00-25.00 sec 3.27 MBytes 27.5 Mbits/sec [ 5] 25.00-26.00 sec 3.97 MBytes 33.3 Mbits/sec [ 5] 26.00-27.00 sec 4.04 MBytes 33.9 Mbits/sec [ 5] 27.00-28.00 sec 4.11 MBytes 34.4 Mbits/sec [ 5] 28.00-29.00 sec 3.82 MBytes 32.0 Mbits/sec [ 5] 29.00-30.00 sec 4.03 MBytes 33.8 Mbits/sec - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-30.05 sec 116 MBytes 32.3 Mbits/sec 38 sender [ 5] 0.00-30.00 sec 114 MBytes 31.8 Mbits/sec receiver iperf Done.
Around 32 Mbit/s, with a few retires. Overall not too shabby.
How about upload:
iperf3 -c 172.16.0.1 -t 30
Here’s the result:
phil@ubuntu:~$ iperf3 -c 172.16.0.1 -t 30 Connecting to host 172.16.0.1, port 5201 [ 5] local 172.16.0.5 port 55842 connected to 172.16.0.1 port 5201 [ ID] Interval Transfer Bitrate Retr Cwnd [ 5] 0.00-1.00 sec 2.65 MBytes 22.2 Mbits/sec 0 140 KBytes [ 5] 1.00-2.00 sec 2.55 MBytes 21.4 Mbits/sec 0 252 KBytes [ 5] 2.00-3.00 sec 2.49 MBytes 20.9 Mbits/sec 0 355 KBytes [ 5] 3.00-4.00 sec 2.42 MBytes 20.3 Mbits/sec 0 465 KBytes [ 5] 4.00-5.00 sec 1.86 MBytes 15.6 Mbits/sec 1 339 KBytes [ 5] 5.00-6.00 sec 1.86 MBytes 15.6 Mbits/sec 0 393 KBytes [ 5] 6.00-7.00 sec 1.86 MBytes 15.6 Mbits/sec 39 298 KBytes [ 5] 7.00-8.00 sec 1018 KBytes 8.34 Mbits/sec 1 216 KBytes [ 5] 8.00-9.00 sec 2.86 MBytes 24.0 Mbits/sec 0 240 KBytes [ 5] 9.00-10.00 sec 1.86 MBytes 15.6 Mbits/sec 0 255 KBytes [ 5] 10.00-11.00 sec 1.86 MBytes 15.6 Mbits/sec 0 260 KBytes [ 5] 11.00-12.00 sec 1.86 MBytes 15.6 Mbits/sec 0 260 KBytes [ 5] 12.00-13.00 sec 1.86 MBytes 15.6 Mbits/sec 0 260 KBytes [ 5] 13.00-14.00 sec 1.86 MBytes 15.6 Mbits/sec 0 263 KBytes [ 5] 14.00-15.00 sec 1.86 MBytes 15.6 Mbits/sec 0 272 KBytes [ 5] 15.00-16.00 sec 1.86 MBytes 15.6 Mbits/sec 0 288 KBytes [ 5] 16.00-17.00 sec 1.86 MBytes 15.6 Mbits/sec 0 318 KBytes [ 5] 17.00-18.00 sec 1.86 MBytes 15.6 Mbits/sec 0 361 KBytes [ 5] 18.00-19.00 sec 1.86 MBytes 15.6 Mbits/sec 0 423 KBytes [ 5] 19.00-20.00 sec 1.86 MBytes 15.6 Mbits/sec 0 506 KBytes [ 5] 20.00-21.00 sec 2.17 MBytes 18.2 Mbits/sec 0 612 KBytes [ 5] 21.00-22.00 sec 2.49 MBytes 20.9 Mbits/sec 0 742 KBytes [ 5] 22.00-23.00 sec 1.25 MBytes 10.5 Mbits/sec 0 901 KBytes [ 5] 23.00-24.00 sec 2.50 MBytes 21.0 Mbits/sec 0 1.06 MBytes [ 5] 24.00-25.00 sec 1.25 MBytes 10.5 Mbits/sec 0 1.28 MBytes [ 5] 25.00-26.00 sec 2.50 MBytes 21.0 Mbits/sec 0 1.52 MBytes [ 5] 26.00-27.00 sec 1.25 MBytes 10.5 Mbits/sec 0 1.64 MBytes [ 5] 27.00-28.00 sec 2.50 MBytes 21.0 Mbits/sec 0 1.64 MBytes [ 5] 28.00-29.00 sec 1.25 MBytes 10.5 Mbits/sec 0 1.64 MBytes [ 5] 29.00-30.00 sec 2.50 MBytes 21.0 Mbits/sec 0 1.64 MBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-30.00 sec 59.7 MBytes 16.7 Mbits/sec 41 sender [ 5] 0.00-30.59 sec 57.9 MBytes 15.9 Mbits/sec receiver iperf Done.
Not quite as stable as a download, with peaks of 21-22Mbits but an average of 16Mbits with some retries. Not bad for a first try.
Given that the devices I’ve been working with lately are happy with a few hundred kilobits of internet access, a connection in the megabits is more than enough to get me started.
Conclusion
If you’ve read this far I hope my waffle helped get your setup working. Or at least helped save some of the Googling I’ve subjected myself to over the last few weeks.
Now with a basic setup in place there’s plenty left to try / refine.
The LimeSDR should be able to handle a 20Mhz wide channel (the configuration described above being for a 10Mhz channel). Which should increase its download throughput to around 75Mbits.
There’s also be the option of MIMO or carrier aggregation to explore as the LimeSDR has two channels. Allowing for a potential downlink of 150Mbps and uplink of 50Mbps in the future.
Updates
04/06/23
- Updated method of setting EARFCN.
- Updated launch examples based on PlutoSDR work.
Leave a Reply to Dm. Goreslavich Cancel reply