/* * 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(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 (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;