mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
synced 2025-11-15 11:21:50 +00:00
Transceiver52M: Reduce and place bounds checking on I/O buffers
Previous send and receive buffers at the radio interface were arbitrarily set to a sufficient size. For normal (non-resampling) devices, use a block (chunk) size of 625 samples. For 64 or 100 MHz resampling devices, use 4 times the reduced resampling numerator or denominator and provide bounds checking where appropriate. Signed-off-by: Thomas Tsou <tom@tsou.cc>
This commit is contained in:
@@ -30,8 +30,8 @@ extern "C" {
|
|||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INCHUNK (625 * SAMPSPERSYM)
|
#define CHUNK 625
|
||||||
#define OUTCHUNK (625 * SAMPSPERSYM)
|
#define NUMCHUNKS 4
|
||||||
|
|
||||||
RadioInterface::RadioInterface(RadioDevice *wRadio,
|
RadioInterface::RadioInterface(RadioDevice *wRadio,
|
||||||
int wReceiveOffset,
|
int wReceiveOffset,
|
||||||
@@ -58,11 +58,11 @@ bool RadioInterface::init(int type)
|
|||||||
|
|
||||||
close();
|
close();
|
||||||
|
|
||||||
sendBuffer = new signalVector(OUTCHUNK * 20);
|
sendBuffer = new signalVector(CHUNK * mSPSTx);
|
||||||
recvBuffer = new signalVector(INCHUNK * 20);
|
recvBuffer = new signalVector(NUMCHUNKS * CHUNK * mSPSRx);
|
||||||
|
|
||||||
convertSendBuffer = new short[OUTCHUNK * 2 * 20];
|
convertSendBuffer = new short[sendBuffer->size() * 2];
|
||||||
convertRecvBuffer = new short[OUTCHUNK * 2 * 2];
|
convertRecvBuffer = new short[recvBuffer->size() * 2];
|
||||||
|
|
||||||
sendCursor = 0;
|
sendCursor = 0;
|
||||||
recvCursor = 0;
|
recvCursor = 0;
|
||||||
@@ -276,23 +276,26 @@ double RadioInterface::getRxGain()
|
|||||||
void RadioInterface::pullBuffer()
|
void RadioInterface::pullBuffer()
|
||||||
{
|
{
|
||||||
bool local_underrun;
|
bool local_underrun;
|
||||||
int num_recv, len = OUTCHUNK / mSPSTx;
|
int num_recv;
|
||||||
float *output;
|
float *output;
|
||||||
|
|
||||||
|
if (recvCursor > recvBuffer->size() - CHUNK)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Outer buffer access size is fixed */
|
/* Outer buffer access size is fixed */
|
||||||
num_recv = mRadio->readSamples(convertRecvBuffer,
|
num_recv = mRadio->readSamples(convertRecvBuffer,
|
||||||
len,
|
CHUNK,
|
||||||
&overrun,
|
&overrun,
|
||||||
readTimestamp,
|
readTimestamp,
|
||||||
&local_underrun);
|
&local_underrun);
|
||||||
if (num_recv != len) {
|
if (num_recv != CHUNK) {
|
||||||
LOG(ALERT) << "Receive error " << num_recv;
|
LOG(ALERT) << "Receive error " << num_recv;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = (float *) (recvBuffer->begin() + recvCursor);
|
output = (float *) (recvBuffer->begin() + recvCursor);
|
||||||
|
|
||||||
convert_short_float(output, convertRecvBuffer, 2 * len);
|
convert_short_float(output, convertRecvBuffer, 2 * num_recv);
|
||||||
|
|
||||||
underrun |= local_underrun;
|
underrun |= local_underrun;
|
||||||
|
|
||||||
@@ -305,9 +308,12 @@ void RadioInterface::pushBuffer()
|
|||||||
{
|
{
|
||||||
int num_sent;
|
int num_sent;
|
||||||
|
|
||||||
if (sendCursor < INCHUNK)
|
if (sendCursor < CHUNK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (sendCursor > sendBuffer->size())
|
||||||
|
LOG(ALERT) << "Send buffer overflow";
|
||||||
|
|
||||||
convert_float_short(convertSendBuffer,
|
convert_float_short(convertSendBuffer,
|
||||||
(float *) sendBuffer->begin(),
|
(float *) sendBuffer->begin(),
|
||||||
powerScaling, 2 * sendCursor);
|
powerScaling, 2 * sendCursor);
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ extern "C" {
|
|||||||
#define RESAMP_100M_INRATE 52
|
#define RESAMP_100M_INRATE 52
|
||||||
#define RESAMP_100M_OUTRATE 75
|
#define RESAMP_100M_OUTRATE 75
|
||||||
|
|
||||||
|
/* Universal resampling parameters */
|
||||||
|
#define NUMCHUNKS 24
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resampling filter bandwidth scaling factor
|
* Resampling filter bandwidth scaling factor
|
||||||
* This narrows the filter cutoff relative to the output bandwidth
|
* This narrows the filter cutoff relative to the output bandwidth
|
||||||
@@ -116,6 +119,11 @@ bool RadioInterfaceResamp::init(int type)
|
|||||||
resamp_inchunk = resamp_inrate * 4;
|
resamp_inchunk = resamp_inrate * 4;
|
||||||
resamp_outchunk = resamp_outrate * 4;
|
resamp_outchunk = resamp_outrate * 4;
|
||||||
|
|
||||||
|
if (resamp_inchunk * NUMCHUNKS < 157 * mSPSTx * 2) {
|
||||||
|
LOG(ALERT) << "Invalid inner chunk size " << resamp_inchunk;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mSPSTx == 4)
|
if (mSPSTx == 4)
|
||||||
cutoff = RESAMP_TX4_FILTER;
|
cutoff = RESAMP_TX4_FILTER;
|
||||||
|
|
||||||
@@ -137,16 +145,17 @@ bool RadioInterfaceResamp::init(int type)
|
|||||||
* and requires headroom equivalent to the filter length. Low
|
* and requires headroom equivalent to the filter length. Low
|
||||||
* rate buffers are allocated in the main radio interface code.
|
* rate buffers are allocated in the main radio interface code.
|
||||||
*/
|
*/
|
||||||
innerSendBuffer = new signalVector(resamp_inchunk * 20,
|
innerSendBuffer =
|
||||||
upsampler->len());
|
new signalVector(NUMCHUNKS * resamp_inchunk, upsampler->len());
|
||||||
outerSendBuffer = new signalVector(resamp_outchunk * 20);
|
outerSendBuffer =
|
||||||
|
new signalVector(NUMCHUNKS * resamp_outchunk);
|
||||||
|
outerRecvBuffer =
|
||||||
|
new signalVector(resamp_outchunk, dnsampler->len());
|
||||||
|
innerRecvBuffer =
|
||||||
|
new signalVector(NUMCHUNKS * resamp_inchunk / mSPSTx);
|
||||||
|
|
||||||
outerRecvBuffer = new signalVector(resamp_outchunk * 2,
|
convertSendBuffer = new short[outerSendBuffer->size() * 2];
|
||||||
dnsampler->len());
|
convertRecvBuffer = new short[outerRecvBuffer->size() * 2];
|
||||||
innerRecvBuffer = new signalVector(resamp_inchunk * 20);
|
|
||||||
|
|
||||||
convertSendBuffer = new short[resamp_outchunk * 2 * 20];
|
|
||||||
convertRecvBuffer = new short[resamp_outchunk * 2 * 2];
|
|
||||||
|
|
||||||
sendBuffer = innerSendBuffer;
|
sendBuffer = innerSendBuffer;
|
||||||
recvBuffer = innerRecvBuffer;
|
recvBuffer = innerRecvBuffer;
|
||||||
@@ -159,35 +168,37 @@ void RadioInterfaceResamp::pullBuffer()
|
|||||||
{
|
{
|
||||||
bool local_underrun;
|
bool local_underrun;
|
||||||
int rc, num_recv;
|
int rc, num_recv;
|
||||||
int inner_len = resamp_inchunk;
|
|
||||||
int outer_len = resamp_outchunk;
|
if (recvCursor > innerRecvBuffer->size() - resamp_inchunk)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Outer buffer access size is fixed */
|
/* Outer buffer access size is fixed */
|
||||||
num_recv = mRadio->readSamples(convertRecvBuffer,
|
num_recv = mRadio->readSamples(convertRecvBuffer,
|
||||||
outer_len,
|
resamp_outchunk,
|
||||||
&overrun,
|
&overrun,
|
||||||
readTimestamp,
|
readTimestamp,
|
||||||
&local_underrun);
|
&local_underrun);
|
||||||
if (num_recv != outer_len) {
|
if (num_recv != resamp_outchunk) {
|
||||||
LOG(ALERT) << "Receive error " << num_recv;
|
LOG(ALERT) << "Receive error " << num_recv;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_short_float((float *) outerRecvBuffer->begin(),
|
convert_short_float((float *) outerRecvBuffer->begin(),
|
||||||
convertRecvBuffer, 2 * outer_len);
|
convertRecvBuffer, 2 * resamp_outchunk);
|
||||||
|
|
||||||
underrun |= local_underrun;
|
underrun |= local_underrun;
|
||||||
readTimestamp += (TIMESTAMP) num_recv;
|
readTimestamp += (TIMESTAMP) resamp_outchunk;
|
||||||
|
|
||||||
/* Write to the end of the inner receive buffer */
|
/* Write to the end of the inner receive buffer */
|
||||||
rc = dnsampler->rotate((float *) outerRecvBuffer->begin(), outer_len,
|
rc = dnsampler->rotate((float *) outerRecvBuffer->begin(),
|
||||||
|
resamp_outchunk,
|
||||||
(float *) (innerRecvBuffer->begin() + recvCursor),
|
(float *) (innerRecvBuffer->begin() + recvCursor),
|
||||||
inner_len);
|
resamp_inchunk);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
LOG(ALERT) << "Sample rate upsampling error";
|
LOG(ALERT) << "Sample rate upsampling error";
|
||||||
}
|
}
|
||||||
|
|
||||||
recvCursor += inner_len;
|
recvCursor += resamp_inchunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a timestamped chunk to the device */
|
/* Send a timestamped chunk to the device */
|
||||||
@@ -199,9 +210,10 @@ void RadioInterfaceResamp::pushBuffer()
|
|||||||
if (sendCursor < resamp_inchunk)
|
if (sendCursor < resamp_inchunk)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (sendCursor > innerSendBuffer->size())
|
||||||
|
LOG(ALERT) << "Send buffer overflow";
|
||||||
|
|
||||||
chunks = sendCursor / resamp_inchunk;
|
chunks = sendCursor / resamp_inchunk;
|
||||||
if (chunks > 8)
|
|
||||||
chunks = 8;
|
|
||||||
|
|
||||||
inner_len = chunks * resamp_inchunk;
|
inner_len = chunks * resamp_inchunk;
|
||||||
outer_len = chunks * resamp_outchunk;
|
outer_len = chunks * resamp_outchunk;
|
||||||
|
|||||||
Reference in New Issue
Block a user