ipa-kernel-tests: ULSO tests, HPC based header insertion tests

Unit tests for the IPv5 ULSO feature and for HPC based
header insertion feature.

Change-Id: I312b135f33486c1171a355a69e6631764d021947
Acked-by: Eliad Ben Yishay <ebenyish@qti.qualcomm.com>
Signed-off-by: Ilia Lin <ilialin@codeaurora.org>
This commit is contained in:
Ilia Lin
2021-08-11 14:51:51 +03:00
parent bedfbae7e6
commit 15ae40cd76
13 changed files with 920 additions and 60 deletions

View File

@@ -23,6 +23,9 @@ enum {
IPA_TEST_IOCTL_HOLB_CONFIG, IPA_TEST_IOCTL_HOLB_CONFIG,
IPA_TEST_IOCTL_FLT_TBL_IN_SRAM, IPA_TEST_IOCTL_FLT_TBL_IN_SRAM,
IPA_TEST_IOCTL_GET_MEM_PART, IPA_TEST_IOCTL_GET_MEM_PART,
IPA_TEST_IOCTL_ULSO_CONFIGURE,
IPA_TEST_IOCTL_ADD_HDR_HPC,
IPA_TEST_IOCTL_PKT_INIT_EX_SET_HDR_OFST,
IPA_TEST_IOCTL_NUM, IPA_TEST_IOCTL_NUM,
}; };
@@ -47,6 +50,15 @@ enum {
#define IPA_TEST_IOC_GET_MEM_PART _IOWR(IPA_TEST_IOC_MAGIC, \ #define IPA_TEST_IOC_GET_MEM_PART _IOWR(IPA_TEST_IOC_MAGIC, \
IPA_TEST_IOCTL_GET_MEM_PART, \ IPA_TEST_IOCTL_GET_MEM_PART, \
struct ipa_test_mem_partition *) struct ipa_test_mem_partition *)
#define IPA_TEST_IOC_ULSO_CONFIGURE _IOWR(IPA_TEST_IOC_MAGIC, \
IPA_TEST_IOCTL_ULSO_CONFIGURE, \
struct ipa_test_config_header *)
#define IPA_TEST_IOC_ADD_HDR_HPC _IOWR(IPA_TEST_IOC_MAGIC, \
IPA_TEST_IOCTL_ADD_HDR_HPC, \
struct ipa_ioc_add_hdr *)
#define IPA_TEST_IOC_PKT_INIT_EX_SET_HDR_OFST _IOWR(IPA_TEST_IOC_MAGIC, \
IPA_TEST_IOCTL_PKT_INIT_EX_SET_HDR_OFST, \
struct ipa_ioc_set_pkt_init_ex_hdr_ofst *)
#define IPA_TEST_CONFIG_MARKER 0x57 #define IPA_TEST_CONFIG_MARKER 0x57
#define IPA_TEST_CHANNEL_CONFIG_MARKER 0x83 #define IPA_TEST_CHANNEL_CONFIG_MARKER 0x83

View File

