srsRAN_4G with LimeSDR Mini - can't get UE to join, seems signal related

I’m trying to use LimeSDR Mini v2.x and a Linux PC, with LimeSuite+Soapy+srsRAN_4G to test a Quectel EC200U UE. The main reason is that this UE is made for Asia and Africa, but I’m in the US. I don’t actually care that much about the RF aspects – I just want to get an international product talking to the Internet so I can work on some higher level software. I read this guide:

And it seemed like it would do the trick.

Obviously, since this is in the US, I am using a conducted/cabled configuration. It looks like this:

    Linux + srsRAN_4G
    LimeSDR Mini 2.x
       TX     RX
        |      |
        |      |
        |     Attenuator #2 (have tried multiple sizes/combinations)
        |      |
    XRDS-RF Wideband 2-Way Splitter 698-2700 MHz
         Attenuator #1 (have tried multiple sizes/combinations)
        Quectel EC200U

The issue I’m having is that my UE won’t seem to actually join the network (apologies for terminology – I’ve got a lot of Wi-Fi experience, but EXTREMELY little LTE knowledge).

Unless I remove almost all of the attenuation, nothing seems to happen at all. (Figuring out attenuation is challenging for the RF newbie.)

But if I do remove most of the attenuation, then I do see some log messages on the ENB:

RACH:  tti=181, cc=0, pci=1, preamble=16, offset=32, temp_crnti=0x46
Disconnecting rnti=0x46.
RACH:  tti=1471, cc=0, pci=1, preamble=14, offset=32, temp_crnti=0x47
Disconnecting rnti=0x47.
RACH:  tti=1921, cc=0, pci=1, preamble=28, offset=32, temp_crnti=0x48
Disconnecting rnti=0x48.

On my EPC, I never see anything like the “Initial UE message” that is documented in the example.

I opened up a support case with Quectel who helps me get some logs on the UE side. Comparing with packet captures in srsENB, here’s what I see.

On the eNB side:

- eNB receives RACH from UE
- eNB sends DL-SCH/RAR
- eNB receives rrcConnectionRequest
- eNB sends rrcConnectionSetup

And then nothing until timeout and the process repeats.

On the UE side:

- UE sends RACH
- UE receives DL-SCH/RAR
- UE sends rrcConnectionRequest
- UE receives rrcConnectionSetup
- UE sends rrcConnectionComplete

And then it times out waiting for the next thing to happen – but as we can see from above, the eNB never gets the rrcConnectionComplete packet, so it’s never going to proceed.

The other thing that Quectel noticed was that their modem was indicating the signal quality was pretty low – the RSRP being reported as -117. I don’t actually know what these numbers mean, but the web seems to indicate this is pretty bad.

So for the last week or so, I’ve been playing with a tinySA ULTRA to see if I could measure transmit power (as mentioned in my previous email, I’ve struggled with the appropriate amount of attenuation – partly because I don’t understand this stuff, but also because I had no way to know where things were).

