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:
Thomas Tsou
2013-10-15 15:12:24 -04:00
parent fe269fe31d
commit 3952d80d05
2 changed files with 49 additions and 31 deletions

View File

@@ -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);

View File

@@ -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;