Files
android_kernel_samsung_sm86…/ipanat/test/main.c
Ilia Lin 5faad0ab9e ipa: Add ipanat library to the techpack.
Moving the ipanat library sources from the ipacm project to here.
The library will be compiled separately and will be common
for the ipacm and ipa-kernel-tests.

Change-Id: I01becf981e15ea0c2958423585ea487affb421d0
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
2021-05-05 06:48:22 +03:00

508 rader
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;
}