during active RF collision defer stale stream reset;

pull/128/head
Bryan Biedenkapp 2 months ago
parent 5321821490
commit 0dc6e2bf41

@ -1024,7 +1024,7 @@ void Control::clock()
if (m_networkWatchdog.isRunning()) {
m_networkWatchdog.clock(ms);
if (m_networkWatchdog.hasExpired()) {
if (m_networkWatchdog.hasExpired() && !(m_netState == RS_NET_IDLE && m_rfState != RS_RF_LISTENING)) {
if (m_netState == RS_NET_AUDIO) {
if (m_voice->m_netFrames > 0.0F) {
::ActivityLog("P25", false, "network watchdog has expired, %.1f seconds, %u%% packet loss",
@ -1454,6 +1454,7 @@ void Control::processNetwork()
if (m_netState != RS_NET_DATA) {
// don't process network frames if the RF modem isn't in a listening state
if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE) {
m_networkWatchdog.start();
return;
}
}

@ -196,6 +196,16 @@ void HostTestHooks::p25SetRFCall(p25::Control& control, uint32_t srcId, uint32_t
control.m_rfTGHang.start();
}
/* Returns P25 control to RF listening state. */
void HostTestHooks::p25ClearRFCall(p25::Control& control)
{
control.m_rfState = RS_RF_LISTENING;
control.m_rfLastSrcId = 0U;
control.m_rfLastDstId = 0U;
control.m_rfTGHang.stop();
}
/* Forces P25 control into RF rejected state. */
void HostTestHooks::p25SetRFRejected(p25::Control& control)

@ -171,6 +171,11 @@ public:
* @param dstId Destination ID to apply to control state.
*/
static void p25SetRFCall(p25::Control& control, uint32_t srcId, uint32_t dstId);
/**
* @brief Returns P25 control to the RF listening state after a synthetic RF call.
* @param control P25 control instance.
*/
static void p25ClearRFCall(p25::Control& control);
/**
* @brief Forces P25 control into RF rejected state for tests.
* @param control P25 control instance.

@ -656,6 +656,123 @@ TEST_CASE("P25 host e2e loopback times out a stream before call state starts", "
REQUIRE(harness.network()->rxP25StreamId() == nextStream);
}
TEST_CASE("P25 host e2e loopback preserves a continuing network stream across an RF collision", "[p25][host][control][net][e2e]")
{
const uint16_t hostPort = reserveLoopbackPort();
const uint16_t senderPort = reserveLoopbackPort();
REQUIRE(hostPort != 0U);
REQUIRE(senderPort != 0U);
REQUIRE(hostPort != senderPort);
const uint32_t hostPeerId = 6009U;
const uint32_t streamId = 0x500201U;
P25HostHarness harness(true, true, hostPort, hostPeerId);
P25TestNetwork sender(senderPort, 6010U);
REQUIRE(harness.network() != nullptr);
REQUIRE(harness.network()->activateLoopback("127.0.0.1", senderPort));
REQUIRE(sender.activateLoopback("127.0.0.1", hostPort));
HostTestHooks::p25SetRFCall(*harness.m_control, 1401U, 2401U);
REQUIRE(sender.sendP25LDU1Frame(hostPeerId, streamId, 600U, 1501U, 2501U));
for (uint32_t i = 0U; i < 40U; i++) {
sender.clock(1U);
harness.network()->clock(1U);
harness.m_control->clock();
if (harness.network()->rxP25StreamId() == streamId &&
HostTestHooks::p25NetworkWatchdog(*harness.m_control).isRunning()) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
REQUIRE(HostTestHooks::p25NetState(*harness.m_control) == RS_NET_IDLE);
REQUIRE(harness.network()->rxP25StreamId() == streamId);
REQUIRE(harness.network()->resetP25Count() == 0U);
HostTestHooks::p25NetworkWatchdog(*harness.m_control).clock(expireTimerTicks(HostTestHooks::p25NetworkWatchdog(*harness.m_control)));
harness.m_control->clock();
REQUIRE(HostTestHooks::p25NetworkWatchdog(*harness.m_control).hasExpired());
REQUIRE(harness.network()->rxP25StreamId() == streamId);
REQUIRE(harness.network()->resetP25Count() == 0U);
HostTestHooks::p25ClearRFCall(*harness.m_control);
REQUIRE(sender.sendP25LDU1Frame(hostPeerId, streamId, 601U, 1501U, 2501U));
REQUIRE(sender.sendP25LDU2Frame(hostPeerId, streamId, 602U, 1501U, 2501U));
for (uint32_t i = 0U; i < 40U; i++) {
sender.clock(1U);
harness.network()->clock(1U);
harness.m_control->clock();
if (HostTestHooks::p25NetState(*harness.m_control) == RS_NET_AUDIO) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
REQUIRE(HostTestHooks::p25NetState(*harness.m_control) == RS_NET_AUDIO);
REQUIRE(harness.network()->rxP25StreamId() == streamId);
REQUIRE(harness.network()->resetP25Count() == 0U);
}
TEST_CASE("P25 host e2e loopback clears a stopped network stream after an RF collision", "[p25][host][control][net][e2e]")
{
const uint16_t hostPort = reserveLoopbackPort();
const uint16_t senderPort = reserveLoopbackPort();
REQUIRE(hostPort != 0U);
REQUIRE(senderPort != 0U);
REQUIRE(hostPort != senderPort);
const uint32_t hostPeerId = 6011U;
const uint32_t streamId = 0x500202U;
P25HostHarness harness(true, true, hostPort, hostPeerId);
P25TestNetwork sender(senderPort, 6012U);
REQUIRE(harness.network() != nullptr);
REQUIRE(harness.network()->activateLoopback("127.0.0.1", senderPort));
REQUIRE(sender.activateLoopback("127.0.0.1", hostPort));
HostTestHooks::p25SetRFCall(*harness.m_control, 1401U, 2401U);
REQUIRE(sender.sendP25LDU1Frame(hostPeerId, streamId, 700U, 1501U, 2501U));
for (uint32_t i = 0U; i < 40U; i++) {
sender.clock(1U);
harness.network()->clock(1U);
harness.m_control->clock();
if (harness.network()->rxP25StreamId() == streamId &&
HostTestHooks::p25NetworkWatchdog(*harness.m_control).isRunning()) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
REQUIRE(HostTestHooks::p25NetState(*harness.m_control) == RS_NET_IDLE);
REQUIRE(harness.network()->rxP25StreamId() == streamId);
REQUIRE(harness.network()->resetP25Count() == 0U);
HostTestHooks::p25NetworkWatchdog(*harness.m_control).clock(expireTimerTicks(HostTestHooks::p25NetworkWatchdog(*harness.m_control)));
harness.m_control->clock();
REQUIRE(HostTestHooks::p25NetworkWatchdog(*harness.m_control).hasExpired());
REQUIRE(harness.network()->rxP25StreamId() == streamId);
REQUIRE(harness.network()->resetP25Count() == 0U);
HostTestHooks::p25ClearRFCall(*harness.m_control);
harness.m_control->clock();
REQUIRE(HostTestHooks::p25NetState(*harness.m_control) == RS_NET_IDLE);
REQUIRE_FALSE(HostTestHooks::p25NetworkWatchdog(*harness.m_control).isRunning());
REQUIRE(harness.network()->rxP25StreamId() == 0U);
REQUIRE(harness.network()->resetP25Count() == 1U);
}
TEST_CASE("P25 host e2e loopback enforces stream lock until active stream terminates", "[p25][host][control][net][e2e]")
{
const uint16_t hostPort = reserveLoopbackPort();

Loading…
Cancel
Save

Powered by TurnKey Linux.