This post belongs to my series about LTE. In the LTE uplink, the PUSCH (physical uplink shared channel) is the channel used to trasmit data from the UEs (phones) to the eNB (base station). It plays a role analogous to the PDSCH (physical downlink shared channel), which is used to transmit data in the downlink. In this post I will decode the PUSCH in a recording that I made of my phone uplink a couple years ago.
The PUSCH uses the same kind of techniques as the PDSCH for transport block coding, so all the Turbo code implementation and related algorithms from my post about the PDSCH will be re-used here. However, there is an important difference between the PDSCH and the PUSCH that makes decoding the PUSCH much harder. The LTE downlink is, in a certain sense, a self-descriptive signal. The UEs don’t know in advance the configuration that will be used to transmit each transport block in the PDSCH, because the eNB decides it on the fly. Therefore, the eNB announces PDSCH transmissions in the PDCCH (physical downlink control channel).
When I decoded the PDCCH and PDSCH, the only slightly clever thing that I had to do was to find the RNTIs (radio network temporary indicators). These are 16-bit numbers that are used to address each PDSCH transmission. There are some of them which are statically allocated to some broadcast purpose (SI-RNTI, P-RNTI, RA-RNTI), and the C-RNTIs, which are individually assigned to each UE. The CRC-16 of the PDCCH DCIs is XORed with the RNTI to which the transmission is addressed. At any time, a UE knows the set of RNTIs that it is monitoring, so it calculates the CRC-16 of the received DCI, computes its XOR with each of its assigned RNTIs, and compares the result with the CRC-16 in the DCI. If there is a match, the DCI is accepted. This is a way of filtering out messages without spending additional bits to put the RNTI in a field in the DCI.
When we are monitoring an LTE downlink, we don’t know which RNTIs are being used. With some cleverness, if the SNR is good enough, we can detect and select each PDCCH transmission by hand (it is necessary to guess the REGs that it occupies and the DCI length) and then, assuming that we have decoded the DCI with no bit errors, obtain the RNTI as the XOR of the calculated CRC and the received CRC. This is what I did in the post about the PDCCH. If we were monitoring the LTE downlink for a longer time, this trick wouldn’t even be necessary. The C-RNTIs assigned to the UEs are communicated to them in a RAR transmitted with the RA-RNTI, as a response to their PRACH (see the post where I analyze this in Wireshark). So a downlink monitor application can simply watch the SI-RNTI, P-RNTI and RA-RNTI, and add any C-RNTIs to a list of known connected UEs when it sees a RAR. The C-RNTIs can be removed from this list after a period of inactivity, because the UE would have been sent to the idle state by the network. This idea really shows that it is possible to decode everything in the LTE downlink without doing clever blind decoding tricks.
In contrast, the LTE uplink is not self-descriptive. The eNB defines the configuration of each PUSCH transmission when it sends the uplink grant to the UE. So the UE doesn’t need to communicate this configuration again to the eNB when it transmits in the PUSCH. The information that describes the PUSCH transmissions is effectively in the PDCCH in the downlink, and in this case I don’t have a recording of the downlink that matches my uplink recording. This makes decoding the PUSCH much more difficult, but nevertheless not impossible. With some clever ideas and blind decoding tricks we can usually find all the information we’re missing. In the rest of this post, I describe how to do this in detail. It will be long and quite technical.