blob: a94ab72f3ffb75265660a229fabae534d2af6f2f [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_platform.h"
//#include <mac/mac_frame.hpp>
//#define DBG_FUZZ 1
bool g_fRadioEnabled = false;
uint8_t g_RecvChannel = 0;
uint8_t g_TransmitPsdu[128];
otRadioFrame g_TransmitRadioFrame;
bool g_fTransmit = false;
bool testFuzzRadioIsEnabled(otInstance *)
{
return g_fRadioEnabled;
}
otError testFuzzRadioEnable(otInstance *)
{
#ifdef DBG_FUZZ
Log("Radio enabled");
#endif
g_fRadioEnabled = true;
return OT_ERROR_NONE;
}
otError testFuzzRadioDisable(otInstance *)
{
#ifdef DBG_FUZZ
Log("Radio disabled");
#endif
g_fRadioEnabled = false;
return OT_ERROR_NONE;
}
otError testFuzzRadioReceive(otInstance *, uint8_t aChannel)
{
#ifdef DBG_FUZZ
Log("==> receive");
#endif
g_RecvChannel = aChannel;
return OT_ERROR_NONE;
}
otError testFuzzRadioTransmit(otInstance *)
{
#ifdef DBG_FUZZ
Log("==> transmit");
#endif
g_fTransmit = true;
return OT_ERROR_NONE;
}
otRadioFrame *testFuzztRadioGetTransmitBuffer(otInstance *)
{
return &g_TransmitRadioFrame;
}
void TestFuzz(uint32_t aSeconds)
{
// Set the radio capabilities to disable any Mac related timer dependencies
g_testPlatRadioCaps = (otRadioCaps)(OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_TRANSMIT_RETRIES);
// Set the platform function pointers
g_TransmitRadioFrame.mPsdu = g_TransmitPsdu;
g_testPlatRadioIsEnabled = testFuzzRadioIsEnabled;
g_testPlatRadioEnable = testFuzzRadioEnable;
g_testPlatRadioDisable = testFuzzRadioDisable;
g_testPlatRadioReceive = testFuzzRadioReceive;
g_testPlatRadioTransmit = testFuzzRadioTransmit;
g_testPlatRadioGetTransmitBuffer = testFuzztRadioGetTransmitBuffer;
// Initialize our timing variables
uint32_t tStart = otPlatAlarmGetNow();
uint32_t tEnd = tStart + (aSeconds * 1000);
otInstance *aInstance;
#ifdef _WIN32
uint32_t seed = (uint32_t)time(NULL);
srand(seed);
Log("Initialized seed = 0x%X", seed);
#endif
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
size_t otInstanceBufferLength = 0;
uint8_t *otInstanceBuffer = NULL;
// Call to query the buffer size
(void)otInstanceInit(NULL, &otInstanceBufferLength);
// Call to allocate the buffer
otInstanceBuffer = (uint8_t *)malloc(otInstanceBufferLength);
VerifyOrQuit(otInstanceBuffer != NULL, "Failed to allocate otInstance");
memset(otInstanceBuffer, 0, otInstanceBufferLength);
// Initialize OpenThread with the buffer
aInstance = otInstanceInit(otInstanceBuffer, &otInstanceBufferLength);
#else
aInstance = otInstanceInitSingle();
#endif
VerifyOrQuit(aInstance != NULL, "Failed to initialize otInstance");
// Start the Thread network
otLinkSetPanId(aInstance, (otPanId)0xFACE);
otIp6SetEnabled(aInstance, true);
otThreadSetEnabled(aInstance, true);
uint32_t countRecv = 0;
while (otPlatAlarmGetNow() < tEnd)
{
otTaskletsProcess(aInstance);
if (g_testPlatAlarmSet && otPlatAlarmGetNow() >= g_testPlatAlarmNext)
{
g_testPlatAlarmSet = false;
otPlatAlarmFired(aInstance);
}
if (g_fRadioEnabled)
{
if (g_fTransmit)
{
g_fTransmit = false;
otPlatRadioTxDone(aInstance, &g_TransmitRadioFrame, NULL, OT_ERROR_NONE);
#ifdef DBG_FUZZ
Log("<== transmit");
#endif
}
if (g_RecvChannel != 0)
{
uint8_t fuzzRecvBuff[128];
otRadioFrame fuzzPacket;
// Initialize the radio packet with a random length
memset(&fuzzPacket, 0, sizeof(fuzzPacket));
fuzzPacket.mPsdu = fuzzRecvBuff;
fuzzPacket.mChannel = g_RecvChannel;
fuzzPacket.mLength = (uint8_t)(otPlatRandomGet() % 127);
// Populate the length with random
for (uint8_t i = 0; i < fuzzPacket.mLength; i++)
{
fuzzRecvBuff[i] = (uint8_t)otPlatRandomGet();
}
// Clear the global flag
g_RecvChannel = 0;
// Indicate the receive complete
otPlatRadioReceiveDone(aInstance, &fuzzPacket, OT_ERROR_NONE);
countRecv++;
#ifdef DBG_FUZZ
Log("<== receive (%llu, %u bytes)", countRecv, fuzzPacket.mLength);
#endif
// Hack to get a receive poll immediately
otLinkSetChannel(aInstance, 11);
}
}
}
Log("%u packets received", countRecv);
// Clean up the instance
otInstanceFinalize(aInstance);
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
free(otInstanceBuffer);
#endif
}
#ifdef ENABLE_TEST_MAIN
int main(void)
{
TestFuzz(30);
printf("All tests passed\n");
return 0;
}
#endif