The bug was:
connect a phone, disconnect, repeat five times. The fifth time the phone
does not reconnect because there is no free RA process.
When an UE is removed, we have to free associated RA processes.
Before this commit, when the gNB crashes, the eNB keeps running.
Same, if the eNB crashes, the gNB keeps running.
In a far past when this happened, the other program (the one not
crashing) was forced to exit.
Then this behavior was changed, for some reason.
But the code was not finished, so now we have a system in an inconsistent
state.
So either we accept that the connection between eNB and gNB can break,
that is one of the programs crashes, and we clean the state of the
program that keeps running. But this is a complex work and it will
surely not survive very long, because someone will change something
in the code later that will break this complex behavior.
Or, simpler, we go back to initial behavior, which is: the program that
did not crash does actually exit when the other crashes.
This commit provides the second solution.
It can easily be reverted whenever someone wants to implement the complex
solution.
We used to set 'does_nr' of an UE if we detect ENDC supported in the
UE capabilities.
Then we activate NR measurements if 'does_nr' is true.
The problem is that if the eNB is not connected to a gNB but the UE
reports some NR measurements (because a gNB is running somewhere near)
then the eNB will crash when starting the switch to NR.
A (quick) solution is to set 'does_nr' only if there is a gNB connected to
the eNB.
Maybe not the best solution. To be changed if needed.
This code has not been tested with a COTS UE. We need SRB1/2 (so we need SA)
to test.
The activation of security and integrity for SRB1 will need more code
(new functions) because it happens after some time, not at creation time
of the PDCP entity and there is no way to do this with current code.
We do some sanity checks for incoming rlc control packets. One of them
is to check that so_start is not > so_end when present.
But when 'range' is present and bigger than 1 it means that so_start refers
to one PDU and so_end to another one. So we may well have so_start > so_end.
This commit fixes that and reorganizes a bit the code to do the check before
processing and rejecting the PDU if the values are not correct. (Before this
commit we were NACKing the whole PDUs if so_start > so_end.)
In case of false positive PDSCH CRC check, a random MAC PDU is processed.
Currently pdu_len is unsigned 16 Bit, so we did break out of the processing loop only if we _exactly_ hit a residual pdu_len of 0, or we hit a LCID of DL_SCH_LCID_PADDING.
If we didn't hit either of these, pdu_len wrapped to a very positive value, and we continued processing the PDU even beyond its bounds!
This behavior was observed with SNR 1 dB and MCS 9.
So better make pdu_len signed and break out of the loop after processing at max. pdu_len Bytes!
The discard timer is used by the PDCP layer to discard packets that were not
transmitted to RLC after some time.
We don't really need it for the moment, maybe never for the default
bearer which is a best-effort bearer passing all kind of IP traffic.
Maybe for voice over IP kind of traffic it's important, or realtime
applications.
I ran an iperf UDP uplink test and saw no error on the PHY layer but still
lots of packets lost in the iperf logs, which was very surprising. By
analyzing the logs in wireshark I saw that, with the current scheduler,
an IP packet sent by the UE took 40ms to be sent piece by piece to the
gNB, and then the next uplink IP packet was never sent at all because
the discard timer was expired, leading to the high count of packets lost
in the iperf logs.
So let's put infinity for the moment for the discard timer. From my
understanding of the moment it's not a problem. If for some reason we
should set it to some non-infinity value, then we can change later.