blob: 08c3a6de6c975284a458fadcb1102f6926173883 [file] [log] [blame]
/*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 "HeaderProcessingContextTestFixture.h"
#include "TestsUtils.h"
const Byte IpaHdrProcCtxTestFixture::WLAN_ETH2_HDR[WLAN_ETH2_HDR_SIZE] =
{
// WLAN hdr - 4 bytes
0xa1, 0xb2, 0xc3, 0xd4,
// ETH2 - 14 bytes
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
const Byte IpaHdrProcCtxTestFixture::ETH2_HDR[ETH_HLEN] =
{
// ETH2 - 14 bytes
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
const Byte IpaHdrProcCtxTestFixture::ETH2_8021Q_HDR[ETH8021Q_HEADER_LEN] =
{
// 802_1Q - 18 bytes
// src and dst MAC - 6 + 6 bytes
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 802_1Q tag - VLAN ID 3
0x81, 0x00, 0x00, 0x03,
// ethertype
0x00, 0x00
};
const Byte IpaHdrProcCtxTestFixture::WLAN_802_3_HDR[WLAN_802_3_HDR_SIZE] =
{
// WLAN hdr - 4 bytes
0x0a, 0x0b, 0x0c, 0x0d,
// 802_3 - 26 bytes
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
IpaHdrProcCtxTestFixture::IpaHdrProcCtxTestFixture():
m_procCtxHandleId(PROC_CTX_HANDLE_ID_MAX),
m_pCurrentProducer(NULL),
m_pCurrentConsumer(NULL),
m_sendSize1 (m_BUFF_MAX_SIZE),
m_sendSize2 (m_BUFF_MAX_SIZE),
m_expectedBufferSize1(0),
m_IpaIPType(IPA_IP_v4)
{
memset(m_headerHandles, 0, sizeof(m_headerHandles));
memset(m_procCtxHHandles, 0, sizeof(m_procCtxHHandles));
memset(m_sendBuffer1, 0, sizeof(m_sendBuffer1));
memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2));
memset(m_expectedBuffer1, 0, sizeof(m_expectedBuffer1));
m_testSuiteName.push_back("HdrProcCtx");
}
bool IpaHdrProcCtxTestFixture::Setup()
{
ConfigureScenario(PHASE_TWENTY_TEST_CONFIGURATION);
// init producers
m_rndisEth2Producer.Open(INTERFACE0_TO_IPA_DATA_PATH,
INTERFACE0_FROM_IPA_DATA_PATH);
m_wlanEth2producer.Open(INTERFACE4_TO_IPA_DATA_PATH,
INTERFACE4_FROM_IPA_DATA_PATH);
m_eth2Producer.Open(INTERFACE5_TO_IPA_DATA_PATH,
INTERFACE5_FROM_IPA_DATA_PATH);
// init consumers
m_defaultConsumer.Open(INTERFACE1_TO_IPA_DATA_PATH,
INTERFACE1_FROM_IPA_DATA_PATH);
m_rndisEth2Consumer.Open(INTERFACE2_TO_IPA_DATA_PATH,
INTERFACE2_FROM_IPA_DATA_PATH);
if (!m_headerInsertion.DeviceNodeIsOpened())
{
LOG_MSG_ERROR("HeaderInsertion block is not ready "
"for immediate commands!\n");
return false;
}
if (!m_routing.DeviceNodeIsOpened())
{
LOG_MSG_ERROR("Routing block is not ready "
"for immediate commands!\n");
return false;
}
if (!m_filtering.DeviceNodeIsOpened())
{
LOG_MSG_ERROR("Filtering block is not ready "
"for immediate commands!\n");
return false;
}
// resetting this component will reset
// both Routing and Filtering tables
m_headerInsertion.Reset();
return true;
} // Setup()
bool IpaHdrProcCtxTestFixture::Teardown()
{
m_rndisEth2Producer.Close();
m_wlanEth2producer.Close();
m_eth2Producer.Close();
m_defaultConsumer.Close();
m_rndisEth2Consumer.Close();
return true;
} // Teardown()
void IpaHdrProcCtxTestFixture::AddAllHeaders()
{
for (int i = 0; i < HEADER_HANDLE_ID_MAX; i++) {
AddHeader(static_cast<HeaderHandleId>(i));
}
}
// Insert a single header
void IpaHdrProcCtxTestFixture::AddHeader(HeaderHandleId handleId)
{
static const int NUM_OF_HEADERS = 1;
struct ipa_ioc_add_hdr *hdrTable = NULL;
struct ipa_hdr_add *hdr = NULL;
// init hdr table
hdrTable = (struct ipa_ioc_add_hdr *) calloc(1,
sizeof(struct ipa_ioc_add_hdr)
+ NUM_OF_HEADERS * sizeof(struct ipa_hdr_add));
if (!hdrTable)
{
LOG_MSG_ERROR(
"calloc failed to allocate pHeaderDescriptor");
return;
}
hdrTable->commit = true;
hdrTable->num_hdrs = NUM_OF_HEADERS;
// init the hdr common fields
hdr = &hdrTable->hdr[0];
hdr->hdr_hdl = -1; //Return Value
hdr->is_partial = false;
hdr->status = -1; // Return Parameter
// init hdr specific fields
switch (handleId)
{
case HEADER_HANDLE_ID_WLAN_ETH2:
memcpy(hdr->hdr, WLAN_ETH2_HDR, WLAN_ETH2_HDR_SIZE);
hdr->hdr_len = WLAN_ETH2_HDR_SIZE;
strlcpy(hdr->name, "WLAN_ETH2", sizeof(hdr->name));
hdr->type = IPA_HDR_L2_ETHERNET_II;
break;
case HEADER_HANDLE_ID_RNDIS_ETH2:
if (!RNDISAggregationHelper::LoadRNDISEth2IP4Header(
hdr->hdr,
IPA_HDR_MAX_SIZE,
0,
(size_t*)&hdr->hdr_len))
return;
strlcpy(hdr->name, "RNDIS_ETH2", sizeof(hdr->name));
hdr->type = IPA_HDR_L2_ETHERNET_II;
break;
case HEADER_HANDLE_ID_ETH2:
strlcpy(hdr->name, "ETH2", sizeof(hdr->name));
memcpy(hdr->hdr, ETH2_HDR, ETH_HLEN);
hdr->type = IPA_HDR_L2_ETHERNET_II;
hdr->hdr_len = ETH_HLEN;
break;
case HEADER_HANDLE_ID_WLAN_802_3:
strlcpy(hdr->name, "WLAN_802_3", sizeof(hdr->name));
memcpy(hdr->hdr, WLAN_802_3_HDR, WLAN_802_3_HDR_SIZE);
hdr->type = IPA_HDR_L2_802_3;
hdr->hdr_len = WLAN_802_3_HDR_SIZE;
LOG_MSG_DEBUG(
"HEADER_HANDLE_ID_WLAN_802_3 NOT supported for now");
return;
break;
case HEADER_HANDLE_ID_VLAN_802_1Q:
strlcpy(hdr->name, "VLAN_8021Q", sizeof(hdr->name));
memcpy(hdr->hdr, ETH2_8021Q_HDR, ETH8021Q_HEADER_LEN);
hdr->type = IPA_HDR_L2_802_1Q;
hdr->hdr_len = ETH8021Q_HEADER_LEN;
break;
default:
LOG_MSG_ERROR("header handleId not supported.");
return;
}
// commit header to HW
if (!m_headerInsertion.AddHeader(hdrTable))
{
LOG_MSG_ERROR("m_headerInsertion.AddHeader() failed.");
return;
}
// save header handle
m_headerHandles[handleId] = hdr->hdr_hdl;
}
void IpaHdrProcCtxTestFixture::AddAllProcCtx()
{
for (int i = 0; i <PROC_CTX_HANDLE_ID_MAX; i++)
{
AddProcCtx(static_cast<ProcCtxHandleId>(i));
}
}
// Insert a single proc_ctx
void IpaHdrProcCtxTestFixture::AddProcCtx(ProcCtxHandleId handleId)
{
static const int NUM_OF_PROC_CTX = 1;
struct ipa_ioc_add_hdr_proc_ctx *procCtxTable = NULL;
struct ipa_hdr_proc_ctx_add *procCtx = NULL;
// init proc ctx table
procCtxTable = (struct ipa_ioc_add_hdr_proc_ctx *)calloc(1,
sizeof(struct ipa_ioc_add_hdr_proc_ctx)
+ NUM_OF_PROC_CTX *
sizeof(struct ipa_hdr_proc_ctx_add));
if (!procCtxTable)
{
LOG_MSG_ERROR("calloc failed to allocate procCtxTable");
return;
}
procCtxTable->commit = true;
procCtxTable->num_proc_ctxs = NUM_OF_PROC_CTX;
// init proc_ctx common fields
procCtx = &procCtxTable->proc_ctx[0];
procCtx->proc_ctx_hdl = -1; // return value
procCtx->status = -1; // Return parameter
// init proc_ctx specific fields
switch (handleId)
{
case PROC_CTX_HANDLE_ID_ETH2_2_WLAN_ETH2:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_WLAN_ETH2];
break;
case PROC_CTX_HANDLE_ID_ETH2_2_RNDIS_ETH2:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_RNDIS_ETH2];
break;
case PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_ETH2];
break;
case PROC_CTX_HANDLE_ID_WLAN_ETH2_2_802_3:
procCtx->type = IPA_HDR_PROC_ETHII_TO_802_3;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_WLAN_802_3];
break;
case PROC_CTX_HANDLE_ID_RNDIS_802_3_2_ETH2:
procCtx->type = IPA_HDR_PROC_802_3_TO_ETHII;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_RNDIS_ETH2];
break;
case PROC_CTX_HANDLE_ID_WLAN_802_3_2_ETH2:
procCtx->type = IPA_HDR_PROC_802_3_TO_802_3;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_WLAN_802_3];
break;
case PROC_CTX_HANDLE_ID_802_1Q_2_802_1Q:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_VLAN_802_1Q];
procCtx->generic_params.input_ethhdr_negative_offset = 18;
procCtx->generic_params.output_ethhdr_negative_offset = 18;
break;
case PROC_CTX_HANDLE_ID_802_1Q_2_ETH2:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_ETH2];
procCtx->generic_params.input_ethhdr_negative_offset = 18;
procCtx->generic_params.output_ethhdr_negative_offset = 14;
break;
case PROC_CTX_HANDLE_ID_ETH2_2_802_1Q:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_VLAN_802_1Q];
procCtx->generic_params.input_ethhdr_negative_offset = 14;
procCtx->generic_params.output_ethhdr_negative_offset = 18;
break;
case PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2_EX:
procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX;
procCtx->hdr_hdl =
m_headerHandles[HEADER_HANDLE_ID_ETH2];
procCtx->generic_params.input_ethhdr_negative_offset = 14;
procCtx->generic_params.output_ethhdr_negative_offset = 14;
break;
default:
LOG_MSG_ERROR("proc ctx handleId %d not supported.", handleId);
return;
}
if (!m_headerInsertion.AddProcCtx(procCtxTable))
{
LOG_MSG_ERROR("m_headerInsertion.AddProcCtx(procCtxTable) failed.");
return;
}
// save proc_ctx handle
m_procCtxHHandles[handleId] = procCtx->proc_ctx_hdl;
}
void IpaHdrProcCtxTestFixture::AddRtBypassRule(uint32_t hdrHdl, uint32_t procCtxHdl)
{
static const char bypass0[] = "bypass0";
struct ipa_ioc_get_rt_tbl routing_table0;
if (!CreateIPv4BypassRoutingTable (
bypass0,
hdrHdl,
procCtxHdl))
{
LOG_MSG_ERROR("CreateIPv4BypassRoutingTable Failed\n");
return;
}
routing_table0.ip = IPA_IP_v4;
strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name));
if (!m_routing.GetRoutingTable(&routing_table0))
{
LOG_MSG_ERROR("m_routing.GetRoutingTable() Failed.");
return;
}
m_routingTableHdl = routing_table0.hdl;
}
void IpaHdrProcCtxTestFixture::AddFltBypassRule()
{
IPAFilteringTable FilterTable0;
struct ipa_flt_rule_add flt_rule_entry;
FilterTable0.Init(IPA_IP_v4,m_currProducerClient,false,1);
printf("FilterTable*.Init Completed Successfully..\n");
// Configuring Filtering Rule No.0
FilterTable0.GeneratePresetRule(1,flt_rule_entry);
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl=-1; // return Value
flt_rule_entry.status = -1; // return value
flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING;
flt_rule_entry.rule.rt_tbl_hdl=m_routingTableHdl;
flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Mask - Bypass rule
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x12345678; // Filter is irrelevant.
if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) ||
!m_filtering.AddFilteringRule(
FilterTable0.GetFilteringTable()))
{
LOG_MSG_ERROR(
"%s::m_filtering.AddFilteringRule() failed",
__FUNCTION__);
return;
}
else
{
printf("flt rule hdl0=0x%x, status=0x%x\n",
FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,
FilterTable0.ReadRuleFromTable(0)->status);
}
}
bool IpaHdrProcCtxTestFixture::ReceivePacketsAndCompare()
{
size_t receivedBufferSize1 = 0;
bool isSuccess = true;
// Receive results
Byte *receivedBuffer1 = new Byte[m_BUFF_MAX_SIZE];
if (NULL == receivedBuffer1)
{
printf("Memory allocation error.\n");
return false;
}
receivedBufferSize1 = m_pCurrentConsumer->ReceiveData(
receivedBuffer1,
m_BUFF_MAX_SIZE);
printf("Received %zu bytes on %s.\n",
receivedBufferSize1,
m_pCurrentConsumer->m_fromChannelName.c_str());
// Compare results
if (!CompareResultVsGolden(
m_expectedBuffer1,
m_expectedBufferSize1,
receivedBuffer1,
receivedBufferSize1))
{
printf("Comparison of Buffer Failed!\n");
isSuccess = false;
}
printf("Expected buffer 1 - %zu bytes\n", m_expectedBufferSize1);
print_buff(m_expectedBuffer1, m_expectedBufferSize1);
printf("Received buffer 1 - %zu bytes\n", receivedBufferSize1);
print_buff(receivedBuffer1, receivedBufferSize1);
delete[] receivedBuffer1;
return isSuccess;
}
// Create 1 IPv4 bypass routing entry and commits it
bool IpaHdrProcCtxTestFixture::CreateIPv4BypassRoutingTable (
const char *name,
uint32_t hdrHdl,
uint32_t procCtxHdl)
{
printf("Entering %s, %s()\n",__FUNCTION__, __FILE__);
struct ipa_ioc_add_rt_rule *rt_table = 0;
struct ipa_rt_rule_add *rt_rule_entry = NULL;
// Verify that only one is nonzero
if ((hdrHdl == 0 && procCtxHdl == 0) ||
(hdrHdl != 0 && procCtxHdl != 0))
{
LOG_MSG_ERROR("Error: hdrHdl = %u, procCtxHdl = %u\n");
return false;
}
rt_table = (struct ipa_ioc_add_rt_rule *)
calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
1*sizeof(struct ipa_rt_rule_add));
if(!rt_table) {
LOG_MSG_ERROR("calloc failed to allocate rt_table\n");
return false;
}
rt_table->num_rules = 1;
rt_table->ip = IPA_IP_v4;
rt_table->commit = true;
strlcpy(rt_table->rt_tbl_name, name, sizeof(rt_table->rt_tbl_name));
rt_rule_entry = &rt_table->rules[0];
rt_rule_entry->at_rear = 0;
rt_rule_entry->rule.dst = m_currConsumerPipeNum;
rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd;
// All Packets will get a "Hit"
rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;
rt_rule_entry->rule.hdr_hdl = hdrHdl;
rt_rule_entry->rule.hdr_proc_ctx_hdl = procCtxHdl;
if (false == m_routing.AddRoutingRule(rt_table))
{
printf("Routing rule addition(rt_table) failed!\n");
Free (rt_table);
return false;
}
Free (rt_table);
printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__);
return true;
}
bool IpaHdrProcCtxTestFixture::AddRules()
{
printf("Entering %s, %s()\n",__FUNCTION__, __FILE__);
if (m_procCtxHandleId == PROC_CTX_HANDLE_ID_MAX)
{
LOG_MSG_ERROR("Test developer didn't implement "
"AddRules() or didn't set m_procCtxHandleId");
return false;
}
AddAllHeaders();
AddAllProcCtx();
AddRtBypassRule(0, m_procCtxHHandles[m_procCtxHandleId]);
AddFltBypassRule();
printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__);
return true;
}// AddRules()
bool IpaHdrProcCtxTestFixture::SendPackets()
{
bool isSuccess = false;
// Send first packet
isSuccess = m_pCurrentProducer->SendData(
m_sendBuffer1,
m_sendSize1);
if (false == isSuccess)
{
LOG_MSG_ERROR("SendPackets Buffer1 failed on client %d\n", m_currProducerClient);
return false;
}
return true;
}
bool IpaHdrProcCtxTestFixture::Run()
{
bool res = false;
bool isSuccess = false;
printf("Entering %s, %s()\n",__FUNCTION__, __FILE__);
res = AddRules();
if (false == res) {
printf("Failed adding filtering rules.\n");
return false;
}
// Load input data - IP packets
res = LoadPackets(m_IpaIPType);
if (false == res) {
printf("Failed loading packets.\n");
return false;
}
res = GenerateExpectedPackets();
if (false == res) {
printf("GenerateExpectedPackets failed\n");
return false;
}
res = SendPackets();
if (false == res) {
printf("SendPackets failed\n");
return false;
}
// Receive packets from the channels and compare results
isSuccess = ReceivePacketsAndCompare();
printf("Leaving %s, %s(), Returning %d\n",
__FUNCTION__,
__FILE__,
isSuccess);
return isSuccess;
} // Run()
IpaHdrProcCtxTestFixture::~IpaHdrProcCtxTestFixture()
{
m_sendSize1 = 0;
}
RoutingDriverWrapper IpaHdrProcCtxTestFixture::m_routing;
Filtering IpaHdrProcCtxTestFixture::m_filtering;
HeaderInsertion IpaHdrProcCtxTestFixture::m_headerInsertion;