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:
@@ -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
|
||||||
|
@@ -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,13 +478,22 @@ 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,
|
||||||
.read = set_skb_for_user,
|
.read = set_skb_for_user,
|
||||||
.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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
@@ -1047,7 +1045,7 @@ int GenericConfigureScenario(struct ipa_test_config_header *header)
|
|||||||
header->to_ipa_channel_config[i]->en_status);
|
header->to_ipa_channel_config[i]->en_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(CONFIGURATION_NODE_PATH, O_RDWR);
|
fd = open(CONFIGURATION_NODE_PATH, O_RDWR);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
g_Logger.AddMessage(LOG_ERROR,
|
g_Logger.AddMessage(LOG_ERROR,
|
||||||
"%s - open %s failed (fd=%d,errno=%s)\n",
|
"%s - open %s failed (fd=%d,errno=%s)\n",
|
||||||
@@ -1055,7 +1053,11 @@ int GenericConfigureScenario(struct ipa_test_config_header *header)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = ioctl(fd, IPA_TEST_IOC_CONFIGURE, header);
|
if(isUlso){
|
||||||
|
retval = ioctl(fd, IPA_TEST_IOC_ULSO_CONFIGURE, header);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
@@ -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
396
kernel-tests/UlsoTest.cpp
Normal 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"};
|
176
kernel-tests/UlsoTestFixture.h
Normal file
176
kernel-tests/UlsoTestFixture.h
Normal 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_ */
|
@@ -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) \
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user