So I did two tests:

  1. I performed a “continuous transmit” test of the Quectel modem, and used the spectrum analyzer to look (using a “max hold” function), measuring at the RX port of the LimeSDR-Mini. This is what the signal looks like, and I sort of think that it looks like it’s supposed to? This is with a 30 dB attenuator (in Attenuator #1 slot from my previous diagram), and no other attenuation.

  1. I don’t know how to do a continuous transmit test of the srsRAN/Soapy/LimeSDR combination. So I just did the same “max hold” function while I started eNodeB and let it run for a minute or so, measuring at the RX port of the Quectel module. This signal doesn’t look as good to me – but, really, what do I know, and maybe it’s not fair because I’m not doing continuous transmit in this case. But right off the bat I notice that the power is lower (maxing out at -30 dBm to -40 dBm, compared to the -20 dBm of the Quectel), but also the “curve” doesn’t look like a nice solid band the way the Quectel modem does. Perhaps it’s not even power that’s my problem – maybe it’s just something wrong with the way the LimeSDR uses the spectrum? (Grasping here, sorry) Oh one more thing – #1 was performed on LTE Band #3, but #2 was performed on LTE Band #5. But the results are similar on either band – I just happened to be experimenting when I took the picture.

Any advice for trying to get this working is very much appreciated. Like I said, I really only care about it working at the higher level – it doesn’t have to perform well or anything. Just need it to be connected to the Internet here in the US.

Thank you!


Try using the LibreCellular fork which has native Lime Suite integration, hence doesn’t need SoapySDR.

I just recently pushed packages to the PPA for Ubuntu 22.04, based on the latest upstream srsRAN_4G (23.11). So the documentation is still to be updated. Of course, you can just build from source on whatever distro. Note that your device_args in enb.conf will be different to the example config provided as you’re not using an original LimeSDR USB, and you may or may not be using an external reference.

I installed the LibreCellular fork of LimeSuite and srsRAN. Built both from source, which did require a few minor tweaks to the code:

- several changes to disable overly aggressive warnings from g++ (since warnings are treated as errors) -- lots of changes to CMakeLists.txt like this:

	`set_source_files_properties( PROPERTIES COMPILE_FLAGS "-Wno-array-bounds -Wno-stringop-overflow")`

- declare the zero_mem buffer in rf_lime_imp.c to be static (otherwise it conflicts with a similarly named buffer in rf_soapy_imp.c, which is also built by default if you have already installed it)

Updated my enb.conf as described on the website.

It certainly didn’t make anything magically work.

However, I did dig into the LibreCellular example here:

And decided to try them out.

I strongly suspect that the main change I made was the “n_prb” (most of the others I’d already made above).

But with that change, my device connects to the network and proceeds through the layers to get an IP address assigned. The masquerading stuff seems to not be fully working for me – from my client device, I can ping through to the enb host (including to its other interfaces). But if I try to ping through to the enb’s upstream router (i.e., the NAT router on my network), then it never gets a response. I haven’t debugged yet, but I am FAR more comfortable debugging at that layer (I spent a long time working on NATs in previous gigs). I’m much more confident I can figure out what needs to happen to make it all the way.

In the end, I’m not particularly surprised that it turned out to be configuration, but I have to admit, these parameters are tough for someone who doesn’t really understand RF. I don’t understand what n_prb really does, and I don’t understand whether or not if there are more or fewer of them, will the UE will be unhappy? I also don’t understand why having fewer of them (I went from n_prb=50 to n_prb=15) makes it work. And of course I have absolutely no idea what “time_adv_nsamples” does – the documentation says, “no harm in experimenting with this parameter” but I don’t know if I should increase it or decrease it :slight_smile: . I’m extremely grateful for the help that got me this far – and even more grateful that these tools exist (and are so inexpensive!) – but if there’s one thing I’d ask for, it would be better documentation of the configuration parameters for folks who do not understand SDRs at all.

I found that with Ubuntu 22.04 I needed to disable the firewall with sudo ufw disable, whereas I’m pretty sure that wasn’t the case with Ubuntu 20.04. Otherwise I had the same issue as you and could ping the eNodeB from the UE and vice versa, but not access the Internet from the UE.

Physical Resource Blocks relate to the cell bandwidth and 15 PRBs = 3MHz wide carrier.

The more PRBs and greater the bandwidth, the more CPU load. Though you went from 50 down to 15, right? 50 PRBs is only 10MHz and most PCs should handle the baseband processing for this sort of bandwidth.

Also since you built from source, just to check that you ran cmake with -DUSE_LTE_RATES=True ? Not doing and just using the srsRAN default, where it uses non-standard sample rates to reduce I/O, can prove problematic with LimeSDR hardware.

The parameter accounts for the transit delay in the SDR, by advancing some number of samples. Samples have to be transmitted at a pretty precise time and all SDRs will introduce some delay, with this varying from one to another, depending mostly on the transceiver and FPGA architecture I think.

Speaking with the srsRAN developers it seems like it can be a case of trial and error tuning this. That value was likely determined with the original LimeSDR USB board, so maybe there is some room for fine tuning, but I wouldn’t imagine it to be far off with a Mini.

Well, we don’t develop the stack and the simple fact is that cellular networks are pretty complex, with lots and lots of parameters. Then with every generation comes new architecture, network elements and yet more parameters. The SDR parts, like which RF port to use, sample rates and parameters like time_adv_nsamples, are a tiny part of the picture. But in any case, the intention with LibreCellular is to try and simplify things and make it easier for anyone to get a network up and running, without having to spend hours studying documentation and tutorials spread across numerous websites.

I found that adding two iptables FORWARD rules (one from the tunnel interface to my “outbound” interface, the other in the reverse direction) got it working for me.

> iptables -A FORWARD -i <public interface> -o <internal/srs tunnel interface> -m state --state RELATED,ESTABLISHED -j ACCEPT
> iptables -A FORWARD -i <internal/srs tunnel interface> -o <public interface>  -j ACCEPT

Now I’ve got a script that automates the running of the masquerading script (after epc is running but before enb is running), and it does the masquerading and forwarding rules all at once.

I hope my post didn’t come off as critical. I truly appreciate how valuable these tools are, and they’re basically free. I am really, really grateful to the Myriad team, the SRS team, and the community for making this available.

I was simply trying to point out that for true newbies, it’s quite hard to figure out how to tweak these low level parameters, and making that easier seems like a noble goal. But you guys know better than anyone how big a task that is (your explanation here was also really, really helpful), so I understand if it’s not super high up in the priority queue – and that you guys have a much better picture of where improvement efforts should be applied.

Thank you again!


1 Like