235599e5f6
git-subtree-dir: qcom/opensource/dataipa git-subtree-mainline:78e1eefbdb
git-subtree-split:c743113db7
Change-Id: repo: https://git.codelinaro.org/clo/la/platform/vendor/opensource/dataipa tag: LA.VENDOR.14.3.0.r1-17300-lanai.QSSI15.0
508 lines
12 KiB
C
508 lines
12 KiB
C
/*
|
|
* Copyright (c) 2014, 2018-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 <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <libgen.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include "ipa_nat_test.h"
|
|
#include "ipa_nat_map.h"
|
|
|
|
#undef strcasesame
|
|
#define strcasesame(x, y) \
|
|
(! strcasecmp((x), (y)))
|
|
|
|
static inline const char* legal_mem_type(
|
|
const char* mt )
|
|
{
|
|
if ( strcasesame(mt, "DDR") ) return "DDR";
|
|
if ( strcasesame(mt, "SRAM") ) return "SRAM";
|
|
if ( strcasesame(mt, "HYBRID") ) return "HYBRID";
|
|
return NULL;
|
|
}
|
|
|
|
static int nat_rule_loop_check(
|
|
ipa_table* table_ptr,
|
|
uint32_t rule_hdl,
|
|
void* record_ptr,
|
|
uint16_t record_index,
|
|
void* meta_record_ptr,
|
|
uint16_t meta_record_index,
|
|
void* arb_data_ptr )
|
|
{
|
|
enum ipa3_nat_mem_in nmi;
|
|
uint8_t is_expn_tbl;
|
|
uint16_t rule_index;
|
|
uint32_t tbl_hdl = (uint32_t) arb_data_ptr;
|
|
|
|
struct ipa_nat_rule* rule_ptr =
|
|
(struct ipa_nat_rule*) record_ptr;
|
|
|
|
BREAK_RULE_HDL(table_ptr, rule_hdl, nmi, is_expn_tbl, rule_index);
|
|
|
|
/*
|
|
* By virtue of this function being called back by the walk, this
|
|
* record_index is valid. Denote it as such in the map...
|
|
*/
|
|
if ( ipa_nat_map_add(MAP_NUM_99, record_index, 1) )
|
|
{
|
|
IPAERR("ipa_nat_map_add(index(%u)) failed\n", record_index);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( rule_ptr->next_index == record_index )
|
|
{
|
|
IPAERR("Infinite loop detected in IPv4 %s table, entry %u\n",
|
|
(is_expn_tbl) ? "expansion" : "base",
|
|
record_index);
|
|
|
|
ipa_nat_dump_ipv4_table(tbl_hdl);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int nat_rule_validity_check(
|
|
ipa_table* table_ptr,
|
|
uint32_t rule_hdl,
|
|
void* record_ptr,
|
|
uint16_t record_index,
|
|
void* meta_record_ptr,
|
|
uint16_t meta_record_index,
|
|
void* arb_data_ptr )
|
|
{
|
|
enum ipa3_nat_mem_in nmi;
|
|
uint8_t is_expn_tbl;
|
|
uint16_t rule_index;
|
|
uint16_t index;
|
|
|
|
struct ipa_nat_rule* rule_ptr =
|
|
(struct ipa_nat_rule*) record_ptr;
|
|
|
|
BREAK_RULE_HDL(table_ptr, rule_hdl, nmi, is_expn_tbl, rule_index);
|
|
|
|
index = rule_ptr->next_index;
|
|
|
|
if ( index && ipa_nat_map_find(MAP_NUM_99, index, NULL) )
|
|
{
|
|
IPAERR("Invalid next index %u found in IPv4 %s table entry %u\n",
|
|
index,
|
|
(is_expn_tbl) ? "expansion" : "base",
|
|
rule_index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( is_expn_tbl )
|
|
{
|
|
index = rule_ptr->prev_index;
|
|
|
|
if ( index && ipa_nat_map_find(MAP_NUM_99, index, NULL) )
|
|
{
|
|
IPAERR("Invalid previous index %u found in IPv4 %s table entry %u\n",
|
|
index,
|
|
"expansion",
|
|
rule_index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int index_loop_check(
|
|
ipa_table* table_ptr,
|
|
uint32_t rule_hdl,
|
|
void* record_ptr,
|
|
uint16_t record_index,
|
|
void* meta_record_ptr,
|
|
uint16_t meta_record_index,
|
|
void* arb_data_ptr )
|
|
{
|
|
enum ipa3_nat_mem_in nmi;
|
|
uint8_t is_expn_tbl;
|
|
uint16_t rule_index;
|
|
uint32_t tbl_hdl = (uint32_t) arb_data_ptr;
|
|
|
|
struct ipa_nat_indx_tbl_rule* itr_ptr =
|
|
(struct ipa_nat_indx_tbl_rule*) record_ptr;
|
|
|
|
BREAK_RULE_HDL(table_ptr, rule_hdl, nmi, is_expn_tbl, rule_index);
|
|
|
|
/*
|
|
* By virtue of this function being called back by the walk, this
|
|
* record_index is valid. Denote it as such in the map...
|
|
*/
|
|
if ( ipa_nat_map_add(MAP_NUM_99, record_index, 1) )
|
|
{
|
|
IPAERR("ipa_nat_map_add(index(%u)) failed\n", record_index);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( itr_ptr->next_index == record_index )
|
|
{
|
|
IPAERR("Infinite loop detected in IPv4 index %s table, entry %u\n",
|
|
(is_expn_tbl) ? "expansion" : "base",
|
|
record_index);
|
|
|
|
ipa_nat_dump_ipv4_table(tbl_hdl);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int index_validity_check(
|
|
ipa_table* table_ptr,
|
|
uint32_t rule_hdl,
|
|
void* record_ptr,
|
|
uint16_t record_index,
|
|
void* meta_record_ptr,
|
|
uint16_t meta_record_index,
|
|
void* arb_data_ptr )
|
|
{
|
|
enum ipa3_nat_mem_in nmi;
|
|
uint8_t is_expn_tbl;
|
|
uint16_t rule_index;
|
|
uint16_t index;
|
|
|
|
struct ipa_nat_indx_tbl_rule* itr_ptr =
|
|
(struct ipa_nat_indx_tbl_rule*) record_ptr;
|
|
|
|
BREAK_RULE_HDL(table_ptr, rule_hdl, nmi, is_expn_tbl, rule_index);
|
|
|
|
index = itr_ptr->next_index;
|
|
|
|
if ( index && ipa_nat_map_find(MAP_NUM_99, index, NULL) )
|
|
{
|
|
IPAERR("Invalid next index %u found in IPv4 index %s table entry %u\n",
|
|
index,
|
|
(is_expn_tbl) ? "expansion" : "base",
|
|
rule_index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ( is_expn_tbl )
|
|
{
|
|
struct ipa_nat_indx_tbl_meta_info* mi_ptr = meta_record_ptr;
|
|
|
|
if ( ! mi_ptr )
|
|
{
|
|
IPAERR("Missing meta pointer for IPv4 index %s table entry %u\n",
|
|
"expansion",
|
|
rule_index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
index = mi_ptr->prev_index;
|
|
|
|
if ( index && ipa_nat_map_find(MAP_NUM_99, index, NULL) )
|
|
{
|
|
IPAERR("Invalid previous index %u found in IPv4 index %s table entry %u\n",
|
|
index,
|
|
"expansion",
|
|
rule_index);
|
|
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ipa_nat_validate_ipv4_table(
|
|
u32 tbl_hdl )
|
|
{
|
|
int ret;
|
|
|
|
/*
|
|
* Map MAP_NUM_99 will be used to keep, and to check for,
|
|
* record validity.
|
|
*
|
|
* The first walk will fill it. The second walk will use it...
|
|
*/
|
|
ipa_nat_map_clear(MAP_NUM_99);
|
|
|
|
IPADBG("Checking IPv4 active rules:\n");
|
|
|
|
ret = ipa_nati_walk_ipv4_tbl(tbl_hdl, USE_NAT_TABLE, nat_rule_loop_check, tbl_hdl);
|
|
|
|
if ( ret != 0 )
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
ret = ipa_nati_walk_ipv4_tbl(tbl_hdl, USE_NAT_TABLE, nat_rule_validity_check, 0);
|
|
|
|
if ( ret != 0 )
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Map MAP_NUM_99 will be used to keep, and to check for,
|
|
* record validity.
|
|
*
|
|
* The first walk will fill it. The second walk will use it...
|
|
*/
|
|
ipa_nat_map_clear(MAP_NUM_99);
|
|
|
|
IPADBG("Checking IPv4 index active rules:\n");
|
|
|
|
ret = ipa_nati_walk_ipv4_tbl(tbl_hdl, USE_INDEX_TABLE, index_loop_check, tbl_hdl);
|
|
|
|
if ( ret != 0 )
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
ret = ipa_nati_walk_ipv4_tbl(tbl_hdl, USE_INDEX_TABLE, index_validity_check, 0);
|
|
|
|
if ( ret != 0 )
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
_dispUsage(
|
|
const char* progNamePtr )
|
|
{
|
|
printf(
|
|
"Usage: %s [-d -r N -i N -e N -m mt]\n"
|
|
"Where:\n"
|
|
" -d Each test is discrete (create table, add rules, destroy table)\n"
|
|
" If not specified, only one table create and destroy for all tests\n"
|
|
" -r N Where N is the number of times to run the inotify regression test\n"
|
|
" -i N Where N is the number of times (iterations) to run test\n"
|
|
" -e N Where N is the number of entries in the NAT\n"
|
|
" -m mt Where mt is the type of memory to use for the NAT\n"
|
|
" Legal mt's: DDR, SRAM, or HYBRID (ie. use SRAM and DDR)\n"
|
|
" -g M-N Run tests M through N only\n",
|
|
progNamePtr);
|
|
|
|
fflush(stdout);
|
|
}
|
|
|
|
static NatTests nt_array[] = {
|
|
NAT_TEST_ENTRY(ipa_nat_test000, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test001, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test002, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test003, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test004, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test005, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test006, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test007, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test008, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test009, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test010, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test011, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test012, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test013, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test014, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test015, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test016, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test017, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test018, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test019, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test020, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test021, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test022, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test023, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test024, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_test025, IPA_NAT_TEST_PRE_COND_TE, 0),
|
|
/*
|
|
* Add new tests just above this comment. Keep the following two
|
|
* at the end...
|
|
*/
|
|
NAT_TEST_ENTRY(ipa_nat_test999, 1, 0),
|
|
NAT_TEST_ENTRY(ipa_nat_testREG, 1, 0),
|
|
};
|
|
|
|
int main(
|
|
int argc,
|
|
char* argv[] )
|
|
{
|
|
int sep = 0;
|
|
int ireg = 0;
|
|
uint32_t nt = 1;
|
|
int total_ents = 100;
|
|
uint32_t ht = 0;
|
|
uint32_t start = 0, end = 0;
|
|
|
|
char* nat_mem_type = "DDR";
|
|
|
|
uint32_t tbl_hdl = 0;
|
|
|
|
uint32_t pub_ip_addr;
|
|
|
|
uint32_t i, ub, cnt, exec, pass;
|
|
|
|
void* adp;
|
|
|
|
time_t t;
|
|
|
|
int c, ret;
|
|
|
|
IPADBG("Testing user space nat driver\n");
|
|
|
|
while ( (c = getopt(argc, argv, "dr:i:e:m:h:g:?")) != -1 )
|
|
{
|
|
switch (c)
|
|
{
|
|
case 'd':
|
|
sep = 1;
|
|
break;
|
|
case 'r':
|
|
ireg = atoi(optarg);
|
|
break;
|
|
case 'i':
|
|
nt = atoi(optarg);
|
|
break;
|
|
case 'e':
|
|
total_ents = atoi(optarg);
|
|
break;
|
|
case 'm':
|
|
if ( ! (nat_mem_type = legal_mem_type(optarg)) )
|
|
{
|
|
fprintf(stderr, "Illegal: -m %s\n", optarg);
|
|
_dispUsage(basename(argv[0]));
|
|
exit(0);
|
|
}
|
|
break;
|
|
case 'h':
|
|
ht = atoi(optarg);
|
|
break;
|
|
case 'g':
|
|
if ( sscanf(optarg, "%u-%u", &start, &end) != 2
|
|
||
|
|
( start >= end || end >= array_sz(nt_array) - 1 ) )
|
|
{
|
|
fprintf(stderr, "Illegal: -f %s\n", optarg);
|
|
_dispUsage(basename(argv[0]));
|
|
exit(0);
|
|
}
|
|
break;
|
|
case '?':
|
|
default:
|
|
_dispUsage(basename(argv[0]));
|
|
exit(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
srand(time(&t));
|
|
|
|
pub_ip_addr = RAN_ADDR;
|
|
|
|
exec = pass = 0;
|
|
|
|
for ( cnt = ret = 0; cnt < nt && ret == 0; cnt++ )
|
|
{
|
|
IPADBG("ITERATION [%u] OF TESING\n", cnt + 1);
|
|
|
|
if ( ireg )
|
|
{
|
|
adp = &ireg;
|
|
i = array_sz(nt_array) - 1;
|
|
ub = array_sz(nt_array);
|
|
}
|
|
else
|
|
{
|
|
adp = &tbl_hdl;
|
|
i = ( end ) ? start : 0;
|
|
ub = ( end ) ? end : array_sz(nt_array) - 1;
|
|
|
|
if ( i != 0 && ! sep )
|
|
{
|
|
ipa_nat_test000(
|
|
nat_mem_type, pub_ip_addr, total_ents, tbl_hdl, 0, adp);
|
|
}
|
|
}
|
|
|
|
for ( ; i < ub && ret == 0; i++ )
|
|
{
|
|
if ( total_ents >= nt_array[i].num_ents_trigger )
|
|
{
|
|
IPADBG("+------------------------------------------------+\n");
|
|
IPADBG("| Executing test: %s |\n", nt_array[i].func_name);
|
|
IPADBG("+------------------------------------------------+\n");
|
|
|
|
ret = nt_array[i].func(
|
|
nat_mem_type, pub_ip_addr, total_ents, tbl_hdl, sep, adp);
|
|
|
|
exec++;
|
|
|
|
if ( ret == 0 )
|
|
{
|
|
IPADBG("<<<<< Test %s SUCCEEDED >>>>>\n", nt_array[i].func_name);
|
|
|
|
pass++;
|
|
|
|
if ( ht || nt_array[i].test_hold_time_in_secs )
|
|
{
|
|
ht = (ht) ? ht : nt_array[i].test_hold_time_in_secs;
|
|
|
|
sleep(ht);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IPAERR("<<<<< Test %s FAILED >>>>>\n", nt_array[i].func_name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ret && tbl_hdl )
|
|
{
|
|
ipa_nat_test999(
|
|
nat_mem_type, pub_ip_addr, total_ents, tbl_hdl, 0, &tbl_hdl);
|
|
}
|
|
|
|
IPADBG("Total NAT Tests Run:%u, Pass:%u, Fail:%u\n",
|
|
exec, pass, exec - pass);
|
|
|
|
return 0;
|
|
}
|