@@ -57,7 +57,10 @@
#define RX_NUM_BUFFS 16 #define RX_NUM_BUFFS 16
#define RX_SZ 32768 #define RX_SZ 32768
#define RX_BUFF_SIZE ((RX_SZ)/(RX_NUM_BUFFS)) /* Lowest power of 2 that is bigger than what is used in Ulso test */
#define MAX_ULSO_SEGMENT_SZ 16384
#define RX_SZ_ULSO ((MAX_ULSO_SEGMENT_SZ) * (RX_NUM_BUFFS))
#define RX_BUFF_SIZE ((rx_size)/(RX_NUM_BUFFS))
#define IPA_TEST_DMUX_HEADER_LENGTH 8 #define IPA_TEST_DMUX_HEADER_LENGTH 8
#define IPA_TEST_META_DATA_IS_VALID 1 #define IPA_TEST_META_DATA_IS_VALID 1
@@ -110,6 +113,7 @@ struct device *ipa_get_pdev(void);
enum fops_type { enum fops_type {
IPA_TEST_REG_CHANNEL, IPA_TEST_REG_CHANNEL,
IPA_TEST_DATA_PATH_TEST_CHANNEL, IPA_TEST_DATA_PATH_TEST_CHANNEL,
IPA_TEST_ULSO_DATA_PATH_TEST_CHANNEL,
MAX_FOPS MAX_FOPS
}; };
@@ -225,6 +229,8 @@ struct ipa_tx_suspend_private_data {
static struct test_context *ipa_test; static struct test_context *ipa_test;
static size_t rx_size;
/** /**
* Allocate memory from system memory. * Allocate memory from system memory.
@@ -472,6 +478,9 @@ static ssize_t set_skb_for_user(struct file *filp, char __user *buf,
static ssize_t get_skb_from_user(struct file *filp, const char __user *buf, static ssize_t get_skb_from_user(struct file *filp, const char __user *buf,
size_t size, loff_t *f_pos); size_t size, loff_t *f_pos);
static ssize_t get_ulso_skb_from_user(struct file *filp, const char __user *buf,
size_t size, loff_t *f_pos);
static const struct file_operations data_path_fops = { static const struct file_operations data_path_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = channel_open, .open = channel_open,
@@ -479,6 +488,12 @@ static const struct file_operations data_path_fops = {
.write = get_skb_from_user, .write = get_skb_from_user,
}; };
static const struct file_operations ulso_data_path_fops = {
.owner = THIS_MODULE,
.open = channel_open,
.read = set_skb_for_user,
.write = get_ulso_skb_from_user,
};
/* /*
* This will create the char device named * This will create the char device named
@@ -566,6 +581,9 @@ int create_channel_device_by_type(
case IPA_TEST_DATA_PATH_TEST_CHANNEL: case IPA_TEST_DATA_PATH_TEST_CHANNEL:
cdev_init(&channel_dev->cdev, &data_path_fops); cdev_init(&channel_dev->cdev, &data_path_fops);
break; break;
case IPA_TEST_ULSO_DATA_PATH_TEST_CHANNEL:
cdev_init(&channel_dev->cdev, &ulso_data_path_fops);
break;
default: default:
IPATEST_ERR("Wrong fops type"); IPATEST_ERR("Wrong fops type");
ret = -EINVAL; ret = -EINVAL;
@@ -632,6 +650,8 @@ struct datapath_ctx {
struct datapath_ctx *p_data_path_ctx; struct datapath_ctx *p_data_path_ctx;
bool init_write_done_completion;
/* /*
* Inits the kfifo needed for the * Inits the kfifo needed for the
@@ -640,6 +660,7 @@ struct datapath_ctx *p_data_path_ctx;
int datapath_ds_init(void) int datapath_ds_init(void)
{ {
int res = 0; int res = 0;
rx_size = RX_SZ;
p_data_path_ctx = kzalloc(sizeof(struct datapath_ctx), GFP_KERNEL); p_data_path_ctx = kzalloc(sizeof(struct datapath_ctx), GFP_KERNEL);
if (!p_data_path_ctx) { if (!p_data_path_ctx) {
@@ -696,6 +717,24 @@ static struct sk_buff *datapath_create_skb(const char *buf, size_t size)
return skb; return skb;
} }
static struct sk_buff *ulso_create_skb(const char *buf, size_t size)
{
struct sk_buff *skb;
IPATEST_DBG("Entering\n");
skb = datapath_create_skb(buf, size);
if (unlikely(!skb))
return NULL;
/* Mark the skb as gso skb */
skb_increase_gso_size(skb_shinfo(skb), 1);
IPATEST_DBG("Exiting\n");
return skb;
}
static int datapath_read_data(void *element, int size) static int datapath_read_data(void *element, int size)
{ {
int res; int res;
@@ -796,6 +835,45 @@ static ssize_t get_skb_from_user(struct file *filp, const char __user *buf,
return size; return size;
} }
/*
* Receives from the user space the buff,
* create an SKB, and send it through
* ipa_tx_dp that was received in the system
*/
static ssize_t get_ulso_skb_from_user(struct file *filp,
const char __user *buf, size_t size, loff_t *f_pos) {
int res = 0;
struct sk_buff *skb;
IPATEST_DBG("Entering\n");
/* Copy the data from the user and transmit */
IPATEST_DBG("-----Copy the data from the user-----\n");
IPATEST_DBG("Creating SKB\n");
skb = ulso_create_skb(buf, size);
if (!skb)
return -EINVAL;
if (!init_write_done_completion) {
init_completion(&p_data_path_ctx->write_done_completion);
init_write_done_completion = true;
} else {
reinit_completion(&p_data_path_ctx->write_done_completion);
}
IPATEST_DBG("Starting transfer through ipa_tx_dp\n");
res = ipa_tx_dp(IPA_CLIENT_TEST_CONS, skb, NULL);
IPATEST_DBG("ipa_tx_dp res = %d.\n", res);
res = wait_for_completion_timeout(
&p_data_path_ctx->write_done_completion,
msecs_to_jiffies(TIME_OUT_TIME));
IPATEST_DBG("timeout result = %d", res);
if (!res)
return -EINVAL;
IPATEST_DBG("-----Exiting-----\n");
return size;
}
/* /*
* Sends the user space the next SKB * Sends the user space the next SKB
* that was received in the system * that was received in the system
@@ -2806,19 +2884,14 @@ void destroy_channel_devices(void)
{ {
IPATEST_DBG("-----Tear Down----\n"); IPATEST_DBG("-----Tear Down----\n");
while (ipa_test->num_tx_channels > 0) { while (ipa_test->num_tx_channels > 0) {
IPATEST_DBG("-- num_tx_channels = %d --\n", IPATEST_DBG("-- num_tx_channels = %d --\n", ipa_test->num_tx_channels);
ipa_test->num_tx_channels); destroy_channel_device(ipa_test->tx_channels[--ipa_test->num_tx_channels]);
destroy_channel_device(
ipa_test->tx_channels[--ipa_test->num_tx_channels]);
ipa_test->tx_channels[ipa_test->num_tx_channels] = NULL; ipa_test->tx_channels[ipa_test->num_tx_channels] = NULL;
} }
while (ipa_test->num_rx_channels > 0) { while (ipa_test->num_rx_channels > 0) {
IPATEST_DBG("-- num_rx_channels = %d --\n", IPATEST_DBG("-- num_rx_channels = %d --\n", ipa_test->num_rx_channels);
ipa_test->num_rx_channels); destroy_channel_device(from_ipa_devs[--ipa_test->num_rx_channels]);
destroy_channel_device
(from_ipa_devs[--ipa_test->num_rx_channels]);
from_ipa_devs[ipa_test->num_rx_channels] = NULL; from_ipa_devs[ipa_test->num_rx_channels] = NULL;
} }
} }
@@ -4069,7 +4142,8 @@ static ssize_t ipa_test_read(struct file *filp,
static struct class *ipa_test_class; static struct class *ipa_test_class;
//TODO make only one configuration function //TODO make only one configuration function
static int configure_app_to_ipa_path(struct ipa_channel_config __user *to_ipa_user) static int configure_app_to_ipa_path(struct ipa_channel_config __user *to_ipa_user,
bool isUlso)
{ {
int retval; int retval;
struct ipa_channel_config to_ipa_channel_config = {0}; struct ipa_channel_config to_ipa_channel_config = {0};
@@ -4106,14 +4180,12 @@ static int configure_app_to_ipa_path(struct ipa_channel_config __user *to_ipa_us
IPATEST_DBG("to_ipa tail_marker value is 0x%x\n", IPATEST_DBG("to_ipa tail_marker value is 0x%x\n",
to_ipa_channel_config.tail_marker); to_ipa_channel_config.tail_marker);
if (to_ipa_channel_config.head_marker != if (to_ipa_channel_config.head_marker != IPA_TEST_CHANNEL_CONFIG_MARKER) {
IPA_TEST_CHANNEL_CONFIG_MARKER) {
IPATEST_ERR("bad head_marker - possible memory corruption\n"); IPATEST_ERR("bad head_marker - possible memory corruption\n");
return -EFAULT; return -EFAULT;
} }
if (to_ipa_channel_config.tail_marker != if (to_ipa_channel_config.tail_marker != IPA_TEST_CHANNEL_CONFIG_MARKER) {
IPA_TEST_CHANNEL_CONFIG_MARKER) {
IPATEST_ERR("bad tail_marker - possible memory corruption\n"); IPATEST_ERR("bad tail_marker - possible memory corruption\n");
return -EFAULT; return -EFAULT;
} }
@@ -4126,39 +4198,37 @@ static int configure_app_to_ipa_path(struct ipa_channel_config __user *to_ipa_us
} }
/* Channel from which the userspace shall communicate to this pipe */ /* Channel from which the userspace shall communicate to this pipe */
retval = create_channel_device(index, "to_ipa", if(isUlso){
&to_ipa_devs[index], TX_SZ); retval = create_channel_device_by_type(index, "to_ipa", &to_ipa_devs[index], TX_SZ,
IPA_TEST_ULSO_DATA_PATH_TEST_CHANNEL);
} else {
retval = create_channel_device(index, "to_ipa", &to_ipa_devs[index], TX_SZ);
}
if (retval) { if (retval) {
IPATEST_ERR("channel device creation error\n"); IPATEST_ERR("channel device creation error\n");
return -1; return -1;
} }
ipa_test->tx_channels[ipa_test->num_tx_channels++] = ipa_test->tx_channels[ipa_test->num_tx_channels++] = to_ipa_devs[index];
to_ipa_devs[index]; if (isUlso)
return 0;
/* Connect IPA --> Apps */ /* Connect IPA --> Apps */
memset(&sys_in, 0, sizeof(sys_in)); memset(&sys_in, 0, sizeof(sys_in));
sys_in.client = to_ipa_channel_config.client; sys_in.client = to_ipa_channel_config.client;
IPATEST_DBG("copying from 0x%px\n", to_ipa_channel_config.cfg); IPATEST_DBG("copying from 0x%px\n", to_ipa_channel_config.cfg);
retval = copy_from_user( retval = copy_from_user(&sys_in.ipa_ep_cfg, to_ipa_channel_config.cfg, to_ipa_channel_config.config_size);
&sys_in.ipa_ep_cfg,
to_ipa_channel_config.cfg,
to_ipa_channel_config.config_size);
if (retval) { if (retval) {
IPATEST_ERR("fail to copy cfg - from_ipa_user\n"); IPATEST_ERR("fail to copy cfg - from_ipa_user\n");
return -1; return -1;
} }
if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, &to_ipa_devs[index]->ipa_client_hdl, false)) {
&to_ipa_devs[index]->ipa_client_hdl, false)) {
IPATEST_ERR("setup sys pipe failed\n"); IPATEST_ERR("setup sys pipe failed\n");
return -1; return -1;
} }
/* Connect APPS MEM --> Tx IPA */ /* Connect APPS MEM --> Tx IPA */
retval = connect_apps_to_ipa(&to_ipa_devs[index]->ep, retval = connect_apps_to_ipa(&to_ipa_devs[index]->ep, to_ipa_channel_config.client, ipa_pipe_num,
to_ipa_channel_config.client, &to_ipa_devs[index]->mem, ipa_gsi_hdl);
ipa_pipe_num,
&to_ipa_devs[index]->mem,
ipa_gsi_hdl);
if (retval) { if (retval) {
IPATEST_ERR("fail to connect ipa to apps\n"); IPATEST_ERR("fail to connect ipa to apps\n");
return -1; return -1;
@@ -4167,7 +4237,7 @@ static int configure_app_to_ipa_path(struct ipa_channel_config __user *to_ipa_us
return 0; return 0;
} }
static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ipa_user) static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ipa_user, bool isUlso)
{ {
int retval; int retval;
struct ipa_channel_config from_ipa_channel_config = {0}; struct ipa_channel_config from_ipa_channel_config = {0};
@@ -4227,7 +4297,7 @@ static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ip
/* Channel from which the userspace shall communicate to this pipe */ /* Channel from which the userspace shall communicate to this pipe */
retval = create_channel_device(index, "from_ipa", retval = create_channel_device(index, "from_ipa",
&from_ipa_devs[index], RX_SZ); &from_ipa_devs[index], rx_size);
if (retval) { if (retval) {
IPATEST_ERR("channel device creation error\n"); IPATEST_ERR("channel device creation error\n");
return -1; return -1;
@@ -4238,6 +4308,9 @@ static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ip
/* Connect IPA --> Apps */ /* Connect IPA --> Apps */
IPATEST_DBG("copying from 0x%px\n", from_ipa_channel_config.cfg); IPATEST_DBG("copying from 0x%px\n", from_ipa_channel_config.cfg);
memset(&sys_in, 0, sizeof(sys_in)); memset(&sys_in, 0, sizeof(sys_in));
if (isUlso) {
sys_in.notify = notify_ipa_write_done;
}
sys_in.client = from_ipa_channel_config.client; sys_in.client = from_ipa_channel_config.client;
retval = copy_from_user( retval = copy_from_user(
&sys_in.ipa_ep_cfg, &sys_in.ipa_ep_cfg,
@@ -4269,7 +4342,8 @@ static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ip
static int configure_test_scenario( static int configure_test_scenario(
struct ipa_test_config_header *ipa_test_config_header, struct ipa_test_config_header *ipa_test_config_header,
struct ipa_channel_config **from_ipa_channel_config_array, struct ipa_channel_config **from_ipa_channel_config_array,
struct ipa_channel_config **to_ipa_channel_config_array) struct ipa_channel_config **to_ipa_channel_config_array,
bool isUlso)
{ {
int retval; int retval;
int i; int i;
@@ -4307,14 +4381,19 @@ static int configure_test_scenario(
for (i = 0 ; i < ipa_test_config_header->from_ipa_channels_num ; i++) { for (i = 0 ; i < ipa_test_config_header->from_ipa_channels_num ; i++) {
IPATEST_DBG("starting configuration of from_ipa_%d\n", i); IPATEST_DBG("starting configuration of from_ipa_%d\n", i);
retval = configure_app_from_ipa_path( retval = configure_app_from_ipa_path(from_ipa_channel_config_array[i], isUlso);
from_ipa_channel_config_array[i]);
if (retval) { if (retval) {
IPATEST_ERR("fail to configure from_ipa_%d", i); IPATEST_ERR("fail to configure from_ipa_%d", i);
goto fail; goto fail;
} }
} }
if (isUlso) {
rx_size = RX_SZ_ULSO;
} else {
rx_size = RX_SZ;
}
retval = insert_descriptors_into_rx_endpoints(RX_BUFF_SIZE); retval = insert_descriptors_into_rx_endpoints(RX_BUFF_SIZE);
if (retval) { if (retval) {
IPATEST_ERR("RX descriptors failed\n"); IPATEST_ERR("RX descriptors failed\n");
@@ -4323,8 +4402,7 @@ static int configure_test_scenario(
IPATEST_DBG("RX descriptors were added to RX pipes\n"); IPATEST_DBG("RX descriptors were added to RX pipes\n");
for (i = 0 ; i < ipa_test_config_header->to_ipa_channels_num ; i++) { for (i = 0 ; i < ipa_test_config_header->to_ipa_channels_num ; i++) {
retval = configure_app_to_ipa_path( retval = configure_app_to_ipa_path(to_ipa_channel_config_array[i], isUlso);
to_ipa_channel_config_array[i]);
if (retval) { if (retval) {
IPATEST_ERR("fail to configure to_ipa_%d", i); IPATEST_ERR("fail to configure to_ipa_%d", i);
goto fail; goto fail;
@@ -4346,7 +4424,55 @@ fail:
return retval; return retval;
} }
static int handle_configuration_ioctl(unsigned long ioctl_arg) static int handle_add_hdr_hpc(unsigned long ioctl_arg)
{
struct ipa_ioc_add_hdr hdrs;
struct ipa_hdr_add *hdr;
int retval;
IPATEST_ERR("copying from 0x%px\n", (u8 *)ioctl_arg);
retval = copy_from_user(&hdrs, (u8 *)ioctl_arg, sizeof(hdrs) + sizeof(*hdr));
if (retval) {
IPATEST_ERR("failing copying header from user\n");
return retval;
}
retval = ipa3_add_hdr_hpc(&hdrs);
if (retval) {
IPATEST_ERR("ipa3_add_hdr_hpc failed\n");
return retval;
}
IPATEST_ERR("ELIAD: \n");
hdr = &hdrs.hdr[0];
if (hdr->status) {
IPATEST_ERR("ipa3_add_hdr_hpc failed\n");
return hdr->status;
}
IPATEST_ERR("ELIAD: \n");
if (copy_to_user((void __user *)ioctl_arg, &hdrs, sizeof(hdrs) + sizeof(*hdr))) {
retval = -EFAULT;
}
IPATEST_ERR("ELIAD: \n");
return 0;
}
static int handle_pkt_init_ex_set_hdr_ofst_ioctl(unsigned long ioctl_arg)
{
struct ipa_pkt_init_ex_hdr_ofst_set hdr_ofst;
int retval;
IPATEST_DBG("copying from 0x%px\n", (u8 *)ioctl_arg);
retval = copy_from_user(&hdr_ofst, (u8 *)ioctl_arg, sizeof(hdr_ofst));
if (retval) {
IPATEST_ERR("failing copying header from user\n");
return retval;
}
return ipa_set_pkt_init_ex_hdr_ofst(&hdr_ofst, true);
}
static int handle_configuration_ioctl(unsigned long ioctl_arg,
bool isUlso)
{ {
int retval; int retval;
int needed_bytes; int needed_bytes;
@@ -4405,10 +4531,10 @@ static int handle_configuration_ioctl(unsigned long ioctl_arg)
goto fail_copy_to; goto fail_copy_to;
} }
retval = configure_test_scenario( retval = configure_test_scenario(&test_header,
&test_header,
from_ipa_channel_config_array, from_ipa_channel_config_array,
to_ipa_channel_config_array); to_ipa_channel_config_array,
isUlso);
if (retval) if (retval)
IPATEST_ERR("fail to configure the system\n"); IPATEST_ERR("fail to configure the system\n");
@@ -4569,7 +4695,7 @@ static long ipa_test_ioctl(struct file *filp,
switch (cmd) { switch (cmd) {
case IPA_TEST_IOC_CONFIGURE: case IPA_TEST_IOC_CONFIGURE:
retval = handle_configuration_ioctl(arg); retval = handle_configuration_ioctl(arg, false);
break; break;
case IPA_TEST_IOC_CLEAN: case IPA_TEST_IOC_CLEAN:
@@ -4593,6 +4719,15 @@ static long ipa_test_ioctl(struct file *filp,
case IPA_TEST_IOC_GET_MEM_PART: case IPA_TEST_IOC_GET_MEM_PART:
retval = ipa_test_get_mem_part(arg); retval = ipa_test_get_mem_part(arg);
break; break;
case IPA_TEST_IOC_ULSO_CONFIGURE:
retval = handle_configuration_ioctl(arg, true);
break;
case IPA_TEST_IOC_ADD_HDR_HPC:
retval = handle_add_hdr_hpc(arg);
break;
case IPA_TEST_IOC_PKT_INIT_EX_SET_HDR_OFST:
retval = handle_pkt_init_ex_set_hdr_ofst_ioctl(arg);
break;
default: default:
IPATEST_ERR("ioctl is not supported (%d)\n", cmd); IPATEST_ERR("ioctl is not supported (%d)\n", cmd);
return -ENOTTY; return -ENOTTY;

View File

@@ -31,8 +31,11 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include "HeaderInsertion.h" #include "HeaderInsertion.h"
#include "TestsUtils.h"
/*All interaction through the driver are /*All interaction through the driver are
* made through this inode. * made through this inode.
@@ -76,6 +79,50 @@ bool HeaderInsertion::AddHeader(struct ipa_ioc_add_hdr *pHeaderTableToAdd)
return (-1 != nRetVal); return (-1 != nRetVal);
} }
bool HeaderInsertion::addHeaderHpc(const string& name, uint8_t* header, const size_t headerLen, bool isPartial, enum ipa_client_type ipaClient){
if(name.empty() || name.size() >= IPA_RESOURCE_NAME_MAX){
return false;
}
int fd = open(CONFIGURATION_NODE_PATH, O_RDONLY);
if (fd < 0) {
cout << "failed to open " << CONFIGURATION_NODE_PATH << endl;
return false;
}
struct ipa_ioc_add_hdr *iocH = static_cast<struct ipa_ioc_add_hdr*>(calloc(1, sizeof(*iocH) + sizeof(struct ipa_hdr_add)));
if(!iocH){
return false;
}
iocH->commit = 1;
iocH->num_hdrs = 1;
struct ipa_hdr_add *h = &iocH->hdr[0];
strlcpy(h->name, name.c_str(), IPA_RESOURCE_NAME_MAX);
memcpy(h->hdr, header, headerLen);
h->hdr_len = headerLen;
h->hdr_hdl = -1;
h->status = -1;
h->is_partial = isPartial;
cout << "h->name=" << h->name << ", h->is_partial=" << h->is_partial << endl;
int result = ioctl(fd, IPA_TEST_IOC_ADD_HDR_HPC, iocH);
if(result || h->status){
free(iocH);
close(fd);
return false;
}
cout << "result=" << result << ", status=" << h->status << ", ipaClient=" << ipaClient << endl;
struct ipa_pkt_init_ex_hdr_ofst_set lookup;
lookup.ep = ipaClient;
strlcpy(lookup.name, name.c_str(), IPA_RESOURCE_NAME_MAX);
result = ioctl(fd, IPA_TEST_IOC_PKT_INIT_EX_SET_HDR_OFST , &lookup);
if (result) {
free(iocH);
close(fd);
return false;
}
free(iocH);
close(fd);
return true;
}
bool HeaderInsertion::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete) bool HeaderInsertion::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete)
{ {
int nRetVal = 0; int nRetVal = 0;
@@ -85,6 +132,32 @@ bool HeaderInsertion::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete)
return (-1 != nRetVal); return (-1 != nRetVal);
} }
bool HeaderInsertion::DeleteHeader(const string& name){
if(name.empty() || name.size() >= IPA_RESOURCE_NAME_MAX){
return false;
}
int hdl = GetHeaderHandle(name);
if(hdl == -1){
return false;
}
struct ipa_ioc_del_hdr *iocD = static_cast<struct ipa_ioc_del_hdr*>(calloc(1, sizeof(*iocD) + sizeof(struct ipa_hdr_del)));
if(!iocD){
return false;
}
iocD->commit = 1;
iocD->num_hdls = 1;
struct ipa_hdr_del *h = &iocD->hdl[0];
h->hdl = hdl;
h->status = -1;
cout << "h->hdl=" << h->hdl << endl;
if(!DeleteHeader(iocD)){
free(iocD);
return false;
}
free(iocD);
return true;
}
bool HeaderInsertion::AddProcCtx(struct ipa_ioc_add_hdr_proc_ctx *procCtxTable) bool HeaderInsertion::AddProcCtx(struct ipa_ioc_add_hdr_proc_ctx *procCtxTable)
{ {
int retval = 0; int retval = 0;
@@ -154,6 +227,23 @@ bool HeaderInsertion::GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct)
return true; return true;
} }
int HeaderInsertion::GetHeaderHandle(const string& name){
if(name.empty() || name.size() >= IPA_RESOURCE_NAME_MAX){
return false;
}
struct ipa_ioc_get_hdr retHeader;
memset(&retHeader, 0, sizeof(retHeader));
strlcpy(retHeader.name, name.c_str(), IPA_RESOURCE_NAME_MAX);
retHeader.hdl = -1;
printf("retHeader.name=%s\n", retHeader.name);
if(!GetHeaderHandle(&retHeader)){
cout << "GetHeaderHandle(&retHeader) Failed" << endl;
return -1;
}
cout << "retHeader.hdl=" << retHeader.hdl << endl;
return retHeader.hdl;
}
bool HeaderInsertion::CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct) bool HeaderInsertion::CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct)
{ {
int retval = 0; int retval = 0;

View File

@@ -31,7 +31,15 @@
#define HEADER_INSERTION_H_ #define HEADER_INSERTION_H_
#include <stdint.h> #include <stdint.h>
#include <string>
#include <iostream>
#include "linux/msm_ipa.h" #include "linux/msm_ipa.h"
#include "ipa_test_module.h"
#include "Constants.h"
using std::string;
using std::cout;
using std::endl;
class HeaderInsertion class HeaderInsertion
{ {
@@ -40,8 +48,11 @@ private:
public: public:
bool AddHeader(struct ipa_ioc_add_hdr *pHeaderTable); bool AddHeader(struct ipa_ioc_add_hdr *pHeaderTable);
bool addHeaderHpc(const string& name, uint8_t* header, const size_t headerLen, bool isPartial, enum ipa_client_type ipaClient);
bool DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTable); bool DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTable);
bool DeleteHeader(const string& name);
bool GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct); bool GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct);
int GetHeaderHandle(const string& name);
bool CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct); bool CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct);
// Processing context // Processing context

View File

@@ -30,10 +30,14 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <iostream>
#include "InterfaceAbstraction.h" #include "InterfaceAbstraction.h"
#define MAX_OPEN_RETRY 10000 #define MAX_OPEN_RETRY 10000
using std::cout;
using std::endl;
bool InterfaceAbstraction::Open(const char * toIPAPath, const char * fromIPAPath) bool InterfaceAbstraction::Open(const char * toIPAPath, const char * fromIPAPath)
{ {
int tries_cnt = MAX_OPEN_RETRY; int tries_cnt = MAX_OPEN_RETRY;
@@ -95,9 +99,9 @@ void InterfaceAbstraction::Close()
close(m_fromIPADescriptor); close(m_fromIPADescriptor);
} }
bool InterfaceAbstraction::SendData(unsigned char *buf, size_t size) long InterfaceAbstraction::SendData(unsigned char *buf, size_t size)
{ {
int bytesWritten = 0; long bytesWritten = 0;
printf("Trying to write %zu bytes to %d.\n", size, m_toIPADescriptor); printf("Trying to write %zu bytes to %d.\n", size, m_toIPADescriptor);
@@ -118,7 +122,7 @@ bool InterfaceAbstraction::SendData(unsigned char *buf, size_t size)
exit(-1); exit(-1);
} }
printf("bytesWritten = %d.\n", bytesWritten); cout << "bytesWritten = " << bytesWritten << endl;
return bytesWritten; return bytesWritten;
} }
@@ -145,6 +149,30 @@ int InterfaceAbstraction::ReceiveData(unsigned char *buf, size_t size)
return totalBytesRead; return totalBytesRead;
} }
int InterfaceAbstraction::ReceiveSingleDataChunk(unsigned char *buf, size_t size){
size_t bytesRead = 0;
printf("Trying to read %zu bytes from %d.\n", size, m_fromIPADescriptor);
bytesRead = read(m_fromIPADescriptor, (void*)buf, size);
printf("Read %zu bytes.\n", bytesRead);
return bytesRead;
}
int InterfaceAbstraction::setReadNoBlock(){
int flags = fcntl(m_fromIPADescriptor, F_GETFL, 0);
if(flags == -1){
return -1;
}
return fcntl(m_fromIPADescriptor, F_SETFL, flags | O_NONBLOCK);
}
int InterfaceAbstraction::clearReadNoBlock(){
int flags = fcntl(m_fromIPADescriptor, F_GETFL, 0);
if(flags == -1){
return -1;
}
return fcntl(m_fromIPADescriptor, F_SETFL, flags & ~O_NONBLOCK);
}
InterfaceAbstraction::~InterfaceAbstraction() InterfaceAbstraction::~InterfaceAbstraction()
{ {
close(m_fromIPADescriptor); close(m_fromIPADescriptor);

View File

@@ -45,8 +45,11 @@ public:
~InterfaceAbstraction(); ~InterfaceAbstraction();
bool Open(const char *toIPAPath, const char *fromIPAPath); bool Open(const char *toIPAPath, const char *fromIPAPath);
void Close(); void Close();
bool SendData(unsigned char *buffer, size_t size); long SendData(unsigned char *buffer, size_t size);
int ReceiveData(unsigned char *buf, size_t size); int ReceiveData(unsigned char *buf, size_t size);
int ReceiveSingleDataChunk(unsigned char *buf, size_t size);
int setReadNoBlock();
int clearReadNoBlock();
string m_toChannelName; string m_toChannelName;
string m_fromChannelName; string m_fromChannelName;

View File

@@ -48,4 +48,5 @@ ipa_kernel_tests_SOURCES =\
FilteringEthernetBridgingTests.cpp \ FilteringEthernetBridgingTests.cpp \
NatTest.cpp \ NatTest.cpp \
IPv6CTTest.cpp \ IPv6CTTest.cpp \
UlsoTest.cpp \
main.cpp main.cpp

View File

@@ -992,18 +992,16 @@ static bool is_reconfigure_required(struct ipa_test_config_header *header)
return false; return false;
} }
int GenericConfigureScenario(struct ipa_test_config_header *header) int GenericConfigureScenario(struct ipa_test_config_header *header, bool isUlso)
{ {
int fd; int fd;
int retval; int retval;
if (is_reconfigure_required(header) == false) { if (is_reconfigure_required(header) == false) {
g_Logger.AddMessage(LOG_DEVELOPMENT , g_Logger.AddMessage(LOG_DEVELOPMENT , "No need to reconfigure, we are all good :)\n");
"No need to reconfigure, we are all good :)\n");
return true; return true;
} else { } else {
g_Logger.AddMessage(LOG_DEVELOPMENT , g_Logger.AddMessage(LOG_DEVELOPMENT , "Need to run configuration again\n");
"Need to run configuration again\n");
} }
g_Logger.AddMessage(LOG_DEVELOPMENT, "configuration has started, parameters:\n"); g_Logger.AddMessage(LOG_DEVELOPMENT, "configuration has started, parameters:\n");
g_Logger.AddMessage(LOG_DEVELOPMENT, "header->head_marker=0x%x\n", header->head_marker); g_Logger.AddMessage(LOG_DEVELOPMENT, "header->head_marker=0x%x\n", header->head_marker);
@@ -1055,7 +1053,11 @@ int GenericConfigureScenario(struct ipa_test_config_header *header)
return false; return false;
} }
if(isUlso){
retval = ioctl(fd, IPA_TEST_IOC_ULSO_CONFIGURE, header);
} else {
retval = ioctl(fd, IPA_TEST_IOC_CONFIGURE, header); retval = ioctl(fd, IPA_TEST_IOC_CONFIGURE, header);
}
if (retval) { if (retval) {
g_Logger.AddMessage(LOG_ERROR, "fail to configure the system (%d)\n", retval); g_Logger.AddMessage(LOG_ERROR, "fail to configure the system (%d)\n", retval);
close(fd); close(fd);

View File

@@ -296,7 +296,8 @@ bool CreateBypassRoutingTable_v2(
*/ */
void ConfigureScenario(int testConfiguration); void ConfigureScenario(int testConfiguration);
void ConfigureScenario(int testConfiguration, const char *params); void ConfigureScenario(int testConfiguration, const char *params);
int GenericConfigureScenario(struct ipa_test_config_header *header); int GenericConfigureScenario(struct ipa_test_config_header *header,
bool isUlso=false);
int GenericConfigureScenarioDestory(void); int GenericConfigureScenarioDestory(void);
int ConfigureSystem(int testConfiguration, int fd); int ConfigureSystem(int testConfiguration, int fd);
int ConfigureSystem(int testConfiguration, int fd, const char *params); int ConfigureSystem(int testConfiguration, int fd, const char *params);
@@ -696,6 +697,11 @@ struct ipa_ep_cfg_seq {
int seq_type; int seq_type;
}; };
struct ipa_ep_cfg_ulso {
int ipid_min_max_idx;
bool is_ulso_pipe;
};
struct ipa_ep_cfg_holb { struct ipa_ep_cfg_holb {
uint32_t tmr_val; uint32_t tmr_val;
uint32_t base_val; uint32_t base_val;
@@ -705,9 +711,9 @@ struct ipa_ep_cfg_holb {
uint8_t scaled_time; uint8_t scaled_time;
}; };
struct ipa_ep_cfg_ulso { struct ipa_pkt_init_ex_hdr_ofst_set {
int ipid_min_max_idx; char name[IPA_RESOURCE_NAME_MAX];
bool is_ulso_pipe; enum ipa_client_type ep;
}; };
/* /*

396
kernel-tests/UlsoTest.cpp Normal file
View File

@@ -0,0 +1,396 @@
/*
* Copyright (c) 2021 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <cstring> // for memcpy
#include "hton.h" // for htonl
#include "InterfaceAbstraction.h"
#include "Constants.h"
#include "Logger.h"
#include "TestsUtils.h"
#include "UlsoTestFixture.h"
#include "HeaderInsertion.h"
#define ARRAY_SIZE(A) (sizeof(ArraySizeHelper(A)))
template <typename T, size_t N>
char (&ArraySizeHelper(T (&a)[N]))[N];
using std::cout;
using std::endl;
using std::string;
using I4 = IPv4Header;
using I6 = IPv6Header;
using UDPH = UdpHeader;
using TCPH = TcpHeader;
/* Packet modification function objects */
template<typename PacketType> class PacketModifier {public:virtual void operator()(PacketType& p) const = 0;};
template<typename PacketType> class NullPacketModifier: public PacketModifier<PacketType> {public:void operator()(PacketType& p) const override {}};
template<typename PacketType> class ZeroChecksumPacketModifier: public PacketModifier<PacketType>
{public:void operator()(PacketType& p) const override {p.mQmapHeader.setmZeroChecksum(1);}};
template<typename PacketType> class OutOfBoundsPacketModifier: public PacketModifier<PacketType>
{public:void operator()(PacketType& p) const override {p.mQmapHeader.setmIpIdCfg(0);p.setIpId(65530);}};
template<typename Transport, typename Internet, const size_t* SegmentSizesArr, size_t SegmentSizesArrSize, const float* SegmentsNumsArr,
size_t SegmentsNumsArrSize, typename Modifier = NullPacketModifier<UlsoPacket<Transport, Internet>>>
class PacketsGeneratorClass {
protected:
using PacketType = UlsoPacket<Transport, Internet>;
public:
vector<PacketType> operator()(){
vector<PacketType> outVec;
Modifier m;
for(size_t i=0; i<SegmentSizesArrSize; i++){
for(size_t j=0; j<SegmentsNumsArrSize; j++){
PacketType p(SegmentSizesArr[i], static_cast<size_t>(SegmentSizesArr[i] * SegmentsNumsArr[j]), true);
m(p);
outVec.emplace_back(p);
}
}
return outVec;
}
};
template<typename Transport, typename Internet, typename PacketsGenerator>
class UlsoTest: public UlsoTestFixture {
private:
using PacketType = UlsoPacket<Transport, Internet>;
bool singlePacketRun(PacketType& p){
memset(m_sendBuf, 0, sizeof(m_sendBuf));
size_t packetSize = p.asArray(m_sendBuf);
size_t numSent = m_producer.SendData(m_sendBuf, packetSize);
if(numSent == 0){
return false;
}
vector<PacketType> segmentedPacketsVec = p.segment();
for(auto& segmentedPacket: segmentedPacketsVec){
memset(m_receiveBuf, 0, sizeof(m_receiveBuf));
memset(m_segmentBuf, 0, sizeof(m_segmentBuf));
packetSize = segmentedPacket.asArray(m_segmentBuf);
size_t recievedBytes = m_consumer.ReceiveSingleDataChunk(m_receiveBuf, packetSize);
if(packetSize != recievedBytes || memcmp(m_segmentBuf, m_receiveBuf, packetSize)){
return fail(numSent, packetSize, recievedBytes);
}
}
return clearPipe() == 0;
}
public:
UlsoTest(const char* name){
m_name = name;
string title = string("ULSO Test");
string packetStructure = string("Structure: ") + string ("QMAP + Ethernet 2 + ")
+ string(Internet().name()) + string(" ") + string(Transport().name());
string testProcess = string(
"1. Config IPA->APPS test pipe\n"
"2. Generate a vector of ULSO packets\n"
"3. For each packet in the packets vector\n"
" a. Send the packet over the APPS->IPA pipe using ipa_tx_dp\n"
" b. Segment the packet using the software simulation and store it in a segments vector\n"
" c. For each segment in the segments vector in order\n"
" # Receive a segment over IPA->APPS test pipe\n"
" # Compare the received segment to the software simulated segment\n"
"4. Clear the IPA->USB pipe and verify there were no bytes left in the pipe");
m_description = string(title + "\n" + packetStructure + "\n" + testProcess + "\n").c_str();
m_minIPAHwType = IPA_HW_v5_0;
Register(*this);
}
virtual bool Run() override {
vector<PacketType> packetsVec = PacketsGenerator()();
for(auto& p: packetsVec){
if(!singlePacketRun(p)){
cout << "Failed With the following packet:" << endl;
cout << p << endl;
return false;
}
}
return true;
}
};
template<typename Transport, typename Internet, typename PacketsGenerator>
class UlsoHPCTest: public UlsoTestFixture {
private:
using PacketType = UlsoPacket<Transport, Internet>;
static constexpr size_t rndisHdrLen {44};
HeaderInsertion m_HeaderInsertion;
uint8_t mRndisHeader[rndisHdrLen] = {0};
bool fail(size_t sendSize=0, size_t totalSegmentsSize=0, size_t recievedBytes=0){
printBuf(m_sendBuf, sendSize, "Sent:");
printBuf(m_receiveBuf, recievedBytes, string("Rceived ")
+ std::to_string(recievedBytes) + string(" Bytes:"));
printBuf(m_segmentBuf, totalSegmentsSize, string("Expected to receive ")
+ std::to_string(totalSegmentsSize) + string(" Bytes:"));
clearPipe();
return false;
}
bool singlePacketRun(PacketType& p){
cout << p << endl;
memset(m_sendBuf, 0, sizeof(m_sendBuf));
size_t sendSize = p.asArray(m_sendBuf);
if(!m_producer.SendData(m_sendBuf, sendSize)){
return fail(sendSize);
}
vector<PacketType> segmentedPacketsVec = p.segment();
memset(m_segmentBuf, 0, sizeof(m_segmentBuf));
uint8_t *segmentBufPtr = m_segmentBuf;
size_t totalSegmentsSize = 0;
vector<size_t> comparisionIntervalsSizesVec;
for(auto& segmentedPacket: segmentedPacketsVec){
memcpy(segmentBufPtr, mRndisHeader, sizeof(mRndisHeader));
segmentBufPtr += sizeof(mRndisHeader);
comparisionIntervalsSizesVec.emplace_back(sizeof(mRndisHeader));
totalSegmentsSize += sizeof(mRndisHeader);
size_t n = segmentedPacket.asArray(segmentBufPtr);
segmentBufPtr += n;
totalSegmentsSize += n;
comparisionIntervalsSizesVec.emplace_back(n);
}
memset(m_receiveBuf, 0, sizeof(m_receiveBuf));
size_t recievedBytes = m_consumer.ReceiveSingleDataChunk(m_receiveBuf, totalSegmentsSize);
if(totalSegmentsSize != recievedBytes){
return fail(sendSize, totalSegmentsSize, recievedBytes);
}
segmentBufPtr = m_segmentBuf;
uint8_t *recieveBufPtr = m_receiveBuf;
while(!comparisionIntervalsSizesVec.empty()){
size_t skipSize = comparisionIntervalsSizesVec.front();
recieveBufPtr += skipSize;
segmentBufPtr += skipSize;
comparisionIntervalsSizesVec.erase(comparisionIntervalsSizesVec.begin());
if(comparisionIntervalsSizesVec.empty()){
return fail(sendSize, totalSegmentsSize, recievedBytes);
}
size_t compareSize = comparisionIntervalsSizesVec.front();
if(memcmp(segmentBufPtr, recieveBufPtr, compareSize)){
return fail(sendSize, totalSegmentsSize, recievedBytes);
}
segmentBufPtr += compareSize;
recieveBufPtr += compareSize;
comparisionIntervalsSizesVec.erase(comparisionIntervalsSizesVec.begin());
}
if(clearPipe()){
return fail(sendSize, totalSegmentsSize, recievedBytes);
}
return true;
}
protected:
virtual void configFromEp(struct test_ipa_ep_cfg *ep_cfg){
ep_cfg->hdr.hdr_len = ETH_HLEN + rndisHdrLen;
ep_cfg->hdr.hdr_additional_const_len = ETH_HLEN;
ep_cfg->hdr.hdr_ofst_pkt_size_valid = true;
ep_cfg->hdr.hdr_ofst_pkt_size = 3 * sizeof(uint32_t);
ep_cfg->hdr_ext.hdr_total_len_or_pad_offset = sizeof(uint32_t);
ep_cfg->hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN;
ep_cfg->hdr_ext.hdr_total_len_or_pad_valid = true;
ep_cfg->hdr_ext.hdr_little_endian = true;
ep_cfg->aggr.aggr_en = IPA_ENABLE_AGGR;
ep_cfg->aggr.aggr = IPA_GENERIC;
ep_cfg->aggr.aggr_byte_limit = 4;
ep_cfg->aggr.aggr_time_limit = 1000;
}
public:
UlsoHPCTest(const char* name, const char* description){
m_name = name;
m_description = description;
m_minIPAHwType = IPA_HW_v5_0;
for(size_t i=0; i<rndisHdrLen; i++){
mRndisHeader[i] = i;
}
Register(*this);
}
virtual bool Run() override {
string headerName("rndis");
if(!m_HeaderInsertion.addHeaderHpc(headerName, mRndisHeader, rndisHdrLen, false, IPA_CLIENT_TEST_CONS)){
LOG_MSG_ERROR("!m_HeaderInsertion.addHeaderHpc(headerName, mRndisHeader, 44, false, true) Failed.");
return false;
}
vector<PacketType> packetsVec = PacketsGenerator()();
for(auto& p: packetsVec){
if(!singlePacketRun(p)){
return false;
}
}
if(!m_HeaderInsertion.DeleteHeader(headerName)){
LOG_MSG_ERROR("Delete rndis header failed");
return false;
}
return true;
}
};
/* Tests Macros */
#define PACKETS_GEN_MODIFY(T, I, a, b, m) PacketsGeneratorClass<T, I, a, ARRAY_SIZE(a), b, ARRAY_SIZE(b), m<UlsoPacket<T, I>>>
#define PACKETS_GEN(T, I, a, b) PACKETS_GEN_MODIFY(T, I, a, b, NullPacketModifier)//todo: change macro parameters to meaningfull names
////////////////////////////////////////////////////////////////////////////////
/////////// Simple Single Packet Tests //////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a single packet and compare the received segments to the software simulation
*/
constexpr size_t segmentSizes1[] = {20};
constexpr float segmentsNum1[] = {5};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes1, segmentsNum1)> ulsoTest0 {"Single Packet: IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes1, segmentsNum1)> ulsoTest1 {"Single Packet: IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes1, segmentsNum1)> ulsoTest2 {"Single Packet: IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes1, segmentsNum1)> ulsoTest3 {"Single Packet: IPV6 TCP"};
////////////////////////////////////////////////////////////////////////////////
/////////// Segmentation & Non-Segmentation mix //////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a sequence of [large, small, large, small, ...] packets and compare the received segments to the software simulation
*/
constexpr size_t segmentSizes2[] = {10, 50, 100, 500, 1460};
constexpr float segmentsNum2[] = {1, 4};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes2, segmentsNum2)> ulsoTest10 {"Segmentation No Segmentation IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes2, segmentsNum2)> ulsoTest11 {"Segmentation No Segmentation IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes2, segmentsNum2)> ulsoTest12 {"Segmentation No Segmentation IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes2, segmentsNum2)> ulsoTest13 {"Segmentation No Segmentation IPV6 TCP"};
////////////////////////////////////////////////////////////////////////////////
//////////////////// Zero Checksum ////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a sequence of large packets with zero checksum=1 and compare the received segments to the software simulation
*/
constexpr size_t segmentSizes3[] = {10, 50, 100, 500, 1460};
constexpr float numSegments3[] = {4};
static UlsoTest<UDPH, I4, PACKETS_GEN_MODIFY(UDPH, I4, segmentSizes3, numSegments3, ZeroChecksumPacketModifier)>
ulsoTest20 {"Zero Checksum IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN_MODIFY(TCPH, I4, segmentSizes3, numSegments3, ZeroChecksumPacketModifier)>
ulsoTest21 {"Zero Checksum IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN_MODIFY(UDPH, I6, segmentSizes3, numSegments3, ZeroChecksumPacketModifier)>
ulsoTest22 {"Zero Checksum IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN_MODIFY(TCPH, I6, segmentSizes3, numSegments3, ZeroChecksumPacketModifier)>
ulsoTest23 {"Zero Checksum IPV6 TCP"};
////////////////////////////////////////////////////////////////////////////////
///////// Segment Size Greater Than Payload Size /////////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a single packet with payload size and MSS matching an edge case and edge case and compare the received segments to the software simulation.
* Edge cases:
* 1. payload size < MSS ==> No segmentation
* 2. payload size == MSS - epsilon ==> No segmentation
* 3. payload size == MSS ==> Segmentation
*/
/* Segment Size = 100 Payload Size = 50 */
constexpr size_t segmentSizes4[] = {100};
constexpr float numSegments4[] = {0.5};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes4, numSegments4)> ulsoTest30 {"Payload Smaller Than MSS IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes4, numSegments4)> ulsoTest31 {"Payload Smaller Than MSS IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes4, numSegments4)> ulsoTest32 {"Payload Smaller Than MSS IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes4, numSegments4)> ulsoTest33 {"Payload Smaller Than MSS IPV6 TCP"};
/* Segment Size = 100 Payload Size = 99 */
constexpr size_t segmentSizes5[] = {100};
constexpr float numSegments5[] = {0.99};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes5, numSegments5)> ulsoTest40 {"Payload slightly Smaller Than MSS IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes5, numSegments5)> ulsoTest41 {"Payload slightly Smaller Than MSS IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes5, numSegments5)> ulsoTest42 {"Payload slightly Smaller Than MSS IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes5, numSegments5)> ulsoTest43 {"Payload slightly Smaller Than MSS IPV6 TCP"};
/* Segment Size = 20 Payload Size = 20 */
constexpr size_t segmentSizes6[] = {100};
constexpr float numSegments6[] = {1};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes6, numSegments6)> ulsoTest50 {"Payload Equals MSS IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes6, numSegments6)> ulsoTest51 {"Payload Equals MSS IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes6, numSegments6)> ulsoTest52 {"Payload Equals MSS IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes6, numSegments6)> ulsoTest53 {"Payload Equals MSS IPV6 TCP"};
////////////////////////////////////////////////////////////////////////////////
////////////// Valid Segment Sizes /////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a sequence of packets with different valid sizes and compare the received segments to the software simulation
*/
constexpr size_t segmentSizes7[] = {1460, 1220, 512, 1};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes7, segmentsNum1)> ulsoTest60 {"Valid Segment Sizes IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes7, segmentsNum1)> ulsoTest61 {"Valid Segment Sizes IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes7, segmentsNum1)> ulsoTest62 {"Valid Segment Sizes IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes7, segmentsNum1)> ulsoTest63 {"Valid Segment Sizes IPV6 TCP"};
////////////////////////////////////////////////////////////////////////////////
//////////////// Big Segment Sizes /////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a sequence of very large packets and compare the received segments to the software simulation
*/
constexpr size_t segmentSizes8[] = {2000, 3000, 4000, 5000, 6000, 10000};
static UlsoTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes8, segmentsNum1)> ulsoTest70 {"Big Segment Sizes IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes8, segmentsNum1)> ulsoTest71 {"Big Segment Sizes IPV4 TCP"};
static UlsoTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes8, segmentsNum1)> ulsoTest72 {"Big Segment Sizes IPV6 UDP"};
static UlsoTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes8, segmentsNum1)> ulsoTest73 {"Big Segment Sizes IPV6 TCP"};
////////////////////////////////////////////////////////////////////////////////
//////////////// IP ID wrapp around min/max bounds ///////////////
////////////////////////////////////////////////////////////////////////////////
/*
* Send a single packet such that:
* IPID + #segments < MAX IPID
* and compare the received segments to the software simulation
*/
constexpr size_t segmentSizes9[] = {2000};
constexpr float numSegments9[] = {10};
static UlsoTest<UDPH, I4, PACKETS_GEN_MODIFY(UDPH, I4, segmentSizes9, numSegments9, OutOfBoundsPacketModifier)> ulsoTest80 {"IPID CFG IPV4 UDP"};
static UlsoTest<TCPH, I4, PACKETS_GEN_MODIFY(TCPH, I4, segmentSizes9, numSegments9, OutOfBoundsPacketModifier)> ulsoTest81 {"IPID CFG IPV4 UDP"};
////////////////////////////////////////////////////////////////////////////////
//////////////// HPC RNDIS Header Insertion //////////////////////
////////////////////////////////////////////////////////////////////////////////
static UlsoHPCTest<UDPH, I4, PACKETS_GEN(UDPH, I4, segmentSizes1, segmentsNum1)> Ipv4UdpHpcRndisTest {"Ipv4UdpHpcRndisTest", "IPv4 + UDP"};
static UlsoHPCTest<TCPH, I4, PACKETS_GEN(TCPH, I4, segmentSizes1, segmentsNum1)> Ipv4TcpHpcRndisTest {"Ipv4TcpHpcRndisTest", "IPv4 + TCP"};
static UlsoHPCTest<UDPH, I6, PACKETS_GEN(UDPH, I6, segmentSizes1, segmentsNum1)> Ipv6UdpHpcRndisTest {"Ipv6UdpHpcRndisTest", "IPv6 + UDP"};
static UlsoHPCTest<TCPH, I6, PACKETS_GEN(TCPH, I6, segmentSizes1, segmentsNum1)> Ipv6TcpHpcRndisTest {"Ipv6TcpHpcRndisTest", "IPv6 + TCP"};

View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef ULSOTESTFIXTURE_H_
#define ULSOTESTFIXTURE_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <linux/if_ether.h>
#include "Constants.h"
#include "Logger.h"
#include "linux/msm_ipa.h"
#include "TestsUtils.h"
#include "TestBase.h"
#include "network_traffic/UlsoPacket.h"
using std::cout;
using std::endl;
using std::string;
class UlsoTestFixture: public TestBase {
public:
UlsoTestFixture(){
m_testSuiteName.push_back("ULSO");
memset(m_sendBuf, 0, sizeof(m_sendBuf));
memset(m_receiveBuf, 0, sizeof(m_receiveBuf));
memset(m_segmentBuf, 0, sizeof(m_segmentBuf));
}
virtual bool Setup() {
if(!setupKernelModule()){
return false;
}
m_producer.Open(INTERFACE0_TO_IPA_DATA_PATH, INTERFACE0_FROM_IPA_DATA_PATH);
m_consumer.Open(INTERFACE1_TO_IPA_DATA_PATH, INTERFACE1_FROM_IPA_DATA_PATH);
return true;
}
virtual bool Teardown(){
m_producer.Close();
m_consumer.Close();
return true;
}
virtual bool Run() = 0;
protected:
virtual void configFromEp(struct test_ipa_ep_cfg *ep_cfg){
return;
}
size_t clearPipe(){
cout << "In clearPipe" << endl;
if(m_consumer.setReadNoBlock() == -1){
cout << "Error: setReadNoBlock returned -1" << endl;
return 0;
}
size_t recievedBytes = m_consumer.ReceiveSingleDataChunk(m_receiveBuf, UlsoPacket<>::maxSize);
size_t totalReceivedBytes = recievedBytes;
if(recievedBytes > 0){
unsigned count = 1;
while(recievedBytes){
cout << "Receive #" << count << endl;
printBuf(m_receiveBuf, recievedBytes, string("Rceived ")
+ std::to_string(recievedBytes) + string(" Bytes:"));
recievedBytes = m_consumer.ReceiveSingleDataChunk(m_receiveBuf, UlsoPacket<>::maxSize);
totalReceivedBytes += recievedBytes;
count ++;
}
} else {
cout << "There were no bytes left in the pipe" << endl;
}
m_consumer.clearReadNoBlock();
return totalReceivedBytes;
}
bool fail(size_t sendSize=0, size_t totalSegmentsSize=0, size_t recievedBytes=0){
printBuf(m_sendBuf, sendSize, "Sent:");
printBuf(m_receiveBuf, recievedBytes, string("Rceived ") + std::to_string(recievedBytes) + string(" Bytes:"));
printBuf(m_segmentBuf, totalSegmentsSize, string("Expected to receive ") + std::to_string(totalSegmentsSize) + string(" Bytes:"));
clearPipe();
return false;
}
virtual int setupKernelModule(bool en_status = 0){
struct ipa_channel_config from_ipa_channels[1];
struct test_ipa_ep_cfg from_ipa_cfg[1];
struct ipa_channel_config to_ipa_channels[1];
struct test_ipa_ep_cfg to_ipa_cfg[1];
struct ipa_test_config_header header = {0};
struct ipa_channel_config *to_ipa_array[1];
struct ipa_channel_config *from_ipa_array[1];
/* From ipa configurations - 1 pipe */
memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0]));
from_ipa_cfg[0].ulso.is_ulso_pipe = true;
configFromEp(&from_ipa_cfg[0]);
prepare_channel_struct(&from_ipa_channels[0],
header.from_ipa_channels_num++,
IPA_CLIENT_TEST_CONS,
(void *)&from_ipa_cfg[0],
sizeof(from_ipa_cfg[0]),
en_status);
from_ipa_array[0] = &from_ipa_channels[0];
/* To ipa configurations - 1 pipe */
memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0]));
to_ipa_cfg[0].ulso.ipid_min_max_idx = 0;
to_ipa_cfg[0].ulso.is_ulso_pipe = true;
prepare_channel_struct(&to_ipa_channels[0],
header.to_ipa_channels_num++,
IPA_CLIENT_TEST_PROD,
(void *)&to_ipa_cfg[0],
sizeof(to_ipa_cfg[0]));
to_ipa_array[0] = &to_ipa_channels[0];
prepare_header_struct(&header, from_ipa_array, to_ipa_array);
return GenericConfigureScenario(&header, true);
}
protected:
static void printBuf(uint8_t* buf, size_t bufSize, string title=""){
if(bufSize == 0){
return;
}
cout << title << endl << std::hex;
for (size_t i = 0; i < bufSize-1; i++)
cout << std::setfill('0') << std::setw(2) << static_cast<int>(buf[i]) << " ";
cout << std::setfill('0') << std::setw(2) << static_cast<int>(buf[bufSize-1]) << std::dec << endl;
}
public:
InterfaceAbstraction m_producer;
InterfaceAbstraction m_consumer;
uint8_t m_sendBuf[UlsoPacket<>::maxSize];
uint8_t m_receiveBuf[UlsoPacket<>::maxSize];
uint8_t m_segmentBuf[UlsoPacket<>::maxSize];
};
#endif /* ULSOTESTFIXTURE_H_ */

View File

@@ -49,7 +49,7 @@ string sFormat = "ip_accelerator <control_flag> <suit/name>, ..., <suit/name>\n"
"ip_accelerator " SHOW_SUIT_FLAG "\n" "ip_accelerator " SHOW_SUIT_FLAG "\n"
"or ip_accelerator --chooser " "or ip_accelerator --chooser "
"for menu chooser interface\n"; "for menu chooser interface\n";
#define MAX_SUITES 15 #define MAX_SUITES 17
#undef strcasesame #undef strcasesame
#define strcasesame(x, y) \ #define strcasesame(x, y) \

View File

@@ -88,7 +88,7 @@ public:
Transport mTransportHeader; Transport mTransportHeader;
vector<uint8_t> mPayload {}; vector<uint8_t> mPayload {};
UlsoPacket(unsigned int segmentSize, unsigned int payloadSize, bool ethernetHeaderValid=false): UlsoPacket(unsigned int segmentSize, unsigned int payloadSize, bool ethernetHeaderValid=true):
mEthernetHeaderValid(ethernetHeaderValid){ mEthernetHeaderValid(ethernetHeaderValid){
bool first = true; bool first = true;
uint32_t seqNum = 0; uint32_t seqNum = 0;