diff --git a/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module.h b/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module.h index 223db248c1..a3ebaf7b94 100644 --- a/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module.h +++ b/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module.h @@ -23,6 +23,9 @@ enum { IPA_TEST_IOCTL_HOLB_CONFIG, IPA_TEST_IOCTL_FLT_TBL_IN_SRAM, 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, }; @@ -47,6 +50,15 @@ enum { #define IPA_TEST_IOC_GET_MEM_PART _IOWR(IPA_TEST_IOC_MAGIC, \ IPA_TEST_IOCTL_GET_MEM_PART, \ 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_CHANNEL_CONFIG_MARKER 0x83 diff --git a/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module_impl.c b/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module_impl.c index 12fd17b429..d0587119d1 100644 --- a/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module_impl.c +++ b/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module_impl.c @@ -57,7 +57,10 @@ #define RX_NUM_BUFFS 16 #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_META_DATA_IS_VALID 1 @@ -110,6 +113,7 @@ struct device *ipa_get_pdev(void); enum fops_type { IPA_TEST_REG_CHANNEL, IPA_TEST_DATA_PATH_TEST_CHANNEL, + IPA_TEST_ULSO_DATA_PATH_TEST_CHANNEL, MAX_FOPS }; @@ -225,6 +229,8 @@ struct ipa_tx_suspend_private_data { static struct test_context *ipa_test; +static size_t rx_size; + /** * 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, 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 = { .owner = THIS_MODULE, .open = channel_open, - .read = set_skb_for_user, + .read = set_skb_for_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 @@ -566,6 +581,9 @@ int create_channel_device_by_type( case IPA_TEST_DATA_PATH_TEST_CHANNEL: cdev_init(&channel_dev->cdev, &data_path_fops); break; + case IPA_TEST_ULSO_DATA_PATH_TEST_CHANNEL: + cdev_init(&channel_dev->cdev, &ulso_data_path_fops); + break; default: IPATEST_ERR("Wrong fops type"); ret = -EINVAL; @@ -632,6 +650,8 @@ struct datapath_ctx { struct datapath_ctx *p_data_path_ctx; +bool init_write_done_completion; + /* * Inits the kfifo needed for the @@ -640,6 +660,7 @@ struct datapath_ctx *p_data_path_ctx; int datapath_ds_init(void) { int res = 0; + rx_size = RX_SZ; p_data_path_ctx = kzalloc(sizeof(struct datapath_ctx), GFP_KERNEL); if (!p_data_path_ctx) { @@ -696,6 +717,24 @@ static struct sk_buff *datapath_create_skb(const char *buf, size_t size) 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) { int res; @@ -796,6 +835,45 @@ static ssize_t get_skb_from_user(struct file *filp, const char __user *buf, 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 * that was received in the system @@ -2806,19 +2884,14 @@ void destroy_channel_devices(void) { IPATEST_DBG("-----Tear Down----\n"); while (ipa_test->num_tx_channels > 0) { - IPATEST_DBG("-- num_tx_channels = %d --\n", - ipa_test->num_tx_channels); - - destroy_channel_device( - ipa_test->tx_channels[--ipa_test->num_tx_channels]); + IPATEST_DBG("-- num_tx_channels = %d --\n", 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; } while (ipa_test->num_rx_channels > 0) { - IPATEST_DBG("-- num_rx_channels = %d --\n", - ipa_test->num_rx_channels); - destroy_channel_device - (from_ipa_devs[--ipa_test->num_rx_channels]); + IPATEST_DBG("-- num_rx_channels = %d --\n", 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; } } @@ -4069,7 +4142,8 @@ static ssize_t ipa_test_read(struct file *filp, static struct class *ipa_test_class; //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; 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", to_ipa_channel_config.tail_marker); - if (to_ipa_channel_config.head_marker != - IPA_TEST_CHANNEL_CONFIG_MARKER) { + if (to_ipa_channel_config.head_marker != IPA_TEST_CHANNEL_CONFIG_MARKER) { IPATEST_ERR("bad head_marker - possible memory corruption\n"); return -EFAULT; } - if (to_ipa_channel_config.tail_marker != - IPA_TEST_CHANNEL_CONFIG_MARKER) { + if (to_ipa_channel_config.tail_marker != IPA_TEST_CHANNEL_CONFIG_MARKER) { IPATEST_ERR("bad tail_marker - possible memory corruption\n"); 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 */ - retval = create_channel_device(index, "to_ipa", - &to_ipa_devs[index], TX_SZ); + if(isUlso){ + 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) { IPATEST_ERR("channel device creation error\n"); return -1; } - ipa_test->tx_channels[ipa_test->num_tx_channels++] = - to_ipa_devs[index]; + ipa_test->tx_channels[ipa_test->num_tx_channels++] = to_ipa_devs[index]; + if (isUlso) + return 0; /* Connect IPA --> Apps */ memset(&sys_in, 0, sizeof(sys_in)); sys_in.client = to_ipa_channel_config.client; IPATEST_DBG("copying from 0x%px\n", to_ipa_channel_config.cfg); - retval = copy_from_user( - &sys_in.ipa_ep_cfg, - to_ipa_channel_config.cfg, - to_ipa_channel_config.config_size); + retval = copy_from_user(&sys_in.ipa_ep_cfg, to_ipa_channel_config.cfg, to_ipa_channel_config.config_size); if (retval) { IPATEST_ERR("fail to copy cfg - from_ipa_user\n"); return -1; } - if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, - &to_ipa_devs[index]->ipa_client_hdl, false)) { + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, &to_ipa_devs[index]->ipa_client_hdl, false)) { IPATEST_ERR("setup sys pipe failed\n"); return -1; } /* Connect APPS MEM --> Tx IPA */ - retval = connect_apps_to_ipa(&to_ipa_devs[index]->ep, - to_ipa_channel_config.client, - ipa_pipe_num, - &to_ipa_devs[index]->mem, - ipa_gsi_hdl); + retval = connect_apps_to_ipa(&to_ipa_devs[index]->ep, to_ipa_channel_config.client, ipa_pipe_num, + &to_ipa_devs[index]->mem, ipa_gsi_hdl); if (retval) { IPATEST_ERR("fail to connect ipa to apps\n"); return -1; @@ -4167,7 +4237,7 @@ static int configure_app_to_ipa_path(struct ipa_channel_config __user *to_ipa_us 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; 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 */ retval = create_channel_device(index, "from_ipa", - &from_ipa_devs[index], RX_SZ); + &from_ipa_devs[index], rx_size); if (retval) { IPATEST_ERR("channel device creation error\n"); return -1; @@ -4238,6 +4308,9 @@ static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ip /* Connect IPA --> Apps */ IPATEST_DBG("copying from 0x%px\n", from_ipa_channel_config.cfg); memset(&sys_in, 0, sizeof(sys_in)); + if (isUlso) { + sys_in.notify = notify_ipa_write_done; + } sys_in.client = from_ipa_channel_config.client; retval = copy_from_user( &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( struct ipa_test_config_header *ipa_test_config_header, 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 i; @@ -4307,14 +4381,19 @@ static int configure_test_scenario( for (i = 0 ; i < ipa_test_config_header->from_ipa_channels_num ; i++) { IPATEST_DBG("starting configuration of from_ipa_%d\n", i); - retval = configure_app_from_ipa_path( - from_ipa_channel_config_array[i]); + retval = configure_app_from_ipa_path(from_ipa_channel_config_array[i], isUlso); if (retval) { IPATEST_ERR("fail to configure from_ipa_%d", i); goto fail; } } + if (isUlso) { + rx_size = RX_SZ_ULSO; + } else { + rx_size = RX_SZ; + } + retval = insert_descriptors_into_rx_endpoints(RX_BUFF_SIZE); if (retval) { 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"); for (i = 0 ; i < ipa_test_config_header->to_ipa_channels_num ; i++) { - retval = configure_app_to_ipa_path( - to_ipa_channel_config_array[i]); + retval = configure_app_to_ipa_path(to_ipa_channel_config_array[i], isUlso); if (retval) { IPATEST_ERR("fail to configure to_ipa_%d", i); goto fail; @@ -4346,7 +4424,55 @@ fail: 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 needed_bytes; @@ -4405,10 +4531,10 @@ static int handle_configuration_ioctl(unsigned long ioctl_arg) goto fail_copy_to; } - retval = configure_test_scenario( - &test_header, + retval = configure_test_scenario(&test_header, from_ipa_channel_config_array, - to_ipa_channel_config_array); + to_ipa_channel_config_array, + isUlso); if (retval) IPATEST_ERR("fail to configure the system\n"); @@ -4569,7 +4695,7 @@ static long ipa_test_ioctl(struct file *filp, switch (cmd) { case IPA_TEST_IOC_CONFIGURE: - retval = handle_configuration_ioctl(arg); + retval = handle_configuration_ioctl(arg, false); break; case IPA_TEST_IOC_CLEAN: @@ -4593,6 +4719,15 @@ static long ipa_test_ioctl(struct file *filp, case IPA_TEST_IOC_GET_MEM_PART: retval = ipa_test_get_mem_part(arg); 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: IPATEST_ERR("ioctl is not supported (%d)\n", cmd); return -ENOTTY; diff --git a/kernel-tests/HeaderInsertion.cpp b/kernel-tests/HeaderInsertion.cpp index 4d92e8b77f..cae0e9142f 100644 --- a/kernel-tests/HeaderInsertion.cpp +++ b/kernel-tests/HeaderInsertion.cpp @@ -31,8 +31,11 @@ #include #include #include +#include +#include #include "HeaderInsertion.h" +#include "TestsUtils.h" /*All interaction through the driver are * made through this inode. @@ -76,6 +79,50 @@ bool HeaderInsertion::AddHeader(struct ipa_ioc_add_hdr *pHeaderTableToAdd) 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(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) { int nRetVal = 0; @@ -85,6 +132,32 @@ bool HeaderInsertion::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete) 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(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) { int retval = 0; @@ -154,6 +227,23 @@ bool HeaderInsertion::GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct) 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) { int retval = 0; diff --git a/kernel-tests/HeaderInsertion.h b/kernel-tests/HeaderInsertion.h index 613aec5339..b5d6410d91 100644 --- a/kernel-tests/HeaderInsertion.h +++ b/kernel-tests/HeaderInsertion.h @@ -31,7 +31,15 @@ #define HEADER_INSERTION_H_ #include +#include +#include #include "linux/msm_ipa.h" +#include "ipa_test_module.h" +#include "Constants.h" + +using std::string; +using std::cout; +using std::endl; class HeaderInsertion { @@ -40,8 +48,11 @@ private: public: 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(const string& name); bool GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct); + int GetHeaderHandle(const string& name); bool CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct); // Processing context diff --git a/kernel-tests/InterfaceAbstraction.cpp b/kernel-tests/InterfaceAbstraction.cpp index f690d203df..a5ec738910 100644 --- a/kernel-tests/InterfaceAbstraction.cpp +++ b/kernel-tests/InterfaceAbstraction.cpp @@ -30,10 +30,14 @@ #include #include #include +#include #include "InterfaceAbstraction.h" #define MAX_OPEN_RETRY 10000 +using std::cout; +using std::endl; + bool InterfaceAbstraction::Open(const char * toIPAPath, const char * fromIPAPath) { int tries_cnt = MAX_OPEN_RETRY; @@ -95,9 +99,9 @@ void InterfaceAbstraction::Close() 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); @@ -118,7 +122,7 @@ bool InterfaceAbstraction::SendData(unsigned char *buf, size_t size) exit(-1); } - printf("bytesWritten = %d.\n", bytesWritten); + cout << "bytesWritten = " << bytesWritten << endl; return bytesWritten; } @@ -145,6 +149,30 @@ int InterfaceAbstraction::ReceiveData(unsigned char *buf, size_t size) 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() { close(m_fromIPADescriptor); diff --git a/kernel-tests/InterfaceAbstraction.h b/kernel-tests/InterfaceAbstraction.h index 074eb09c01..6a110e5e3d 100644 --- a/kernel-tests/InterfaceAbstraction.h +++ b/kernel-tests/InterfaceAbstraction.h @@ -45,8 +45,11 @@ public: ~InterfaceAbstraction(); bool Open(const char *toIPAPath, const char *fromIPAPath); 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 ReceiveSingleDataChunk(unsigned char *buf, size_t size); + int setReadNoBlock(); + int clearReadNoBlock(); string m_toChannelName; string m_fromChannelName; diff --git a/kernel-tests/Makefile.am b/kernel-tests/Makefile.am index 5a6a4ad36e..e38320b7cc 100644 --- a/kernel-tests/Makefile.am +++ b/kernel-tests/Makefile.am @@ -48,4 +48,5 @@ ipa_kernel_tests_SOURCES =\ FilteringEthernetBridgingTests.cpp \ NatTest.cpp \ IPv6CTTest.cpp \ + UlsoTest.cpp \ main.cpp diff --git a/kernel-tests/TestsUtils.cpp b/kernel-tests/TestsUtils.cpp index 4a6e36fc4c..9be9691efa 100644 --- a/kernel-tests/TestsUtils.cpp +++ b/kernel-tests/TestsUtils.cpp @@ -992,18 +992,16 @@ static bool is_reconfigure_required(struct ipa_test_config_header *header) return false; } -int GenericConfigureScenario(struct ipa_test_config_header *header) +int GenericConfigureScenario(struct ipa_test_config_header *header, bool isUlso) { int fd; int retval; if (is_reconfigure_required(header) == false) { - g_Logger.AddMessage(LOG_DEVELOPMENT , - "No need to reconfigure, we are all good :)\n"); + g_Logger.AddMessage(LOG_DEVELOPMENT , "No need to reconfigure, we are all good :)\n"); return true; } else { - g_Logger.AddMessage(LOG_DEVELOPMENT , - "Need to run configuration again\n"); + g_Logger.AddMessage(LOG_DEVELOPMENT , "Need to run configuration again\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); @@ -1047,7 +1045,7 @@ int GenericConfigureScenario(struct ipa_test_config_header *header) 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) { g_Logger.AddMessage(LOG_ERROR, "%s - open %s failed (fd=%d,errno=%s)\n", @@ -1055,7 +1053,11 @@ int GenericConfigureScenario(struct ipa_test_config_header *header) 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) { g_Logger.AddMessage(LOG_ERROR, "fail to configure the system (%d)\n", retval); close(fd); diff --git a/kernel-tests/TestsUtils.h b/kernel-tests/TestsUtils.h index f2a50fc1f6..4a35fce1fa 100644 --- a/kernel-tests/TestsUtils.h +++ b/kernel-tests/TestsUtils.h @@ -296,7 +296,8 @@ bool CreateBypassRoutingTable_v2( */ void ConfigureScenario(int testConfiguration); 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 ConfigureSystem(int testConfiguration, int fd); int ConfigureSystem(int testConfiguration, int fd, const char *params); @@ -696,6 +697,11 @@ struct ipa_ep_cfg_seq { int seq_type; }; +struct ipa_ep_cfg_ulso { + int ipid_min_max_idx; + bool is_ulso_pipe; +}; + struct ipa_ep_cfg_holb { uint32_t tmr_val; uint32_t base_val; @@ -705,9 +711,9 @@ struct ipa_ep_cfg_holb { uint8_t scaled_time; }; -struct ipa_ep_cfg_ulso { - int ipid_min_max_idx; - bool is_ulso_pipe; +struct ipa_pkt_init_ex_hdr_ofst_set { + char name[IPA_RESOURCE_NAME_MAX]; + enum ipa_client_type ep; }; /* diff --git a/kernel-tests/UlsoTest.cpp b/kernel-tests/UlsoTest.cpp new file mode 100644 index 0000000000..e3f182af7d --- /dev/null +++ b/kernel-tests/UlsoTest.cpp @@ -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 +#include +#include +#include +#include +#include // 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 +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 class PacketModifier {public:virtual void operator()(PacketType& p) const = 0;}; +template class NullPacketModifier: public PacketModifier {public:void operator()(PacketType& p) const override {}}; +template class ZeroChecksumPacketModifier: public PacketModifier + {public:void operator()(PacketType& p) const override {p.mQmapHeader.setmZeroChecksum(1);}}; +template class OutOfBoundsPacketModifier: public PacketModifier + {public:void operator()(PacketType& p) const override {p.mQmapHeader.setmIpIdCfg(0);p.setIpId(65530);}}; + +template>> +class PacketsGeneratorClass { + +protected: + + using PacketType = UlsoPacket; + +public: + + vector operator()(){ + vector outVec; + Modifier m; + for(size_t i=0; i(SegmentSizesArr[i] * SegmentsNumsArr[j]), true); + m(p); + outVec.emplace_back(p); + } + } + return outVec; + } +}; + +template +class UlsoTest: public UlsoTestFixture { + +private: + + using PacketType = UlsoPacket; + + 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 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 packetsVec = PacketsGenerator()(); + for(auto& p: packetsVec){ + if(!singlePacketRun(p)){ + cout << "Failed With the following packet:" << endl; + cout << p << endl; + return false; + } + } + return true; + } +}; + +template +class UlsoHPCTest: public UlsoTestFixture { + +private: + + using PacketType = UlsoPacket; + 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 segmentedPacketsVec = p.segment(); + memset(m_segmentBuf, 0, sizeof(m_segmentBuf)); + uint8_t *segmentBufPtr = m_segmentBuf; + size_t totalSegmentsSize = 0; + vector 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 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>> +#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 ulsoTest0 {"Single Packet: IPV4 UDP"}; +static UlsoTest ulsoTest1 {"Single Packet: IPV4 TCP"}; +static UlsoTest ulsoTest2 {"Single Packet: IPV6 UDP"}; +static UlsoTest 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 ulsoTest10 {"Segmentation No Segmentation IPV4 UDP"}; +static UlsoTest ulsoTest11 {"Segmentation No Segmentation IPV4 TCP"}; +static UlsoTest ulsoTest12 {"Segmentation No Segmentation IPV6 UDP"}; +static UlsoTest 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 + ulsoTest20 {"Zero Checksum IPV4 UDP"}; +static UlsoTest + ulsoTest21 {"Zero Checksum IPV4 TCP"}; +static UlsoTest + ulsoTest22 {"Zero Checksum IPV6 UDP"}; +static UlsoTest + 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 ulsoTest30 {"Payload Smaller Than MSS IPV4 UDP"}; +static UlsoTest ulsoTest31 {"Payload Smaller Than MSS IPV4 TCP"}; +static UlsoTest ulsoTest32 {"Payload Smaller Than MSS IPV6 UDP"}; +static UlsoTest 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 ulsoTest40 {"Payload slightly Smaller Than MSS IPV4 UDP"}; +static UlsoTest ulsoTest41 {"Payload slightly Smaller Than MSS IPV4 TCP"}; +static UlsoTest ulsoTest42 {"Payload slightly Smaller Than MSS IPV6 UDP"}; +static UlsoTest 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 ulsoTest50 {"Payload Equals MSS IPV4 UDP"}; +static UlsoTest ulsoTest51 {"Payload Equals MSS IPV4 TCP"}; +static UlsoTest ulsoTest52 {"Payload Equals MSS IPV6 UDP"}; +static UlsoTest 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 ulsoTest60 {"Valid Segment Sizes IPV4 UDP"}; +static UlsoTest ulsoTest61 {"Valid Segment Sizes IPV4 TCP"}; +static UlsoTest ulsoTest62 {"Valid Segment Sizes IPV6 UDP"}; +static UlsoTest 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 ulsoTest70 {"Big Segment Sizes IPV4 UDP"}; +static UlsoTest ulsoTest71 {"Big Segment Sizes IPV4 TCP"}; +static UlsoTest ulsoTest72 {"Big Segment Sizes IPV6 UDP"}; +static UlsoTest 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 ulsoTest80 {"IPID CFG IPV4 UDP"}; +static UlsoTest ulsoTest81 {"IPID CFG IPV4 UDP"}; +//////////////////////////////////////////////////////////////////////////////// +//////////////// HPC RNDIS Header Insertion ////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +static UlsoHPCTest Ipv4UdpHpcRndisTest {"Ipv4UdpHpcRndisTest", "IPv4 + UDP"}; +static UlsoHPCTest Ipv4TcpHpcRndisTest {"Ipv4TcpHpcRndisTest", "IPv4 + TCP"}; +static UlsoHPCTest Ipv6UdpHpcRndisTest {"Ipv6UdpHpcRndisTest", "IPv6 + UDP"}; +static UlsoHPCTest Ipv6TcpHpcRndisTest {"Ipv6TcpHpcRndisTest", "IPv6 + TCP"}; diff --git a/kernel-tests/UlsoTestFixture.h b/kernel-tests/UlsoTestFixture.h new file mode 100644 index 0000000000..e2d5aecb37 --- /dev/null +++ b/kernel-tests/UlsoTestFixture.h @@ -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 +#include +#include +#include +#include +#include + +#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(buf[i]) << " "; + cout << std::setfill('0') << std::setw(2) << static_cast(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_ */ diff --git a/kernel-tests/main.cpp b/kernel-tests/main.cpp index 7f83a9feb0..b30f6c774b 100644 --- a/kernel-tests/main.cpp +++ b/kernel-tests/main.cpp @@ -49,7 +49,7 @@ string sFormat = "ip_accelerator , ..., \n" "ip_accelerator " SHOW_SUIT_FLAG "\n" "or ip_accelerator --chooser " "for menu chooser interface\n"; -#define MAX_SUITES 15 +#define MAX_SUITES 17 #undef strcasesame #define strcasesame(x, y) \ diff --git a/kernel-tests/network_traffic/UlsoPacket.h b/kernel-tests/network_traffic/UlsoPacket.h index ece7e563de..f3936af88c 100644 --- a/kernel-tests/network_traffic/UlsoPacket.h +++ b/kernel-tests/network_traffic/UlsoPacket.h @@ -88,7 +88,7 @@ public: Transport mTransportHeader; vector mPayload {}; - UlsoPacket(unsigned int segmentSize, unsigned int payloadSize, bool ethernetHeaderValid=false): + UlsoPacket(unsigned int segmentSize, unsigned int payloadSize, bool ethernetHeaderValid=true): mEthernetHeaderValid(ethernetHeaderValid){ bool first = true; uint32_t seqNum = 0;