diff --git a/config/dataipa_debug.conf b/config/dataipa_debug.conf index 4aad364440..2c999cde21 100644 --- a/config/dataipa_debug.conf +++ b/config/dataipa_debug.conf @@ -1,2 +1,3 @@ export CONFIG_IPA_DEBUG=y export CONFIG_IPA_UT=y +export CONFIG_IPA_KERNEL_TESTS_MODULE=y diff --git a/config/dataipa_debug.h b/config/dataipa_debug.h index defea06a85..7b2cc4bc77 100644 --- a/config/dataipa_debug.h +++ b/config/dataipa_debug.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* -* Copyright (c) 2020, The Linux Foundation. All rights reserved. +* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #define CONFIG_IPA_DEBUG 1 #define CONFIG_IPA_UT 1 +#define CONFIG_IPA_KERNEL_TESTS_MODULE 1 diff --git a/drivers/platform/msm/Kbuild b/drivers/platform/msm/Kbuild index 7307526929..6f78be38bc 100644 --- a/drivers/platform/msm/Kbuild +++ b/drivers/platform/msm/Kbuild @@ -52,6 +52,9 @@ LINUXINCLUDE += -I$(DATAIPADRVTOP)/ipa LINUXINCLUDE += -I$(DATAIPADRVTOP)/ipa/ipa_v3 LINUXINCLUDE += -I$(DATAIPADRVTOP)/ipa/ipa_v3/ipahal LINUXINCLUDE += -I$(DATAIPADRVTOP)/ipa/ipa_clients +ifneq (,$(filter $(CONFIG_IPA_KERNEL_TESTS_MODULE),y m)) +LINUXINCLUDE += -I$(DATAIPADRVTOP)/ipa/ipa_test_module +endif endif ifneq (,$(filter $(CONFIG_IPA3_REGDUMP),y m)) diff --git a/drivers/platform/msm/ipa/Kbuild b/drivers/platform/msm/ipa/Kbuild index 48bc30063e..0bb02fbd44 100644 --- a/drivers/platform/msm/ipa/Kbuild +++ b/drivers/platform/msm/ipa/Kbuild @@ -49,10 +49,15 @@ ipam-$(CONFIG_IPA_UT) += test/ipa_ut_framework.o test/ipa_test_example.o \ test/ipa_test_hw_stats.o test/ipa_pm_ut.o \ test/ipa_test_wdi3.o +ipatestm-$(CONFIG_IPA_KERNEL_TESTS_MODULE) += \ + ipa_test_module/ipa_test_module_impl.o \ + ipa_test_module/ipa_rm_ut.o + ipanetm-y += ipa_v3/ipa_net.o obj-$(CONFIG_IPA3) += ipam.o obj-$(CONFIG_IPA3) += ipanetm.o +obj-$(CONFIG_IPA_KERNEL_TESTS_MODULE) += ipatestm.o obj-y += ipa_v3/ ipa_clients/ diff --git a/drivers/platform/msm/ipa/ipa_test_module/ipa_rm_ut.c b/drivers/platform/msm/ipa/ipa_test_module/ipa_rm_ut.c new file mode 100644 index 0000000000..56c32202cc --- /dev/null +++ b/drivers/platform/msm/ipa/ipa_test_module/ipa_rm_ut.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +*/ + +#include +#include +#include +#include +#include +#include +#include "ipa_rm_ut.h" + +#define IPA_UT_DBG(x...) pr_err(x) + +/** + * enum ut_wq_cmd - workqueue commands + */ +enum ut_wq_cmd { + UT_WQ_REQ, + UT_WQ_REL +}; + +/** + * struct ipa_rm_ut_wq_work_type - IPA RM worqueue specific + * work type + * @work: work struct + * @wq_cmd: command that should be processed in workqueue context + * @resource_name: name of the resource on which this work + * should be done + * @dep_graph: data structure to search for resource if exists + * @event: event to notify + */ +struct ipa_rm_ut_wq_work_type { + struct work_struct work; + enum ut_wq_cmd wq_cmd; + enum ipa_rm_resource_name resource_name; + enum ipa_rm_event event; +}; + + + +static struct { + int (*add_dependency)(enum ipa_rm_resource_name + dependant_name, + enum ipa_rm_resource_name + dependency_name); + int (*resource_request)(enum ipa_rm_resource_name resource_name); + int (*resource_release)(enum ipa_rm_resource_name resource_name); + int (*consumer_cb)(enum ipa_rm_event, + enum ipa_rm_resource_name resource_name); + struct workqueue_struct *wq; +} ipa_rm_ut_cb; + +struct device_manager_type { + void *user_data; + ipa_rm_notify_cb notify_cb; + int (*release_function)(void); + int (*request_function)(void); +}; + +static void ipa_ut_wq_handler(struct work_struct *work); +int ipa_ut_wq_send_cmd(enum ut_wq_cmd wq_cmd, + enum ipa_rm_resource_name resource_name, + enum ipa_rm_event event); +static int usb_mgr_release_function(void); +static int usb_mgr_request_function(void); +static void usb_mgr_notify_function(void *user_data, + enum ipa_rm_event event, + unsigned long data); + +static struct device_manager_type usb_device_manager = { + NULL, + usb_mgr_notify_function, + usb_mgr_release_function, + usb_mgr_request_function +}; + +/* USB device manager */ +static int usb_mgr_release_function(void) +{ + IPA_UT_DBG("USB Released\n"); + IPA_UT_DBG("ASYNC CALL USB calling to IPA RM provided CB\n"); + ipa_ut_wq_send_cmd(UT_WQ_REL, + IPA_RM_RESOURCE_USB_CONS, + IPA_RM_RESOURCE_RELEASED); + + return -EINPROGRESS; +} + +static int usb_mgr_request_function(void) +{ + IPA_UT_DBG("USB Requested\n"); + IPA_UT_DBG("ASYNC CALL USB calling to IPA RM provided CB\n"); + ipa_ut_wq_send_cmd(UT_WQ_REQ, + IPA_RM_RESOURCE_USB_CONS, + IPA_RM_RESOURCE_GRANTED); + + return -EINPROGRESS; +} + +static void usb_mgr_notify_function(void *notify_cb_data, + enum ipa_rm_event event, + unsigned long data) +{ + IPA_UT_DBG("USB got event [%d]\n", event); +} + +/* HSIC device manager */ +static int hsic_mgr_release_function(void) +{ + int result = 0; + IPA_UT_DBG("HSIC Released\n"); + IPA_UT_DBG("HSIC calling to IPA RM provided CB\n"); + result = ipa_rm_ut_cb.consumer_cb(IPA_RM_RESOURCE_RELEASED, + IPA_RM_RESOURCE_HSIC_CONS); + + return -EINPROGRESS; +} + +static int hsic_mgr_request_function(void) +{ + int result = 0; + IPA_UT_DBG("HSIC Requested\n"); + IPA_UT_DBG("HSIC calling to IPA RM provided CB\n"); + result = ipa_rm_ut_cb.consumer_cb(IPA_RM_RESOURCE_GRANTED, + IPA_RM_RESOURCE_HSIC_CONS); + + return -EINPROGRESS; +} + +static void hsic_notify_function(void *notify_cb_data, + enum ipa_rm_event event, + unsigned long data) +{ + IPA_UT_DBG("HSIC got event [%d]\n", event); +} + +static struct device_manager_type hsic_device_manager = { + NULL, + hsic_notify_function, + hsic_mgr_release_function, + hsic_mgr_request_function +}; + +static void rmnet_bridge_mgr_notify_function + (void *notify_cb_data, + enum ipa_rm_event event, + unsigned long data) +{ + IPA_UT_DBG("RmNet got event [%d]\n", event); +} + +static struct device_manager_type rmnet_bridge_device_manager = { + NULL, + rmnet_bridge_mgr_notify_function, + NULL, + NULL +}; + + +static void ipa_ut_wq_handler(struct work_struct *work) +{ + enum ut_wq_cmd ut_cmd; + struct ipa_rm_ut_wq_work_type *ipa_rm_work = + (struct ipa_rm_ut_wq_work_type *)work; + if (!ipa_rm_work) + return; + ut_cmd = (enum ut_wq_cmd)ipa_rm_work->wq_cmd; + IPA_UT_DBG("***UT CMD Q command [%d]\n", ut_cmd); + switch (ut_cmd) { + case UT_WQ_REQ: + switch (ipa_rm_work->resource_name) { + case IPA_RM_RESOURCE_USB_CONS: + IPA_UT_DBG + ("***calling to USB consumer notify request CB\n"); + ipa_rm_ut_cb.consumer_cb(IPA_RM_RESOURCE_GRANTED, + IPA_RM_RESOURCE_USB_CONS); + break; + case IPA_RM_RESOURCE_HSIC_CONS: + break; + default: + return; + } + break; + case UT_WQ_REL: + switch (ipa_rm_work->resource_name) { + case IPA_RM_RESOURCE_USB_CONS: + IPA_UT_DBG + ("***calling to USB consumer notify release CB\n"); + ipa_rm_ut_cb.consumer_cb(IPA_RM_RESOURCE_RELEASED, + IPA_RM_RESOURCE_USB_CONS); + break; + case IPA_RM_RESOURCE_HSIC_CONS: + break; + default: + return; + } + break; + default: + break; + } + + kfree((void *) work); +} + +int ipa_ut_wq_send_cmd(enum ut_wq_cmd wq_cmd, + enum ipa_rm_resource_name resource_name, + enum ipa_rm_event event) +{ + int result = 0; + struct ipa_rm_ut_wq_work_type *work = + (struct ipa_rm_ut_wq_work_type *) + kzalloc(sizeof(*work), GFP_KERNEL); + if (work) { + INIT_WORK((struct work_struct *)work, ipa_ut_wq_handler); + work->wq_cmd = (enum ut_wq_cmd) wq_cmd; + work->resource_name = resource_name; + work->event = event; + result = queue_work(ipa_rm_ut_cb.wq, + (struct work_struct *)work); + } else { + result = -ENOMEM; + } + return result; +} + +/** + * build_rmnet_bridge_use_case_graph() - simulate resource creation + * + * @create_resource: create resource function provided by ipa_rm + * unit under test + * @consumer_cb: consumer CB function provided by ipa_rm + * unit under test + * + * Returns: 0 on success, negative on failure + */ +int build_rmnet_bridge_use_case_graph( + int (*create_resource) + (struct ipa_rm_create_params *create_params), + int (*consumer_cb)(enum ipa_rm_event event, + enum ipa_rm_resource_name resource_name)) +{ + int result = 0; + struct ipa_rm_create_params create_params = {0}; + + IPA_UT_DBG("build_rmnet_bridge_use_case_graph ENTER\n"); + + ipa_rm_ut_cb.consumer_cb = consumer_cb; + + /* create USB PROD */ + create_params.name = IPA_RM_RESOURCE_USB_PROD; + create_params.reg_params.notify_cb = + usb_device_manager.notify_cb; + create_params.reg_params.user_data = + usb_device_manager.user_data; + result = create_resource(&create_params); + if (result) + goto bail; + + /* create USB CONS */ + create_params.name = IPA_RM_RESOURCE_USB_CONS; + create_params.release_resource = + usb_device_manager.release_function; + create_params.request_resource = + usb_device_manager.request_function; + result = create_resource(&create_params); + if (result) + goto bail; + + /* create HSIC PROD */ + create_params.name = IPA_RM_RESOURCE_HSIC_PROD; + create_params.reg_params.notify_cb = + hsic_device_manager.notify_cb; + create_params.reg_params.user_data = + hsic_device_manager.user_data; + result = create_resource(&create_params); + if (result) + goto bail; + + /* create HSIC CONS */ + create_params.name = IPA_RM_RESOURCE_HSIC_CONS; + create_params.release_resource = + hsic_device_manager.release_function; + create_params.request_resource = + hsic_device_manager.request_function; + result = create_resource(&create_params); + if (result) + goto bail; + + /* BRIDGE PROD */ + create_params.name = IPA_RM_RESOURCE_WWAN_0_PROD; + create_params.reg_params.notify_cb = + rmnet_bridge_device_manager.notify_cb; + create_params.reg_params.user_data = + rmnet_bridge_device_manager.user_data; + result = create_resource(&create_params); + if (result) + goto bail; + + ipa_rm_ut_cb.wq = create_singlethread_workqueue("ut_wq"); + if (!ipa_rm_ut_cb.wq) { + result = -ENOMEM; + goto bail; + } + + IPA_UT_DBG("build_rmnet_bridge_use_case_graph EXIT SUCCESS\n"); + +bail: + + return result; +} + +/** + * build_rmnet_bridge_use_case_dependencies() - simulate build + * dependency graph process + * @add_dependency: add dependency function provided by ipa_rm + * unit under test + * + * Returns: 0 on success, negative on failure + */ +int build_rmnet_bridge_use_case_dependencies( + int (*add_dependency) + (enum ipa_rm_resource_name dependant_name, + enum ipa_rm_resource_name dependency_name)) +{ + int result = 0; + + IPA_UT_DBG("build_rmnet_bridge_use_case_dependencies ENTER\n"); + + ipa_rm_ut_cb.add_dependency = add_dependency; + + result = add_dependency(IPA_RM_RESOURCE_USB_PROD, + IPA_RM_RESOURCE_HSIC_CONS); + if (result) + goto bail; + result = add_dependency(IPA_RM_RESOURCE_HSIC_PROD, + IPA_RM_RESOURCE_USB_CONS); + if (result) + goto bail; + result = add_dependency(IPA_RM_RESOURCE_WWAN_0_PROD, + IPA_RM_RESOURCE_HSIC_CONS); + if (result) + goto bail; + result = add_dependency(IPA_RM_RESOURCE_WWAN_0_PROD, + IPA_RM_RESOURCE_USB_CONS); + + if (result) + goto bail; + +bail: + IPA_UT_DBG( + "build_rmnet_bridge_use_case_dependencies EXIT result [%d]\n", + result); + return result; +} + +/** + * request_release_resource_sequence() - simulate request / release + * resource sequence + * @resource_request: request resource function provided by ipa_rm + * unit under test + * @resource_release: release resource function provided by ipa_rm + * unit under test + * + * Returns: 0 on success, negative on failure + */ +int request_release_resource_sequence( + int (*resource_request) + (enum ipa_rm_resource_name resource_name), + int (*resource_release) + (enum ipa_rm_resource_name resource_name)) +{ + int result = 0; + ipa_rm_ut_cb.resource_request = resource_request; + ipa_rm_ut_cb.resource_release = resource_release; + + IPA_UT_DBG("request_release_resource_sequence ENTER\n"); + + result = resource_request(IPA_RM_RESOURCE_USB_PROD); + IPA_UT_DBG("result [%d]\n", result); + result = resource_request(IPA_RM_RESOURCE_HSIC_PROD); + IPA_UT_DBG("result [%d]\n", result); + + result = resource_release(IPA_RM_RESOURCE_USB_PROD); + IPA_UT_DBG("result [%d]\n", result); + result = resource_release(IPA_RM_RESOURCE_HSIC_PROD); + IPA_UT_DBG("result [%d]\n", result); + + IPA_UT_DBG("request_release_resource_sequence EXIT SUCCESS\n"); + return result; +} + +/** + * clean_ut() - free unit test module resources + * + */ +void clean_ut(void) +{ + IPA_UT_DBG("clean_ut ENTER\n"); + if (ipa_rm_ut_cb.wq) + destroy_workqueue(ipa_rm_ut_cb.wq); + IPA_UT_DBG("clean_ut EXIT SUCCESS\n"); +} diff --git a/drivers/platform/msm/ipa/ipa_test_module/ipa_rm_ut.h b/drivers/platform/msm/ipa/ipa_test_module/ipa_rm_ut.h new file mode 100644 index 0000000000..51b4d0f774 --- /dev/null +++ b/drivers/platform/msm/ipa/ipa_test_module/ipa_rm_ut.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +*/ + +#ifndef _IPA_RM_UT_H_ +#define _IPA_RM_UT_H_ + +/** + * ipa_rm_ut - unit test module + * Defines sanity test scenarios executed from debugfs + * writer function defined in ipa_rm module + */ + +#include +#include + +int build_rmnet_bridge_use_case_graph( + int (*create_resource)(struct ipa_rm_create_params *create_params), + int (*consumer_cb)(enum ipa_rm_event event, + enum ipa_rm_resource_name resource_name)); + +int build_rmnet_bridge_use_case_dependencies( + int (*add_dependency)(enum ipa_rm_resource_name dependant_name, + enum ipa_rm_resource_name dependency_name)); +int request_release_resource_sequence( + int (*resource_request)(enum ipa_rm_resource_name resource_name), + int (*resource_release)(enum ipa_rm_resource_name resource_name)); + +void clean_ut(void); + +#endif /* _IPA_RM_UT_H_ */ 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 new file mode 100644 index 0000000000..8937e162f5 --- /dev/null +++ b/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module.h @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved. +*/ + +#ifndef _IPA_TEST_MODULE_H_ +#define _IPA_TEST_MODULE_H_ + +#include +#include +#include +#ifdef _KERNEL_ +#include +#endif + +#define IPA_TEST_IOC_MAGIC 0xA5 +enum { + IPA_TEST_IOCTL_GET_HW_TYPE = 1, + IPA_TEST_IOCTL_CONFIGURE, + IPA_TEST_IOCTL_CLEAN, + IPA_TEST_IOCTL_EP_CTRL, + IPA_TEST_IOCTL_REG_SUSPEND_HNDL, + IPA_TEST_IOCTL_HOLB_CONFIG, + IPA_TEST_IOCTL_NUM, +}; + +#define IPA_TEST_IOC_GET_HW_TYPE _IO(IPA_TEST_IOC_MAGIC, \ + IPA_TEST_IOCTL_GET_HW_TYPE) +#define IPA_TEST_IOC_CONFIGURE _IOWR(IPA_TEST_IOC_MAGIC, \ + IPA_TEST_IOCTL_CONFIGURE, \ + struct ipa_test_config_header *) +#define IPA_TEST_IOC_CLEAN _IO(IPA_TEST_IOC_MAGIC, \ + IPA_TEST_IOCTL_CLEAN) +#define IPA_TEST_IOC_EP_CTRL _IOWR(IPA_TEST_IOC_MAGIC, \ + IPA_TEST_IOCTL_EP_CTRL, \ + struct ipa_test_ep_ctrl *) +#define IPA_TEST_IOC_REG_SUSPEND_HNDL _IOWR(IPA_TEST_IOC_MAGIC, \ + IPA_TEST_IOCTL_REG_SUSPEND_HNDL, \ + struct ipa_test_reg_suspend_handler *) +#define IPA_TEST_IOC_HOLB_CONFIG _IOWR(IPA_TEST_IOC_MAGIC, \ + IPA_TEST_IOCTL_HOLB_CONFIG, \ + struct handle_holb_config_ioctl *) + +#define IPA_TEST_CONFIG_MARKER 0x57 +#define IPA_TEST_CHANNEL_CONFIG_MARKER 0x83 + +/* + * This is the configuration number that is saved for Generic configuration + * we need it in order to allow coexistence of Generic + * configured tests with old fashion tests + */ +#define GENERIC_TEST_CONFIGURATION_IDX 37788239 + +struct ipa_test_config_header +{ + unsigned char head_marker; /* IPA_TEST_CONFIG_MARKER */ + int to_ipa_channels_num; + struct ipa_channel_config **to_ipa_channel_config; + int from_ipa_channels_num; + struct ipa_channel_config **from_ipa_channel_config; + unsigned char tail_marker; /* IPA_TEST_CONFIG_MARKER */ +}; + +struct ipa_test_en_status +{ + int num_clients; + enum ipa_client_type *clients; +}; + +struct ipa_test_ep_ctrl +{ + bool ipa_ep_suspend; + bool ipa_ep_delay; + int from_dev_num; +}; + +struct ipa_test_reg_suspend_handler +{ + int DevNum; + bool reg; + bool deferred_flag; +}; + +struct ipa_channel_config +{ + unsigned char head_marker; /* IPA_TEST_CHANNEL_CONFIG_MARKER */ + enum ipa_client_type client; + int index; /* shall be used for to_ipa_x or from_ipa_x */ + size_t config_size; + void *cfg; + bool en_status; + unsigned char tail_marker; /* IPA_TEST_CHANNEL_CONFIG_MARKER */ +}; + +struct ipa_test_holb_config +{ + enum ipa_client_type client; + unsigned tmr_val; + unsigned short en; +}; +#endif /* _IPA_TEST_MODULE_H_ */ 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 new file mode 100644 index 0000000000..1f236ac62b --- /dev/null +++ b/drivers/platform/msm/ipa/ipa_test_module/ipa_test_module_impl.c @@ -0,0 +1,4666 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. +*/ + +#include /* u32 */ +#include /* pr_debug() */ +#include /* kzalloc() */ +#include /* mutex */ +#include /* list_head */ +#include /* msleep */ +#include /* memset */ +#include /* device */ +#include /* cdev_alloc() */ +#include /* alloc_chrdev_region() */ +#include /* module_init() */ +#include /* dma_alloc_coherent() */ +#include +#include +#include +#include +#include /* sk_buff */ +#include /* Kernel FIFO Implementation */ +#include /* msleep() */ +#include +#include +#include +#include "gsi.h" +#include "ipa_i.h" +#include "ipa_rm_ut.h" +#include "ipa_test_module.h" + +#ifdef INIT_COMPLETION +#define reinit_completion(x) INIT_COMPLETION(*(x)) +#endif /* INIT_COMPLETION */ + + +/** Module name string */ +#define IPA_TEST_DRV_NAME "ipa_test" + +//#define IPA_SUMMING_THRESHOLD 0x10 +#define IPA_EVENT_THRESHOLD 0x10 +#define IPA_NUM_PIPES 0x24 + +#define TEST_SIGNATURE 0xfacecafe +#define DFAB_ARB1_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2564) + +#define DESC_FIFO_SZ 0x100 +#define DATA_FIFO_SZ 0x2000 + +#define GSI_CHANNEL_RING_LEN 4096 +#define GSI_EVT_RING_LEN 4096 + +#define TX_NUM_BUFFS 16 +#define TX_SZ 32768 +#define TX_BUFF_SIZE ((TX_SZ)/(TX_NUM_BUFFS)) + +#define RX_NUM_BUFFS 16 +#define RX_SZ 32768 +#define RX_BUFF_SIZE ((RX_SZ)/(RX_NUM_BUFFS)) + +#define IPA_TEST_DMUX_HEADER_LENGTH 8 +#define IPA_TEST_META_DATA_IS_VALID 1 +#define IPA_TEST_DMUX_HEADER_META_DATA_OFFSET 4 + +#define IPA_TEST_ADDITIONAL_HDR_LEN 4 + +#define IPA_TEST_META_DATA_OFFSET_NONE 0 + +#define IPA_TEST_HDI_802_HEADER_LENGTH 22 +#define IPA_TEST_HDI_802_LENGTH_FIELD_OFFSET 11 +#define IPA_TEST_HDI_802_LENGTH_FIELD_OFFSET_VALID 1 +#define IPA_TEST_HDI_802_ADD_CONST_LENGTH 0 + +#define IPA_TEST_HDI_RMNET_HEADER_LENGTH 6 +#define IPA_TEST_HDI_RMNET_LENGTH_FIELD_OFFSET 0 +#define IPA_TEST_HDI_RMNET_LENGTH_FIELD_OFFSET_VALID 0 +#define IPA_TEST_HDI_RMNET_ADD_CONST_LENGTH 0 + +/* Settings of Exception Handling */ +#define RX_DESCRIPTOR_SIZE 2048 +#define EXCEPTION_DRV_NAME "ipa_exception_pipe" +#define EXCEPTION_KFIFO_SIZE (8) +#define EXCEPTION_KFIFO_SLEEP_MS (EXCEPTION_KFIFO_SLEEP_MS) +#define EXCEPTION_KFIFO_DEBUG_VERBOSE 1 +#define SAVE_HEADER 1 + +#define IPATEST_DBG(fmt, args...) \ + do { \ + pr_debug(IPA_TEST_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\ + } while (0) + +#define IPATEST_ERR(fmt, args...) \ + do { \ + pr_err(IPA_TEST_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\ + } while (0) + +#define IPATEST_DUMP(fmt, args...) \ + do { \ + pr_debug(fmt, ## args);\ + } while (0) + +int ipa_sys_setup(struct ipa_sys_connect_params *sys_in, + unsigned long *ipa_gsi_hdl, + u32 *ipa_pipe_num, u32 *clnt_hdl, bool en_status); +int ipa_sys_teardown(u32 clnt_hdl); +int ipa_sys_update_gsi_hdls(u32 clnt_hdl, unsigned long gsi_ch_hdl, + unsigned long gsi_ev_hdl); +struct device *ipa_get_pdev(void); +enum fops_type { + IPA_TEST_REG_CHANNEL, + IPA_TEST_DATA_PATH_TEST_CHANNEL, + MAX_FOPS +}; + +struct notify_cb_data_st { + struct kfifo_rec_ptr_2 exception_kfifo; +}; + +struct exception_hdl_data { + struct class *class; + struct device *dev; + struct cdev *p_cdev; + dev_t dev_num; + struct notify_cb_data_st notify_cb_data; +}; + +/*struct exception_hdl_data *p_exception_hdl_data = NULL;*/ +struct exception_hdl_data *p_exception_hdl_data; + +struct ipa_dma_chan { + u32 dest_pipe_index; + u32 src_pipe_index; +}; + +/** + * This struct specifies memory buffer properties. + * + * @base - Buffer virtual address. + * @phys_base - Buffer physical address. + * @size - Specifies buffer size (or maximum size). + * + */ +//struct ipa_mem_buffer { +// void *base; +// phys_addr_t phys_base; +// u32 size; +//}; + +struct test_endpoint_sys { + struct completion xfer_done; /*A completion object for end transfer*/ + struct gsi_chan_props gsi_channel_props; + struct gsi_evt_ring_props gsi_evt_ring_props; + bool gsi_valid; + unsigned long gsi_chan_hdl; + unsigned long gsi_evt_ring_hdl; +}; + +#define MAX_CHANNEL_NAME (20) + +/* A channel device is the representation of the flow of data from APPS + to IPA and vice versa. */ +struct channel_dev { + /*OS structures for representation of a channel.*/ + struct class *class; + dev_t dev_num; + struct device *dev; + struct cdev cdev; + + /*The representation of the connection from APPS to GSI/IPA*/ + struct test_endpoint_sys ep; + /*The representation of the connection from GSI to IPA*/ + struct ipa_dma_chan dma_ep; + /*The data FIFO for the APPS to IPA*/ + struct ipa_mem_buffer mem; + /*Index of the next available buffer to use under mem.buff*/ + int mem_buff_index; + /*A pointer to the test context - should be deleted - TODO*/ + struct test_context *test; + + int index;/*to_ipa_/from_ipa_*/ + char name[MAX_CHANNEL_NAME]; + int rx_pool_inited;/*check... - should be moved to contex?*/ + int ipa_client_hdl;/*returned from ipa_connect*/ +}; + +#define MAX_CHANNEL_DEVS (10) +static struct channel_dev *to_ipa_devs[MAX_CHANNEL_DEVS/2]; +/*TODO - legacy*/ +static struct channel_dev *from_ipa_devs[MAX_CHANNEL_DEVS/2]; + +/*This structure holds all the data required for the test module.*/ +struct test_context { + + /*OS structures for representation of the test module.*/ + dev_t dev_num; + struct device *dev; + struct cdev *cdev; + + /*All channels that are used to read data from + * the IPA(Receive channel)*/ + struct channel_dev *rx_channels[MAX_CHANNEL_DEVS/2]; + + /*All channels that are used to write data + * to the IPA(Transmit channel)*/ + struct channel_dev *tx_channels[MAX_CHANNEL_DEVS/2]; + int num_rx_channels; + int num_tx_channels; + + /*current test case(-EINVAL is for not-configured)TODO*/ + s32 configuration_idx; + s32 current_configuration_idx; + + u32 signature;/*Legacy*/ +}; + +/** + * struct ipa_tx_suspend_private_data - private data for IPA_TX_SUSPEND_IRQ use + * @clnt_hdl: client handle assigned by IPA + */ +struct ipa_tx_suspend_private_data { + u32 clnt_hdl; + u32 gsi_chan_hdl; +}; + +static struct test_context *ipa_test; + + +/** + * Allocate memory from system memory. + * + * @param mem + */ +static void test_alloc_mem(struct ipa_mem_buffer *mem) +{ + dma_addr_t dma_addr; + + /* need to check return value in formal code */ + mem->base = dma_alloc_coherent(ipa3_get_pdev(), mem->size, &dma_addr, GFP_KERNEL); + mem->phys_base = dma_addr; +} + +/** + * Free memory from system memory. + * + * @param mem + */ +static void test_free_mem(struct ipa_mem_buffer *mem) +{ + dma_addr_t dma_addr = mem->phys_base; + + if (dma_addr) + dma_free_coherent(ipa3_get_pdev(), mem->size, mem->base, dma_addr); + + mem->phys_base = 0; + mem->base = NULL; +} + +void print_buff(void *data, size_t size) +{ + u8 bytes_in_line = 16; + int i, j, num_lines; + char str[256], tmp[4]; + + num_lines = size / bytes_in_line; + if (size % bytes_in_line > 0) + num_lines++; + + IPATEST_DBG("Printing buffer at address 0x%px, size = %zu:\n" + , data, size); + for (i = 0; i < num_lines; i++) { + str[0] = '\0'; + for (j = 0; (j < bytes_in_line) && + ((i * bytes_in_line + j) < size); j++) { + snprintf(tmp, sizeof(tmp), "%02x ", + ((unsigned char *)data) + [i * bytes_in_line + j]); + strlcat(str, tmp, sizeof(str)); + } + IPATEST_DUMP(": %s\n", str); + } +} + +static int channel_open(struct inode *inode, struct file *filp) +{ + struct channel_dev *channel_dev; + + /* Get the channel device data */ + channel_dev = container_of(inode->i_cdev, struct channel_dev, cdev); + + IPATEST_DBG("channel_dev address = 0x%px\n", channel_dev); + + filp->private_data = channel_dev; + + return 0; +} + +int insert_descriptors_into_rx_endpoints(u32 count) +{ + struct channel_dev *rx_channel = NULL; + int i, j, res = 0; + + /* Insert a descriptor into the receiving end(s) */ + for (i = 0; i < ipa_test->num_rx_channels; i++) { + rx_channel = ipa_test->rx_channels[i]; + if (!rx_channel->rx_pool_inited) { + res = 0; + for (j = 0; j < RX_NUM_BUFFS; j++) { + struct gsi_xfer_elem gsi_xfer; + + memset(&gsi_xfer, 0, sizeof(gsi_xfer)); + gsi_xfer.addr = rx_channel->mem.phys_base + j * count; + gsi_xfer.flags |= GSI_XFER_FLAG_EOT; + gsi_xfer.len = count; + gsi_xfer.type = GSI_XFER_ELEM_DATA; + gsi_xfer.xfer_user_data = (void*)(rx_channel->mem.phys_base + j * count); + + IPATEST_DBG("submitting credit to gsi\n"); + res |= gsi_queue_xfer(rx_channel->ep.gsi_chan_hdl, 1, &gsi_xfer, true); + if (res) { + IPATEST_ERR("gsi_queue_xfer failed %d\n", res); + return -EFAULT; + } + } + + if (res == 0) + rx_channel->rx_pool_inited = 1; + } + } + + return res; +} + +static ssize_t channel_write_gsi(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct channel_dev *channel_dev = filp->private_data; + int res = 0; + void *data_address = channel_dev->mem.base + + channel_dev->mem_buff_index * TX_BUFF_SIZE; + u32 data_phys_addr = channel_dev->mem.phys_base + + channel_dev->mem_buff_index * TX_BUFF_SIZE; + struct gsi_xfer_elem gsi_xfer; + + if (count > (RX_BUFF_SIZE)) + IPATEST_ERR("-----PROBLEM----- count=%zu RX_BUFF_SIZE=%d\n", + count, RX_BUFF_SIZE); + + /* Copy the data from the user and transmit */ + res = copy_from_user(data_address, buf, count); + if (res) { + IPATEST_ERR("copy_from_user() failure.\n"); + return -EINVAL; + } + + /* Print the data */ + print_buff(data_address, count); + + IPATEST_DBG("-----Start Transfer-----\n"); + + /* Transmit */ + memset(&gsi_xfer, 0, sizeof(gsi_xfer)); + gsi_xfer.addr = data_phys_addr; + gsi_xfer.flags |= GSI_XFER_FLAG_EOT; + gsi_xfer.len = count; + gsi_xfer.type = GSI_XFER_ELEM_DATA; + + IPATEST_DBG("sending a packet to gsi\n"); + res = gsi_queue_xfer(channel_dev->ep.gsi_chan_hdl, 1, &gsi_xfer, true); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("GSI xfer failed %d\n", res); + return res; + } + + channel_dev->mem_buff_index = (channel_dev->mem_buff_index + 1) % + TX_NUM_BUFFS; + return count; +} + +static ssize_t channel_read_gsi(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + struct channel_dev *channel_dev = filp->private_data; + int res = 0; + int i; + phys_addr_t offset = 0; + struct gsi_chan_xfer_notify xfer_notify; + int max_retry = 10; + struct gsi_xfer_elem gsi_xfer; + + IPATEST_DBG("size to read = %zu\n", count); + for (i = 0; i < max_retry; i++) { + res = gsi_poll_channel(channel_dev->ep.gsi_chan_hdl, + &xfer_notify); + + if (res != GSI_STATUS_SUCCESS && res != GSI_STATUS_POLL_EMPTY) { + IPATEST_ERR("gsi_poll_channel failed %d\n", res); + return res; + } + if (res == GSI_STATUS_SUCCESS) + break; + + IPATEST_DBG("channel empty %d/%d\n", i + 1, max_retry); + msleep(5); + } + + if (i == max_retry) { + IPATEST_ERR("transfer not completed.\n"); + return 0; + } + + IPATEST_DBG("received %d bytes from 0x%px.\n", + xfer_notify.bytes_xfered, xfer_notify.xfer_user_data); + + /* Copy the received data to the user buffer */ + offset = (phys_addr_t)xfer_notify.xfer_user_data - channel_dev->mem.phys_base; + res = copy_to_user(buf, + channel_dev->mem.base + offset, + xfer_notify.bytes_xfered); + if (res < 0) { + IPATEST_ERR("copy_to_user() failed.\n"); + return 0; + } + + /* Re-insert the descriptor back to pipe */ + memset(&gsi_xfer, 0, sizeof(gsi_xfer)); + gsi_xfer.addr = (phys_addr_t)xfer_notify.xfer_user_data; + gsi_xfer.flags |= GSI_XFER_FLAG_EOT; + gsi_xfer.len = RX_BUFF_SIZE; + gsi_xfer.type = GSI_XFER_ELEM_DATA; + gsi_xfer.xfer_user_data = xfer_notify.xfer_user_data; + + IPATEST_DBG("submitting credit to gsi\n"); + res = gsi_queue_xfer(channel_dev->ep.gsi_chan_hdl, 1, &gsi_xfer, true); + if (res) { + IPATEST_ERR("gsi_queue_xfer failed %d\n", res); + return 0; + } + + IPATEST_DBG("Returning %d.\n", xfer_notify.bytes_xfered); + return xfer_notify.bytes_xfered; +} + +static ssize_t channel_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + return channel_write_gsi(filp, buf, count, f_pos); +} + +static ssize_t channel_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + return channel_read_gsi(filp, buf, count, f_pos); +} + +static const struct file_operations channel_dev_fops = { + .owner = THIS_MODULE, + .open = channel_open, + .write = channel_write, + .read = channel_read, +}; + +static ssize_t set_skb_for_user(struct file *filp, char __user *buf, + size_t size, loff_t *p_pos); + +static ssize_t get_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, + .write = get_skb_from_user, +}; + + +/* + * This will create the char device named + * "_" and allocate data + * FIFO(size mem_size). + * In this case, we will differentiate + * channel_dev_fops, which are used for + * regular data transmission + * in all the tests,and data_path_fops + * which will be used + * in DataPath tests for handling + * the SKB we will transfer + */ +int create_channel_device_by_type( + const int index, + const char *dev_name, + struct channel_dev **channel_dev_ptr, + size_t mem_size, + enum fops_type type) +{ + int ret; + char name[MAX_CHANNEL_NAME]; + struct channel_dev *channel_dev = NULL; + + scnprintf(name, sizeof(name), "%s_%d", dev_name, index); + + IPATEST_DBG(":Creating channel %d device, name = %s.\n", + index, name); + + /* Allocate memory for the device */ + *channel_dev_ptr = kzalloc(sizeof(struct channel_dev), GFP_KERNEL); + if (NULL == *channel_dev_ptr) { + IPATEST_ERR("kzalloc err for channel dev\n"); + ret = -ENOMEM; + goto create_channel_device_failure; + } + + channel_dev = *channel_dev_ptr; + + strlcpy(channel_dev->name, name, MAX_CHANNEL_NAME); + + /* Allocate memory data buffer for the pipe */ + IPATEST_DBG(":-----Allocate memory data buffer-----\n"); + channel_dev->mem.size = mem_size; + test_alloc_mem(&channel_dev->mem); + if (NULL == channel_dev->mem.base) { + IPATEST_ERR("data fifo alloc fail\n"); + ret = -ENOMEM; + goto create_channel_device_failure; + } + IPATEST_DBG(": data fifo: mem phys=0x%pa.virt=0x%px.\n", + &channel_dev->mem.phys_base, channel_dev->mem.base); + memset(channel_dev->mem.base, 0xbb, channel_dev->mem.size); + + channel_dev->mem_buff_index = 0; + + /* Add a pointer from the channel device to the test context info */ + channel_dev->test = ipa_test; + + channel_dev->class = class_create(THIS_MODULE, name); + if (IS_ERR(channel_dev->class)) { + IPATEST_ERR(":class_create() err.\n"); + ret = -ENOMEM; + goto create_class_failure; + } + + ret = alloc_chrdev_region(&channel_dev->dev_num, 0, 1, name); + if (ret) { + IPATEST_ERR("alloc_chrdev_region err.\n"); + ret = -ENOMEM; + goto alloc_chrdev_failure; + } + + channel_dev->dev = device_create(channel_dev->class, NULL, + channel_dev->dev_num, channel_dev, name); + if (IS_ERR(channel_dev->dev)) { + IPATEST_ERR("device_create err.\n"); + ret = -ENODEV; + goto device_create_failure; + } + switch (type) { + case IPA_TEST_REG_CHANNEL: + cdev_init(&channel_dev->cdev, &channel_dev_fops); + break; + case IPA_TEST_DATA_PATH_TEST_CHANNEL: + cdev_init(&channel_dev->cdev, &data_path_fops); + break; + default: + IPATEST_ERR("Wrong fops type"); + ret = -EINVAL; + goto invalid_type_err; + } + channel_dev->cdev.owner = THIS_MODULE; + + ret = cdev_add(&channel_dev->cdev, channel_dev->dev_num, 1); + if (ret) { + IPATEST_ERR("cdev_add err=%d\n", -ret); + ret = -ENODEV; + goto cdev_add_failure; + } + + if (!ret) + IPATEST_DBG("Channel device:%d, name:%s created, address:0x%px.\n", + index, name, channel_dev); + + return 0; + +cdev_add_failure: + memset(&channel_dev->cdev, 0, sizeof(channel_dev->cdev)); +invalid_type_err: + device_destroy(channel_dev->class, channel_dev->dev_num); +device_create_failure: + unregister_chrdev_region(channel_dev->dev_num, 1); +alloc_chrdev_failure: + class_destroy(channel_dev->class); +create_class_failure: + test_free_mem(&channel_dev->mem); +create_channel_device_failure: + kfree(channel_dev); + IPATEST_ERR("Channel device %d, name %s creation FAILED.\n", + index, name); + + return ret; +} + +int create_channel_device(const int index, + const char *dev_name, + struct channel_dev **channel_dev_ptr, + size_t mem_size) { + return create_channel_device_by_type( + index, + dev_name, + channel_dev_ptr, + mem_size, + IPA_TEST_REG_CHANNEL); +} + +/* + * DataPath test definitions: + */ + +#define MAX_TEST_SKB 15 +#define TIME_OUT_TIME 2000 /* 2 seconds */ + +struct datapath_ctx { + struct mutex lock; + struct kfifo_rec_ptr_2 fifo; + struct completion write_done_completion; + struct completion ipa_receive_completion; +}; + +struct datapath_ctx *p_data_path_ctx; + + +/* + * Inits the kfifo needed for the + * DataPath tests + */ +int datapath_ds_init(void) +{ + int res = 0; + + p_data_path_ctx = kzalloc(sizeof(struct datapath_ctx), GFP_KERNEL); + if (!p_data_path_ctx) { + IPATEST_ERR("kzalloc returned error (%d)\n", res); + return res; + } + IPATEST_DBG("called.\n"); + + res = kfifo_alloc(&p_data_path_ctx->fifo + , (sizeof(struct sk_buff *)*MAX_TEST_SKB) + , GFP_KERNEL); + if (0 != res) { + IPATEST_ERR("kfifo_alloc returned error (%d)\n", res); + kfree(p_data_path_ctx); + return res; + } + + mutex_init(&p_data_path_ctx->lock); + init_completion(&p_data_path_ctx->ipa_receive_completion); + + IPATEST_DBG("completed.(%d)\n", res); + + return res; +} + +static struct sk_buff *datapath_create_skb(const char *buf, size_t size) +{ + struct sk_buff *skb; + unsigned char *data; + int err = 0; + + IPATEST_DBG("allocating SKB, len=%zu", size); + skb = alloc_skb(size, GFP_KERNEL); + if (unlikely(!skb)) + return NULL; + IPATEST_DBG("skb allocated, skb->len=%d", skb->len); + data = skb_put(skb, size); + if (unlikely(!data)) { + kfree_skb(skb); + return NULL; + } + IPATEST_DBG("skb put finish, skb->len=%d", skb->len); + skb->csum = csum_and_copy_from_user( + buf, data, + size, 0, &err); + if (err) { + kfree_skb(skb); + return NULL; + } + IPATEST_DBG("The following packet was created:\n"); + print_buff(skb->data, size); + IPATEST_DBG("Exiting\n"); + + return skb; +} + +static int datapath_read_data(void *element, int size) +{ + int res; + + IPATEST_DBG("Entering\n"); + + mutex_lock(&p_data_path_ctx->lock); + reinit_completion(&p_data_path_ctx->ipa_receive_completion); + IPATEST_DBG("Init completion\n"); + IPATEST_DBG("Checking if kfifo is empty\n"); + if (kfifo_is_empty(&p_data_path_ctx->fifo)) { + IPATEST_DBG("kfifo is empty\n"); + mutex_unlock(&p_data_path_ctx->lock); + IPATEST_DBG("wait_for_ipa_receive_completion\n"); + res = wait_for_completion_timeout( + &p_data_path_ctx->ipa_receive_completion, + msecs_to_jiffies(TIME_OUT_TIME)); + IPATEST_DBG("came back from wait_for_completion_timeout\n"); + if (!res) { + IPATEST_ERR("Error in wait_for_ipa_receive_completion\n"); + return -EINVAL; + } + IPATEST_DBG("locking lock\n"); + mutex_lock(&p_data_path_ctx->lock); + } + res = kfifo_out(&p_data_path_ctx->fifo, element, size); + if (res != size) { + IPATEST_ERR("Error in taking out an element\n"); + IPATEST_ERR("unlocking lock\n"); + mutex_unlock(&p_data_path_ctx->lock); + return -EINVAL; + } + IPATEST_DBG("took %d bytes out\n", res); + IPATEST_DBG("unlocking lock\n"); + IPATEST_DBG("Exiting\n"); + mutex_unlock(&p_data_path_ctx->lock); + return res; +} + +static int datapath_write_fifo( + void *element, + int size) { + + int res; + + IPATEST_DBG("Entering\n"); + mutex_lock(&p_data_path_ctx->lock); + IPATEST_DBG("Mutex locked\n"); + IPATEST_DBG("putting %px into fifo\n", element); + res = kfifo_in(&p_data_path_ctx->fifo, &element, size); + IPATEST_DBG("finished kfifo in\n"); + if (res != size) { + IPATEST_ERR("Error in saving element\n"); + return -EINVAL; + } + IPATEST_DBG("Mutex unlocked\n"); + + complete(&p_data_path_ctx->ipa_receive_completion); + IPATEST_DBG("Completed ipa_receive_completion\n"); + mutex_unlock(&p_data_path_ctx->lock); + return 0; +} + +/* + * 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_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 = datapath_create_skb(buf, size); + if (!skb) + return -EINVAL; + init_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 + */ + +static ssize_t set_skb_for_user(struct file *filp, char __user *buf, + size_t size, loff_t *p_pos) +{ + int res; + struct sk_buff *p_skb; + + IPATEST_DBG("Entering\n"); + /* Copy the result to the user buffer */ + + IPATEST_DBG("datapath_read_data\n"); + if (datapath_read_data( + (void *)&p_skb, + sizeof(struct sk_buff *)) < 0) { + IPATEST_ERR("error in datapath_read_data\n"); + return -EINVAL; + } + print_buff(p_skb->data, size); + IPATEST_DBG("Copying data back to user\n"); + res = copy_to_user(buf, p_skb->data, size); + kfree_skb(p_skb); + /* Return the number of bytes copied to the user */ + + return res; +} + +static void datapath_ds_clean(void) +{ + kfifo_reset(&p_data_path_ctx->fifo); +} + +/* + * Destroy the kfifo needed for the + * DataPath tests + */ + +static void datapath_exit(void) +{ + kfifo_free(&p_data_path_ctx->fifo); + /* freeing kfifo */ + kfree(p_data_path_ctx); + p_data_path_ctx = NULL; +} + +/* + * CB func. for the IPA_WRITE_DONE + * event. Used in IpaTxDpTest + */ + +static void notify_ipa_write_done( + void *priv, + enum ipa_dp_evt_type evt, + unsigned long data) { + + IPATEST_DBG("Entering function\n"); + + if (evt == IPA_WRITE_DONE) { + IPATEST_DBG("evt IPA_WRITE_DONE\n"); + IPATEST_DBG("Printing received buff from IPA\n"); + print_buff( + ((struct sk_buff *)data)->data, + ((struct sk_buff *)data)->len); + + kfree_skb((struct sk_buff *)data); + complete(&p_data_path_ctx->write_done_completion); + + } else { + IPATEST_DBG("Error, wrong event %d\n", evt); + } +} + +/* + * CB func. for the IPA_RECEIVE + * event. Used in IPAToAppsTest + */ + +static void notify_ipa_received( + void *priv, + enum ipa_dp_evt_type evt, + unsigned long data){ + + struct sk_buff *p_skb = (struct sk_buff *)data; + + IPATEST_DBG("Entering function\n"); + + if (evt == IPA_RECEIVE) { + IPATEST_DBG("evt IPA_RECEIVE\n"); + IPATEST_DBG("Printing received buff from IPA\n"); + print_buff(p_skb->data, p_skb->len); + datapath_write_fifo(p_skb, sizeof(struct sk_buff *)); + } else { + IPATEST_ERR("Error: wrong event %d", evt); + } +} + +static void ipa_test_gsi_evt_ring_err_cb(struct gsi_evt_err_notify *notify) +{ + if (notify) { + switch (notify->evt_id) { + case GSI_EVT_OUT_OF_BUFFERS_ERR: + IPATEST_ERR("Received GSI_EVT_OUT_OF_BUFFERS_ERR\n"); + break; + case GSI_EVT_OUT_OF_RESOURCES_ERR: + IPATEST_ERR("Received GSI_EVT_OUT_OF_RESOURCES_ERR\n"); + break; + case GSI_EVT_UNSUPPORTED_INTER_EE_OP_ERR: + IPATEST_ERR("Received GSI_EVT_UNSUPPORTED_INTER_EE_OP_ERR\n"); + break; + case GSI_EVT_EVT_RING_EMPTY_ERR: + IPATEST_ERR("Received GSI_EVT_EVT_RING_EMPTY_ERR\n"); + break; + default: + IPATEST_ERR("Unexpected err evt: %d\n", notify->evt_id); + } + } + return; +} + +static void ipa_test_gsi_chan_err_cb(struct gsi_chan_err_notify *notify) +{ + if (notify) { + switch (notify->evt_id) { + case GSI_CHAN_INVALID_TRE_ERR: + IPATEST_ERR("Received GSI_CHAN_INVALID_TRE_ERR\n"); + break; + case GSI_CHAN_NON_ALLOCATED_EVT_ACCESS_ERR: + IPATEST_ERR("Received GSI_CHAN_NON_ALLOCATED_EVT_ACCESS_ERR\n"); + break; + case GSI_CHAN_OUT_OF_BUFFERS_ERR: + IPATEST_ERR("Received GSI_CHAN_OUT_OF_BUFFERS_ERR\n"); + break; + case GSI_CHAN_OUT_OF_RESOURCES_ERR: + IPATEST_ERR("Received GSI_CHAN_OUT_OF_RESOURCES_ERR\n"); + break; + case GSI_CHAN_UNSUPPORTED_INTER_EE_OP_ERR: + IPATEST_ERR("Received GSI_CHAN_UNSUPPORTED_INTER_EE_OP_ERR\n"); + break; + case GSI_CHAN_HWO_1_ERR: + IPATEST_ERR("Received GSI_CHAN_HWO_1_ERR\n"); + break; + default: + IPATEST_ERR("Unexpected err ch: %d\n", notify->evt_id); + } + } + return; +} + +static void ipa_test_gsi_irq_notify_cb(struct gsi_chan_xfer_notify *notify) +{ + IPATEST_DBG("ipa_test_gsi_irq_notify_cb: channel 0x%px xfer 0x%px\n", notify->chan_user_data, notify->xfer_user_data); + IPATEST_DBG("ipa_test_gsi_irq_notify_cb: event %d notified\n", notify->evt_id); + IPATEST_DBG("ipa_test_gsi_irq_notify_cb: bytes_xfered %d\n", notify->bytes_xfered); +} + +int connect_ipa_to_apps(struct test_endpoint_sys *rx_ep, + enum ipa_client_type client, + u32 pipe_index, + unsigned long ipa_gsi_hdl) +{ + int res = 0; + + dma_addr_t dma_addr; + const struct ipa_gsi_ep_config *gsi_ep_config; + + memset(&rx_ep->gsi_evt_ring_props, 0, sizeof(rx_ep->gsi_evt_ring_props)); + rx_ep->gsi_evt_ring_props.intf = GSI_EVT_CHTYPE_GPI_EV; + rx_ep->gsi_evt_ring_props.intr = GSI_INTR_IRQ; + rx_ep->gsi_evt_ring_props.re_size = + GSI_EVT_RING_RE_SIZE_16B; + + rx_ep->gsi_evt_ring_props.ring_len = GSI_EVT_RING_LEN; + rx_ep->gsi_evt_ring_props.ring_base_vaddr = + dma_alloc_coherent(ipa3_get_pdev(), GSI_EVT_RING_LEN, + &dma_addr, 0); + rx_ep->gsi_evt_ring_props.ring_base_addr = dma_addr; + + rx_ep->gsi_evt_ring_props.int_modt = 3200; //0.1s under 32KHz clock + rx_ep->gsi_evt_ring_props.int_modc = 1; + rx_ep->gsi_evt_ring_props.rp_update_addr = 0; + rx_ep->gsi_evt_ring_props.exclusive = true; + rx_ep->gsi_evt_ring_props.err_cb = ipa_test_gsi_evt_ring_err_cb; + rx_ep->gsi_evt_ring_props.user_data = NULL; + + res = gsi_alloc_evt_ring(&rx_ep->gsi_evt_ring_props, ipa_gsi_hdl, + &rx_ep->gsi_evt_ring_hdl); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_alloc_evt_ring failed %d\n", res); + return -EFAULT; + } + + memset(&rx_ep->gsi_channel_props, 0, + sizeof(rx_ep->gsi_channel_props)); + rx_ep->gsi_channel_props.prot = GSI_CHAN_PROT_GPI; + rx_ep->gsi_channel_props.dir = GSI_CHAN_DIR_FROM_GSI; + gsi_ep_config = ipa_get_gsi_ep_info(client); + if (!gsi_ep_config) { + IPATEST_ERR("invalid gsi_ep_config\n"); + return -EFAULT; + } + rx_ep->gsi_channel_props.ch_id = + gsi_ep_config->ipa_gsi_chan_num; + rx_ep->gsi_channel_props.evt_ring_hdl = rx_ep->gsi_evt_ring_hdl; + rx_ep->gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_16B; + + rx_ep->gsi_channel_props.ring_len = GSI_CHANNEL_RING_LEN; + rx_ep->gsi_channel_props.ring_base_vaddr = + dma_alloc_coherent(ipa3_get_pdev(), GSI_CHANNEL_RING_LEN, + &dma_addr, 0); + if (!rx_ep->gsi_channel_props.ring_base_vaddr) { + IPATEST_ERR("connect_ipa_to_apps: falied to alloc GSI ring\n"); + return -EFAULT; + } + + rx_ep->gsi_channel_props.ring_base_addr = dma_addr; + rx_ep->gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE; + rx_ep->gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG; + rx_ep->gsi_channel_props.low_weight = 1; + rx_ep->gsi_channel_props.chan_user_data = rx_ep; + if (ipa_get_hw_type() >= IPA_HW_v4_9) + rx_ep->gsi_channel_props.db_in_bytes = 1; + + rx_ep->gsi_channel_props.err_cb = ipa_test_gsi_chan_err_cb; + rx_ep->gsi_channel_props.xfer_cb = ipa_test_gsi_irq_notify_cb; + res = gsi_alloc_channel(&rx_ep->gsi_channel_props, ipa_gsi_hdl, + &rx_ep->gsi_chan_hdl); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_alloc_channel failed %d\n", res); + return -EFAULT; + } + rx_ep->gsi_valid = true; + + res = ipa3_sys_update_gsi_hdls(pipe_index, rx_ep->gsi_chan_hdl, rx_ep->gsi_evt_ring_hdl); + if (res) { + IPATEST_ERR("ipa_sys_update_gsi_hdls failed %d\n", res); + return -EFAULT; + } + + res = gsi_start_channel(rx_ep->gsi_chan_hdl); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_start_channel failed %d\n", res); + return -EFAULT; + } + + IPATEST_DBG("setting channel to polling mode\n"); + res = gsi_config_channel_mode(rx_ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_config_channel_mode failed %d\n", res); + return -EFAULT; + } + + return 0; +} + +int connect_apps_to_ipa(struct test_endpoint_sys *tx_ep, + enum ipa_client_type client, + u32 pipe_index, + struct ipa_mem_buffer *desc_fifo, + unsigned long ipa_gsi_hdl) +{ + int res = 0; + dma_addr_t dma_addr; + const struct ipa_gsi_ep_config *gsi_ep_config; + + memset(&tx_ep->gsi_evt_ring_props, 0, sizeof(tx_ep->gsi_evt_ring_props)); + tx_ep->gsi_evt_ring_props.intf = GSI_EVT_CHTYPE_GPI_EV; + tx_ep->gsi_evt_ring_props.intr = GSI_INTR_IRQ; + tx_ep->gsi_evt_ring_props.re_size = + GSI_EVT_RING_RE_SIZE_16B; + + tx_ep->gsi_evt_ring_props.ring_len = GSI_EVT_RING_LEN; + tx_ep->gsi_evt_ring_props.ring_base_vaddr = + dma_alloc_coherent(ipa3_get_pdev(), GSI_EVT_RING_LEN, + &dma_addr, 0); + tx_ep->gsi_evt_ring_props.ring_base_addr = dma_addr; + + tx_ep->gsi_evt_ring_props.int_modt = 3200; //0.1s under 32KHz clock + tx_ep->gsi_evt_ring_props.int_modc = 1; + tx_ep->gsi_evt_ring_props.rp_update_addr = 0; + tx_ep->gsi_evt_ring_props.exclusive = true; + tx_ep->gsi_evt_ring_props.err_cb = ipa_test_gsi_evt_ring_err_cb; + tx_ep->gsi_evt_ring_props.user_data = NULL; + + res = gsi_alloc_evt_ring(&tx_ep->gsi_evt_ring_props, ipa_gsi_hdl, + &tx_ep->gsi_evt_ring_hdl); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_alloc_evt_ring failed %d\n", res); + return -EFAULT; + } + + memset(&tx_ep->gsi_channel_props, 0, sizeof(tx_ep->gsi_channel_props)); + tx_ep->gsi_channel_props.prot = GSI_CHAN_PROT_GPI; + tx_ep->gsi_channel_props.dir = GSI_CHAN_DIR_TO_GSI; + gsi_ep_config = ipa_get_gsi_ep_info(client); + if (!gsi_ep_config) { + IPATEST_ERR("invalid gsi_ep_config\n"); + return -EFAULT; + } + tx_ep->gsi_channel_props.ch_id = + gsi_ep_config->ipa_gsi_chan_num; + tx_ep->gsi_channel_props.evt_ring_hdl = tx_ep->gsi_evt_ring_hdl; + tx_ep->gsi_channel_props.re_size = GSI_CHAN_RE_SIZE_16B; + + tx_ep->gsi_channel_props.ring_len = GSI_CHANNEL_RING_LEN; + tx_ep->gsi_channel_props.ring_base_vaddr = + dma_alloc_coherent(ipa3_get_pdev(), GSI_CHANNEL_RING_LEN, + &dma_addr, 0); + if (!tx_ep->gsi_channel_props.ring_base_vaddr) { + IPATEST_ERR("connect_apps_to_ipa: falied to alloc GSI ring\n"); + return -EFAULT; + } + + tx_ep->gsi_channel_props.ring_base_addr = dma_addr; + tx_ep->gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE; + tx_ep->gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG; + tx_ep->gsi_channel_props.low_weight = 1; + tx_ep->gsi_channel_props.chan_user_data = tx_ep; + if (ipa_get_hw_type() >= IPA_HW_v4_9) + tx_ep->gsi_channel_props.db_in_bytes = 1; + + tx_ep->gsi_channel_props.err_cb = ipa_test_gsi_chan_err_cb; + tx_ep->gsi_channel_props.xfer_cb = ipa_test_gsi_irq_notify_cb; + res = gsi_alloc_channel(&tx_ep->gsi_channel_props, ipa_gsi_hdl, + &tx_ep->gsi_chan_hdl); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_alloc_channel failed %d\n", res); + return -EFAULT; + } + tx_ep->gsi_valid = true; + + res = ipa3_sys_update_gsi_hdls(pipe_index, tx_ep->gsi_chan_hdl, tx_ep->gsi_evt_ring_hdl); + if (res) { + IPATEST_ERR("ipa_sys_update_gsi_hdls failed %d\n", res); + return -EFAULT; + } + + res = gsi_start_channel(tx_ep->gsi_chan_hdl); + if (res != GSI_STATUS_SUCCESS) { + IPATEST_ERR("gsi_start_channel failed %d\n", res); + return -EFAULT; + } + + return 0; +} + +int configure_ipa_endpoint(struct ipa_ep_cfg *ipa_ep_cfg, + enum ipa_mode_type mode) +{ + const char *DEFAULT_ROUTING_TABLE_NAME = "LAN"; + const enum ipa_client_type DEFAULT_CLIENT = IPA_CLIENT_TEST4_CONS; + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + struct ipa_ioc_get_rt_tbl rt_lookup; + + memset(ipa_ep_cfg, 0, sizeof(*ipa_ep_cfg)); + /* Configure mode */ + ipa_ep_cfg->mode.mode = mode; + /* Add default routing rule */ + rt_rule = kzalloc(sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add), GFP_KERNEL); + if (!rt_rule) { + IPATEST_ERR("Allocation failure.\n"); + return -EINVAL; + } + rt_rule->commit = 1; + rt_rule->num_rules = 1; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, + DEFAULT_ROUTING_TABLE_NAME, + IPA_RESOURCE_NAME_MAX); + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = DEFAULT_CLIENT; + /* Issuing a routing rule without + * any equations will cause a default rule + which catches every packet and sends it + to the default endpoint. */ + if (ipa_add_rt_rule(rt_rule)) { + IPATEST_ERR("ipa_add_rt_rule() failure.\n"); + } + IPATEST_DBG("rt rule hdl1=%x.\n", rt_rule_entry->rt_rule_hdl); + /* At this point, there is a routing table in memory, + with one defalut rule. + user space test application will enter more valid + rules the default rule + must be last on the list. + Get a handle to the routing table which holds + the added rule. This will + also increment an internal reference count. */ + memset(&rt_lookup, 0, sizeof(struct ipa_ioc_get_rt_tbl)); + rt_lookup.ip = IPA_IP_v4; + strlcpy(rt_lookup.name, + DEFAULT_ROUTING_TABLE_NAME, + IPA_RESOURCE_NAME_MAX); + if (ipa3_get_rt_tbl(&rt_lookup)) { + IPATEST_ERR("ipa_get_rt_tbl() failure.\n"); + } + ipa_ep_cfg->route.rt_tbl_hdl = rt_lookup.hdl; + /* Now release the routing table hdl. This code assumes + that routing table + will continue to exist when the endpoint + connection is requested. */ + if (ipa_put_rt_tbl(rt_lookup.hdl)) { + IPATEST_ERR("ipa_put_rt_tbl() failure.\n"); + } + return 0; +} + +/* + * Configures the system as follows: + * This configuration is for one input pipe + * and one output pipe where both are USB1 + * /dev/to_ipa_0 -> MEM -> IPA + * -> MEM -> /dev/from_ipa_0 + * Those client will be configured in DMA mode thus + * no Header removal/insertion will be + * made on their data. +*/ +int configure_system_1(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + IPATEST_DBG("Configure_system_1 was called\n"); + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + /* Prepare EP configuration details */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + if (res) + goto fail; +fail: + /* cleanup and tear down goes here*/ + return res; +} + +/* + Configures the system with one input to IPA and 2 outputs. + /dev/to_ipa_0 -> MEM -> GSI -> IPA |-> GSI + -> MEM -> /dev/from_ipa_0 +|-> GSI -> MEM -> /dev/from_ipa_1 +*/ +int configure_system_2(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect second Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[1]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect third (Default) Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST4_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[2]->ep, + IPA_CLIENT_TEST4_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + + + if (res) + goto fail; + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + /* configure header removal on Tx */ + ipa_ep_cfg.hdr.hdr_len = ETH_HLEN; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[1]->ep, + IPA_CLIENT_TEST2_PROD, + ipa_pipe_num, + &to_ipa_devs[1]->mem, + ipa_gsi_hdl); + + + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + +/*Configuration used for Header Insertion Tests*/ +int configure_system_5(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + /* configure header Insertion on Tx */ + +/* ipa_ep_cfg.hdr.hdr_len = IPA_TEST_DMUX_HEADER_LENGTH; + !< Header length in bytes to be added/removed. + Assuming heaser len is constant per endpoint. + Valid for both Input and Output Pipes + Length of Header to add / to remove + ipa_ep_cfg.hdr.hdr_additional_const_len = 0; + !< Defines the constant length that should be added + to the payload length in order for IPA to update + correctly the length field within the header + (valid only in case Hdr_Ofst_Pkt_Size_Valid=1) + Valid for Output Pipes (IPA Producer) + ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 0; + !< 0: Hdr_Ofst_Pkt_Size value is invalid, i.e., + no length field within the inserted header + 1: Hdr_Ofst_Pkt_Size value is valid, i.e., + a packet length field resides within the header + Valid for Output Pipes (IPA Producer) + ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0; + !< Offset within header in which packet size + reside. Upon Header Insertion, IPA will update this + field within the header with the packet length . + Assumption is that header length field size is + constant and is 2Bytes Valid for Output Pipes (IPA Producer) + ipa_ep_cfg.hdr.hdr_a5_mux = 0; + 0: Do not insert APPS Mux Header + 1: Insert APPS Mux Header + !< Determines whether APPS Mux header should be + added to the packet. This bit is valid only when + Hdr_En=01(Header Insertion) SW should set this bit + for IPA-to-APPS pipes. + 0: Do not insert APPS Mux Header + 1: Insert APPS Mux Header + Valid for Output Pipes (IPA Producer) */ + + + + /* Connect IPA -> first Rx GSI */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.hdr.hdr_len = + IPA_TEST_HDI_RMNET_HEADER_LENGTH; + /* Length of Header to add / to remove */ + ipa_ep_cfg.hdr.hdr_additional_const_len = + IPA_TEST_HDI_RMNET_ADD_CONST_LENGTH; + /* constant length that should be added to the payload + * length or IPA to update correctly the length + * field within the header */ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid + = IPA_TEST_HDI_RMNET_LENGTH_FIELD_OFFSET_VALID; + /*0: Hdr_Ofst_Pkt_Size value is invalid, i.e., + no length field within the inserted header + 1: Hdr_Ofst_Pkt_Size value is valid, i.e., + a packet length field resides within the header*/ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size + = IPA_TEST_HDI_RMNET_LENGTH_FIELD_OFFSET; + /* Offset within header in which packet size reside. + Upon Header Insertion, IPA will update this field + within the header with the packet length . + Assumption is that header length field size + is constant and is 2Bytes */ + + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.hdr.hdr_len = IPA_TEST_HDI_802_HEADER_LENGTH; + /*Length of Header to add / to remove*/ + ipa_ep_cfg.hdr.hdr_additional_const_len + = IPA_TEST_HDI_802_ADD_CONST_LENGTH; + /* constant length that should be added + * to the payload length + or IPA to update correctly the + length field within the header */ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid + = IPA_TEST_HDI_802_LENGTH_FIELD_OFFSET_VALID; + /*0: Hdr_Ofst_Pkt_Size value is invalid, i.e., + no length field within the inserted header + 1: Hdr_Ofst_Pkt_Size value is valid, i.e. + a packet length field resides within the header*/ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size + = IPA_TEST_HDI_802_LENGTH_FIELD_OFFSET; + /* Offset within header in which packet size reside. + Upon Header Insertion, IPA will update this field + within the header with the packet length. + Assumption is that header length field size is constant + and is 2Bytes */ + /* Connect second Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, + &from_ipa_devs[1]->ipa_client_hdl, + false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[1]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect IPA -> third (default) Rx GSI */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.hdr.hdr_len + = IPA_TEST_HDI_802_HEADER_LENGTH; + /* Length of Header to add / to remove */ + ipa_ep_cfg.hdr.hdr_additional_const_len + = IPA_TEST_HDI_802_ADD_CONST_LENGTH+1; + /* constant length that should be + * added to the payload length + or IPA to update correctly the length + field within the header */ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid + = IPA_TEST_HDI_802_LENGTH_FIELD_OFFSET_VALID; + /* 0: Hdr_Ofst_Pkt_Size value is invalid, i.e., + no length field within the inserted header + 1: Hdr_Ofst_Pkt_Size value is valid, i.e., + a packet length field resides within the header */ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size + = IPA_TEST_HDI_802_LENGTH_FIELD_OFFSET; + /* Offset within header in which packet size reside. + * Upon Header Insertion, IPA will update this field + * within the header with the packet length . + * Assumption is that header length field size is constant + * and is 2Bytes */ + /* Connect third (Default) Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST4_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &from_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[2]->ep, + IPA_CLIENT_TEST4_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + + if (res) + goto fail; + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + +/*Configuration Used for USB Integration (on R3PC) */ +int configure_system_6(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + /* Prepare an endpoint configuration structure */ + ipa_ep_cfg.mode.mode = IPA_BASIC; + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST2_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + if (res) + goto fail; +fail: + /* cleanup and tear down goes here */ + return res; +} + + +/* + Configures the system as follows: + This configuration is for 4 input pipes and 3 output pipes: + /dev/to_ipa_0 -> MEM -> GSI -> + * IPA -> GSI -> MEM -> /dev/from_ipa_0 + /dev/to_ipa_1 -> MEM -> GSI -> + * IPA -> GSI -> MEM -> /dev/from_ipa_1 + /dev/to_ipa_2 -> MEM -> GSI -> + * IPA -> GSI -> MEM -> /dev/from_ipa_0 + /dev/to_ipa_3 -> MEM -> GSI -> + * IPA -> GSI -> MEM -> /dev/from_ipa_2 + to_ipa_1, to_ipa_2, from_ipa_0 & + from_ipa_2 transfer TLP aggregated packets + to_ipa_0, to_ipa_3 & from_ipa_1 transfer raw packets +*/ +int configure_system_8(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + IPATEST_DBG("Configure_system_8 was called\n"); + + /* Setup GSI pipes */ + to_ipa_devs[0]->dma_ep.src_pipe_index = 4; + to_ipa_devs[0]->dma_ep.dest_pipe_index = 5; + to_ipa_devs[1]->dma_ep.src_pipe_index = 6; + to_ipa_devs[1]->dma_ep.dest_pipe_index = 7; + to_ipa_devs[2]->dma_ep.src_pipe_index = 8; + to_ipa_devs[2]->dma_ep.dest_pipe_index = 9; + to_ipa_devs[3]->dma_ep.src_pipe_index = 10; + to_ipa_devs[3]->dma_ep.dest_pipe_index = 11; + + from_ipa_devs[0]->dma_ep.src_pipe_index = 14; + from_ipa_devs[0]->dma_ep.dest_pipe_index = 15; + from_ipa_devs[1]->dma_ep.src_pipe_index = 16; + from_ipa_devs[1]->dma_ep.dest_pipe_index = 17; + from_ipa_devs[2]->dma_ep.src_pipe_index = 18; + from_ipa_devs[2]->dma_ep.dest_pipe_index = 19; + /* configure aggregation on Tx */ + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_TLP; + ipa_ep_cfg.aggr.aggr_byte_limit = 1; + ipa_ep_cfg.aggr.aggr_time_limit = 0; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[1]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* configure aggregation on Tx */ + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_TLP; + ipa_ep_cfg.aggr.aggr_byte_limit = 1; + ipa_ep_cfg.aggr.aggr_time_limit = 30; + if (ipa_get_hw_type() >= IPA_HW_v4_2) + ipa_ep_cfg.aggr.aggr_time_limit *= 1000; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[2]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Prepare EP configuration details */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST3_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + + /* configure deaggregation on Rx */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST3_CONS; + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_ep_cfg.aggr.aggr = IPA_TLP; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[1]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[1]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + + /* configure deaggregation on Rx */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_ep_cfg.aggr.aggr = IPA_TLP; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[2]->ep, + IPA_CLIENT_TEST2_PROD, + ipa_pipe_num, + &to_ipa_devs[2]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Prepare EP configuration details */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST2_CONS; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST4_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[3]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[3]->ep, + IPA_CLIENT_TEST4_PROD, + ipa_pipe_num, + &to_ipa_devs[3]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + + +/* + Configures the system as follows: + This configuration is for 4 input pipes and 3 output pipes: + /dev/to_ipa_0 -> MEM -> GSI + * -> IPA -> GSI -> MEM -> /dev/from_ipa_0 + /dev/to_ipa_1 -> MEM -> GSI + * -> IPA -> GSI -> MEM -> /dev/from_ipa_1 + /dev/to_ipa_2 -> MEM -> GSI + * -> IPA -> GSI -> MEM -> /dev/from_ipa_0 + /dev/to_ipa_3 -> MEM -> GSI + * -> IPA -> GSI -> MEM -> /dev/from_ipa_2 + to_ipa_1, to_ipa_2, from_ipa_0 & + from_ipa_2 transfer MBIM aggregated packets + to_ipa_0, to_ipa_3 & from_ipa_1 transfer raw packets +*/ +int configure_system_9(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + enum ipa_aggr_mode mode; + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + mode = IPA_MBIM_AGGR; + res = ipa_set_aggr_mode(mode); + if (res) + goto fail; + res = ipa_set_single_ndp_per_mbim(true); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + IPATEST_DBG("Configure_system_9 was called\n"); + + /* Setup GSI pipes */ + to_ipa_devs[0]->dma_ep.src_pipe_index = 4; + to_ipa_devs[0]->dma_ep.dest_pipe_index = 5; + to_ipa_devs[1]->dma_ep.src_pipe_index = 6; + to_ipa_devs[1]->dma_ep.dest_pipe_index = 7; + to_ipa_devs[2]->dma_ep.src_pipe_index = 8; + to_ipa_devs[2]->dma_ep.dest_pipe_index = 9; + to_ipa_devs[3]->dma_ep.src_pipe_index = 10; + to_ipa_devs[3]->dma_ep.dest_pipe_index = 11; + + from_ipa_devs[0]->dma_ep.src_pipe_index = 14; + from_ipa_devs[0]->dma_ep.dest_pipe_index = 15; + from_ipa_devs[1]->dma_ep.src_pipe_index = 16; + from_ipa_devs[1]->dma_ep.dest_pipe_index = 17; + from_ipa_devs[2]->dma_ep.src_pipe_index = 18; + from_ipa_devs[2]->dma_ep.dest_pipe_index = 19; + + /* configure aggregation on Tx */ + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + ipa_ep_cfg.aggr.aggr_byte_limit = 1; + ipa_ep_cfg.aggr.aggr_time_limit = 0; + ipa_ep_cfg.hdr.hdr_len = 1; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[1]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* configure aggregation on Tx */ + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + ipa_ep_cfg.aggr.aggr_byte_limit = 1; + ipa_ep_cfg.aggr.aggr_time_limit = 30; + if (ipa_get_hw_type() >= IPA_HW_v4_2) + ipa_ep_cfg.aggr.aggr_time_limit *= 1000; + ipa_ep_cfg.hdr.hdr_len = 1; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[2]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Prepare EP configuration details */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST3_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + + /* configure deaggregation on Rx */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST3_CONS; + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[1]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[1]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + + /* configure deaggregation on Rx */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[2]->ep, + IPA_CLIENT_TEST2_PROD, + ipa_pipe_num, + &to_ipa_devs[2]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Prepare EP configuration details */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST2_CONS; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST4_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[3]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[3]->ep, + IPA_CLIENT_TEST4_PROD, + ipa_pipe_num, + &to_ipa_devs[3]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + +/* + Configures the system as follows: + This configuration is for 1 input pipe and 1 output pipe: + /dev/to_ipa_0 -> MEM -> GSI -> IPA -> GSI -> MEM -> /dev/from_ipa_0 + /dev/to_ipa_1 -> MEM -> GSI -> IPA -> GSI -> MEM -> /dev/from_ipa_1 + from_ipa_0, from_ipa_1 transfer IPA_MBIM_AGGR aggregated packets + to_ipa_0, to_ipa_1 transfer raw packets +*/ +int configure_system_10(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + enum ipa_aggr_mode mode; + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + mode = IPA_MBIM_AGGR; + res = ipa_set_aggr_mode(mode); + if (res) + goto fail; + res = ipa_set_single_ndp_per_mbim(false); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + IPATEST_DBG("Configure_system_10 was called\n"); + + /* Setup GSI pipes */ + to_ipa_devs[0]->dma_ep.src_pipe_index = 4; + to_ipa_devs[0]->dma_ep.dest_pipe_index = 5; + + from_ipa_devs[0]->dma_ep.src_pipe_index = 6; + from_ipa_devs[0]->dma_ep.dest_pipe_index = 7; + + /* configure aggregation on Tx */ + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + ipa_ep_cfg.aggr.aggr_byte_limit = 0; + ipa_ep_cfg.aggr.aggr_time_limit = 0; + ipa_ep_cfg.hdr.hdr_len = 1; + + /* Connect IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Prepare EP configuration details */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.mode.mode = IPA_DMA; + ipa_ep_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + +int configure_system_12(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + enum ipa_aggr_mode mode; + char qcncm_sig[3]; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + mode = IPA_QCNCM_AGGR; + res = ipa_set_aggr_mode(mode); + if (res) + goto fail; + res = ipa_set_single_ndp_per_mbim(false); + if (res) + goto fail; + qcncm_sig[0] = 0x51; + qcncm_sig[1] = 0x4e; + qcncm_sig[2] = 0x44; + res = ipa_set_qcncm_ndp_sig(qcncm_sig); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + + /* Connect IPA -> first Rx GSI */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + ipa_ep_cfg.aggr.aggr_byte_limit = 1; + ipa_ep_cfg.aggr.aggr_time_limit = 0; + ipa_ep_cfg.hdr.hdr_len = 1; + + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &from_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + /* Connect second Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &from_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[1]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect IPA -> first Rx GSI */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + ipa_ep_cfg.aggr.aggr_byte_limit = 0; + ipa_ep_cfg.aggr.aggr_time_limit = 30; + if (ipa_get_hw_type() >= IPA_HW_v4_2) + ipa_ep_cfg.aggr.aggr_time_limit *= 1000; + ipa_ep_cfg.hdr.hdr_len = 1; + + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &from_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[2]->ep, + IPA_CLIENT_TEST_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect IPA -> first Rx GSI */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + ipa_ep_cfg.aggr.aggr_byte_limit = 0; + ipa_ep_cfg.aggr.aggr_time_limit = 0; + ipa_ep_cfg.hdr.hdr_len = 1; + + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST4_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &from_ipa_devs[3]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[3]->ep, + IPA_CLIENT_TEST4_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + + if (res) + goto fail; + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_ep_cfg.aggr.aggr = IPA_MBIM_16; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, + &ipa_pipe_num, &to_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[1]->ep, + IPA_CLIENT_TEST2_PROD, + ipa_pipe_num, + &to_ipa_devs[1]->mem, + ipa_gsi_hdl); + + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + +void suspend_handler(enum ipa_irq_type interrupt, + void *private_data, + void *interrupt_data) +{ + u32 *suspend_data; + u32 clnt_hdl; + u32 gsi_chan_hdl; + struct ipa_ep_cfg_ctrl ipa_to_usb_ep_cfg_ctrl; + int i, res; + + suspend_data = + ((struct ipa_tx_suspend_irq_data *)interrupt_data)->endpoints; + clnt_hdl = + ((struct ipa_tx_suspend_private_data *)private_data)->clnt_hdl; + gsi_chan_hdl = + ((struct ipa_tx_suspend_private_data *)private_data)->gsi_chan_hdl; + + IPATEST_DBG("in suspend handler: interrupt=%d, private_data=%d, interrupt_data=", + interrupt, clnt_hdl, suspend_data[0], suspend_data[1]); + for (i = 0; i < IPA_EP_ARR_SIZE; i++) + IPATEST_DBG("%d", suspend_data[i]); + + IPATEST_DBG("\nEnabling back data path for IPA_CLIENT_USB_CONS\n"); + memset(&ipa_to_usb_ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl)); + ipa_to_usb_ep_cfg_ctrl.ipa_ep_suspend = false; + + if(ipa_get_hw_type() >= IPA_HW_v4_0) + res = gsi_start_channel(gsi_chan_hdl); + else + res = ipa_cfg_ep_ctrl(clnt_hdl, &ipa_to_usb_ep_cfg_ctrl); + + if (res) + IPATEST_ERR("failed enabling back data path for IPA_CLIENT_USB_CONS\n"); +} +/* + * Configures the system as follows: + * This configuration is for one input pipe and one output pipe + * where both are USB1 + * /dev/to_ipa_0 -> MEM -> GSI -> IPA -> GSI-> MEM -> /dev/from_ipa_0 + * Those clients will be configured in DMA mode thus no Header removal/insertion + * will be made on their data. + * Then disable USB_CONS EP for creating the suspend interrupt and register + * a handler for it. +*/ +int configure_system_19(void) +{ + struct ipa_ep_cfg_ctrl ipa_to_usb_ep_cfg_ctrl; + int res; + + res = configure_system_1(); + if (res) { + IPATEST_ERR("configure system (19) failed\n"); + goto fail; + } + + memset(&ipa_to_usb_ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl)); + ipa_to_usb_ep_cfg_ctrl.ipa_ep_suspend = true; + + if(ipa_get_hw_type() >= IPA_HW_v4_0) + res = ipa_stop_gsi_channel(from_ipa_devs[0]->ipa_client_hdl); + else + res = ipa_cfg_ep_ctrl(from_ipa_devs[0]->ipa_client_hdl, &ipa_to_usb_ep_cfg_ctrl); + + if (res) { + IPATEST_ERR("end-point ctrl register configuration failed\n"); + goto fail; + } + IPATEST_DBG("end-point ctrl register configured successfully (ipa_ep_suspend = true)\n"); + + return 0; + +fail: + + return res; +} + +int configure_system_18(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + datapath_ds_clean(); + + /* Connect IPA -> Rx GSI */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + /* Connect Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + sys_in.notify = notify_ipa_write_done; + if (ipa3_sys_setup(&sys_in, + &ipa_gsi_hdl, + &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, + false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + sys_in.notify = notify_ipa_received; + if (ipa3_sys_setup(&sys_in, + &ipa_gsi_hdl, + &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, + false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + + +/** + * Read File. + * + * @note This function is used by User Mode Application + * in order to read data from the device node /dev/ipa_exception_pipe. + * This implementation assumes Single Reader and Single Writer. + * + */ +ssize_t exception_kfifo_read(struct file *filp, char __user *buf, + size_t count, loff_t *p_pos) +{ + int ret = 0; + size_t data_len = 0; + unsigned int copied; + + if (kfifo_is_empty( + &(p_exception_hdl_data-> + notify_cb_data.exception_kfifo))) { + /* Optimization*/ + + IPATEST_DBG("No Data in exception pipe, Sleeping...\n"); + msleep(200); + IPATEST_DBG("Sleeping Done...\n"); + if (kfifo_is_empty(&(p_exception_hdl_data-> + notify_cb_data.exception_kfifo))) { + IPATEST_DBG("No Data in exception pipe.Returning\n"); + return 0; + } + } + data_len = kfifo_peek_len + (&(p_exception_hdl_data + ->notify_cb_data.exception_kfifo)); + if (data_len > count) { + IPATEST_ERR("buffer(%zu) too small (%zu) required\n", + data_len, count); + return -ENOSPC; + } + ret = kfifo_to_user(& + (p_exception_hdl_data-> + notify_cb_data.exception_kfifo) + , buf, data_len, &copied); +#if (EXCEPTION_KFIFO_DEBUG_VERBOSE) + { + int i = 0; + + IPATEST_DBG("Exception packet's length=%zu, Packet's content:\n" + , data_len); + if (data_len - 3 > 0) { + for (i = 0; i < data_len-4; i += 4) { + IPATEST_DUMP("%02x %02x %02x %02x\n", + (buf)[i], (buf)[i+1], + (buf)[i+2], (buf)[i+3]); + } + } + } +#endif + return ret ? ret : copied; +} + +/** + * Write File. + * + * @note This function is used by User + * in order to write data to the device node /dev/ipa_exception_pipe. + * This implementation assumes Single Reader and Single Writer. + * + */ +ssize_t exception_kfifo_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int ret; + unsigned int copied; + + ret = kfifo_from_user + (&(p_exception_hdl_data->notify_cb_data.exception_kfifo) + , buf, count, &copied); + if (ret) { + IPATEST_ERR("(%d/%zu) Bytes were written to kfifo.\n", + copied, count); + } + return ret ? ret : copied; +} + +static const struct file_operations exception_fops = { + .owner = THIS_MODULE, + .read = exception_kfifo_read, + .write = exception_kfifo_write, +}; + +void notify_upon_exception(void *priv, + enum ipa_dp_evt_type evt, unsigned long data) +{ + int i = 0; + size_t data_len; + int res = 0; + char *p_data = NULL; + struct sk_buff *p_sk_buff = (struct sk_buff *)data; + struct notify_cb_data_st *p_notify_cb_data + = (struct notify_cb_data_st *)priv; + + IPATEST_DBG("was called, evt=%s(%d)", + (evt == IPA_RECEIVE) ? + "IPA_RECEIVE" : + "IPA_WRITE_DONE", evt); + if (IPA_RECEIVE != evt) { + IPATEST_ERR("unexpected value of evt == %d\n", evt); + return; + } + +#if (SAVE_HEADER) + data_len = p_sk_buff->len + 8; /* store len */ + p_data = (p_sk_buff->data) - 8; /* store pointer to the data */ +#else + data_len = p_sk_buff->len; /* store len */ + p_data = p_sk_buff->data; /* store pointer to the data */ +#endif + +#if (EXCEPTION_KFIFO_DEBUG_VERBOSE) + IPATEST_DBG("Exception packet length = %zu,Packet content:\n", + data_len); + for (i = 0; i < data_len - 4; i += 4) { + IPATEST_DUMP("%02x %02x %02x %02x", + (p_data)[i], (p_data)[i+1], + (p_data)[i+2], (p_data)[i+3]); + } +#endif + res = kfifo_in( + &p_notify_cb_data->exception_kfifo, + p_data , data_len); + if (res != data_len) { + IPATEST_ERR("kfifo_in copied %d Bytes instead of %zu\n", + res, data_len); + return; + } +} +/* + * This function Inits the KFIFO and the Device Node of the exceptions + */ +int exception_hdl_init(void) +{ + int res = 0; + struct notify_cb_data_st *p_notify_cb_data; + + IPATEST_DBG("called.\n"); + + if (NULL != p_exception_hdl_data) { + IPATEST_ERR("p_exception_hdl_data is initialized?=(0x%px)\n", + p_exception_hdl_data); + return -EINVAL; + } + p_exception_hdl_data = + kzalloc(sizeof(struct exception_hdl_data), GFP_KERNEL); + if (NULL == p_exception_hdl_data) { + IPATEST_ERR("kzalloc return NULL, can't alloc %zu Bytes\n", + sizeof(struct exception_hdl_data)); + return -ENOMEM; + } + IPATEST_DBG("Continue...\n"); + p_notify_cb_data = &(p_exception_hdl_data->notify_cb_data); + + res = kfifo_alloc(&(p_notify_cb_data->exception_kfifo) + , EXCEPTION_KFIFO_SIZE*(sizeof(char)*RX_DESCRIPTOR_SIZE) + , GFP_KERNEL); + if (0 != res) { + IPATEST_ERR("kfifo_alloc returned error (%d)\n", + res); + return res; + } + res = alloc_chrdev_region(&p_exception_hdl_data->dev_num + , 0, 1, EXCEPTION_DRV_NAME); + if (0 != res) { + IPATEST_ERR("alloc_chrdev_region failed (%d)\n", res); + return res; + } + p_exception_hdl_data->class = + class_create(THIS_MODULE, EXCEPTION_DRV_NAME); + p_exception_hdl_data->dev = + device_create(p_exception_hdl_data->class + , NULL, p_exception_hdl_data->dev_num, + ipa_test, EXCEPTION_DRV_NAME); + if (IS_ERR(p_exception_hdl_data->dev)) { + IPATEST_ERR("device_create returned error\n"); + return -ENODEV; + } + p_exception_hdl_data->p_cdev = cdev_alloc(); + if (NULL == p_exception_hdl_data->p_cdev) { + IPATEST_ERR("cdev_alloc() returned NULL (0x%px)\n" + , p_exception_hdl_data->p_cdev); + return -EINVAL; + } + cdev_init(p_exception_hdl_data->p_cdev, &exception_fops); + p_exception_hdl_data->p_cdev->owner = THIS_MODULE; + res = cdev_add(p_exception_hdl_data->p_cdev + , p_exception_hdl_data->dev_num, 1); + if (0 != res) { + IPATEST_ERR("cdev_add failed (%d)\n", res); + return res; + } + + IPATEST_DBG("completed.(%d)\n", res); + return res; +} +/* + * Clear the Exception Device and KFIFO + */ +void exception_hdl_exit(void) +{ + + unregister_chrdev_region + (p_exception_hdl_data->dev_num, 1); + kfifo_free(&(p_exception_hdl_data + ->notify_cb_data.exception_kfifo)); + /* freeing kfifo */ + memset(&(p_exception_hdl_data + ->notify_cb_data.exception_kfifo), 0, + sizeof(p_exception_hdl_data + ->notify_cb_data.exception_kfifo)); + kfree(p_exception_hdl_data); + p_exception_hdl_data = NULL; +} + +/* Configuration used for Exception Tests */ +int configure_system_7(void) +{ + int res = 0; + struct ipa_ep_cfg ipa_ep_cfg; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + res = exception_hdl_init(); + if (0 != res) { + IPATEST_ERR("exception_hdl_init() failed (%d)\n", res); + return res; + } + + + /* Connect first Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[0]->ipa_client_hdl, + false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[0]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect second Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[1]->ipa_client_hdl, + false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[1]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect third (Default) Rx IPA --> APPS MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST4_CONS; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[2]->ipa_client_hdl, + false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[2]->ep, + IPA_CLIENT_TEST4_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + sys_in.notify = ¬ify_upon_exception; + sys_in.priv = &(p_exception_hdl_data->notify_cb_data); + + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, + false)) + goto fail; + + /* Connect APPS MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + + if (res) + goto fail; +fail: + /* cleanup and tear down goes here */ + return res; +} + +void destroy_channel_device(struct channel_dev *channel_dev) +{ + int res = 0; + + IPATEST_DBG("Destroying device channel_dev = 0x%px,name %s.\n", + channel_dev, channel_dev->name); + + IPATEST_DBG("ep=0x%px gsi_chan_hdl=0x%lx\n", &channel_dev->ep, channel_dev->ep.gsi_chan_hdl); + if (channel_dev->ep.gsi_valid) { + IPATEST_DBG("stopping channel 0x%lx\n", channel_dev->ep.gsi_chan_hdl); + res = ipa_stop_gsi_channel(channel_dev->ipa_client_hdl); + if (res != GSI_STATUS_SUCCESS) + IPATEST_ERR("ipa_stop_gsi_channel failed %d\n\n", res); + + IPATEST_DBG("reset channel 0x%lx\n", channel_dev->ep.gsi_chan_hdl); + res = gsi_reset_channel(channel_dev->ep.gsi_chan_hdl); + if (res != GSI_STATUS_SUCCESS) + IPATEST_ERR("gsi_reset_channel failed %d\n\n", res); + + IPATEST_DBG("deallocate channel 0x%lx\n", channel_dev->ep.gsi_chan_hdl); + res = gsi_dealloc_channel(channel_dev->ep.gsi_chan_hdl); + if (res != GSI_STATUS_SUCCESS) + IPATEST_ERR("gsi_dealloc_channel failed %d\n\n", res); + + dma_free_coherent(ipa3_get_pdev(), channel_dev->ep.gsi_channel_props.ring_len, channel_dev->ep.gsi_channel_props.ring_base_vaddr, channel_dev->ep.gsi_channel_props.ring_base_addr); + + IPATEST_DBG("deallocate channel event ring 0x%lx\n", channel_dev->ep.gsi_evt_ring_hdl); + res = gsi_dealloc_evt_ring(channel_dev->ep.gsi_evt_ring_hdl); + if (res != GSI_STATUS_SUCCESS) + IPATEST_ERR("gsi_dealloc_evt_ring failed %d\n\n", res); + dma_free_coherent(ipa3_get_pdev(), channel_dev->ep.gsi_evt_ring_props.ring_len, channel_dev->ep.gsi_evt_ring_props.ring_base_vaddr, channel_dev->ep.gsi_evt_ring_props.ring_base_addr); + + res = ipa3_sys_teardown(channel_dev->ipa_client_hdl); + if (res) { + IPATEST_ERR("Failure on ipa_sys_teardown()," + " channel_dev = 0x%px, res = %d.\n", + channel_dev, res); + } + } + + + cdev_del(&channel_dev->cdev); + memset(&channel_dev->cdev, 0, sizeof(channel_dev->cdev)); + device_destroy(channel_dev->class, channel_dev->dev_num); + unregister_chrdev_region(channel_dev->dev_num, 1); + class_destroy(channel_dev->class); + test_free_mem(&channel_dev->mem); + memset(channel_dev, 0, sizeof(struct channel_dev)); + kfree(channel_dev); +} + +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]); + 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]); + from_ipa_devs[ipa_test->num_rx_channels] = NULL; + } +} + +int register_lan_interface(void) +{ + struct ipa_rx_intf rx_intf; + struct ipa_tx_intf tx_intf; + struct ipa_ioc_tx_intf_prop tx_prop; + struct ipa_ioc_rx_intf_prop rx_prop; + char *name = "rmnet1"; + int res; + + IPATEST_DBG(":new version\n"); + memset(&tx_prop, 0, sizeof(tx_prop)); + tx_prop.ip = IPA_IP_v6; + tx_prop.dst_pipe = IPA_CLIENT_TEST_CONS; + + memset(&rx_prop, 0, sizeof(rx_prop)); + rx_prop.ip = IPA_IP_v6; + rx_prop.src_pipe = IPA_CLIENT_TEST_PROD; + + memset(&rx_intf, 0, sizeof(rx_intf)); + rx_intf.num_props = 1; + rx_intf.prop = &rx_prop; + + memset(&tx_intf, 0, sizeof(tx_intf)); + tx_intf.num_props = 1; + tx_intf.prop = &tx_prop; + + res = ipa_register_intf(name, &tx_intf, &rx_intf); + if (res != 0) + goto fail; + + IPATEST_DBG(":registered interface %s !\n", name); + +fail: + return res; +} + +/* add wlan header to ipa */ + +#define IPA_TO_WLAN_HEADER_NAME "wlan0" +int add_wlan_header(void) +{ + +#define IPA_TO_WLAN_HEADER_LEN 34 + + uint8_t hdr[IPA_TO_WLAN_HEADER_LEN + 1] = { + /* HTC Header - 6 bytes */ + 0x00, 0x00, /* Reserved */ + 0x00, 0x00, /* length to be filled by IPA, + after adding 32 with IP Payload + length 32 will be + programmed while + intializing the header */ + 0x00, 0x00, /* Reserved */ + /* WMI header - 6 bytes*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* 802.3 header - 14 bytes*/ + 0x00, 0x03, 0x7f, 0x44, 0x33, 0x89, + /* Des. MAC to be filled by IPA */ + 0x00, 0x03, 0x7f, 0x17, 0x12, 0x69, + /* Src. MAC to be filled by IPA */ + 0x00, 0x00, + /* length can be zero */ + + /* LLC SNAP header - 8 bytes */ + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, + 0x08, 0x00 /* type value(2 bytes) to + be filled by IPA, by reading + from ethernet header */ + /* 0x0800 - IPV4, 0x86dd - IPV6 */ + }; + + int ret = 0; + int len = 0; + struct ipa_ioc_add_hdr *ipa_to_wlan_header_partial; + struct ipa_hdr_add ipa_to_wlan_header; + + memset(&ipa_to_wlan_header, 0, sizeof(ipa_to_wlan_header)); + /* Copy header name */ + memcpy(ipa_to_wlan_header.name, + IPA_TO_WLAN_HEADER_NAME, + sizeof(IPA_TO_WLAN_HEADER_NAME)); + + /* poplate other fields of header add */ + ipa_to_wlan_header.hdr_len = IPA_TO_WLAN_HEADER_LEN; + ipa_to_wlan_header.is_partial = 1; + ipa_to_wlan_header.hdr_hdl = 0; + ipa_to_wlan_header.status = -1; + /* copy the parital header */ + memcpy(ipa_to_wlan_header.hdr, hdr, IPA_TO_WLAN_HEADER_LEN); + + /* Add wlan partial header to ipa */ + len = (sizeof(struct ipa_ioc_add_hdr)) + + (1 * sizeof(struct ipa_hdr_add)); + ipa_to_wlan_header_partial = kmalloc(len, GFP_KERNEL); + if (!ipa_to_wlan_header_partial) { + IPATEST_ERR("Memory allocation failure"); + return false; + } + + ipa_to_wlan_header_partial->commit = 1; + ipa_to_wlan_header_partial->num_hdrs = 1; + memcpy(&ipa_to_wlan_header_partial->hdr[0], + &ipa_to_wlan_header, + sizeof(ipa_to_wlan_header)); + ret = ipa_add_hdr(ipa_to_wlan_header_partial); + if (ret) { + IPATEST_ERR("unable to add wlan header %d", ret); + goto fail; + } else if (ipa_to_wlan_header_partial->hdr[0].status) { + IPATEST_ERR("unable to add wlan header %d", ret); + goto fail; + } + + IPATEST_DBG("added wlan header successfully\n"); + +fail: + kfree(ipa_to_wlan_header_partial); + + return ret; +} + +/* Wlan interface has 4 rx and 1 Tx endpoint */ +int register_wlan_interface(void) +{ + struct ipa_rx_intf rx_intf; + struct ipa_tx_intf tx_intf; + struct ipa_ioc_tx_intf_prop tx_prop[4]; + struct ipa_ioc_rx_intf_prop rx_prop; + char *name = "eth0"; + int res, index = 0; + + res = add_wlan_header(); + if (res) + return res; + + memset(&tx_prop, 0, 4 * sizeof(struct ipa_ioc_tx_intf_prop)); + + index = 0; + tx_prop[index].ip = IPA_IP_v6; + tx_prop[index].dst_pipe = IPA_CLIENT_TEST1_CONS; + memcpy(tx_prop[index].hdr_name, IPA_TO_WLAN_HEADER_NAME, + sizeof(IPA_TO_WLAN_HEADER_NAME)); + + index++; + tx_prop[index].ip = IPA_IP_v6; + tx_prop[index].dst_pipe = IPA_CLIENT_TEST2_CONS; + memcpy(tx_prop[index].hdr_name, IPA_TO_WLAN_HEADER_NAME, + sizeof(IPA_TO_WLAN_HEADER_NAME)); + + index++; + tx_prop[index].ip = IPA_IP_v6; + tx_prop[index].dst_pipe = IPA_CLIENT_TEST3_CONS; + memcpy(tx_prop[index].hdr_name, IPA_TO_WLAN_HEADER_NAME, + sizeof(IPA_TO_WLAN_HEADER_NAME)); + + index++; + tx_prop[index].ip = IPA_IP_v6; + tx_prop[index].dst_pipe = IPA_CLIENT_TEST4_CONS; + memcpy(tx_prop[index].hdr_name, IPA_TO_WLAN_HEADER_NAME, + sizeof(IPA_TO_WLAN_HEADER_NAME)); + + memset(&rx_prop, 0, sizeof(struct ipa_ioc_rx_intf_prop)); + rx_prop.ip = IPA_IP_v6; + rx_prop.src_pipe = IPA_CLIENT_TEST1_PROD; + + memset(&rx_intf, 0, sizeof(rx_intf)); + rx_intf.num_props = 1; + rx_intf.prop = &rx_prop; + + memset(&tx_intf, 0, sizeof(tx_intf)); + tx_intf.num_props = 4; + tx_intf.prop = tx_prop; + + res = ipa_register_intf(name, &tx_intf, &rx_intf); + if (res) { + IPATEST_ERR("Unable to register interface %s, %d\n", + name, res); + return res; + } + + IPATEST_DBG("Registered interface %s\n", name); + return res; +} + +/* Wan interface has 1 rx and 1 Tx endpoint */ +int register_wan_interface(void) +{ + struct ipa_rx_intf rx_intf; + struct ipa_tx_intf tx_intf; + struct ipa_ioc_tx_intf_prop tx_prop; + struct ipa_ioc_rx_intf_prop rx_prop; + char *name = "rmnet0"; + int res; + + memset(&tx_prop, 0, sizeof(tx_prop)); + tx_prop.ip = IPA_IP_v6; + tx_prop.dst_pipe = IPA_CLIENT_TEST3_CONS; + + memset(&rx_prop, 0, sizeof(rx_prop)); + rx_prop.ip = IPA_IP_v6; + rx_prop.src_pipe = IPA_CLIENT_TEST3_PROD; + + memset(&rx_intf, 0, sizeof(rx_intf)); + rx_intf.num_props = 1; + rx_intf.prop = &rx_prop; + + memset(&tx_intf, 0, sizeof(tx_intf)); + tx_intf.num_props = 1; + tx_intf.prop = &tx_prop; + + res = ipa_register_intf(name, &tx_intf, &rx_intf); + if (res != 0) + goto fail; + + IPATEST_DBG("registered interface %s !\n", name); + +fail: + return res; +} + +/* + Configures the system with one input to IPA and 2 outputs. + /dev/to_ipa_0 -> MEM -> GSI -> IPA |-> GSI + -> MEM -> /dev/from_ipa_0 +|-> GSI -> MEM -> /dev/from_ipa_1 +*/ +int configure_system_20(void) +{ + int res = 0; + int index = 0; + struct ipa_ep_cfg ipa_ep_cfg; + + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + + + /* Connect first Rx IPA --> AP MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_CONS; + if (ipa3_sys_setup(&sys_in, + &ipa_gsi_hdl, &ipa_pipe_num, + &from_ipa_devs[index]->ipa_client_hdl, false)) + goto fail; + + res = connect_ipa_to_apps(&from_ipa_devs[index]->ep, + IPA_CLIENT_TEST2_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + + index++; + + /* Connect IPA -> 1 Tx GSI */ + /* RNDIS Aggregation with ETH2 header */ + memset(&ipa_ep_cfg, 0, sizeof(ipa_ep_cfg)); + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; + ipa_ep_cfg.aggr.aggr = IPA_GENERIC; + ipa_ep_cfg.aggr.aggr_byte_limit = 1; + ipa_ep_cfg.aggr.aggr_time_limit = 0; + ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = true; + ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 12; + ipa_ep_cfg.hdr.hdr_additional_const_len = 14; + ipa_ep_cfg.hdr.hdr_len = 58; + ipa_ep_cfg.hdr_ext.hdr_little_endian = true; + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_valid = true; + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN; + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_offset = 4; + + /* Connect 1 Tx IPA --> AP MEM */ + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_CONS; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup( + &sys_in, + &ipa_gsi_hdl, + &ipa_pipe_num, + &from_ipa_devs[index]->ipa_client_hdl, + false)) + goto fail; + + res = connect_ipa_to_apps( + &from_ipa_devs[index]->ep, + IPA_CLIENT_TEST3_CONS, + ipa_pipe_num, + ipa_gsi_hdl); + if (res) + goto fail; + + /* Connect Rx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + /* configure RNDIS+ETH2 header removal on Rx */ + /* configure RNDIS de-aggregation on Rx */ + ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_ep_cfg.aggr.aggr = IPA_GENERIC; + ipa_ep_cfg.deaggr.deaggr_hdr_len = 44; /* RNDIS hdr */ + ipa_ep_cfg.deaggr.packet_offset_valid = true; + ipa_ep_cfg.deaggr.packet_offset_location = 8; + ipa_ep_cfg.hdr.hdr_len = 14; /* Ethernet header */ + ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 12; + ipa_ep_cfg.hdr.hdr_remove_additional = false; + ipa_ep_cfg.hdr_ext.hdr_little_endian = 1; + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_valid = 1; + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN; + ipa_ep_cfg.hdr_ext.hdr_payload_len_inc_padding = 0; + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_offset = 4; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[0]->ipa_client_hdl, false)) + goto fail; + + /* Connect AP MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[0]->ep, + IPA_CLIENT_TEST_PROD, + ipa_pipe_num, + &to_ipa_devs[0]->mem, + ipa_gsi_hdl); + + + if (res) + goto fail; + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + /* configure ETH2+WLAN\ETH2_802_1Q (18B) header removal on Tx */ + ipa_ep_cfg.hdr.hdr_len = ETH_HLEN + IPA_TEST_ADDITIONAL_HDR_LEN; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST2_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[1]->ipa_client_hdl, false)) + goto fail; + + /* Connect AP MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[1]->ep, + IPA_CLIENT_TEST2_PROD, + ipa_pipe_num, + &to_ipa_devs[1]->mem, + ipa_gsi_hdl); + + + if (res) + goto fail; + + /* Connect Tx GSI -> IPA */ + /* Prepare an endpoint configuration structure */ + res = configure_ipa_endpoint(&ipa_ep_cfg, IPA_BASIC); + if (res) + goto fail; + + /* configure ETH2 header removal on Tx */ + ipa_ep_cfg.hdr.hdr_len = ETH_HLEN; + + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = IPA_CLIENT_TEST3_PROD; + sys_in.ipa_ep_cfg = ipa_ep_cfg; + if (ipa3_sys_setup(&sys_in, &ipa_gsi_hdl, &ipa_pipe_num, + &to_ipa_devs[2]->ipa_client_hdl, false)) + goto fail; + + /* Connect AP MEM --> Tx IPA */ + res = connect_apps_to_ipa(&to_ipa_devs[2]->ep, + IPA_CLIENT_TEST3_PROD, + ipa_pipe_num, + &to_ipa_devs[2]->mem, + ipa_gsi_hdl); + + + if (res) + goto fail; + +fail: + /* cleanup and tear down goes here */ + return res; +} + +static char **str_split(char *str, const char *delim) +{ + char **res = NULL; + char **tmp = NULL; + char *p = strsep(&str, delim); + int n_spaces = 0; + + /* split string and append tokens to 'res' */ + while (p) { + tmp = krealloc(res, sizeof(char *) * ++n_spaces, GFP_KERNEL); + + if (tmp == NULL) { + IPATEST_ERR("krealloc failed\n"); + goto fail; /* memory allocation failed */ + } + + res = tmp; + res[n_spaces-1] = p; + p = strsep(&str, delim); + } + /* realloc one extra element for the last NULL */ + tmp = krealloc(res, sizeof(char *) * (n_spaces+1), GFP_KERNEL); + if (tmp == NULL) { + IPATEST_ERR("krealloc failed\n"); + goto fail; /* memory allocation failed */ + } + res = tmp; + res[n_spaces] = 0; + return res; +fail: + kfree(res); + return res; +} + +/** + * Write File. + * + * @note Configure the system by writing a configuration + * index to the device node /dev/ipa_test + */ +ssize_t ipa_test_write(struct file *filp, const char __user *buf, + size_t size, loff_t *f_pos) +{ + int ret = 0; + int index; + + unsigned long missing; + char *str; + char **params; + + str = kzalloc(size+1, GFP_KERNEL); + if (str == NULL) { + IPATEST_ERR("kzalloc err.\n"); + return -ENOMEM; + } + + missing = copy_from_user(str, buf, size); + if (missing) { + kfree(str); + return -EFAULT; + } + IPATEST_DBG("ipa_test_write: input string= %s\n", str); + str[size] = '\0'; + + params = str_split(str, " "); + if (params == NULL) { + kfree(str); + return -EFAULT; + } + + ret = kstrtos32(params[0], 10, (s32 *)&ipa_test->configuration_idx); + if (ret) { + IPATEST_ERR("kstrtoul() failed.\n"); + ret = -EFAULT; + goto bail; + } + + IPATEST_DBG(":Invoking configuration %d.\n", + ipa_test->configuration_idx); + + /* Setup GSI */ + + switch (ipa_test->configuration_idx) { + case -1: + destroy_channel_devices(); + /*exception_hdl_exit();TODO: hsnapy un-comment this*/ + break; + + case 2: + index = 0; + ret = create_channel_device(index, + "to_ipa", &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test->tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test->rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + index++; + ret = create_channel_device(index, + "to_ipa", &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test->tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test->rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + index++; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test->rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_2(); + if (ret) { + IPATEST_ERR("System configuration failed."); + ret = -ENODEV; + goto bail; + } + break; + + case 5: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + index++; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + index++; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_5(); + if (ret) { + IPATEST_ERR("System configuration failed."); + ret = -ENODEV; + goto bail; + } + break; + + case 6: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_6(); + if (ret) { + IPATEST_ERR("System configuration failed."); + ret = -ENODEV; + goto bail; + } + break; + + case 7: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + index++; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + index++; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_7(); + if (ret) { + IPATEST_ERR("System configuration failed."); + ret = -ENODEV; + goto bail; + } + break; + + case 8: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + index = 0; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_8(); + if (ret) { + IPATEST_ERR("System configuration failed.\n"); + ret = -ENODEV; + goto bail; + } + break; + + case 9: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + index = 0; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_9(); + if (ret) { + IPATEST_ERR("System configuration failed.\n"); + ret = -ENODEV; + goto bail; + } + break; + + case 10: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + index = 0; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_10(); + if (ret) { + IPATEST_ERR("System configuration failed.\n"); + ret = -ENODEV; + goto bail; + } + break; + + case 12: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + index = 0; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + index++; + + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_12(); + if (ret) { + IPATEST_ERR("System configuration failed.\n"); + ret = -ENODEV; + goto bail; + } + break; + + case 18: + index = 0; + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + return -ENODEV; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + index++; + ret = create_channel_device_by_type(index, "to_ipa", + &to_ipa_devs[index], RX_SZ, + IPA_TEST_DATA_PATH_TEST_CHANNEL); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + return -ENODEV; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + index = 0; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + return -ENODEV; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_18(); + if (ret) { + IPATEST_ERR("System configuration failed."); + return -ENODEV; + } + break; + + case 19: + index = 0; + /*Create the device on user space and allocate + * buffers for its GSI connection*/ + ret = create_channel_device(index, "to_ipa", + &to_ipa_devs[index], TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + /*Create the device on user space and allocate + * buffers for its GSI connection*/ + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test->rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + /*Make all the configurations required + * (IPA connect)*/ + ret = configure_system_19(); + if (ret) { + IPATEST_ERR("System configuration failed.\n"); + ret = -ENODEV; + goto bail; + } + break; + + case 20: + + /* Create producer channel 0 */ + index = 0; + ret = create_channel_device(index, + "to_ipa", &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + + /* Create producer channel 1 */ + index++; + ret = create_channel_device(index, + "to_ipa", &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + /* Create producer channel 2 */ + index++; + ret = create_channel_device(index, + "to_ipa", &to_ipa_devs[index], + TX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + tx_channels[ipa_test->num_tx_channels++] = + to_ipa_devs[index]; + + /* Create consumer channel 0 */ + index = 0; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + /* Create consumer channel 1 */ + index++; + ret = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], + RX_SZ); + if (ret) { + IPATEST_ERR("Channel device creation error.\n"); + ret = -ENODEV; + goto bail; + } + ipa_test-> + rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + ret = configure_system_20(); + if (ret) { + IPATEST_ERR("System configuration failed."); + ret = -ENODEV; + goto bail; + } + break; + + default: + IPATEST_ERR("Unsupported configuration index.\n"); + break; + } + + /* Insert descriptors into the receiving end(s) */ + ret = insert_descriptors_into_rx_endpoints(RX_BUFF_SIZE); + if (ret) { + IPATEST_DBG("Descriptor insertion into rx " + "endpoints failed.\n"); + ret = -EINVAL; + goto bail; + } + + IPATEST_DBG("System configured !\n"); + + /* Set the current configuration index */ + ipa_test->current_configuration_idx = + ipa_test->configuration_idx; + + ret = size; + +bail: + kfree(params); + kfree(str); + return ret; +} + +static ssize_t ipa_test_read(struct file *filp, + char __user *buf, + size_t count, loff_t *f_pos) +{ + int res, len; + char str[10]; + + if (0 != *f_pos) { + *f_pos = 0; + return 0; + } + + /* Convert the configuration index to a null terminated string */ + len = snprintf(str, 10, "%d", + ipa_test->current_configuration_idx); + + IPATEST_DBG("str = %s, len = %d\n", str, len); + + /* Copy the result to the user buffer */ + res = copy_to_user(buf, str, len + 1); + if (res < 0) { + IPATEST_ERR("copy_to_user() failed.\n"); + return -EFAULT; + } + + /* Increment the file position pointer */ + *f_pos += len; + + /* Return the number of bytes copied to the user */ + return len + 1; +} + +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) +{ + int retval; + struct ipa_channel_config to_ipa_channel_config = {0}; + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + int index; + + IPATEST_DBG("copying from 0x%px %zu bytes\n", + to_ipa_user, + sizeof(struct ipa_channel_config)); + retval = copy_from_user( + &to_ipa_channel_config, + to_ipa_user, + sizeof(struct ipa_channel_config)); + if (retval) { + IPATEST_ERR("fail to copy from user - to_ipa_user\n"); + return -1; + } + + index = to_ipa_channel_config.index; + + IPATEST_DBG("to_ipa head_marker value is 0x%x\n", + to_ipa_channel_config.head_marker); + + IPATEST_DBG("to_ipa config_size value is %zu\n", + to_ipa_channel_config.config_size); + + IPATEST_DBG("to_ipa index value is %d\n", index); + + IPATEST_DBG("client=%d\n", + to_ipa_channel_config.client); + + 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) { + IPATEST_ERR("bad head_marker - possible memory corruption\n"); + return -EFAULT; + } + + if (to_ipa_channel_config.tail_marker != + IPA_TEST_CHANNEL_CONFIG_MARKER) { + IPATEST_ERR("bad tail_marker - possible memory corruption\n"); + return -EFAULT; + } + + if (to_ipa_channel_config.config_size != sizeof(struct ipa_ep_cfg)) { + IPATEST_ERR("bad config size (%zu.vs.%zu) update test struct?\n", + to_ipa_channel_config.config_size, + sizeof(struct ipa_ep_cfg)); + return -EFAULT; + } + + /* Channel from which the userspace shall communicate to this pipe */ + 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]; + + /* 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); + 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)) { + 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); + if (retval) { + IPATEST_ERR("fail to connect ipa to apps\n"); + return -1; + } + + return 0; +} + +static int configure_app_from_ipa_path(struct ipa_channel_config __user *from_ipa_user) +{ + int retval; + struct ipa_channel_config from_ipa_channel_config = {0}; + struct ipa_sys_connect_params sys_in; + unsigned long ipa_gsi_hdl; + u32 ipa_pipe_num; + int index; + + IPATEST_DBG("copying from 0x%px %zu bytes\n", + from_ipa_user, + sizeof(struct ipa_channel_config)); + retval = copy_from_user( + &from_ipa_channel_config, + from_ipa_user, + sizeof(struct ipa_channel_config)); + if (retval) { + IPATEST_ERR("fail to copy from user - from_ipa_user (%d.vs.%zu)\n", + retval, sizeof(from_ipa_user)); + return -1; + } + + index = from_ipa_channel_config.index; + + IPATEST_DBG("from_ipa head_marker value is 0x%x\n", + from_ipa_channel_config.head_marker); + + IPATEST_DBG("from_ipa config_size value is %zu\n", + from_ipa_channel_config.config_size); + + IPATEST_DBG("from_ipa index value is %d\n", + index); + + IPATEST_DBG("client=%d\n", + from_ipa_channel_config.client); + + IPATEST_DBG("from_ipa tail_marker value is 0x%x\n", + from_ipa_channel_config.tail_marker); + + if (from_ipa_channel_config.head_marker != + IPA_TEST_CHANNEL_CONFIG_MARKER) { + IPATEST_ERR("bad head_marker - possible memory corruption\n"); + return -EFAULT; + } + + if (from_ipa_channel_config.tail_marker != + IPA_TEST_CHANNEL_CONFIG_MARKER) { + IPATEST_ERR("bad tail_marker - possible memory corruption\n"); + return -EFAULT; + } + + if (from_ipa_channel_config.config_size != sizeof(struct ipa_ep_cfg)) { + IPATEST_ERR("bad config size (%zu.vs.%zu) update test struct?\n", + from_ipa_channel_config.config_size, + sizeof(struct ipa_ep_cfg)); + return -EFAULT; + } + + /* Channel from which the userspace shall communicate to this pipe */ + retval = create_channel_device(index, "from_ipa", + &from_ipa_devs[index], RX_SZ); + if (retval) { + IPATEST_ERR("channel device creation error\n"); + return -1; + } + ipa_test->rx_channels[ipa_test->num_rx_channels++] = + from_ipa_devs[index]; + + /* Connect IPA --> Apps */ + IPATEST_DBG("copying from 0x%px\n", from_ipa_channel_config.cfg); + memset(&sys_in, 0, sizeof(sys_in)); + sys_in.client = from_ipa_channel_config.client; + retval = copy_from_user( + &sys_in.ipa_ep_cfg, + from_ipa_channel_config.cfg, + from_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, + &from_ipa_devs[index]->ipa_client_hdl, from_ipa_channel_config.en_status)) { + IPATEST_ERR("setup sys pipe failed\n"); + return -1; + } + + retval = connect_ipa_to_apps(&from_ipa_devs[index]->ep, + from_ipa_channel_config.client, + ipa_pipe_num, + ipa_gsi_hdl); + if (retval) { + IPATEST_ERR("fail to connect ipa to apps\n"); + return -1; + } + + return 0; +} + +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) +{ + int retval; + int i; + + if (ipa_test->num_tx_channels > 0 || ipa_test->num_rx_channels >0) { + IPATEST_DBG("cleanning previous configuration before new one\n"); + destroy_channel_devices(); + } else { + IPATEST_DBG("system is clean, starting new configuration"); + } + + IPATEST_DBG("starting scenario configuration\n"); + + IPATEST_DBG("head_marker value is 0x%x\n", + ipa_test_config_header->head_marker); + + IPATEST_DBG("from_ipa_channels_num=%d\n\n", + ipa_test_config_header->from_ipa_channels_num); + + IPATEST_DBG("to_ipa_channels_num=%d\n\n", + ipa_test_config_header->to_ipa_channels_num); + + IPATEST_DBG("tail_marker value is 0x%x\n", + ipa_test_config_header->tail_marker); + + if (ipa_test_config_header->head_marker != IPA_TEST_CONFIG_MARKER) { + IPATEST_ERR("bad header marker - possible memory corruption\n"); + return -EFAULT; + } + + if (ipa_test_config_header->tail_marker != IPA_TEST_CONFIG_MARKER) { + IPATEST_ERR("bad tail marker - possible memory corruption\n"); + return -EFAULT; + } + + 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]); + if (retval) { + IPATEST_ERR("fail to configure from_ipa_%d", i); + goto fail; + } + } + + retval = insert_descriptors_into_rx_endpoints(RX_BUFF_SIZE); + if (retval) { + IPATEST_ERR("RX descriptors failed\n"); + goto fail; + } + 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]); + if (retval) { + IPATEST_ERR("fail to configure to_ipa_%d", i); + goto fail; + } + } + + /* + * This value is arbitrary, it is used in + * order to be able to cleanup + */ + ipa_test->current_configuration_idx = GENERIC_TEST_CONFIGURATION_IDX; + + IPATEST_DBG("finished scenario configuration\n"); + + return 0; +fail: + destroy_channel_devices(); + + return retval; +} + +static int handle_configuration_ioctl(unsigned long ioctl_arg) +{ + int retval; + int needed_bytes; + struct ipa_test_config_header test_header; + struct ipa_channel_config **from_ipa_channel_config_array; + struct ipa_channel_config **to_ipa_channel_config_array; + + /* header copy */ + IPATEST_DBG("copying from 0x%px\n", (u8 *)ioctl_arg); + retval = copy_from_user(&test_header, + (u8 *)ioctl_arg, + sizeof(test_header)); + if (retval) { + IPATEST_ERR("failing copying header from user\n"); + return retval; + } + + /* allocate place for the configuration array for "from" */ + needed_bytes = test_header.from_ipa_channels_num* + sizeof(*test_header.from_ipa_channel_config); + + from_ipa_channel_config_array = kzalloc(needed_bytes, GFP_KERNEL); + if (!from_ipa_channel_config_array) { + IPATEST_ERR("fail mem alloc for from_ipa\n"); + retval = -ENOMEM; + goto fail_from_alloc; + } + + /* copy the configuration array for "from" */ + IPATEST_DBG("copying from 0x%px\n", test_header.from_ipa_channel_config); + retval = copy_from_user(from_ipa_channel_config_array, + test_header.from_ipa_channel_config, + needed_bytes); + if (retval) { + IPATEST_ERR("failing copying to_ipa from user\n"); + goto fail_copy_from; + } + + /* allocate place for the configuration array for "from" */ + needed_bytes = test_header.to_ipa_channels_num* + sizeof(*test_header.to_ipa_channel_config); + + to_ipa_channel_config_array = kzalloc(needed_bytes, GFP_KERNEL); + if (!to_ipa_channel_config_array) { + IPATEST_ERR("fail mem alloc for to_ipa\n"); + goto fail_to_alloc; + } + + /* copy the configuration array for "to" */ + IPATEST_DBG("copying from 0x%px\n", test_header.to_ipa_channel_config); + retval = copy_from_user(to_ipa_channel_config_array, + test_header.to_ipa_channel_config, + needed_bytes); + if (retval) { + IPATEST_ERR("failing copying to_ipa from user\n"); + goto fail_copy_to; + } + + retval = configure_test_scenario( + &test_header, + from_ipa_channel_config_array, + to_ipa_channel_config_array); + if (retval) + IPATEST_ERR("fail to configure the system\n"); + +fail_copy_to: + kfree(to_ipa_channel_config_array); +fail_to_alloc: +fail_copy_from: + kfree(from_ipa_channel_config_array); +fail_from_alloc: + return retval; + +} + +int handle_clean_ioctl(void) +{ + IPATEST_DBG("cleanning previous configuration\n"); + destroy_channel_devices(); + + return 0; +} + +static int handle_ep_ctrl_ioctl(unsigned long ioctl_arg) +{ + int retval = 0; + struct ipa_ep_cfg_ctrl ep_ctrl; + struct ipa_test_ep_ctrl test_ep_ctrl; + + retval = copy_from_user(&test_ep_ctrl, + (u8 *)ioctl_arg, + sizeof(test_ep_ctrl)); + if (retval) { + IPATEST_ERR("failed copying ep_ctrl data from user\n"); + return retval; + } + + ep_ctrl.ipa_ep_delay = test_ep_ctrl.ipa_ep_delay; + ep_ctrl.ipa_ep_suspend = test_ep_ctrl.ipa_ep_suspend; + + /* pipe suspend is not supported in IPA_v4 or higher */ + if(ipa_get_hw_type() >= IPA_HW_v4_0){ + if(ep_ctrl.ipa_ep_suspend) + retval = ipa_stop_gsi_channel(from_ipa_devs[test_ep_ctrl.from_dev_num]->ipa_client_hdl); + else + retval = gsi_start_channel(from_ipa_devs[test_ep_ctrl.from_dev_num]->ep.gsi_chan_hdl); + + if (retval) { + IPATEST_ERR("failed closing/opening the GSI channel\n"); + return retval; + } + ep_ctrl.ipa_ep_suspend = false; + } + + IPATEST_DBG("handle_ep_ctrl_ioctl: sending hdl %d\n\n", + from_ipa_devs[test_ep_ctrl.from_dev_num]->ipa_client_hdl); + + return ipa_cfg_ep_ctrl(from_ipa_devs[test_ep_ctrl.from_dev_num]->ipa_client_hdl, &ep_ctrl); +} + +static int handle_reg_suspend_handler(unsigned long ioctl_arg) +{ + int res = 0; + struct ipa_tx_suspend_private_data *suspend_priv_data = NULL; + struct ipa_test_reg_suspend_handler reg_data; + + res = copy_from_user(®_data, + (u8 *)ioctl_arg, + sizeof(reg_data)); + if (res) { + IPATEST_ERR("failed copying ep_ctrl data from user\n"); + return res; + } + + if (reg_data.reg) { + if (reg_data.DevNum >= (MAX_CHANNEL_DEVS / 2)) + { + res = -ENXIO; + IPATEST_ERR("DevNum is incorrect %d\n", reg_data.DevNum); + goto fail; + } + + suspend_priv_data = + kzalloc(sizeof(*suspend_priv_data), GFP_KERNEL); + if (!suspend_priv_data) { + IPATEST_ERR("failed allocating suspend_priv_data\n"); + res = -ENOMEM; + goto fail; + } + + suspend_priv_data->clnt_hdl = from_ipa_devs[reg_data.DevNum]->ipa_client_hdl; + suspend_priv_data->gsi_chan_hdl = from_ipa_devs[reg_data.DevNum]->ep.gsi_chan_hdl; + IPATEST_DBG("registering interrupt handle to clnt_hdl %d\n", suspend_priv_data->clnt_hdl); + res = ipa_add_interrupt_handler(IPA_TX_SUSPEND_IRQ, suspend_handler, + reg_data.deferred_flag, (void *)suspend_priv_data); + if (res) { + IPATEST_ERR("register handler for suspend interrupt failed\n"); + goto fail_allocated; + } + + } else { + res = ipa_restore_suspend_handler(); + } +fail: + return res; +fail_allocated: + kfree(suspend_priv_data); + return res; +} + +static int handle_holb_config_ioctl(unsigned long ioctl_arg) +{ + int retval = 0; + int clnt_hdl; + struct ipa_ep_cfg_holb holb_cfg = {0}; + struct ipa_test_holb_config test_holb_config; + + retval = copy_from_user(&test_holb_config, + (u8 *)ioctl_arg, + sizeof(test_holb_config)); + if (retval) { + IPATEST_ERR("failed copying holb_config data from user\n"); + return retval; + } + + clnt_hdl = ipa_get_ep_mapping(test_holb_config.client); + + IPATEST_ERR("Sending clnt_hdl %d", clnt_hdl); + + holb_cfg.en = test_holb_config.en; + holb_cfg.tmr_val = test_holb_config.tmr_val; + + return ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg); +} + +static long ipa_test_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int retval; + + IPATEST_DBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); + if (_IOC_TYPE(cmd) != IPA_TEST_IOC_MAGIC) + return -ENOTTY; + + switch (cmd) { + case IPA_TEST_IOC_CONFIGURE: + retval = handle_configuration_ioctl(arg); + break; + + case IPA_TEST_IOC_CLEAN: + retval = handle_clean_ioctl(); + break; + + case IPA_TEST_IOC_GET_HW_TYPE: + retval = ipa_get_hw_type(); + break; + case IPA_TEST_IOC_EP_CTRL: + retval = handle_ep_ctrl_ioctl(arg); + break; + case IPA_TEST_IOC_REG_SUSPEND_HNDL: + retval = handle_reg_suspend_handler(arg); + break; + case IPA_TEST_IOC_HOLB_CONFIG: + retval = handle_holb_config_ioctl(arg); + break; + default: + IPATEST_ERR("ioctl is not supported (%d)\n", cmd); + return -ENOTTY; + } + + return retval; +} + +static int ipa_test_open(struct inode *inode, struct file *file) +{ + IPATEST_DBG("ipa_test module opened by %s\n", current->comm); + return 0; +} + +static int ipa_test_release(struct inode *inode, struct file *file) +{ + IPATEST_DBG("ipa_test module closed by %s\n", current->comm); + return 0; +} + + +static const struct file_operations ipa_test_fops = { + .owner = THIS_MODULE, + .write = ipa_test_write, + .read = ipa_test_read, + .open = ipa_test_open, + .release = ipa_test_release, + .unlocked_ioctl = ipa_test_ioctl, +}; + +/** + * Module Init. + */ +static int __init ipa_test_init(void) +{ + int ret; + + IPATEST_DBG("IPA test driver load...\n"); + + ipa_test = kzalloc(sizeof(*ipa_test), GFP_KERNEL); + if (ipa_test == NULL) { + IPATEST_ERR("kzalloc err.\n"); + return -ENOMEM; + } + ipa_test->signature = TEST_SIGNATURE; + ipa_test->current_configuration_idx = -1; + + ipa_test_class = class_create(THIS_MODULE, IPA_TEST_DRV_NAME); + + ret = alloc_chrdev_region(&ipa_test->dev_num, 0, 1, IPA_TEST_DRV_NAME); + if (ret) { + IPATEST_ERR("alloc_chrdev_region err.\n"); + return -ENODEV; + } + + ipa_test->dev = device_create(ipa_test_class, NULL, + ipa_test->dev_num, + ipa_test, IPA_TEST_DRV_NAME); + if (IS_ERR(ipa_test->dev)) { + IPATEST_ERR("device_create err.\n"); + return -ENODEV; + } + + ipa_test->cdev = cdev_alloc(); + if (ipa_test->cdev == NULL) { + IPATEST_ERR("cdev_alloc err.\n"); + return -ENODEV; + } + + cdev_init(ipa_test->cdev, &ipa_test_fops); + ipa_test->cdev->owner = THIS_MODULE; + + ret = cdev_add(ipa_test->cdev, ipa_test->dev_num, 1); + if (ret) + IPATEST_ERR("cdev_add err=%d\n", -ret); + + if (ret == 0) + IPATEST_DBG("IPA Test init OK, waiting for configuration index.\n"); + else + IPATEST_DBG("IPA Test init FAIL.\n"); + + ret = datapath_ds_init(); + if (ret != 0) + IPATEST_DBG("datapath_ds_init() failed (%d)\n", ret); + + return ret; +} + +/** + * Module Exit. + */ +static void __exit ipa_test_exit(void) +{ + IPATEST_DBG("ipa_test_exit.\n"); + + exception_hdl_exit(); /* Clear the Exception Device and KFIFO*/ + + datapath_exit(); + + destroy_channel_devices(); + + cdev_del(ipa_test->cdev); + device_destroy(ipa_test_class, ipa_test->dev_num); + class_destroy(ipa_test_class); + unregister_chrdev_region(ipa_test->dev_num, 1); + + kfree(ipa_test); + + IPATEST_DBG("ipa_test_exit complete.\n"); +} + +module_init(ipa_test_init); +module_exit(ipa_test_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("IPA Testing"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 2fdded88a2..f4ac8b2e4c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2932,6 +2932,14 @@ bool ipa3_get_lan_rx_napi(void); bool ipa3_get_qmap_pipe_enable(void); +struct device *ipa3_get_pdev(void); +int ipa3_sys_update_gsi_hdls(u32 clnt_hdl, unsigned long gsi_ch_hdl, + unsigned long gsi_ev_hdl); +int ipa3_sys_setup(struct ipa_sys_connect_params *sys_in, + unsigned long *ipa_transport_hdl, + u32 *ipa_pipe_num, u32 *clnt_hdl, bool en_status); +int ipa3_sys_teardown(u32 clnt_hdl); + /* internal functions */ u8 ipa3_get_hw_type_index(void); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 1458f2cb01..e5c3fbda5a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -2108,6 +2108,7 @@ ret: return result; } +EXPORT_SYMBOL(ipa3_get_rt_tbl); /** * ipa3_put_rt_tbl() - Release the specified routing table handle diff --git a/kernel-tests/Constants.h b/kernel-tests/Constants.h new file mode 100644 index 0000000000..7e1ad6b338 --- /dev/null +++ b/kernel-tests/Constants.h @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2017,2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + + +#include +#include + +#define PRE_PHASE_ZERO_TEST_CONFIGURATION 0 +/*---------------------------------------------------------------------- + *Configuration 1 (see configure_system_1 ) + *-----USB_PROD--->[IPA DMA]----USB_CONS---> + *---------------------------------------------------------------------- + */ +#define PHASE_ZERO_TEST_CONFIGURATION 1 +/*---------------------------------------------------------------------- + *Configuration 2 (see configure_system_2 ) + * [IPA]----USB2_CONS--> + *-----USB_PROD--->[IPA]----USB3_CONS---> + * [IPA]----USB4_CONS---> + *---------------------------------------------------------------------- + */ +#define PHASE_TWO_TEST_CONFIGURATION 2 +/*---------------------------------------------------------------------- + *Configuration 3 (see configure_system_3 ) + * [IPA]----USB_CONS------> + *-----USB2_PROD--->[IPA]----USB2_CONS---> + * [IPA]----USB4_CONS----> + *---------------------------------------------------------------------- + */ +#define PHASE_THREE_TEST_CONFIGURATION 3 +/*Configuration 5 (see configure_system_5 ) + * [IPA]----USB2_CONS + Header Insertion (6Bytes) --> + *-----USB_PROD--->[IPA]----USB3_CONS + + *Header Insertion (22Bytes) + Length offset (11Bytes) --> + * [IPA]----USB4_CONS + + *Header Insertion (22Bytes) + Length offset (11Bytes) + Const(1Byte)--> + */ + +/* This Cfg is only for USB Integration Phase I*/ +#define PHASE_FIVE_TEST_CONFIGURATION 5 +#define PHASE_SIX_TEST_CONFIGURATION 6 +/*Configuration 7 (see configure_system_7 ) + * [IPA]----USB2_CONS--> + *-----USB_PROD--->[IPA]----USB3_CONS---> + * [IPA]----USB4_CONS---> + * [IPA]----A5 - Exception Pipe---> + */ +#define PHASE_SEVEN_TEST_CONFIGURATION 7 +/*---------------------------------------------------------------------- + *Configuration 8 (see configure_system_8 ) + *-----USB3_CONS--->[IPA DMA]----USB_CONS (TLP aggregation byte limit)---> + *-----USB_PROD (TLP deaggregation)--->[IPA DMA]----USB3_CONS---> + *-----USB2_PROD (TLP deaggregation)---> + *-----[IPA DMA]----USB_CONS (TLP aggregation byte limit)---> + *-----USB4_PROD--->[IPA DMA]----USB2_CONS (TLP aggregation time limit)---> + *---------------------------------------------------------------------- + */ +#define PHASE_EIGHT_TEST_CONFIGURATION 8 +/*---------------------------------------------------------------------- + *Configuration 9 (see configure_system_9 ) + *-----USB3_PROD--->[IPA DMA]----USB_CONS (MBIM aggregation byte limit)---> + *-----USB_PROD (MBIM deaggregation)--->[IPA DMA]----USB3_CONS---> + *-----USB2_PROD (MBIM deaggregation)---> + *-----[IPA DMA]----USB_CONS (MBIM aggregation byte limit)---> + *-----USB4_PROD--->[IPA DMA]----USB2_CONS (MBIM aggregation time limit)---> + *---------------------------------------------------------------------- + */ +#define PHASE_NINE_TEST_CONFIGURATION 9 +/*---------------------------------------------------------------------- + *Configuration 10 (see configure_system_10 ) + *-----USB_PROD--->[IPA DMA]----USB_CONS (MBIM aggregation no limits)---> + *---------------------------------------------------------------------- + */ +#define PHASE_TEN_TEST_CONFIGURATION 10 +/*---------------------------------------------------------------------- + *Configuration 11 (see configure_system_11 ) + *-----USB_PROD----->[IPA]---- + * USB2_CONS(MBIM aggregation byte limit)---> + *-USB2_PROD (MBIM deaggregation)->[IPA]----USB3_CONS---> + *------------------>[IPA]---- + *USB_CONS (MBIM aggregation time limit)-----------> + *------------------>[IPA]---- + *A5_LAN_WAN_CONS (MBIM aggregation no limits)----> + *---------------------------------------------------------------------- + */ +#define PHASE_ELEVEN_TEST_CONFIGURATION 11 +/*---------------------------------------------------------------------- + *Configuration 12 (see configure_system_12 ) + *-----USB_PROD----->[IPA]----USB2_CONS (MBIM aggregation byte limit)---> + *-USB2_PROD (MBIM deaggregation)->[IPA]----USB3_CONS---> + *------------------>[IPA]---- + * USB_CONS (MBIM aggregation time limit)-----------> + *------------------>[IPA]---- + * A5_LAN_WAN_CONS (MBIM aggregation no limits)----> + *---------------------------------------------------------------------- + */ +#define PHASE_TWELVE_TEST_CONFIGURATION 12 +/*---------------------------------------------------------------------- + *Configuration 9 (see configure_system_17 ) + *-----USB3_PROD--->[IPA DMA]----USB_CONS (RNDIS aggregation byte limit)---> + *-----USB_PROD (RNDIS deaggregation)--->[IPA DMA]----USB3_CONS---> + *-----USB2_PROD (RNDIS deaggregation)---> + *-----[IPA DMA]----USB_CONS (RNDIS aggregation byte limit)---> + *-----USB4--->[IPA DMA]----USB2_CONS (RNDIS aggregation time limit)---> + *---------------------------------------------------------------------- + */ +#define PHASE_SEVENTEEN_TEST_CONFIGURATION 17 + +/* + * Data path test + */ +#define PHASE_EIGHTEEN_TEST_CONFIGURATION 18 + +/*---------------------------------------------------------------------- + *Configuration 19 (see configure_system_19 ) + *-----USB_PROD--->[IPA DMA]----USB_CONS---> + *-----suspend [IPA DMA]----USB_CONS (for testing suspend interrupt)---> + *---------------------------------------------------------------------- + */ +#define PHASE_NINETEEN_TEST_CONFIGURATION 19 + +#define PHASE_TWENTY_TEST_CONFIGURATION 20 +/*---------------------------------------------------------------------- + *Configuration 20 (see configure_system_20 ) + *-----PROD (WLAN header removal)--------------------->[IPA]----CONS----> + *-----PROD (RNDIS de-aggregation + Header removal)--->[IPA] + *---------------------------------------------------------------------- + */ + +enum IPATestConfiguration { + IPA_TEST_CONFIFURATION_0 = PRE_PHASE_ZERO_TEST_CONFIGURATION, + IPA_TEST_CONFIFURATION_1 = PHASE_ZERO_TEST_CONFIGURATION, + IPA_TEST_CONFIFURATION_2 = PHASE_TWO_TEST_CONFIGURATION, + IPA_TEST_CONFIFURATION_3 = PHASE_THREE_TEST_CONFIGURATION, + IPA_TEST_CONFIFURATION_5 = PHASE_FIVE_TEST_CONFIGURATION, + IPA_TEST_CONFIFURATION_6 = PHASE_SIX_TEST_CONFIGURATION, + IPA_TEST_CONFIFURATION_7 = PHASE_SEVEN_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_8 = PHASE_EIGHT_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_9 = PHASE_NINE_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_10 = PHASE_TEN_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_11 = PHASE_ELEVEN_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_12 = PHASE_TWELVE_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_17 = PHASE_SEVENTEEN_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_18 = PHASE_EIGHTEEN_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_19 = PHASE_NINETEEN_TEST_CONFIGURATION, + IPA_TEST_CONFIGURATION_20 = PHASE_NINETEEN_TEST_CONFIGURATION, +}; +#define CONFIGURATION_NODE_PATH "/dev/ipa_test" + +/*producer*/ +#define INTERFACE0_TO_IPA_DATA_PATH "/dev/to_ipa_0" +#define INTERFACE0_FROM_IPA_DATA_PATH NULL + +/*producer*/ +#define INTERFACE4_TO_IPA_DATA_PATH "/dev/to_ipa_1" +#define INTERFACE4_FROM_IPA_DATA_PATH NULL + +/*producer*/ +#define INTERFACE5_TO_IPA_DATA_PATH "/dev/to_ipa_2" +#define INTERFACE5_FROM_IPA_DATA_PATH NULL + +/*consumer*/ +#define INTERFACE1_TO_IPA_DATA_PATH NULL +#define INTERFACE1_FROM_IPA_DATA_PATH "/dev/from_ipa_0" + +/*consumer 2*/ +#define INTERFACE2_TO_IPA_DATA_PATH NULL +#define INTERFACE2_FROM_IPA_DATA_PATH "/dev/from_ipa_1" + +/*Default consumer*/ +#define INTERFACE3_TO_IPA_DATA_PATH NULL +#define INTERFACE3_FROM_IPA_DATA_PATH "/dev/from_ipa_2" + +/*Exceptions producer*/ +#define INTERFACE_TO_IPA_EXCEPTION_PATH NULL +#define INTERFACE_FROM_IPA_EXCEPTION_PATH "/dev/ipa_exception_pipe" + +/*The next configuration should be used by the ITAKEM as well.*/ + +/*---------------------------------------------------------------------- + *Configuration 1 (see configure_system_1 ) + *-----USB_PROD--->[IPA DMA]----USB_CONS---> + *---------------------------------------------------------------------- + */ +#define CONFIG_1_FROM_USB1_TO_IPA_DMA "/dev/to_ipa_0" +#define CONFIG_1_FROM_IPA_TO_USB1_DMA "/dev/from_ipa_0" + +/*---------------------------------------------------------------------- + *Configuration 2 (see configure_system_2 ) + * [IPA]----USB2_CONS--> + *-----USB_PROD--->[IPA]----USB3_CONS---> + * [IPA]----Q6_LAN_CONS---> + *--------------------------------------------------------------------- + */ +#define CONFIG_2_FROM_USB_TO_IPA "/dev/to_ipa_0" +#define CONFIG_2_FROM_IPA_TO_A2_NDUN "/dev/from_ipa_0" +#define CONFIG_2_FROM_IPA_TO_A2_DUN "/dev/from_ipa_1" +#define CONFIG_2_FROM_IPA_TO_Q6_LAN "/dev/from_ipa_2" + +/*USB1 is an EthernetII Client*/ +#define FROM_USB1_TO_IPA "/dev/to_ipa_0" +#define FROM_IPA_TO_USB1 "/dev/from_ipa_0" +#define USB1_CLIENT_HEADER_LENGTH 14 + +/*---------------------------------------------------------------------- + *Configuration 3 (see configure_system_3 ) + * [IPA]----USB_CONS------> + *-----USB2_PROD--->[IPA]----USB2_CONS---> + * [IPA]----Q6_LAN_CONS----> + *---------------------------------------------------------------------- + */ +#define CONFIG_3_FROM_A2_NDUN_TO_IPA "/dev/to_ipa_0" +#define CONFIG_3_FROM_IPA_TO_USB1 "/dev/from_ipa_0" +#define CONFIG_3_FROM_IPA_TO_A2_NDUN "/dev/from_ipa_1" +#define CONFIG_3_FROM_IPA_TO_Q6_LAN "/dev/from_ipa_2" + +/*---------------------------------------------------------------------- + *Configuration 8 (see configure_system_8 ) + *-----USB3_PROD--->[IPA DMA]---- + *-----USB_CONS (TLP aggregation byte limit)---> + *-----USB_PROD (TLP deaggregation)--->[IPA DMA]----USB3_CONS---> + *-----USB2_PROD (TLP deaggregation)---> + * [IPA DMA]----USB_CONS (TLP aggregation byte limit)---> + *-----USB4--->[IPA DMA]----USB2_CONS (TLP aggregation time limit)---> + *---------------------------------------------------------------------- + */ +#define CONFIG_8_NO_AGG_TO_IPA_AGG "/dev/to_ipa_0" +#define CONFIG_8_DEAGG_TO_IPA_NO_AGG "/dev/to_ipa_1" +#define CONFIG_8_DEAGG_TO_IPA_AGG "/dev/to_ipa_2" +#define CONFIG_8_NO_AGG_TO_IPA_AGG_TIME "/dev/to_ipa_3" +#define CONFIG_8_FROM_IPA_AGG "/dev/from_ipa_0" +#define CONFIG_8_FROM_IPA_NO_AGG "/dev/from_ipa_1" +#define CONFIG_8_DEAGG_FROM_IPA_AGG "/dev/from_ipa_2" + +/*---------------------------------------------------------------------- + *Configuration 9 (see configure_system_9 ) + *-----USB3_PROD--->[IPA DMA]---- + * USB_CONS (MBIM aggregation byte limit)---> + *-----USB_PROD (MBIM deaggregation)--->[IPA DMA]----USB3_CONS---> + *-----USB2_PROD (MBIM deaggregation)---> + * [IPA DMA]----USB_CONS (MBIM aggregation byte limit)---> + *-----USB4--->[IPA DMA]---- + * USB2_CONS (MBIM aggregation time limit)---> + *---------------------------------------------------------------------- + */ +#define CONFIG_9_NO_AGG_TO_IPA_AGG "/dev/to_ipa_0" +#define CONFIG_9_DEAGG_TO_IPA_NO_AGG "/dev/to_ipa_1" +#define CONFIG_9_DEAGG_TO_IPA_AGG "/dev/to_ipa_2" +#define CONFIG_9_NO_AGG_TO_IPA_AGG_TIME "/dev/to_ipa_3" +#define CONFIG_9_FROM_IPA_AGG "/dev/from_ipa_0" +#define CONFIG_9_FROM_IPA_NO_AGG "/dev/from_ipa_1" +#define CONFIG_9_DEAGG_FROM_IPA_AGG "/dev/from_ipa_2" + +/*---------------------------------------------------------------------- + *Configuration 10 (see configure_system_10 ) + *-----USB_PROD--->[IPA DMA]---- + * USB_CONS (MBIM aggregation no limits)---> + *---------------------------------------------------------------------- + */ +#define CONFIG_10_TO_IPA_AGG_ZERO_LIMITS "/dev/to_ipa_0" +#define CONFIG_10_FROM_IPA_AGG_ZERO_LIMITS "/dev/from_ipa_0" + +/*---------------------------------------------------------------------- + *Configuration 11 (see configure_system_11 ) + *-----USB_PROD----->[IPA]---- + * USB2_CONS (MBIM aggregation byte limit)---> + * USB2_PROD (MBIM deaggregation)->[IPA]----USB3_CONS---> + *------------------>[IPA]---- + * USB_CONS (MBIM aggregation time limit)-----------> + *------------------>[IPA + * A5_LAN_WAN_CONS (MBIM aggregation no limits)----> + *---------------------------------------------------------------------- + */ +#define CONFIG_11_TO_IPA "/dev/to_ipa_0" +#define CONFIG_11_TO_IPA_DEAGG "/dev/to_ipa_1" +#define CONFIG_11_FROM_IPA_AGG "/dev/from_ipa_0" +#define CONFIG_11_FROM_IPA "/dev/from_ipa_1" +#define CONFIG_11_FROM_IPA_AGG_TIME "/dev/from_ipa_2" +#define CONFIG_11_FROM_IPA_ZERO_LIMITS "/dev/from_ipa_3" + +/*---------------------------------------------------------------------- + *Configuration 12 (see configure_system_12 ) + *-----USB_PROD----->[IPA]---- + * USB2_CONS (MBIM aggregation byte limit)---> + *-USB2_PROD (MBIM deaggregation)->[IPA]----USB3_CONS---> + *------------------>[IPA]---- + * USB_CONS (MBIM aggregation time limit)-----------> + *------------------>[IPA]---- + * A5_LAN_WAN_CONS (MBIM aggregation no limits)----> + *---------------------------------------------------------------------- + */ +#define CONFIG_12_TO_IPA "/dev/to_ipa_0" +#define CONFIG_12_TO_IPA_DEAGG "/dev/to_ipa_1" +#define CONFIG_12_FROM_IPA_AGG "/dev/from_ipa_0" +#define CONFIG_12_FROM_IPA "/dev/from_ipa_1" +#define CONFIG_12_FROM_IPA_AGG_TIME "/dev/from_ipa_2" +#define CONFIG_12_FROM_IPA_ZERO_LIMITS "/dev/from_ipa_3" + +/*Configuration 7 (see configure_system_7 ) + * [IPA]----USB2_CONS--> + *-----USB_PROD--->[IPA]----USB3_CONS---> + * [IPA]----Q6_LAN_CONS---> + * [IPA]----A5 - Exception Pipe---> + */ +#define CONFIG_7_FROM_USB1_TO_IPA "/dev/to_ipa_0" +#define CONFIG_7_FROM_IPA_TO_A5_EXCEPTION "/dev/ipa_exception_pipe" + +/*---------------------------------------------------------------------- + *Configuration 17 (see configure_system_17 ) + *-----USB_PROD----->[IPA]---- + * USB2_CONS (RNDIS aggregation byte limit)---> + * USB2_PROD (RNDIS deaggregation)->[IPA]----USB3_CONS---> + *------------------>[IPA]---- + * USB_CONS (RNDIS aggregation time limit)-----------> + *------------------>[IPA]---- + * A5_LAN_WAN_CONS (RNDIS aggregation no limits)----> + *---------------------------------------------------------------------- + */ +#define CONFIG_17_TO_IPA "/dev/to_ipa_0" +#define CONFIG_17_TO_IPA_NO_HDR "/dev/to_ipa_1" +#define CONFIG_17_TO_IPA_DEAGG "/dev/to_ipa_2" +#define CONFIG_17_FROM_IPA_AGG "/dev/from_ipa_0" +#define CONFIG_17_FROM_IPA "/dev/from_ipa_1" +#define CONFIG_17_FROM_IPA_AGG_TIME "/dev/from_ipa_2" +#define CONFIG_17_FROM_IPA_ZERO_LIMITS "/dev/from_ipa_3" + +/*---------------------------------------------------------------------- + *Configuration 18 (see configure_system_18 )--------------------------- + *-----USB_PROD----->[IPA]--------------->USB_CONS--------->A5---------- + *-----USB_PROD2 is a dummy endpoint handle for packet handling between- + *-----user space and kernel space in the IPA driver-------------------- + *---------------------------------------------------------------------- + */ +#define CONFIG_18_TO_IPA "/dev/to_ipa_0" +#define CONFIG_18_DUMMY_ENDPOINT "/dev/to_ipa_1" +#define CONFIG_18_FROM_IPA "/dev/from_ipa_0" + +/*---------------------------------------------------------------------- + *Configuration 19 (see configure_system_19 ) + *-----USB_PROD--->[IPA DMA]----USB_CONS---> + *---------------------------------------------------------------------- + */ +#define CONFIG_19_FROM_USB_TO_IPA_DMA "/dev/to_ipa_0" +#define CONFIG_19_FROM_IPA_TO_USB_DMA "/dev/from_ipa_0" + +enum ipv6_ext_hdr_type { + HOP_BY_HOP_OPT = 0, + DEST_OPT = 60, + ROUTING = 43, + FRAGMENT = 44, + AH = 51, + ESP = 50, + DEST_OPT_UL = 60, + Mobility = 135, + NONE = 59 +}; +/*File that are being used by the test application:*/ + +#define IPV4_FILE_PATH "Input/IPV4_3" + +/*--------------------------------------------------------------------- + *XUnit tests results format file name + *---------------------------------------------------------------------- + */ +#define XUNIT_REPORT_PATH_AND_NAME "junit_result.xml" + +#endif /* CONSTANTS_H_ */ diff --git a/kernel-tests/DataPathTestFixture.cpp b/kernel-tests/DataPathTestFixture.cpp new file mode 100644 index 0000000000..e08ecc2562 --- /dev/null +++ b/kernel-tests/DataPathTestFixture.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017 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 "DataPathTestFixture.h" + +Pipe DataPathTestFixture::m_FromIPAPipe(IPA_CLIENT_TEST_CONS, + IPA_TEST_CONFIGURATION_18); +Pipe DataPathTestFixture::m_ToIpaPipe(IPA_CLIENT_TEST_PROD, + IPA_TEST_CONFIGURATION_18); +Pipe DataPathTestFixture::m_IpaDriverPipe(IPA_CLIENT_TEST2_PROD, + IPA_TEST_CONFIGURATION_18); + + +RoutingDriverWrapper DataPathTestFixture::m_Routing; +Filtering DataPathTestFixture::m_Filtering; +HeaderInsertion DataPathTestFixture::m_HeaderInsertion; + +DataPathTestFixture::DataPathTestFixture() +{ + m_testSuiteName.push_back("DataPath"); + Register(*this); +} + +bool DataPathTestFixture::Setup() +{ + bool bRetVal = true; + + /*Set the configuration to support USB->IPA and IPA->USB pipes.*/ + ConfigureScenario(IPA_TEST_CONFIGURATION_18); + + bRetVal &= m_ToIpaPipe.Init(); + bRetVal &= m_FromIPAPipe.Init(); + bRetVal &= m_IpaDriverPipe.Init(); + + if (!m_Routing.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Routing block is not ready for immediate commands!\n"); + return false; + } + if (!m_Filtering.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Filtering block is not ready for immediate commands!\n"); + return false; + } + if (!m_HeaderInsertion.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Header Insertion block is not ready for immediate commands!\n"); + return false; + }\ + /*resetting this component will reset both Routing and Filtering tables*/ + m_HeaderInsertion.Reset(); + + return bRetVal; +} + +bool DataPathTestFixture::Teardown() +{ + /*The Destroy method will close the inode.*/ + m_FromIPAPipe.Destroy(); + m_ToIpaPipe.Destroy(); + m_IpaDriverPipe.Destroy(); + return true; +} + +bool DataPathTestFixture::Run() +{ + LOG_MSG_DEBUG("Entering Function"); + + if (!TestLogic()) { + LOG_MSG_ERROR( + "Test failed, Input and expected output mismatch."); + return false; + } + + LOG_MSG_DEBUG("Leaving Function (Returning True)"); + return true; +} + + diff --git a/kernel-tests/DataPathTestFixture.h b/kernel-tests/DataPathTestFixture.h new file mode 100644 index 0000000000..e7995a0322 --- /dev/null +++ b/kernel-tests/DataPathTestFixture.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017 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 DATAPATHTESTFIXTURE_H_ +#define DATAPATHTESTFIXTURE_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 "Pipe.h" +#include "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" + +class DataPathTestFixture:public TestBase +{ +public: + /* + * This Constructor will register each instance + * that it creates. + */ + DataPathTestFixture(); + + /* + * This method will create and initialize two Pipe object for the USB + * (Ethernet) Pipes, one as input and the other as output. + */ + virtual bool Setup(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + virtual bool Run(); + + virtual bool TestLogic() = 0; + + /*The client type are set from the peripheral perspective*/ + static Pipe m_FromIPAPipe; + static Pipe m_ToIpaPipe; + static Pipe m_IpaDriverPipe; + + static RoutingDriverWrapper m_Routing; + static Filtering m_Filtering; + static HeaderInsertion m_HeaderInsertion; +}; +#endif /* DATAPATHTESTFIXTURE_H_ */ diff --git a/kernel-tests/DataPathTests.cpp b/kernel-tests/DataPathTests.cpp new file mode 100644 index 0000000000..e9a629d7af --- /dev/null +++ b/kernel-tests/DataPathTests.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2017,2020 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 "hton.h" /* for htonl*/ +#include "DataPathTestFixture.h" +#include "Constants.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" + +#define PACKET_SIZE ((10)*(4)) + +class IpaTxDpTest:public DataPathTestFixture { + +public: + IpaTxDpTest() { + m_name = "IpaTxDpTest"; + m_description = "Sending one SKB via ipa_tx_dp() and checking" + "if it was received"; + m_runInRegression = true; + } + + bool TestLogic() { + LOG_MSG_DEBUG("Entering %s\n", __func__); + int ret; + unsigned char *input, *output; + char pkt[PACKET_SIZE] = { + 0x59, 0x61, 0x6e, 0x69, + 0x76, 0x5f, 0x48 ,0x61, + 0x73 ,0x62 ,0x61 ,0x6e, + 0x69 ,0x5f ,0x54 ,0x68, + 0x65 ,0x5f ,0x47 ,0x72, + 0x65 ,0x61 ,0x74 ,0x16, + 0x32 ,0x49 ,0x0c ,0x3f, + 0x37 ,0x23 ,0x6d ,0x15, + 0x50 ,0x10 ,0x3f ,0xbd, + 0xcc ,0xd8 ,0x00, 0x00 + }; + + input = (unsigned char *)malloc(PACKET_SIZE); + if(!input) { + LOG_MSG_ERROR("Error in allocation\n"); + goto fail; + } + + output = (unsigned char *)malloc(PACKET_SIZE); + if(!output) { + LOG_MSG_ERROR("Error in allocation\n"); + free(input); + goto fail; + } + + memcpy(input, pkt, PACKET_SIZE); + LOG_MSG_DEBUG("Sending packet through ipa_tx_dp() in func %s\n", __func__); + ret = m_IpaDriverPipe.Send(input, PACKET_SIZE); + + if (ret != PACKET_SIZE) { + LOG_MSG_ERROR( + "Amount of bits sent are: %d instead of %d\nExiting..\n" + , ret + , PACKET_SIZE); + free(input); + free(output); + goto fail; + } + + ret = m_FromIPAPipe.Receive(output, PACKET_SIZE); + if (ret != PACKET_SIZE) { + LOG_MSG_ERROR( + "Amount of bits sent are: %d instead of %d\nExiting..\n", + ret, + PACKET_SIZE); + free(input); + free(output); + goto fail; + } + + LOG_MSG_INFO("Input buff:\n"); + print_buff(input, PACKET_SIZE); + LOG_MSG_INFO("Output buff:\n"); + print_buff(output, PACKET_SIZE); + if (memcmp(input,output, PACKET_SIZE)) { + free(input); + free(output); + return false; + } + + free(input); + free(output); + return true; +fail: + return false; + } +}; + +class IpaTxDpMultipleTest:public DataPathTestFixture { + +public: + IpaTxDpMultipleTest() { + m_name = "IpaTxDpMultipleTest"; + m_description = "Sending multiple SKB via ipa_tx_dp() and checking" + "if it was received"; + m_runInRegression = false; + } + + bool TestLogic() { + int packet_to_send = 10; + int loop_size = 100; + int i; + int j; + + LOG_MSG_DEBUG("Entering %s\n", __func__); + int ret; + unsigned char *input, *output; + char pkt[PACKET_SIZE] = { + 0x59, 0x61, 0x6e, 0x69, + 0x76, 0x5f, 0x48 ,0x61, + 0x73 ,0x62 ,0x61 ,0x6e, + 0x69 ,0x5f ,0x54 ,0x68, + 0x65 ,0x5f ,0x47 ,0x72, + 0x65 ,0x61 ,0x74 ,0x16, + 0x32 ,0x49 ,0x0c ,0x3f, + 0x37 ,0x23 ,0x6d ,0x15, + 0x50 ,0x10 ,0x3f ,0xbd, + 0xcc ,0xd8 ,0x00, 0x00 + }; + + input = (unsigned char *)malloc(PACKET_SIZE); + if(!input) { + LOG_MSG_ERROR("Error in allocation\n"); + goto fail; + } + + output = (unsigned char *)malloc(PACKET_SIZE); + if(!output) { + LOG_MSG_ERROR("Error in allocation\n"); + free(input); + goto fail; + } + + memcpy(input, pkt, PACKET_SIZE); + for (i = 0; i < loop_size; i++) { + for (j = 0; j < packet_to_send; j++) { + input[0] = i; + input[1] = j; + LOG_MSG_DEBUG("Sending packet through ipa_tx_dp() in func %s\n", __func__); + ret = m_IpaDriverPipe.Send(input, PACKET_SIZE); + if (ret != PACKET_SIZE) { + LOG_MSG_ERROR( + "Amount of bits sent are: %d instead of %d\nExiting..\n" + , ret + , PACKET_SIZE); + free(input); + free(output); + goto fail; + } + } + + for (j = 0; j < packet_to_send; j++) { + ret = m_FromIPAPipe.Receive(output, PACKET_SIZE); + if (ret != PACKET_SIZE) { + LOG_MSG_ERROR( + "Amount of bits sent are: %d instead of %d\nExiting..\n", + ret, + PACKET_SIZE); + free(input); + free(output); + goto fail; + } + input[0] = i; + input[1] = j; + LOG_MSG_INFO("Input buff:\n"); + print_buff(input, PACKET_SIZE); + LOG_MSG_INFO("Output buff:\n"); + print_buff(output, PACKET_SIZE); + if (memcmp(input,output, PACKET_SIZE)) { + free(input); + free(output); + LOG_MSG_ERROR("Failed in buffers comparison"); + return false; + } + } + } + + free(input); + free(output); + return true; +fail: + return false; + } +}; + +class IPAToAppsTest:public DataPathTestFixture { + +public: + IPAToAppsTest() { + m_name = "IPAToApps"; + m_description = "Sending one SKB via USB_PROD pipe and checking" + "if it was received"; + m_runInRegression = true; + } + + bool TestLogic() { + int ret; + unsigned char *input, *output; + unsigned char pkt[PACKET_SIZE] = { + 0x59, 0x61, 0x6e, 0x69, + 0x76, 0x5f, 0x48 ,0x61, + 0x73 ,0x62 ,0x61 ,0x6e, + 0x69 ,0x5f ,0x54 ,0x68, + 0x65 ,0x5f ,0x47 ,0x72, + 0x65 ,0x61 ,0x74 ,0x16, + 0x32 ,0x49 ,0x0c ,0x3f, + 0x37 ,0x23 ,0x6d ,0x15, + 0x50 ,0x10 ,0x3f ,0xbd, + 0xcc ,0xd8 ,0x00, 0x00 + }; + + input = (unsigned char *)malloc(PACKET_SIZE); + if(!input) { + LOG_MSG_ERROR("Error in allocation\n"); + goto fail; + } + output = (unsigned char *)malloc(PACKET_SIZE); + if(!output) { + LOG_MSG_ERROR("Error in allocation\n"); + free(input); + goto fail; + } + memcpy(input, pkt, PACKET_SIZE); + + LOG_MSG_DEBUG("Sending packet through USB_PROD pipe in func %s\n", __func__); + ret = m_ToIpaPipe.Send(input, PACKET_SIZE); + if (ret != PACKET_SIZE) { + LOG_MSG_ERROR( + "Amount of bits sent are: %d instead of %d\nExiting..\n", + ret, + PACKET_SIZE); + goto fail; + } + LOG_MSG_DEBUG("Reading packet through Dummy Endpoint pipe in func %s\n", __func__); + ret = m_IpaDriverPipe.Receive(output, PACKET_SIZE); + if (ret != 0) { + LOG_MSG_ERROR("Failed in reading buffer. %d error", ret); + free(input); + free(output); + goto fail; + } + LOG_MSG_DEBUG("SKB original packet:\n"); + print_buff(input, PACKET_SIZE); + LOG_MSG_DEBUG("SKB received packet:\n"); + print_buff(output, PACKET_SIZE); + if (memcmp(input,output, PACKET_SIZE)) { + free(input); + free(output); + return false; + } + free(input); + free(output); + return true; +fail: + return false; + } +}; + +class IPAToAppsMultipleTest:public DataPathTestFixture { + +public: + IPAToAppsMultipleTest() { + m_name = "IPAToAppsMultipleTest"; + m_description = "Sending multiple SKB via USB_PROD pipe and checking" + "if they was received"; + m_runInRegression = false; + } + + bool TestLogic() { + int packet_to_send = 10; + int loop_size = 100; + int i; + int j; + int ret; + unsigned char *input, *output; + unsigned char pkt[PACKET_SIZE] = { + 0x59, 0x61, 0x6e, 0x69, + 0x76, 0x5f, 0x48 ,0x61, + 0x73 ,0x62 ,0x61 ,0x6e, + 0x69 ,0x5f ,0x54 ,0x68, + 0x65 ,0x5f ,0x47 ,0x72, + 0x65 ,0x61 ,0x74 ,0x16, + 0x32 ,0x49 ,0x0c ,0x3f, + 0x37 ,0x23 ,0x6d ,0x15, + 0x50 ,0x10 ,0x3f ,0xbd, + 0xcc ,0xd8 ,0x00, 0x00 + }; + + input = (unsigned char *)malloc(PACKET_SIZE); + if(!input) { + LOG_MSG_ERROR("Error in allocation\n"); + goto fail; + } + output = (unsigned char *)malloc(PACKET_SIZE); + if(!output) { + LOG_MSG_ERROR("Error in allocation\n"); + free(input); + goto fail; + } + memcpy(input, pkt, PACKET_SIZE); + for (i = 0; i < loop_size; i++) { + for (j = 0; j < packet_to_send; j++) { + input[0] = i; + input[1] = j; + + LOG_MSG_DEBUG("Sending packet through USB_PROD pipe in func %s\n", __func__); + ret = m_ToIpaPipe.Send(input, PACKET_SIZE); + if (ret != PACKET_SIZE) { + LOG_MSG_ERROR( + "Amount of bits sent are: %d instead of %d\nExiting..\n", + ret, + PACKET_SIZE); + free(input); + free(output); + goto fail; + } + } + + for (j = 0; j < packet_to_send; j++) { + input[0] = i; + input[1] = j; + LOG_MSG_DEBUG("Reading packet through Dummy Endpoint pipe in func %s\n", __func__); + ret = m_IpaDriverPipe.Receive(output, PACKET_SIZE); + if (ret != 0) { + LOG_MSG_ERROR("Failed in reading buffer. %d error", ret); + free(input); + free(output); + goto fail; + } + LOG_MSG_DEBUG("SKB original packet:\n"); + print_buff(input, PACKET_SIZE); + LOG_MSG_DEBUG("SKB received packet:\n"); + print_buff(output, PACKET_SIZE); + if (memcmp(input,output, PACKET_SIZE)) { + free(input); + free(output); + LOG_MSG_ERROR("Failed in buffers comparison"); + return false; + } + } + } + free(input); + free(output); + return true; +fail: + return false; + } +}; + + +static IpaTxDpTest ipaTxDpTest; +static IpaTxDpMultipleTest ipaTxDpMultipleTest; +static IPAToAppsTest ipaToApps; +static IPAToAppsMultipleTest iPAToAppsMultipleTestApps; diff --git a/kernel-tests/ExceptionTests.cpp b/kernel-tests/ExceptionTests.cpp new file mode 100644 index 0000000000..1c5847f206 --- /dev/null +++ b/kernel-tests/ExceptionTests.cpp @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2017 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 "TestsUtils.h" +#include "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" +#include + +using namespace IPA; + +class IPAExceptionTestFixture: public TestBase { +public: + + IPAExceptionTestFixture() : + m_uBufferSize(0) { + memset(m_aBuffer, 0, sizeof(m_aBuffer)); + m_testSuiteName.push_back("Exception"); + } + + virtual bool AddRules() = 0; + virtual bool ModifyPackets() = 0; + virtual bool TestLogic() = 0; + + bool Setup() { + + ConfigureScenario(PHASE_SEVEN_TEST_CONFIGURATION); + + m_producer.Open(INTERFACE0_TO_IPA_DATA_PATH, + INTERFACE0_FROM_IPA_DATA_PATH); + m_Consumer1.Open(INTERFACE1_TO_IPA_DATA_PATH, + INTERFACE1_FROM_IPA_DATA_PATH); + m_Consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, + INTERFACE2_FROM_IPA_DATA_PATH); + m_Consumer3.Open(INTERFACE3_TO_IPA_DATA_PATH, + INTERFACE3_FROM_IPA_DATA_PATH); + m_Exceptions.Open(INTERFACE_TO_IPA_EXCEPTION_PATH, + INTERFACE_FROM_IPA_EXCEPTION_PATH); + + + if (!m_Routing.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Routing block is not ready for immediate commands!\n"); + return false; + } + if (!m_Filtering.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Filtering block is not ready for immediate commands!\n"); + return false; + } + if (!m_HeaderInsertion.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Header Insertion block is not ready for immediate commands!\n"); + return false; + } + m_HeaderInsertion.Reset(); + + return true; + } // Setup() + + bool Run() { + m_uBufferSize = BUFF_MAX_SIZE; + LOG_MSG_STACK("Entering Function"); + + // Configure the system by adding Routing / Filtering / HDR + if (!AddRules()) { + LOG_MSG_ERROR("Failed adding Routing / Filtering / HDR."); + return false; + } + // Load input data (IP packet) from file + if (!LoadDefaultPacket(m_eIP, m_aBuffer, m_uBufferSize)) { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + if (!ModifyPackets()) { + LOG_MSG_ERROR("Failed to modify packets."); + return false; + } + if (!TestLogic()) { + LOG_MSG_ERROR("Test failed, Input and expected output mismatch."); + return false; + } + LOG_MSG_STACK("Leaving Function (Returning True)"); + return true; + } // Run() + + bool Teardown() { + m_producer.Close(); + m_Consumer1.Close(); + m_Consumer2.Close(); + m_Consumer3.Close(); + m_Exceptions.Close(); + return true; + } // Teardown() + + ~IPAExceptionTestFixture() { + } + + static RoutingDriverWrapper m_Routing; + static Filtering m_Filtering; + static HeaderInsertion m_HeaderInsertion; + InterfaceAbstraction m_producer; + InterfaceAbstraction m_Consumer1; + InterfaceAbstraction m_Consumer2; + InterfaceAbstraction m_Consumer3; + InterfaceAbstraction m_Exceptions; + +protected: + static const size_t BUFF_MAX_SIZE = 1024; + static const uint8_t MAX_HEADER_SIZE = 64; // 64Bytes - Max Header Length + enum ipa_ip_type m_eIP; + uint8_t m_aBuffer[BUFF_MAX_SIZE]; // Input file \ IP packet + size_t m_uBufferSize; + +}; +RoutingDriverWrapper IPAExceptionTestFixture::m_Routing; +Filtering IPAExceptionTestFixture::m_Filtering; +HeaderInsertion IPAExceptionTestFixture::m_HeaderInsertion; + +//----------------------------------------------------------------------------------------------------------------------------------------/ +// Test001: Test that when a packet with (IPVer != 4) && (IPVer Ver != 6) , an exception packet is created and received & exception_pipe / +//----------------------------------------------------------------------------------------------------------------------------------------/ +class IPAExceptionPacketTest001: public IPAExceptionTestFixture { +public: + IPAExceptionPacketTest001() { + m_name = "IPAExceptionPacketTest001"; + m_description = "\ + IPA Exception Test 001 - Test that when a packet with (IPVer != 4) && (IPVer Ver != 6) , an exception packet is created and received & exception_pipe \ + Test Generates send NUM_OF_EXCEPTION_PKTS packets with IP Version changing from 0 to 9.\ + First IP Version == 4, hence it is not considered as exception (same goes for IP Ver == 6) \ + "; + m_eIP = IPA_IP_v4; + Register(*this); + } + + virtual bool AddRules() { + // Clear All Rules + bool bRetVal = true; + LOG_MSG_STACK("Entering Function"); + + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl sRoutingTable; + IPAFilteringTable cFilterTable; + struct ipa_flt_rule_add sFilterRuleEntry; + uint32_t nRTTableHdl=0; + memset(&sRoutingTable, 0, sizeof(sRoutingTable)); + + LOG_MSG_STACK("Entering Function"); + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, bypass0, IPA_CLIENT_TEST2_CONS, + 0,&nRTTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("CreateBypassRoutingTable completed successfully"); + sRoutingTable.ip = m_eIP; + strlcpy(sRoutingTable.name, bypass0, sizeof(sRoutingTable.name)); + if (!m_Routing.GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&sRoutingTable=0x%p) Failed.", &sRoutingTable); + bRetVal = false; + goto bail; + } + // Creating Filtering Rules + cFilterTable.Init(m_eIP,IPA_CLIENT_TEST_PROD,true,1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable.GeneratePresetRule(0,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl = -1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action = IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nRTTableHdl; + if ( + ((uint8_t)-1 == cFilterTable.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable.ReadRuleFromTable(0)->status); + } + + bail: + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + m_eIP = IPA_IP_v6; + + AddRules(); // Need to add Routing / Filtering rules for IPv6 as well. + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + int i = 0, nIPVer = 0;; + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + m_aExpectedBuffer[2] = 0x0b; + m_aExpectedBuffer[3] = 0x80; + + memcpy(m_aExpectedBuffer+8, m_aBuffer, m_uBufferSize); + m_aExpectedBufSize = m_uBufferSize+8; + + for (i=0;iflt_rule_hdl,cFilterTable.ReadRuleFromTable(0)->status); + } + + bail: + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + m_aExpectedBuffer[2] = 0x0b; + m_aExpectedBuffer[3] = 0x20; + + memcpy(m_aExpectedBuffer+8, m_aBuffer, m_uBufferSize); + m_aExpectedBufSize = m_uBufferSize+8; + + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Exceptions, m_aExpectedBuffer, m_aExpectedBufSize)) + { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + return false; + } + return true; + } +private: + uint8_t m_aExpectedBuffer[BUFF_MAX_SIZE]; + size_t m_aExpectedBufSize; +}; + +//-----------------------------------------------------------------------------------------------------------------------------------------/ +// Test006: Test that when a packet with Internet Header Length < 5 Arrives, an exception packet is created and received & exception_pipe / +//-----------------------------------------------------------------------------------------------------------------------------------------/ +class IPAExceptionPacketTest006: public IPAExceptionTestFixture { +public: + IPAExceptionPacketTest006() { + m_name = "IPAExceptionPacketTest006" + m_description = "\ + IPA Exception Test 006 - Test that when a packet with Internet Header Length < 5 Arrives, an exception packet is created and received & exception_pipe \ + Test Generates a Packet with Internet Header Length (IHL == 4). \ + and verifies that the packet is recieved @ the Exception Pipe. \ + "; + m_eIP = IPA_IP_v4; + Register(*this); + } + + virtual bool AddRules() { + // Clear All Rules + bool bRetVal = true; + LOG_MSG_STACK("Entering Function"); + + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl sRoutingTable; + IPAFilteringTable cFilterTable; + struct ipa_flt_rule_add sFilterRuleEntry; + uint32_t nRTTableHdl=0; + memset(&sRoutingTable, 0, sizeof(sRoutingTable)); + + LOG_MSG_STACK("Entering Function"); + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, bypass0, IPA_CLIENT_TEST2_CONS, + 0,&nRTTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("CreateBypassRoutingTable completed successfully"); + sRoutingTable.ip = m_eIP; + strlcpy(sRoutingTable.name, bypass0, sizeof(sRoutingTable.name)); + if (!m_Routing.GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&sRoutingTable=0x%p) Failed.", &sRoutingTable); + bRetVal = false; + goto bail; + } + // Creating Filtering Rules + cFilterTable.Init(m_eIP,IPA_CLIENT_TEST_PROD,true,1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable.GeneratePresetRule(0,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl = -1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action = IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nRTTableHdl; + if ( + ((uint8_t)-1 == cFilterTable.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable.ReadRuleFromTable(0)->status); + } + + bail: + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + m_aBuffer[0] =(m_aBuffer[0] & 0xF0)+0x04;// Change the IHL to 4 + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + m_aExpectedBuffer[2] = 0x0b; + m_aExpectedBuffer[3] = 0x04; + + memcpy(m_aExpectedBuffer+8, m_aBuffer, m_uBufferSize); + m_aExpectedBufSize = m_uBufferSize+8; + + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Exceptions, m_aExpectedBuffer, m_aExpectedBufSize)) + { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + return false; + } + return true; + } +private: + uint8_t m_aExpectedBuffer[BUFF_MAX_SIZE]; + size_t m_aExpectedBufSize; +}; + +static IPAExceptionPacketTest001 ipaExceptionPacketTest001; +static IPAExceptionPacketTest002 ipaExceptionPacketTest002; +static IPAExceptionPacketTest003 ipaExceptionPacketTest003; +static IPAExceptionPacketTest006 ipaExceptionPacketTest006; + diff --git a/kernel-tests/ExceptionsTestFixture.cpp b/kernel-tests/ExceptionsTestFixture.cpp new file mode 100644 index 0000000000..fae6c9b7bc --- /dev/null +++ b/kernel-tests/ExceptionsTestFixture.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017 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 "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" +#include "TestsUtils.h" +#include +#include "ExceptionsTestFixture.h" + +/////////////////////////////////////////////////////////////////////////////// + +Pipe ExceptionsTestFixture::m_USB1ToIpaPipe(IPA_CLIENT_TEST_PROD, IPA_TEST_CONFIFURATION_7); +Pipe ExceptionsTestFixture::m_IpaToA5ExceptionPipe(IPA_TEST_CONFIFURATION_7);//Exception pipe + +/////////////////////////////////////////////////////////////////////////////// + +ExceptionsTestFixture::ExceptionsTestFixture(){ + Register(*this); + m_testSuiteName.push_back("Exceptions"); +} + +/////////////////////////////////////////////////////////////////////////////// + + + +/////////////////////////////////////////////////////////////////////////////// +/////// EOF /////// +/////////////////////////////////////////////////////////////////////////////// + diff --git a/kernel-tests/ExceptionsTestFixture.h b/kernel-tests/ExceptionsTestFixture.h new file mode 100644 index 0000000000..958f35ec40 --- /dev/null +++ b/kernel-tests/ExceptionsTestFixture.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 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 "Routing.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" +#include "TestsUtils.h" +#include "Pipe.h" +#include + +#ifndef _EXCEPTION_TESTS_FIXTURE_ +#define _EXCEPTION_TESTS_FIXTURE_ + +class ExceptionsTestFixture:public TestBase { +public: + /*This Constructor will register the + *exception tests and set the suit name + */ + ExceptionsTestFixture(); +protected: + static Pipe m_USB1ToIpaPipe; + /*from the test application into the IPA(DMUX header)*/ + static Pipe m_IpaToA5ExceptionPipe; + /*from the IPA back to the test application(Exception pipe)*/ +}; + +#endif diff --git a/kernel-tests/ExceptionsTests.cpp b/kernel-tests/ExceptionsTests.cpp new file mode 100644 index 0000000000..61441306d7 --- /dev/null +++ b/kernel-tests/ExceptionsTests.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2017 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 "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" +#include "TestsUtils.h" +#include "ExceptionsTestFixture.h" +#include "IPv4Packet.h" +#include + +#define MAX_SENT_BUFFER_SIZE 1500 +#define MAX_RECEIVE_BUFFER_SIZE 1500 +#define VALIDATE_WITH_MSG_AND_RETVAL(bRetVal,msg) \ + if (false == bRetVal){ \ + LOG_MSG_ERROR(msg); \ + return false; \ + } + +using namespace IPA; + +/////////////////////////////////////////////////////////////////////////////// + +class ExceptionsTestNonIpPacket: public ExceptionsTestFixture { +public: + //The packet size to be sent + size_t m_nPacketSize; + //A buffer to hold the non-IP(V4/V6) packet + Byte *m_pSendBuffer; + + /////////////////////////////////////////////////////////////////////////// + + //Set the tests name and description + ExceptionsTestNonIpPacket() : + m_nPacketSize(0), m_pSendBuffer(NULL) { + m_name = "ExceptionsTestNonIpPacket"; + m_description = + "Create a non-IP packet(version!=4 && version !=6) and \ + expect exception from Filter block"; + } + + /////////////////////////////////////////////////////////////////////////// + + virtual bool Run() { + bool bRetVal = true; + Byte *pReceiveBuffer = new Byte[MAX_RECEIVE_BUFFER_SIZE]; + //Send the non-IPV4/IPV6 packet to the IPA + LOG_MSG_DEBUG("Send the non-IPV4/IPV6 packet to the IPA"); + size_t nBytesSent = m_USB1ToIpaPipe.Send(m_pSendBuffer, m_nPacketSize); + if (nBytesSent != m_nPacketSize) { + LOG_MSG_ERROR("Not all data was sent into the IPA"); + return false; + } + + //Read from the exception pipe(from IPA to A5) - try to read as much as we can + size_t nBytesRead = m_IpaToA5ExceptionPipe.Receive(pReceiveBuffer, + MAX_RECEIVE_BUFFER_SIZE); + if (nBytesRead != nBytesSent) { + LOG_MSG_ERROR("Not all data was read:"); + print_buff(pReceiveBuffer, nBytesRead); + return false; + } + + //check the exception packet against the one that we sent + bRetVal = !memcmp(m_pSendBuffer, pReceiveBuffer, nBytesSent); + if (false == bRetVal) { + LOG_MSG_ERROR("Received packet is not equal, Received:"); + print_buff(pReceiveBuffer, nBytesRead); + LOG_MSG_ERROR("Received packet is not equal, Sent:"); + print_buff(m_pSendBuffer, m_nPacketSize); + return false; + } + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + //build the non-IP packet + virtual bool Setup() { + bool bRetVal = true; + m_pSendBuffer = new Byte[MAX_SENT_BUFFER_SIZE]; + //Load some default IPV4 packet and save its size + m_nPacketSize = MAX_SENT_BUFFER_SIZE; //This parameter is In/Out + bRetVal = LoadDefaultPacket(IPA_IP_v4, m_pSendBuffer, m_nPacketSize); + VALIDATE_WITH_MSG_AND_RETVAL(bRetVal, "Load failed"); + //Set the version field to non-IPV4/IPV6(version = 5) + m_pSendBuffer[0] &= 0x0F; + m_pSendBuffer[0] |= 0x50; + + //initialize Pipes + bRetVal = m_USB1ToIpaPipe.Init(); + VALIDATE_WITH_MSG_AND_RETVAL(bRetVal, "Pipe Initialization failed"); + bRetVal = m_IpaToA5ExceptionPipe.Init(); + VALIDATE_WITH_MSG_AND_RETVAL(bRetVal, "Pipe Initialization failed"); + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + virtual bool Teardown() { + bool bRetVal = true; + delete[] m_pSendBuffer; + m_USB1ToIpaPipe.Destroy(); + m_IpaToA5ExceptionPipe.Destroy(); + return bRetVal; + } + + /////////////////////////////////////////////////////////////////////////// + +}; +//ExceptionTestNoneIpPacket + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// + +class ExceptionsTestFragmentedException: public ExceptionsTestFixture { +public: + //The packet size to be sent + size_t m_nPacketSize; + //A buffer to hold the non-IP(V4/V6) packet + Byte *m_pSendBuffer; + Byte *m_pReceiveBuffer; + + /////////////////////////////////////////////////////////////////////////// + + //Set the tests name and description + ExceptionsTestFragmentedException():m_nPacketSize(0), m_pSendBuffer(NULL), + m_pReceiveBuffer(NULL){ + m_name = "ExceptionsTestFragmentedException"; + m_description = + "Send IP packet with MF set, create global Filter rule \ + that will hit it as Exception"; + } + + /////////////////////////////////////////////////////////////////////////// + + virtual bool Run() { + bool bRetVal = true; + //configuring the Filter block to catch the fragmented packet: + ConfigureFilterGlobalRuleForMF(); + //Send the non-IPV4/IPV6 packet to the IPA + LOG_MSG_DEBUG("Send the IP packet with the MF bit set(size = %d)", m_nPacketSize); + size_t nBytesSent = m_USB1ToIpaPipe.Send(m_pSendBuffer, m_nPacketSize); + if (nBytesSent != m_nPacketSize) { + LOG_MSG_ERROR("Not all data was sent into the IPA(only %d)", nBytesSent); + return false; + } + //Read from the exception pipe(from IPA to A5) - try to read as much as we can + size_t nBytesRead = m_IpaToA5ExceptionPipe.Receive(m_pReceiveBuffer, + MAX_RECEIVE_BUFFER_SIZE); + if (nBytesRead != nBytesSent) { + LOG_MSG_ERROR("Not all data was read:"); + print_buff(m_pReceiveBuffer, nBytesRead); + return false; + } + //check the exception packet against the one that we sent + bRetVal = !memcmp(m_pSendBuffer, m_pReceiveBuffer, nBytesSent); + if (false == bRetVal) { + LOG_MSG_ERROR("Received packet is not equal, Received:"); + print_buff(m_pReceiveBuffer, nBytesRead); + LOG_MSG_ERROR("Received packet is not equal, Sent:"); + print_buff(m_pSendBuffer, m_nPacketSize); + return false; + } + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + //build the non-IP packet + virtual bool Setup() { + bool bRetVal = true; + m_pReceiveBuffer = new Byte[MAX_RECEIVE_BUFFER_SIZE]; + m_pSendBuffer = new Byte[MAX_RECEIVE_BUFFER_SIZE]; + //Load some default TCP packet + TCPPacket tcpPacket; + //Set the MF bit + tcpPacket.SetMF(true); + //copy the packet to the send buffer + m_nPacketSize = tcpPacket.GetSize(); + tcpPacket.ToNetworkByteStream(m_pSendBuffer); + //initialize Pipes + bRetVal = m_USB1ToIpaPipe.Init(); + VALIDATE_WITH_MSG_AND_RETVAL(bRetVal, "Pipe Initialization failed"); + bRetVal = m_IpaToA5ExceptionPipe.Init(); + VALIDATE_WITH_MSG_AND_RETVAL(bRetVal, "Pipe Initialization failed"); + return true; + } + + /////////////////////////////////////////////////////////////////////////// + + virtual bool Teardown() { + bool bRetVal = true; + delete[] m_pSendBuffer; + m_USB1ToIpaPipe.Destroy(); + m_IpaToA5ExceptionPipe.Destroy(); + return bRetVal; + } + + + + /////////////////////////////////////////////////////////////////////////// + + void ConfigureFilterGlobalRuleForMF(){ + //struct ipa_ioc_add_flt_rule *pRuleTable; + //Allocate memory for a table with one rule. + + //Instruct the Driver to write this table(with its one rule) to the HW + + //Continue from here - build the rule to catch the fragmented packet + } + + /////////////////////////////////////////////////////////////////////////// + + +}; +//ExceptionsTestFragmentedException + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +class ExceptionsTestNonTCPUDP: public ExceptionsTestFixture { + +}; + +/////////////////////////////////////////////////////////////////////////////// +//Classes instances: +static ExceptionsTestNonIpPacket exceptionsTestNonIpPacket; +static ExceptionsTestFragmentedException exceptionsTestFragmentedException; + +/////////////////////////////////////////////////////////////////////////////// +////////////// EOF //////// +/////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/Filtering.cpp b/kernel-tests/Filtering.cpp new file mode 100644 index 0000000000..d42a0a85fb --- /dev/null +++ b/kernel-tests/Filtering.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017,2020 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 "Filtering.h" + +const char* Filtering::DEVICE_NAME = "/dev/ipa"; + +Filtering::Filtering() +{ + fd = open(DEVICE_NAME, O_RDWR); + if (0 == fd) { + printf("Failed opening %s.\n", DEVICE_NAME); + } +} + +Filtering::~Filtering() +{ + close(fd); +} + +bool Filtering::DeviceNodeIsOpened() +{ + return fd; +} + +bool Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const * ruleTable) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE, ruleTable); + if (retval) { + printf("%s(), failed adding Filtering rule table %p\n", __FUNCTION__, ruleTable); + return false; + } + + printf("%s(), Added Filtering rule to table %p\n", __FUNCTION__, ruleTable); + return true; +} + +bool Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule_v2 const * ruleTable) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_V2, ruleTable); + if (retval) { + printf("%s(), failed adding Filtering rule table %p\n", __FUNCTION__, ruleTable); + return false; + } + + printf("%s(), Added Filtering rule to table %p\n", __FUNCTION__, ruleTable); + return true; +} + +bool Filtering::DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_DEL_FLT_RULE, ruleTable); + if (retval) { + printf("%s(), failed deleting Filtering rule in table %p\n", __FUNCTION__, ruleTable); + return false; + } + + printf("%s(), Deleted Filtering rule in table %p\n", __FUNCTION__, ruleTable); + return true; +} + +bool Filtering::Commit(enum ipa_ip_type ip) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_COMMIT_FLT, ip); + if (retval) { + printf("%s(), failed committing Filtering rules.\n", __FUNCTION__); + return false; + } + + printf("%s(), Committed Filtering rules to IPA HW.\n", __FUNCTION__); + return true; +} + +bool Filtering::Reset(enum ipa_ip_type ip) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_RESET_FLT, ip); + retval |= ioctl(fd, IPA_IOC_COMMIT_FLT, ip); + if (retval) { + printf("%s(), failed resetting Filtering block.\n", __FUNCTION__); + return false; + } + + printf("%s(), Reset command issued to IPA Filtering block.\n", __FUNCTION__); + return true; +} + diff --git a/kernel-tests/Filtering.h b/kernel-tests/Filtering.h new file mode 100644 index 0000000000..4cd08695cd --- /dev/null +++ b/kernel-tests/Filtering.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017,2020 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 FILTERING_H_ +#define FILTERING_H_ + +#include +#include "linux/msm_ipa.h" + +class Filtering +{ +public: + Filtering(); + ~Filtering(); + bool AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable); + bool AddFilteringRule(ipa_ioc_add_flt_rule_v2 const *ruleTable); + bool DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable); + bool Commit(enum ipa_ip_type ip); + bool Reset(enum ipa_ip_type ip); + bool DeviceNodeIsOpened(); + +private: + static const char *DEVICE_NAME; + int fd; /*File descriptor of the IPA device node /dev/ipa*/ +}; + +#endif + diff --git a/kernel-tests/FilteringEthernetBridgingTestFixture.cpp b/kernel-tests/FilteringEthernetBridgingTestFixture.cpp new file mode 100644 index 0000000000..715b88aa8f --- /dev/null +++ b/kernel-tests/FilteringEthernetBridgingTestFixture.cpp @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2017 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 "FilteringEthernetBridgingTestFixture.h" + +IpaFilteringEthernetBridgingTestFixture::IpaFilteringEthernetBridgingTestFixture(): + m_sendSize1 (m_BUFF_MAX_SIZE), + m_sendSize2 (m_BUFF_MAX_SIZE), + m_sendSize3 (m_BUFF_MAX_SIZE), + m_IpaIPType(IPA_IP_v4) +{ + memset(m_sendBuffer1, 0, sizeof(m_sendBuffer1)); + memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2)); + memset(m_sendBuffer3, 0, sizeof(m_sendBuffer3)); + m_testSuiteName.push_back("FilteringEth"); +} + +bool IpaFilteringEthernetBridgingTestFixture::Setup() +{ + ConfigureScenario(PHASE_TWO_TEST_CONFIGURATION); + + m_producer.Open(INTERFACE0_TO_IPA_DATA_PATH, INTERFACE0_FROM_IPA_DATA_PATH); + m_producer2.Open(INTERFACE4_TO_IPA_DATA_PATH, INTERFACE4_FROM_IPA_DATA_PATH); + + m_consumer.Open(INTERFACE1_TO_IPA_DATA_PATH, INTERFACE1_FROM_IPA_DATA_PATH); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); + m_routing.Reset(IPA_IP_v6); + return true; +} // Setup() + +bool IpaFilteringEthernetBridgingTestFixture::Teardown() +{ + m_producer.Close(); + m_producer2.Close(); + m_consumer.Close(); + m_consumer2.Close(); + m_defaultConsumer.Close(); + return true; +} // Teardown() + +bool IpaFilteringEthernetBridgingTestFixture::LoadFiles(enum ipa_ip_type ip) +{ + if (!LoadDefaultEth2Packet(ip, m_sendBuffer1, m_sendSize1)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + LOG_MSG_DEBUG ("Loaded %zu Bytes to Buffer 1\n",m_sendSize1); + + if (!LoadDefaultEth2Packet(ip, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + LOG_MSG_DEBUG ("Loaded %zu Bytes to Buffer 2\n",m_sendSize2); + + if (!LoadDefaultEth2Packet(ip, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + LOG_MSG_DEBUG ("Loaded %zu Bytes to Buffer 3\n",m_sendSize3); + + return true; +} + +bool IpaFilteringEthernetBridgingTestFixture::ReceivePacketsAndCompare() +{ + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[m_BUFF_MAX_SIZE]; + Byte *rxBuff2 = new Byte[m_BUFF_MAX_SIZE]; + Byte *rxBuff3 = new Byte[m_BUFF_MAX_SIZE]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, + m_BUFF_MAX_SIZE); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", + receivedSize, + m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, + m_BUFF_MAX_SIZE); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", + receivedSize2, + m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, + m_BUFF_MAX_SIZE); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", + receivedSize3, + m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden(m_sendBuffer1, + m_sendSize1, + rxBuff1, + receivedSize)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!"); + isSuccess = false; + } + + char recievedBuffer[256] = {0}; + char SentBuffer[256] = {0}; + + size_t j; + for(j = 0; j < m_sendSize1; j++) + snprintf(&SentBuffer[3*j], sizeof(SentBuffer) - (3*j + 1), " %02X", m_sendBuffer1[j]); + for(j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3*j], sizeof(recievedBuffer) - (3*j + 1), " %02X", rxBuff1[j]); + printf("Expected Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", + m_sendSize1,SentBuffer,receivedSize,recievedBuffer); + recievedBuffer[0] = 0; + + for(j = 0; j < m_sendSize2; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3*j + 1), " %02X", m_sendBuffer2[j]); + for(j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer[3*j], sizeof(recievedBuffer) - (3*j + 1), " %02X", rxBuff2[j]); + printf("Expected Value2 (%zu)\n%s\n, Received Value2(%zu)\n%s\n", + m_sendSize2,SentBuffer,receivedSize2,recievedBuffer); + recievedBuffer[0] = 0; + + for(j = 0; j < m_sendSize3; j++) + snprintf(&SentBuffer[3*j], sizeof(SentBuffer) - (3*j + 1), " %02X", m_sendBuffer3[j]); + for(j = 0; j < receivedSize3; j++) + snprintf(&recievedBuffer[3*j], sizeof(recievedBuffer) - (3*j + 1), " %02X", rxBuff3[j]); + printf("Expected Value3 (%zu)\n%s\n, Received Value3(%zu)\n%s\n", + m_sendSize3,SentBuffer,receivedSize3,recievedBuffer); + recievedBuffer[0] = 0; + + isSuccess &= CompareResultVsGolden(m_sendBuffer2, + m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden(m_sendBuffer3, + m_sendSize3, rxBuff3, receivedSize3); + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; +} + +// This function creates three IPv4 bypass routing entries and commits them. +bool IpaFilteringEthernetBridgingTestFixture::CreateThreeIPv4BypassRoutingTables(const char *bypass0, const char *bypass1, + const char *bypass2) +{ + LOG_MSG_DEBUG("Entering"); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0,*rt_rule2 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_rule0) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule0"); + return false; + } + rt_rule1 = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_rule1) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule1"); + Free(rt_rule0); + return false; + } + rt_rule2 = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_rule2) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule2"); + Free(rt_rule0); + Free(rt_rule1); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v4; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule0) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + rt_rule1->num_rules = 1; + rt_rule1->ip = IPA_IP_v4; + rt_rule1->commit = true; + strlcpy(rt_rule1->rt_tbl_name, bypass1, sizeof(rt_rule1->rt_tbl_name)); + rt_rule_entry = &rt_rule1->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule1)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule1) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + rt_rule2->num_rules = 1; + rt_rule2->ip = IPA_IP_v4; + rt_rule2->commit = true; + strlcpy(rt_rule2->rt_tbl_name, bypass2, sizeof(rt_rule2->rt_tbl_name)); + rt_rule_entry = &rt_rule2->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule2)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule2)\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + LOG_MSG_DEBUG("Leaving"); + return true; +} + +// This function creates three IPv6 bypass routing entries and commits them. +bool IpaFilteringEthernetBridgingTestFixture::CreateThreeIPv6BypassRoutingTables (const char *bypass0, const char *bypass1, + const char *bypass2) +{ + LOG_MSG_DEBUG("Entering"); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0, + *rt_rule2 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1,sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_rule0) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule0\n"); + return false; + } + rt_rule1 = (struct ipa_ioc_add_rt_rule *) + calloc(1,sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_rule1) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule1\n"); + Free(rt_rule0); + return false; + } + rt_rule2 = (struct ipa_ioc_add_rt_rule *) + calloc(1,sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_rule2) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule2\n"); + Free(rt_rule0); + Free(rt_rule1); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v6; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule0)"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + rt_rule1->num_rules = 1; + rt_rule1->ip = IPA_IP_v6; + rt_rule1->commit = true; + strlcpy(rt_rule1->rt_tbl_name, bypass1, sizeof(rt_rule1->rt_tbl_name)); + rt_rule_entry = &rt_rule1->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule1)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule1)"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + rt_rule2->num_rules = 1; + rt_rule2->ip = IPA_IP_v6; + rt_rule2->commit = true; + strlcpy(rt_rule2->rt_tbl_name, bypass2, sizeof(rt_rule2->rt_tbl_name)); + rt_rule_entry = &rt_rule2->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule2)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule2)"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + LOG_MSG_DEBUG("Leaving function\n"); + return true; +} + +bool IpaFilteringEthernetBridgingTestFixture::Run() +{ + bool res = false; + bool isSuccess = false; + + LOG_MSG_DEBUG("Entering"); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + LOG_MSG_ERROR("Failed adding filtering rules"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + LOG_MSG_ERROR("Failed loading files"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + LOG_MSG_ERROR("Failed to modify packets"); + return false; + } + + // Send first packet + isSuccess = m_pCurrentProducer->SendData(m_sendBuffer1, + m_sendSize1); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure"); + return false; + } + + // Send second packet + isSuccess = m_pCurrentProducer->SendData(m_sendBuffer2, + m_sendSize2); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure"); + return false; + } + + // Send third packet + isSuccess = m_pCurrentProducer->SendData(m_sendBuffer3, + m_sendSize3); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + LOG_MSG_DEBUG("Leaving function returning %d", isSuccess); + + return isSuccess; +} // Run() + + +IpaFilteringEthernetBridgingTestFixture::~IpaFilteringEthernetBridgingTestFixture() +{ + m_sendSize1 = 0; + m_sendSize2 = 0; + m_sendSize3 = 0; +} + +static const size_t m_BUFF_MAX_SIZE = 1024; +static Filtering m_filtering; +static RoutingDriverWrapper m_routing; + +InterfaceAbstraction m_producer; +InterfaceAbstraction m_producer2; // Pipe with ETH2 header removal +InterfaceAbstraction *m_pCurrentProducer; +InterfaceAbstraction m_consumer; +InterfaceAbstraction m_consumer2; +InterfaceAbstraction m_defaultConsumer; + +Byte m_sendBuffer1[m_BUFF_MAX_SIZE]; +Byte m_sendBuffer2[m_BUFF_MAX_SIZE]; +Byte m_sendBuffer3[m_BUFF_MAX_SIZE]; +size_t m_sendSize1; +size_t m_sendSize2; +size_t m_sendSize3; +enum ipa_ip_type m_IpaIPType; + +RoutingDriverWrapper IpaFilteringEthernetBridgingTestFixture::m_routing; +Filtering IpaFilteringEthernetBridgingTestFixture::m_filtering; + +const uint8_t IpaFilteringEthernetBridgingTestFixture::m_ETH2_DST_ADDR[ETH_ALEN] = +{ + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11 +}; + +const uint8_t IpaFilteringEthernetBridgingTestFixture::m_ETH2_SRC_ADDR[ETH_ALEN] = +{ + 0x22, 0xee, 0xdd, 0xcc, 0xbb, 0xaa +}; + +const uint8_t IpaFilteringEthernetBridgingTestFixture::m_MAC_ADDR_MASK_ALL[ETH_ALEN] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + diff --git a/kernel-tests/FilteringEthernetBridgingTestFixture.h b/kernel-tests/FilteringEthernetBridgingTestFixture.h new file mode 100644 index 0000000000..b7340e8abb --- /dev/null +++ b/kernel-tests/FilteringEthernetBridgingTestFixture.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017 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 "Filtering.h" +#include "RoutingDriverWrapper.h" +#include "IPAFilteringTable.h" + +#define IPV4_DST_ADDR_OFFSET (16) +#define IPV4_SRC_PORT_OFFSET (20) +#define IPV4_DST_PORT_OFFSET (20+2) + +#define DST_ADDR_LSB_OFFSET_IPV4 (19) +#define DST_ADDR_LSB_OFFSET_IPV6 (39) + +class IpaFilteringEthernetBridgingTestFixture : public TestBase +{ +public: + virtual bool ModifyPackets() = 0; + virtual bool AddRules() = 0; + + IpaFilteringEthernetBridgingTestFixture(); + + bool Setup(); + + bool Teardown(); + + virtual bool LoadFiles(enum ipa_ip_type ip); + + bool ReceivePacketsAndCompare(); + + // This function creates three IPv4 bypass routing entries and commits them. + bool CreateThreeIPv4BypassRoutingTables (const char *bypass0, const char *bypass1, + const char *bypass2); + + // This function creates three IPv6 bypass routing entries and commits them. + bool CreateThreeIPv6BypassRoutingTables (const char *bypass0, const char *bypass1, + const char *bypass2); + + bool Run(); + + ~IpaFilteringEthernetBridgingTestFixture(); + + static const size_t m_BUFF_MAX_SIZE = 1024; + static const uint8_t m_ETH2_DST_ADDR[ETH_ALEN]; + static const uint8_t m_ETH2_SRC_ADDR[ETH_ALEN]; + static const uint8_t m_MAC_ADDR_MASK_ALL[ETH_ALEN]; + static Filtering m_filtering; + static RoutingDriverWrapper m_routing; + + InterfaceAbstraction m_producer; + InterfaceAbstraction m_producer2; // Pipe with ETH2 header removal + InterfaceAbstraction *m_pCurrentProducer; + InterfaceAbstraction m_consumer; + InterfaceAbstraction m_consumer2; + InterfaceAbstraction m_defaultConsumer; + + Byte m_sendBuffer1[m_BUFF_MAX_SIZE]; + Byte m_sendBuffer2[m_BUFF_MAX_SIZE]; + Byte m_sendBuffer3[m_BUFF_MAX_SIZE]; + size_t m_sendSize1; + size_t m_sendSize2; + size_t m_sendSize3; + enum ipa_ip_type m_IpaIPType; + +private: +}; + diff --git a/kernel-tests/FilteringEthernetBridgingTests.cpp b/kernel-tests/FilteringEthernetBridgingTests.cpp new file mode 100644 index 0000000000..9f01a946ed --- /dev/null +++ b/kernel-tests/FilteringEthernetBridgingTests.cpp @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2017 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 "FilteringEthernetBridgingTestFixture.h" + +/*---------------------------------------------------------------------------*/ +/* Test 00: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilterEthIPv4Test00 : public IpaFilteringEthernetBridgingTestFixture +{ +public: + IpaFilterEthIPv4Test00() + { + m_name = "IpaFilterEthIPv4Test00"; + m_description = + "Filtering block test 01 - Ethernet Bridge, ETH2 filters, \ + IPv4 address (EP Filtering Table, \ + Insert all rules in a single commit) \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule \ + (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit 3 ETH2 filtering rules: \ + All MAC DST == (aabbccddee11) traffic goes to routing table 0 \ + All MAC SRC == (22eeddccbbaa) traffic goes to routing table 1 \ + All (1) traffic goes to routing table 2"; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + Register(*this); + m_pCurrentProducer = &m_producer2; + } + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering"); + + const char bypass0[] = "bypass0"; + const char bypass1[] = "bypass1"; + const char bypass2[] = "bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeIPv4BypassRoutingTables"); + return false; + } + + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table0=0x%p)", + &routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table1=0x%p)", + &routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table2=0x%p)", + &routing_table2); + return false; + } + + // Create 3 filter rules + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST2_PROD,false,3); + + // Configuring Filtering Rule 0 - ETH2 DST + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.retain_hdr = 1; // retain header removed in producer pipe + flt_rule_entry.flt_rule_hdl = -1; // return value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; // Handle corresponding to routing table 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_DST_ADDR_ETHER_II; // Filter using ETH2 DST address + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr_mask, + m_MAC_ADDR_MASK_ALL, + sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask)); // ETH2 DST address mask + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, + m_ETH2_DST_ADDR, + sizeof(flt_rule_entry.rule.attrib.dst_mac_addr)); // ETH2 DST address + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(0) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule 1 - ETH2 SRC + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; // Handle corresponding to routing table 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_SRC_ADDR_ETHER_II; // Filter using ETH2 SRC address + memcpy(flt_rule_entry.rule.attrib.src_mac_addr_mask, + m_MAC_ADDR_MASK_ALL, + sizeof(flt_rule_entry.rule.attrib.src_mac_addr_mask)); // ETH2 SRC address mask + memcpy(flt_rule_entry.rule.attrib.src_mac_addr, + m_ETH2_SRC_ADDR, + sizeof(flt_rule_entry.rule.attrib.src_mac_addr)); // ETH2 SRC address + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(1) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule 2 - Accept all + flt_rule_entry.rule.rt_tbl_hdl = routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Accept all + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; // Has no effect + if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + LOG_MSG_ERROR ("Adding RuleTable(2) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(2)->status); + } + LOG_MSG_DEBUG("Leaving function\n"); + return true; + + }// AddRules() + + virtual bool ModifyPackets() + { + memcpy(&m_sendBuffer1[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + + memcpy(&m_sendBuffer2[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + m_sendBuffer2[ETH2_DST_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer2[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + + // swap destination and source addresses so that both + // rule0 and rule1 are miss and rule2 (accept all) is hit + memcpy(&m_sendBuffer3[ETH2_DST_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer3[ETH2_SRC_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test 01: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilterEthIPv4Test01 : public IpaFilteringEthernetBridgingTestFixture +{ +public: + IpaFilterEthIPv4Test01() + { + m_name = "IpaFilterEthIPv4Test01"; + m_description = + "Filtering block test 01 - Ethernet Bridge, ETH2 filters, \ + IPv4 address (EP Filtering Table, \ + Insert all rules in a single commit) \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule \ + (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit 3 ETH2 filtering rules: \ + All MAC DST == (aabbccddee11) traffic goes to routing table 0 \ + All MAC ETH TYPE == (0800) traffic goes to routing table 1 \ + All (1) traffic goes to routing table 2"; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + Register(*this); + m_pCurrentProducer = &m_producer2; + } + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering"); + + const char bypass0[] = "bypass0"; + const char bypass1[] = "bypass1"; + const char bypass2[] = "bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeIPv4BypassRoutingTables"); + return false; + } + + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table0=0x%p)", + &routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p)", + &routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table2=0x%p)", + &routing_table2); + return false; + } + + // Create 3 filter rules + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST2_PROD,false,3); + + // Configuring Filtering Rule 0 - ETH2 DST + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.retain_hdr = 1; // retain header removed in producer pipe + flt_rule_entry.flt_rule_hdl = -1; // return value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + + // DST + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_DST_ADDR_ETHER_II; + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr_mask, + m_MAC_ADDR_MASK_ALL, + sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask)); + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, + m_ETH2_DST_ADDR, + sizeof(flt_rule_entry.rule.attrib.dst_mac_addr)); + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(0) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule 1 - ETH2 type + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_ETHER_TYPE; + flt_rule_entry.rule.attrib.ether_type = ETH_P_IP; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(1) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule 2 - Accept all + flt_rule_entry.rule.rt_tbl_hdl = routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Accept all + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; // Has no effect + if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + LOG_MSG_ERROR ("Adding RuleTable(2) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(2)->status); + } + LOG_MSG_DEBUG("Leaving function\n"); + return true; + + }// AddRules() + + virtual bool ModifyPackets() + { + uint16_t ether_type = ETH_P_IP; + uint16_t wrong_ether_type = 0x1234; + + // DST && SRC correct + memcpy(&m_sendBuffer1[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer1[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + + // DST is wrong, ETH2 type is correct + memcpy(&m_sendBuffer2[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + m_sendBuffer2[ETH2_DST_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer2[ETH2_ETH_TYPE_OFFSET], + ðer_type, sizeof(ether_type)); + + // DST is wrong, ETH2 type is wrong + memcpy(&m_sendBuffer3[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + m_sendBuffer3[ETH2_DST_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer3[ETH2_ETH_TYPE_OFFSET], + &wrong_ether_type, sizeof(wrong_ether_type)); + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test 02: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilterEthIPv4Test02 : public IpaFilteringEthernetBridgingTestFixture +{ +public: + IpaFilterEthIPv4Test02() + { + m_name = "IpaFilterEthIPv4Test02"; + m_description = + "Filtering block test 02 - Ethernet Bridge, ETH2 filters, \ + IPv4 address (EP Filtering Table, \ + Insert all rules in a single commit) \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule \ + (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit 3 ETH2 filtering rules: \ + All MAC SRC == (22eeddccbbaa) traffic goes to routing table 0 \ + All MAC ETH TYPE == (0801) traffic goes to routing table 1 \ + All (1) traffic goes to routing table 2"; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + Register(*this); + m_pCurrentProducer = &m_producer2; + } + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering"); + + const char bypass0[] = "bypass0"; + const char bypass1[] = "bypass1"; + const char bypass2[] = "bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeIPv4BypassRoutingTables"); + return false; + } + + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table0=0x%p)", + &routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p)", + &routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table2=0x%p)", + &routing_table2); + return false; + } + + // Create 3 filter rules + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST2_PROD,false,3); + + // Configuring Filtering Rule 0 - ETH2 SRC + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.retain_hdr = 1; // retain header removed in producer pipe + flt_rule_entry.flt_rule_hdl = -1; // return value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_SRC_ADDR_ETHER_II; + memcpy(flt_rule_entry.rule.attrib.src_mac_addr_mask, + m_MAC_ADDR_MASK_ALL, + sizeof(flt_rule_entry.rule.attrib.src_mac_addr_mask)); + memcpy(flt_rule_entry.rule.attrib.src_mac_addr, + m_ETH2_SRC_ADDR, + sizeof(flt_rule_entry.rule.attrib.src_mac_addr)); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(0) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule 1 - ETH2 type + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_ETHER_TYPE; + flt_rule_entry.rule.attrib.ether_type = ETH_P_IP + 1; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(1) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule 2 - Accept all + flt_rule_entry.rule.rt_tbl_hdl = routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Accept all + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; // Has no effect + if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + LOG_MSG_ERROR ("Adding RuleTable(2) to Filtering"); + return false; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x", + FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(2)->status); + } + LOG_MSG_DEBUG("Leaving function\n"); + return true; + + }// AddRules() + + virtual bool ModifyPackets() + { + uint16_t ether_type = ETH_P_IP; + uint16_t wrong_ether_type = 0x1234; + + memcpy(&m_sendBuffer1[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer1[ETH2_ETH_TYPE_OFFSET], + ðer_type, sizeof(ether_type)); + + memcpy(&m_sendBuffer2[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + m_sendBuffer2[ETH2_SRC_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer2[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + ether_type++; + memcpy(&m_sendBuffer2[ETH2_ETH_TYPE_OFFSET], + ðer_type, sizeof(ether_type)); + + memcpy(&m_sendBuffer3[ETH2_DST_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer3[ETH2_SRC_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer3[ETH2_ETH_TYPE_OFFSET], + &wrong_ether_type, sizeof(wrong_ether_type)); + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test 03: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilterEthIPv4Test03 : public IpaFilteringEthernetBridgingTestFixture +{ +public: + IpaFilterEthIPv4Test03() + { + m_name = "IpaFilterEthIPv4Test03"; + m_description = + "Filtering block test 03 - Ethernet Bridge, ETH2 filters, \ + IPv4 address (EP Filtering Table, \ + Insert all rules in a single commit) \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule \ + (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit 3 ETH2 filtering rules: \ + All MAC SRC == (22eeddccbbaa) traffic goes to routing table 0 \ + All MAC ETH TYPE == (0800) traffic goes to routing table 1 \ + All (1) traffic goes to routing table 2"; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + Register(*this); + m_pCurrentProducer = &m_producer2; + } + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering"); + + const char bypass0[] = "bypass0"; + const char bypass1[] = "bypass1"; + const char bypass2[] = "bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeIPv4BypassRoutingTables"); + return false; + } + + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table0=0x%p)", + &routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p)", + &routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&routing_table2=0x%p)", + &routing_table2); + return false; + } + + // Create 3 filter rules + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST2_PROD,false,3); + + // Configuring Filtering Rule 0 - ETH2 DST + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.retain_hdr = 1; // retain header removed in producer pipe + flt_rule_entry.flt_rule_hdl = -1; // return value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + + // SRC + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_SRC_ADDR_ETHER_II; + memcpy(flt_rule_entry.rule.attrib.src_mac_addr_mask, + m_MAC_ADDR_MASK_ALL, + sizeof(flt_rule_entry.rule.attrib.src_mac_addr_mask)); + memcpy(flt_rule_entry.rule.attrib.src_mac_addr, + m_ETH2_SRC_ADDR, + sizeof(flt_rule_entry.rule.attrib.src_mac_addr)); + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(0) to Filtering"); + return false; + } + + // Configuring Filtering Rule 1 - ETH2 type + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_MAC_ETHER_TYPE; + flt_rule_entry.rule.attrib.ether_type = ETH_P_IP; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR ("Adding RuleTable(1) to Filtering"); + return false; + } + + // Configuring Filtering Rule 2 - Accept all + flt_rule_entry.rule.rt_tbl_hdl = routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Accept all + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; // Has no effect + if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + LOG_MSG_ERROR ("Adding RuleTable(2) to Filtering"); + return false; + } + + LOG_MSG_DEBUG("flt rule status: s0=0x%x, s1=0x%x s2=0x%x", + FilterTable0.ReadRuleFromTable(0)->status, + FilterTable0.ReadRuleFromTable(1)->status, + FilterTable0.ReadRuleFromTable(2)->status); + + LOG_MSG_DEBUG("Leaving function\n"); + return true; + + }// AddRules() + + virtual bool ModifyPackets() + { + uint16_t ether_type = ETH_P_IP; + uint16_t wrong_ether_type = 0x1234; + + // SRC correct, DST wrong, ETH type wrong + memcpy(&m_sendBuffer1[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer1[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + m_sendBuffer1[ETH2_DST_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer1[ETH2_ETH_TYPE_OFFSET], + &wrong_ether_type, sizeof(wrong_ether_type)); + + // SRC wrong, DST wrong, ETH type correct + memcpy(&m_sendBuffer2[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + m_sendBuffer2[ETH2_SRC_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer2[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + m_sendBuffer2[ETH2_DST_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer2[ETH2_ETH_TYPE_OFFSET], + ðer_type, sizeof(ether_type)); + + // SRC wrong, DST correct, ETH type wrong + memcpy(&m_sendBuffer3[ETH2_SRC_ADDR_OFFSET], + m_ETH2_SRC_ADDR, ETH_ALEN); + m_sendBuffer3[ETH2_SRC_ADDR_OFFSET] = 0x00; + memcpy(&m_sendBuffer3[ETH2_DST_ADDR_OFFSET], + m_ETH2_DST_ADDR, ETH_ALEN); + memcpy(&m_sendBuffer3[ETH2_ETH_TYPE_OFFSET], + &wrong_ether_type, sizeof(wrong_ether_type)); + + return true; + }// ModifyPacktes () +}; + +static IpaFilterEthIPv4Test00 ipaFilterEthIPv4Test00; +static IpaFilterEthIPv4Test01 ipaFilterEthIPv4Test01; +static IpaFilterEthIPv4Test02 ipaFilterEthIPv4Test02; +static IpaFilterEthIPv4Test03 ipaFilterEthIPv4Test03; diff --git a/kernel-tests/FilteringTest.cpp b/kernel-tests/FilteringTest.cpp new file mode 100644 index 0000000000..91ddc43bfa --- /dev/null +++ b/kernel-tests/FilteringTest.cpp @@ -0,0 +1,8585 @@ +/* + * Copyright (c) 2017-2020 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 "Filtering.h" +#include "RoutingDriverWrapper.h" +#include "IPAFilteringTable.h" + +//TODO Add Enum for IP/TCP/UDP Fields + +#define IP4_TOS_FIELD_OFFSET (1) +#define IPV4_PROTOCOL_OFFSET (9) +#define IPV6_NEXT_HDR_OFFSET (6) +#define IPV4_SRC_ADDR_OFFSET (12) +#define IPV4_DST_ADDR_OFFSET (16) +#define IPV4_SRC_PORT_OFFSET (20) +#define IPV4_DST_PORT_OFFSET (20+2) +#define IPV6_SRC_PORT_OFFSET (40) +#define IPV6_DST_PORT_OFFSET (40+2) + +#define DST_ADDR_LSB_OFFSET_IPV4 (19) +#define DST_ADDR_LSB_OFFSET_IPV6 (39) + +#define IPV4_FRAGMENT_FLAGS_OFFSET (6) +#define IPV6_FRAGMENT_FLAGS_OFFSET (42) +#define IPV6_FRAGMENT_NEXT_HDR_OFFSET (40) + +#define IPv4_TCP_FLAGS_OFFSET (20+13) +#define TCP_ACK_FLAG_MASK (0x10) + +#define TAG_802_1Q_OFFSET (12) + +extern Logger g_Logger; + +class IpaFilteringBlockTestFixture : public TestBase +{ +public: + + IpaFilteringBlockTestFixture(): + m_sendSize (BUFF_MAX_SIZE), + m_sendSize2 (BUFF_MAX_SIZE), + m_sendSize3 (BUFF_MAX_SIZE), + m_IpaIPType(IPA_IP_v4), + m_extHdrType(NONE) + { + memset(m_sendBuffer, 0, sizeof(m_sendBuffer)); // First input file / IP packet + memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2)); // Second input file / IP packet + memset(m_sendBuffer3, 0, sizeof(m_sendBuffer3)); // Third input file (default) / IP packet + m_testSuiteName.push_back("Filtering"); + } + + static int SetupKernelModule(bool en_status = 0) + { + int retval; + struct ipa_channel_config from_ipa_channels[3]; + struct test_ipa_ep_cfg from_ipa_cfg[3]; + struct ipa_channel_config to_ipa_channels[2]; + struct test_ipa_ep_cfg to_ipa_cfg[2]; + + struct ipa_test_config_header header = {0}; + struct ipa_channel_config *to_ipa_array[2]; + struct ipa_channel_config *from_ipa_array[3]; + + /* From ipa configurations - 3 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0])); + prepare_channel_struct(&from_ipa_channels[0], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[0], + sizeof(from_ipa_cfg[0]), + en_status); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST3_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1]), + en_status); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2]), + en_status); + from_ipa_array[2] = &from_ipa_channels[2]; + + /* To ipa configurations - 1 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + 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]; + + /* header removal for Ethernet header + 8021Q header */ + memset(&to_ipa_cfg[1], 0, sizeof(to_ipa_cfg[1])); + to_ipa_cfg[1].hdr.hdr_len = ETH8021Q_HEADER_LEN; + to_ipa_cfg[1].hdr.hdr_ofst_metadata_valid = 1; + to_ipa_cfg[1].hdr.hdr_ofst_metadata = + ETH8021Q_METADATA_OFFSET; + prepare_channel_struct(&to_ipa_channels[1], + header.to_ipa_channels_num++, + IPA_CLIENT_TEST2_PROD, + (void *)&to_ipa_cfg[1], + sizeof(to_ipa_cfg[1])); + to_ipa_array[1] = &to_ipa_channels[1]; + + prepare_header_struct(&header, from_ipa_array, to_ipa_array); + + retval = GenericConfigureScenario(&header); + + return retval; + } + + bool Setup() + { + bool bRetVal = true; + + if (SetupKernelModule() != true) + return bRetVal; + + m_producer.Open(INTERFACE0_TO_IPA_DATA_PATH, INTERFACE0_FROM_IPA_DATA_PATH); + m_producer2.Open(INTERFACE4_TO_IPA_DATA_PATH, INTERFACE4_FROM_IPA_DATA_PATH); + + m_consumer.Open(INTERFACE1_TO_IPA_DATA_PATH, INTERFACE1_FROM_IPA_DATA_PATH); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) + { + printf("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + printf("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); // This will issue a Reset command to the Filtering as well + m_routing.Reset(IPA_IP_v6); // This will issue a Reset command to the Filtering as well + return true; + } // Setup() + + bool Setup(bool en_status = false) + { + bool bRetVal = true; + + if (SetupKernelModule(en_status) != true) + return bRetVal; + + 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); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) + { + printf("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + printf("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); // This will issue a Reset command to the Filtering as well + m_routing.Reset(IPA_IP_v6); // This will issue a Reset command to the Filtering as well + return true; + } // Setup() + + bool Teardown() + { + m_producer.Close(); + m_producer2.Close(); + m_consumer.Close(); + m_consumer2.Close(); + m_defaultConsumer.Close(); + return true; + } // Teardown() + + virtual bool LoadFiles(enum ipa_ip_type ip) + { + string fileName; + + if (IPA_IP_v4 == ip) { + fileName = "Input/IPv4_1"; + } else { + fileName = "Input/IPv6"; + } + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to Buffer 1\n",m_sendSize); + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to Buffer 2\n",m_sendSize2); + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to Buffer 3\n",m_sendSize3); + + return true; + } + + inline bool VerifyStatusReceived(size_t SendSize, size_t RecvSize) + { + size_t stts_size = sizeof(struct ipa3_hw_pkt_status); + + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) { + stts_size = sizeof(struct ipa3_hw_pkt_status_hw_v5_0); + } + + if ((RecvSize <= SendSize) || + ((RecvSize - SendSize) != stts_size)){ + printf("received buffer size does not match! sent:receive [%zu]:[%zu]\n",SendSize,RecvSize); + return false; + } + + return true; + } + + inline bool IsCacheHit(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status *pStatus = (struct ipa3_hw_pkt_status *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if((bool)pStatus->filt_hash){ + printf ("%s::cache hit!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache miss!! \n",__FUNCTION__); + return false; + } + + inline bool IsCacheHit_v5_0(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status_hw_v5_0 *pStatus = (struct ipa3_hw_pkt_status_hw_v5_0 *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if((bool)pStatus->filt_hash){ + printf ("%s::cache hit!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache miss!! \n",__FUNCTION__); + return false; + } + + inline bool IsCacheMiss(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status *pStatus = (struct ipa3_hw_pkt_status *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if(!((bool)pStatus->filt_hash)){ + printf ("%s::cache miss!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache hit!! \n",__FUNCTION__); + return false; + } + + inline bool IsCacheMiss_v5_0(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status_hw_v5_0 *pStatus = (struct ipa3_hw_pkt_status_hw_v5_0 *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if(!((bool)pStatus->filt_hash)){ + printf ("%s::cache miss!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache hit!! \n",__FUNCTION__); + return false; + } + + + bool ReceivePacketAndCompareFrom(InterfaceAbstraction& cons, Byte* send, + size_t send_sz, bool shouldBeHit) + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = cons.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, cons.m_fromChannelName.c_str()); + + // Compare results + isSuccess &= CompareResultVsGolden_w_Status(send, send_sz, rxBuff1, receivedSize); + + if (shouldBeHit) { + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(send_sz, receivedSize, rxBuff1) : IsCacheHit(send_sz, receivedSize, rxBuff1); + } + else + { + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(send_sz, receivedSize, rxBuff1) : IsCacheMiss(send_sz, receivedSize, rxBuff1); + } + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + size_t j; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + for(j = 0; j < m_sendSize; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", send[j]); + for(j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff1[j]); + printf("Expected Value (%zu)\n%s\n, Received Value1(%zu)\n%s\n",send_sz,sentBuffer,receivedSize,recievedBuffer); + + delete[] rxBuff1; + delete[] recievedBuffer; + delete[] sentBuffer; + + //receivedSize = excp_cons.ReceiveData(rxBuff1, 0x400); + //printf("Received %zu bytes on %s.\n", receivedSize, excp_cons.m_fromChannelName.c_str()); + + return isSuccess; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool pkt1_cmp_succ, pkt2_cmp_succ, pkt3_cmp_succ; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + memset(rxBuff1, 0, 0x400); + memset(rxBuff2, 0, 0x400); + memset(rxBuff3, 0, 0x400); + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + pkt1_cmp_succ = CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + pkt2_cmp_succ = CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + pkt3_cmp_succ = CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + size_t recievedBufferSize = + MAX3(receivedSize, receivedSize2, receivedSize3) * 3; + size_t sentBufferSize = + MAX3(m_sendSize, m_sendSize2, m_sendSize3) * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + size_t j; + + if (NULL == recievedBuffer || NULL == sentBuffer) { + printf("Memory allocation error\n"); + return false; + } + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + for(j = 0; j < m_sendSize; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", m_sendBuffer[j]); + for(j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff1[j]); + printf("Expected Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n-->Value1 %s\n", + m_sendSize,sentBuffer,receivedSize,recievedBuffer, + pkt1_cmp_succ?"Match":"no Match"); + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + for(j = 0; j < m_sendSize2; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for(j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff2[j]); + printf("Expected Value2 (%zu)\n%s\n, Received Value2(%zu)\n%s\n-->Value2 %s\n", + m_sendSize2,sentBuffer,receivedSize2,recievedBuffer, + pkt2_cmp_succ?"Match":"no Match"); + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + for(j = 0; j < m_sendSize3; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", m_sendBuffer3[j]); + for(j = 0; j < receivedSize3; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff3[j]); + printf("Expected Value3 (%zu)\n%s\n, Received Value3(%zu)\n%s\n-->Value3 %s\n", + m_sendSize3,sentBuffer,receivedSize3,recievedBuffer, + pkt3_cmp_succ?"Match":"no Match"); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return pkt1_cmp_succ && pkt2_cmp_succ && pkt3_cmp_succ; + } + + // This function creates three IPv4 bypass routing entries and commits them. + bool CreateThreeIPv4BypassRoutingTables (const char * bypass0, const char * bypass1, const char * bypass2) + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0,*rt_rule2 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!rt_rule0) { + printf("calloc failed to allocate rt_rule0 in %s\n",__FUNCTION__); + return false; + } + rt_rule1 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!rt_rule1) { + printf("calloc failed to allocate rt_rule1 in %s\n",__FUNCTION__); + Free(rt_rule0); + return false; + } + rt_rule2 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!rt_rule2) { + printf("calloc failed to allocate rt_rule2 in %s\n",__FUNCTION__); + Free(rt_rule0); + Free(rt_rule1); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v4; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS;//Setting + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO Header Inserion - gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + printf("Routing rule addition(rt_rule0) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + rt_rule1->num_rules = 1; + rt_rule1->ip = IPA_IP_v4; + rt_rule1->commit = true; + strlcpy(rt_rule1->rt_tbl_name, bypass1, sizeof(rt_rule1->rt_tbl_name)); + rt_rule_entry = &rt_rule1->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO Header Inserion - gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule1)) + { + printf("Routing rule addition(rt_rule1) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + rt_rule2->num_rules = 1; + rt_rule2->ip = IPA_IP_v4; + rt_rule2->commit = true; + strlcpy(rt_rule2->rt_tbl_name, bypass2, sizeof(rt_rule2->rt_tbl_name)); + rt_rule_entry = &rt_rule2->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO Header Inserion - gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule2)) + { + printf("Routing rule addition(rt_rule2) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + // This function creates three IPv6 bypass routing entries and commits them. + bool CreateThreeIPv6BypassRoutingTables (const char * bypass0, const char * bypass1, const char * bypass2) + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0,*rt_rule2 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!rt_rule0) { + printf("calloc failed to allocate rt_rule0 in %s\n",__FUNCTION__); + return false; + } + rt_rule1 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!rt_rule1) { + printf("calloc failed to allocate rt_rule1 in %s\n",__FUNCTION__); + Free(rt_rule0); + return false; + } + rt_rule2 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!rt_rule2) { + printf("calloc failed to allocate rt_rule2 in %s\n",__FUNCTION__); + Free(rt_rule0); + Free(rt_rule1); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v6; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS;//Setting + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO Header Inserion - gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + printf("Routing rule addition(rt_rule0) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + rt_rule1->num_rules = 1; + rt_rule1->ip = IPA_IP_v6; + rt_rule1->commit = true; + strlcpy(rt_rule1->rt_tbl_name, bypass1, sizeof(rt_rule1->rt_tbl_name)); + rt_rule_entry = &rt_rule1->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO Header Inserion - gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule1)) + { + printf("Routing rule addition(rt_rule1) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + rt_rule2->num_rules = 1; + rt_rule2->ip = IPA_IP_v6; + rt_rule2->commit = true; + strlcpy(rt_rule2->rt_tbl_name, bypass2, sizeof(rt_rule2->rt_tbl_name)); + rt_rule_entry = &rt_rule2->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO Header Inserion - gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule2)) + { + printf("Routing rule addition(rt_rule2) failed!\n"); + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + return false; + } + + + Free (rt_rule2); + Free (rt_rule1); + Free (rt_rule0); + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + bool GetThreeIPv6BypassRoutingTables(uint32_t *Hndl0, uint32_t *Hndl1, uint32_t *Hndl2) + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + *Hndl0 = routing_table0.hdl; + *Hndl1 = routing_table1.hdl; + *Hndl2 = routing_table2.hdl; + + return true; + + } + + void print_packets(size_t receivedSize, size_t m_sendSize, size_t recievedBufferSize, size_t sentBufferSize, Byte *rxBuff, Byte *m_sendBuffer, char *recievedBuffer, char *sentBuffer) + { + size_t j; + + for(j = 0; j < m_sendSize; j++) { + snprintf(&sentBuffer[3 * j], sentBufferSize - 3 * j, + " %02X", m_sendBuffer[j]); + } + for(j = 0; j < receivedSize; j++) { + snprintf(&recievedBuffer[3 * j], recievedBufferSize- 3 * j, + " %02X", rxBuff[j]); + } + printf("Expected Value (%zu)\n%s\n, Received Value(%zu)\n%s\n",m_sendSize,sentBuffer,receivedSize,recievedBuffer); + } + + virtual bool ModifyPackets() = 0; + virtual bool AddRules() = 0; + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__,isSuccess); + + return isSuccess; + } // Run() + + + ~IpaFilteringBlockTestFixture() + { + m_sendSize = 0; + m_sendSize2 = 0; + m_sendSize3 = 0; + } + + static Filtering m_filtering; + static RoutingDriverWrapper m_routing; + InterfaceAbstraction m_producer; + InterfaceAbstraction m_producer2; + InterfaceAbstraction m_consumer; + InterfaceAbstraction m_consumer2; + InterfaceAbstraction m_defaultConsumer; + + static const size_t BUFF_MAX_SIZE = 1024; + + Byte m_sendBuffer[BUFF_MAX_SIZE]; // First input file / IP packet + Byte m_sendBuffer2[BUFF_MAX_SIZE]; // Second input file / IP packet + Byte m_sendBuffer3[BUFF_MAX_SIZE]; // Third input file (default) / IP packet + size_t m_sendSize; + size_t m_sendSize2; + size_t m_sendSize3; + enum ipa_ip_type m_IpaIPType; + enum ipv6_ext_hdr_type m_extHdrType; + +private: +}; + +RoutingDriverWrapper IpaFilteringBlockTestFixture::m_routing; +Filtering IpaFilteringBlockTestFixture::m_filtering; + + +/*---------------------------------------------------------------------------*/ +/* Test001: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest001 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest001() + { + m_name = "IpaFilteringBlockTest001"; + m_description = + "Filtering block test 001 - Destination IP address and subnet mask match against LAN subnet (Global Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 \ + All DST_IP == (192.169.1.1 & 255.0.0.255)traffic goes to routing table 1 \ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.2 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test002: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest002 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest002() + { + m_name = "IpaFilteringBlockTest002"; + m_description = + "Filtering block test 002 - Destination IP address exact match against broadcast IP address (Global Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules (MASK = 0xFF..FF). \ + All DST_IP == 127.0.0.1 traffic goes to routing table 0 \ + All DST_IP == 192.169.1.1 traffic goes to routing table 1 \ + All DST_IP == 192.169.1.2 traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Exact Match + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + + + +/*---------------------------------------------------------------------------*/ +/* Test003: Destination UDP port exact match against DHCP port */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest003 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest003() + { + m_name = "IpaFilteringBlockTest003"; + m_description = + "Filtering block test 003 - Destination UDP port exact match against DHCP port (Global Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All DST_UDP_PORT == 546 (DHCP Client)traffic goes to routing table 0 \ + All DST_UDP_PORT == 547 (DHCP Server) traffic goes to routing table 1 \ + All DST_UDP_PORT == 500 (Non DHCP) traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.dst_port = 546; // DHCP Client Port No 546 + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 547; // DHCP Server Port No 547 + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 500; // Non-DHCP Port + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Port should be switched to Network Mode. + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(547);//DHCP Server Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(500);//Non - DHCP Port + memcpy (&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + return true; + }// ModifyPacktes () +}; + +/*------------------------------------------------------------------------------*/ +/* Test004: Firewall filtering rules based on source and destination port ranges */ +/*------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest004 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest004() + { + m_name = "IpaFilteringBlockTest004"; + m_description = + "Filtering block test 004 - Firewall filtering rules based on source and destination port ranges (Global Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All (5 >= SRC_PORT_RANGE >= 15) & (50 >= DST_PORT_RANGE >= 150) traffic goes to routing table 0 \ + All (15 >= SRC_PORT_RANGE >= 25) & (150 >= DST_PORT_RANGE >= 250) traffic goes to routing table 1 \ + All (25 >= SRC_PORT_RANGE >= 35) & (250 >= DST_PORT_RANGE >= 350) traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_PORT_RANGE | IPA_FLT_DST_PORT_RANGE; + //TODO: Fix from here..... + flt_rule_entry.rule.attrib.src_port_lo =5; + flt_rule_entry.rule.attrib.src_port_hi =15; + flt_rule_entry.rule.attrib.dst_port_lo =50; + flt_rule_entry.rule.attrib.dst_port_hi =150; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 15; + flt_rule_entry.rule.attrib.src_port_hi = 25; + flt_rule_entry.rule.attrib.dst_port_lo = 150; + flt_rule_entry.rule.attrib.dst_port_hi = 250; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 25; + flt_rule_entry.rule.attrib.src_port_hi = 35; + flt_rule_entry.rule.attrib.dst_port_lo = 250; + flt_rule_entry.rule.attrib.dst_port_hi = 350; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + port = htons(10); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(100); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(20); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(200); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(30); + memcpy(&m_sendBuffer3[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(300); + memcpy(&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; +/*---------------------------------------------------------------------------*/ +/* Test005: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest005 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest005() + { + m_name = "IpaFilteringBlockTest005"; + m_description = + "Filtering block test 005 - Filtering Based on Protocol type (TCP/UDP/ICMP) (Global Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All UDP traffic goes to routing table 0 \ + All TCP traffic goes to routing table 1 \ + All ICMP traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit two routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0 and 1 (accordingly)) +// 2. Generate and commit two filtering rules. +// All UDP traffic goes to routing table 1 +// All TCP traffic goes to routing table 2 + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name,bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = 17; // Filter only UDP Packets. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 6; // Filter only TCP Packets. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 1; // Filter only ICMP Packets. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + m_sendBuffer[IPV4_PROTOCOL_OFFSET] = 0x11;// UDP 0x11 = 17 + m_sendBuffer2[IPV4_PROTOCOL_OFFSET] = 0x06;// TCP 0x06 = 6 + m_sendBuffer3[IPV4_PROTOCOL_OFFSET] = 0x01;// ICMP 0x01 = 1 + return true; + }// ModifyPacktes () +}; + + +/*---------------------------------------------------------------------------*/ +/* Test006: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest006 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest006() + { + m_name = "IpaFilteringBlockTest006"; + m_description = + "Filtering block test 006 - Destination IP address and subnet mask match against LAN subnet (Global Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 \ + All DST_IP == (192.169.1.1 & 255.0.0.255)traffic goes to routing table 1 \ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test007: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest007 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest007() + { + m_name = "IpaFilteringBlockTest007"; + m_description = + "Filtering block test 007 - Destination IP address exact match against broadcast IP address (Global Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules (MASK = 0xFF..FF). \ + All DST_IP == 127.0.0.1 traffic goes to routing table 0 \ + All DST_IP == 192.169.1.1 traffic goes to routing table 1 \ + All DST_IP == 192.169.1.2 traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + // Test Description: + // 1. Generate and commit three routing tables. + // Each table will contain a single "bypass" rule (all data goes to output pipe 0, 1 and 2(accordingly)) + // 2. Generate and commit three filtering rules (each in different Filtering Table) + // All Filter DST_IP == 127.0.0.1 traffic goes to routing table 1 + // All Filter DST_IP == 192.168.1.1 traffic goes to routing table 2 + // All Filter DST_IP == 192.168.1.2 traffic goes to routing table 3 + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2,sizeof(routing_table2.name) ); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Exact Match + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + + + +/*---------------------------------------------------------------------------*/ +/* Test008: Destination UDP port exact match against DHCP port */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest008 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest008() + { + m_name = "IpaFilteringBlockTest008"; + m_description = + "Filtering block test 008 - Destination UDP port exact match against DHCP port (Global Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All DST_UDP_PORT == 546 (DHCP Client)traffic goes to routing table 0 \ + All DST_UDP_PORT == 547 (DHCP Server) traffic goes to routing table 1 \ + All DST_UDP_PORT == 500 (Non DHCP) traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit three routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) +// 2. Generate and commit Three filtering rules. +// All DEST_IP == 127.0.0.1 traffic goes to routing table 0 +// All DEST_IP == 192.169.1.1 traffic goes to routing table 1 +// Non Matching traffic goes to routing table 3 + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.dst_port = 546; // DHCP Client Port No 546 + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 547; // DHCP Server Port No 547 + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 500; // Non-DHCP Port + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Port should be switched to Network Mode. + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(547);//DHCP Server Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(500);//Non - DHCP Port + memcpy (&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; + +/*------------------------------------------------------------------------------*/ +/* Test009: Firewall filtering rules based on source and destination port ranges */ +/*------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest009 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest009() + { + m_name = "IpaFilteringBlockTest009"; + m_description = + "Filtering block test 009 - Firewall filtering rules based on source and destination port ranges (Global Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All (5 >= SRC_PORT_RANGE >= 15) & (50 >= DST_PORT_RANGE >= 150) traffic goes to routing table 0 \ + All (15 >= SRC_PORT_RANGE >= 25) & (150 >= DST_PORT_RANGE >= 250) traffic goes to routing table 1 \ + All (25 >= SRC_PORT_RANGE >= 35) & (250 >= DST_PORT_RANGE >= 350) traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit two routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0 and 1 (accordingly)) +// 2. Generate and commit two filtering rules. +// All UDP traffic goes to routing table 1 +// All TCP traffic goes to routing table 2 + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_PORT_RANGE | IPA_FLT_DST_PORT_RANGE; + //TODO: Fix from here..... + flt_rule_entry.rule.attrib.src_port_lo =5; + flt_rule_entry.rule.attrib.src_port_hi =15; + flt_rule_entry.rule.attrib.dst_port_lo =50; + flt_rule_entry.rule.attrib.dst_port_hi =150; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 15; + flt_rule_entry.rule.attrib.src_port_hi = 25; + flt_rule_entry.rule.attrib.dst_port_lo = 150; + flt_rule_entry.rule.attrib.dst_port_hi = 250; + + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 25; + flt_rule_entry.rule.attrib.src_port_hi = 35; + flt_rule_entry.rule.attrib.dst_port_lo = 250; + flt_rule_entry.rule.attrib.dst_port_hi = 350; + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + port = htons(10); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(100); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(20); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(200); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(30); + memcpy(&m_sendBuffer3[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(300); + memcpy(&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; +/*---------------------------------------------------------------------------*/ +/* Test010: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest010 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest010() + { + m_name = "IpaFilteringBlockTest010"; + m_description = + "Filtering block test 010 - Filtering Based on Protocol type (TCP/UDP/ICMP) (Global Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All UDP traffic goes to routing table 0 \ + All TCP traffic goes to routing table 1 \ + All ICMP traffic goes to routing table 2"; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit two routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0 and 1 (accordingly)) +// 2. Generate and commit two filtering rules. +// All UDP traffic goes to routing table 1 +// All TCP traffic goes to routing table 2 + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,true,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = 17; // Filter only UDP Packets. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 6; // Filter only TCP Packets. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 1; // Filter only ICMP Packets. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + m_sendBuffer[IPV4_PROTOCOL_OFFSET] = 0x11;// UDP 0x11 = 17 + m_sendBuffer2[IPV4_PROTOCOL_OFFSET] = 0x06;// TCP 0x06 = 6 + m_sendBuffer3[IPV4_PROTOCOL_OFFSET] = 0x01;// ICMP 0x01 = 1 + return true; + }// ModifyPacktes () +}; + + +/*---------------------------------------------------------------------------*/ +/* Test021: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest021 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest021() + { + m_name = "IpaFilteringBlockTest021"; + m_description = + "Filtering block test 021 - Destination IP address and subnet mask match against LAN subnet (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 \ + All DST_IP == (192.169.1.1 & 255.0.0.255)traffic goes to routing table 1 \ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("%s route table handle = %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test022: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest022 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest022() + { + m_name = "IpaFilteringBlockTest022"; + m_description = + "Filtering block test 022 - Destination IP address exact match against broadcast IP address (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules (MASK = 0xFF..FF). \ + All DST_IP == 127.0.0.1 traffic goes to routing table 0 \ + All DST_IP == 192.169.1.1 traffic goes to routing table 1 \ + All DST_IP == 192.169.1.2 traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Exact Match + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + + + +/*---------------------------------------------------------------------------*/ +/* Test023: Destination UDP port exact match against DHCP port */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest023 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest023() + { + m_name = "IpaFilteringBlockTest023"; + m_description = + "Filtering block test 023 - Destination UDP port exact match against DHCP port (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All DST_UDP_PORT == 546 (DHCP Client)traffic goes to routing table 0 \ + All DST_UDP_PORT == 547 (DHCP Server) traffic goes to routing table 1 \ + All DST_UDP_PORT == 500 (Non DHCP) traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.dst_port = 546; // DHCP Client Port No 546 + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 547; // DHCP Server Port No 547 + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 500; // Non-DHCP Port + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Port should be switched to Network Mode. + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(547);//DHCP Server Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(500);//Non - DHCP Port + memcpy (&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; + +/*------------------------------------------------------------------------------*/ +/* Test004: Firewall filtering rules based on source and destination port ranges*/ +/*------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest024 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest024() + { + m_name = "IpaFilteringBlockTest024"; + m_description = + "Filtering block test 024 - Firewall filtering rules based on source and destination port ranges (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All (5 >= SRC_PORT_RANGE >= 15) & (50 >= DST_PORT_RANGE >= 150) traffic goes to routing table 0 \ + All (15 >= SRC_PORT_RANGE >= 25) & (150 >= DST_PORT_RANGE >= 250) traffic goes to routing table 1 \ + All (25 >= SRC_PORT_RANGE >= 35) & (250 >= DST_PORT_RANGE >= 350) traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_PORT_RANGE | IPA_FLT_DST_PORT_RANGE; + //TODO: Fix from here..... + flt_rule_entry.rule.attrib.src_port_lo =5; + flt_rule_entry.rule.attrib.src_port_hi =15; + flt_rule_entry.rule.attrib.dst_port_lo =50; + flt_rule_entry.rule.attrib.dst_port_hi =150; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 15; + flt_rule_entry.rule.attrib.src_port_hi = 25; + flt_rule_entry.rule.attrib.dst_port_lo = 150; + flt_rule_entry.rule.attrib.dst_port_hi = 250; + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 25; + flt_rule_entry.rule.attrib.src_port_hi = 35; + flt_rule_entry.rule.attrib.dst_port_lo = 250; + flt_rule_entry.rule.attrib.dst_port_hi = 350; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + port = htons(10); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(100); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(20); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(200); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(30); + memcpy(&m_sendBuffer3[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(300); + memcpy(&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; +/*---------------------------------------------------------------------------*/ +/* Test005: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest025 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest025() + { + m_name = "IpaFilteringBlockTest025"; + m_description = + "Filtering block test 025 - Filtering Based on Protocol type (TCP/UDP/ICMP) (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All UDP traffic goes to routing table 0 \ + All TCP traffic goes to routing table 1 \ + All ICMP traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit two routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0 and 1 (accordingly)) +// 2. Generate and commit two filtering rules. +// All UDP traffic goes to routing table 1 +// All TCP traffic goes to routing table 2 + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = 17; // Filter only UDP Packets. + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 6; // Filter only TCP Packets. + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 1; // Filter only ICMP Packets. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + m_sendBuffer[IPV4_PROTOCOL_OFFSET] = 0x11;// UDP 0x11 = 17 + m_sendBuffer2[IPV4_PROTOCOL_OFFSET] = 0x06;// TCP 0x06 = 6 + m_sendBuffer3[IPV4_PROTOCOL_OFFSET] = 0x01;// ICMP 0x01 = 1 + return true; + }// ModifyPacktes () +}; + + +/*---------------------------------------------------------------------------*/ +/* Test006: Destination IP address and subnet mask match against LAN subnet */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest026 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest026() + { + m_name = "IpaFilteringBlockTest026"; + m_description = + "Filtering block test 026 - Destination IP address and subnet mask match against LAN subnet (End-Point specific Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 \ + All DST_IP == (192.169.1.1 & 255.0.0.255)traffic goes to routing table 1 \ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test007: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest027 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest027() + { + m_name = "IpaFilteringBlockTest027"; + m_description = + "Filtering block test 027 - Destination IP address exact match against broadcast IP address (End-Point specific Filtering Table, each rule is added in a Insert using a dedicated single commit) \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules (MASK = 0xFF..FF). \ + All DST_IP == 127.0.0.1 traffic goes to routing table 0 \ + All DST_IP == 192.169.1.1 traffic goes to routing table 1 \ + All DST_IP == 192.169.1.2 traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + // Test Description: + // 1. Generate and commit three routing tables. + // Each table will contain a single "bypass" rule (all data goes to output pipe 0, 1 and 2(accordingly)) + // 2. Generate and commit three filtering rules (each in different Filtering Table) + // All Filter DST_IP == 127.0.0.1 traffic goes to routing table 1 + // All Filter DST_IP == 192.168.1.1 traffic goes to routing table 2 + // All Filter DST_IP == 192.168.1.2 traffic goes to routing table 3 + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Exact Match + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + }// ModifyPacktes () +}; + + + +/*---------------------------------------------------------------------------*/ +/* Test008: Destination UDP port exact match against DHCP port */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest028 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest028() + { + m_name = "IpaFilteringBlockTest028"; + m_description = + "Filtering block test 028 - Destination UDP port exact match against DHCP port (End-Point specific Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All DST_UDP_PORT == 546 (DHCP Client)traffic goes to routing table 0 \ + All DST_UDP_PORT == 547 (DHCP Server) traffic goes to routing table 1 \ + All DST_UDP_PORT == 500 (Non DHCP) traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit three routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) +// 2. Generate and commit Three filtering rules. +// All DEST_IP == 127.0.0.1 traffic goes to routing table 0 +// All DEST_IP == 192.169.1.1 traffic goes to routing table 1 +// Non Matching traffic goes to routing table 3 + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.dst_port = 546; // DHCP Client Port No 546 + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 547; // DHCP Server Port No 547 + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.dst_port = 500; // Non-DHCP Port + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Port should be switched to Network Mode. + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(547);//DHCP Server Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = ntohs(500);//Non - DHCP Port + memcpy (&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; + +/*------------------------------------------------------------------------------*/ +/* Test009: Firewall filtering rules based on source and destination port ranges */ +/*------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest029 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest029() + { + m_name = "IpaFilteringBlockTest029"; + m_description = + "Filtering block test 029 - Firewall filtering rules based on source and destination port ranges (End-Point specific Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules . \ + All (5 >= SRC_PORT_RANGE >= 15) & (50 >= DST_PORT_RANGE >= 150) traffic goes to routing table 0 \ + All (15 >= SRC_PORT_RANGE >= 25) & (150 >= DST_PORT_RANGE >= 250) traffic goes to routing table 1 \ + All (25 >= SRC_PORT_RANGE >= 35) & (250 >= DST_PORT_RANGE >= 350) traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit two routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0 and 1 (accordingly)) +// 2. Generate and commit two filtering rules. +// All UDP traffic goes to routing table 1 +// All TCP traffic goes to routing table 2 + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_PORT_RANGE | IPA_FLT_DST_PORT_RANGE; + //TODO: Fix from here..... + flt_rule_entry.rule.attrib.src_port_lo =5; + flt_rule_entry.rule.attrib.src_port_hi =15; + flt_rule_entry.rule.attrib.dst_port_lo =50; + flt_rule_entry.rule.attrib.dst_port_hi =150; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 15; + flt_rule_entry.rule.attrib.src_port_hi = 25; + flt_rule_entry.rule.attrib.dst_port_lo = 150; + flt_rule_entry.rule.attrib.dst_port_hi = 250; + + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.src_port_lo = 25; + flt_rule_entry.rule.attrib.src_port_hi = 35; + flt_rule_entry.rule.attrib.dst_port_lo = 250; + flt_rule_entry.rule.attrib.dst_port_hi = 350; + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + port = htons(10); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(100); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(20); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(200); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(30); + memcpy(&m_sendBuffer3[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(300); + memcpy(&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; +/*---------------------------------------------------------------------------*/ +/* Test010: Destination IP address exact match against broadcast IP address */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest030 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest030() + { + m_name = "IpaFilteringBlockTest030"; + m_description = + "Filtering block test 030 - Filtering Based on Protocol type (TCP/UDP/ICMP) (End-Point specific Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All UDP traffic goes to routing table 0 \ + All TCP traffic goes to routing table 1 \ + All ICMP traffic goes to routing table 2"; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); +// Test Description: +// 1. Generate and commit two routing tables. +// Each table will contain a single "bypass" rule (all data goes to output pipe 0 and 1 (accordingly)) +// 2. Generate and commit two filtering rules. +// All UDP traffic goes to routing table 1 +// All TCP traffic goes to routing table 2 + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable1.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + FilterTable2.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = 17; // Filter only UDP Packets. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 6; // Filter only TCP Packets. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.protocol = 1; // Filter only ICMP Packets. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + m_sendBuffer[IPV4_PROTOCOL_OFFSET] = 0x11;// UDP 0x11 = 17 + m_sendBuffer2[IPV4_PROTOCOL_OFFSET] = 0x06;// TCP 0x06 = 6 + m_sendBuffer3[IPV4_PROTOCOL_OFFSET] = 0x01;// ICMP 0x01 = 1 + return true; + }// ModifyPacktes () +}; +/*-------------------------------------------------------------------------------------*/ +/* Test031: Filtering Based on fragment extension, End-Point specific Filtering Table */ +/*-------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest031 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest031() + { + m_name = "IpaFilteringBlockTest031"; + m_description = + "Filtering block test 031 - Filtering Based on fragment extension(End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit 2 filtering rules: \ + All fragmented packets goes to routing table 0: \ + Packets with MF flag set & \ + Packets with MF flag set to zero and fragment offset field nonzero \ + All other packets(non fragmented) goes to routing table 1: \ + Packets with MF flag set to zero and fragment offset field zero goes to routing table 1"; + Register(*this); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_FRAGMENT; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xaabbccdd; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + m_sendBuffer[IPV4_FRAGMENT_FLAGS_OFFSET] = 0x20;//MF=1 + m_sendBuffer[IPV4_FRAGMENT_FLAGS_OFFSET+1] = 0x0;//MF=1 + m_sendBuffer2[IPV4_FRAGMENT_FLAGS_OFFSET] = 0x0;//MF=0 && frag_off =126 + m_sendBuffer2[IPV4_FRAGMENT_FLAGS_OFFSET+1] = 0x7E;//MF=0 && frag_off =126 + m_sendBuffer3[IPV4_FRAGMENT_FLAGS_OFFSET] = 0x0;// MF=0 && frag_off =0 + m_sendBuffer3[IPV4_FRAGMENT_FLAGS_OFFSET+1] = 0x0;// MF=0 && frag_off =0 + return true; + }// ModifyPacktes () + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_consumer2.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_consumer2.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize - 1, sentBufferSize - 1, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + recievedBuffer[0] = '\0'; + print_packets(receivedSize2, m_sendSize2, recievedBufferSize - 1, sentBufferSize - 1, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + recievedBuffer[0] = '\0'; + print_packets(receivedSize3, m_sendSize3, recievedBufferSize - 1, sentBufferSize - 1, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test050: Destination IPv6 address and Subnet Mask exact match against broadcast IP address */ +/*---------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest050 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest050() + { + m_name = "IpaFilteringBlockTest050"; + m_description = + "Filtering block test 050 - Destination IPv6 address and Mask exact match against broadcast IP address (Global Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 \ + All DST_IPv6 == 0x...BB traffic goes to routing table 2 \ + All DST_IPv6 == 0x...CC traffic goes to routing table 3"; + m_IpaIPType = IPA_IP_v6; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,true,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677BB; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xBB; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () +}; + + +/*---------------------------------------------------------------------------------------------*/ +/* Test051: Destination IPv6 address and Subnet Mask exact match against broadcast IP address */ +/*---------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest051 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest051() + { + m_name = "IpaFilteringBlockTest051"; + m_description = + "Filtering block test 051 - Destination IPv6 address and Mask exact match against broadcast IP address (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 \ + All DST_IPv6 == 0x...BB traffic goes to routing table 2 \ + All DST_IPv6 == 0x...CC traffic goes to routing table 3"; + m_IpaIPType = IPA_IP_v6; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // TODO: Fix this, doesn't match the Rule's Requirements + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677BB; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xBB; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test052: IPv6 Filtering Based on Protocol type (TCP/UDP/ICMP) */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest052 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest052() + { + m_name = "IpaFilteringBlockTest052"; + m_description = + "Filtering block test 052 - Filtering Based on Protocol type (TCP/UDP/ICMP) (Global Filtering Table, each rule is added in a Insert using a dedicated single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All UDP traffic goes to routing table 0 \ + All TCP traffic goes to routing table 1 \ + All ICMP traffic goes to routing table 2"; + m_IpaIPType = IPA_IP_v6; + m_extHdrType = FRAGMENT; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0,FilterTable1,FilterTable2; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,true,1); + FilterTable1.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,true,1); + FilterTable2.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,true,1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = 17; // Filter only UDP Packets. + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(0) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.next_hdr = 6; // Filter only TCP Packets. + if ( + ((uint8_t)-1 == FilterTable1.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable1.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(1) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable1.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.next_hdr = 1; // Filter only ICMP Packets. + + if ( + ((uint8_t)-1 == FilterTable2.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable2.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable2.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable2.ReadRuleFromTable(0)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + m_sendBuffer[IPV6_NEXT_HDR_OFFSET] = 0x2C;//FRAGMENT HEADER(44) + m_sendBuffer[IPV6_FRAGMENT_NEXT_HDR_OFFSET] = 0x11;// UDP 0x11 = 17 + m_sendBuffer2[IPV6_FRAGMENT_NEXT_HDR_OFFSET] = 0x06;// TCP 0x06 = 6 + m_sendBuffer3[IPV6_FRAGMENT_NEXT_HDR_OFFSET] = 0x01;// ICMP 0x01 = 1 + return true; + }// ModifyPacktes () +}; +/*-------------------------------------------------------------------------------------*/ +/* Test053: Filtering Based on fragment extension, End-Point specific Filtering Table */ +/*-------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest053 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest053() + { + m_name = "IpaFilteringBlockTest053"; + m_description = + "Filtering block test 053 - Filtering Based on fragment extension(End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit 2 filtering rules: \ + All fragmented packets goes to routing table 0: \ + Packets with MF flag set & \ + Packets with MF flag set to zero and fragment offset field nonzero \ + All other packets(non fragmented) goes to routing table 1: \ + Packets with MF flag set to zero and fragment offset field zero goes to routing table 1"; + m_IpaIPType = IPA_IP_v6; + m_extHdrType = FRAGMENT; + m_minIPAHwType = IPA_HW_v2_5; + Register(*this); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables(bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,2); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_FRAGMENT; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x22334455; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x66778899; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + m_sendBuffer[IPV6_NEXT_HDR_OFFSET] = 0x2C;//FRAGMENT HEADER(44) + m_sendBuffer[IPV6_FRAGMENT_FLAGS_OFFSET] = 0x00;//MF=1 + m_sendBuffer[IPV6_FRAGMENT_FLAGS_OFFSET+1] = 0x1;//MF=1 + m_sendBuffer2[IPV6_FRAGMENT_FLAGS_OFFSET] = 0x3;//MF=0 && frag_off =126 + m_sendBuffer2[IPV6_FRAGMENT_FLAGS_OFFSET+1] = 0xF0;//MF=0 && frag_off =126 + m_sendBuffer3[IPV6_FRAGMENT_FLAGS_OFFSET] = 0x0;// MF=0 && frag_off =0 + m_sendBuffer3[IPV6_FRAGMENT_FLAGS_OFFSET+1] = 0x0;// MF=0 && frag_off =0 + return true; + }// ModifyPacktes () + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_consumer2.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_consumer2.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize - 1, sentBufferSize - 1, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + recievedBuffer[0] = '\0'; + print_packets(receivedSize2, m_sendSize2, recievedBufferSize - 1, sentBufferSize - 1, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + recievedBuffer[0] = '\0'; + print_packets(receivedSize3, m_sendSize3, recievedBufferSize - 1, sentBufferSize - 1, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test054: IPV6 filtering based on based on source and destination port */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest054 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest054() + { + m_name = "IpaFilteringBlockTest054"; + m_description = + "Filtering block test 054 - IPV6 filtering rules based on source and destination port (End-Point specific Filtering Table, Insert all rules in a single commit)\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules:\ + All (SRC_PORT = 1000) traffic goes to routing table 0 \ + All (DST_PORT = 100) traffic goes to routing table 1 \ + All (5 >= SRC_PORT_RANGE >= 15) traffic goes to routing table 2"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v2_5; + Register(*this); + } + + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_PORT; + flt_rule_entry.rule.attrib.src_port = 1000; + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.dst_port = 100; + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_PORT_RANGE; + flt_rule_entry.rule.attrib.src_port_lo = 5; + flt_rule_entry.rule.attrib.src_port_hi = 15; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + port = htons(1000); + memcpy(&m_sendBuffer[IPV6_SRC_PORT_OFFSET], &port, sizeof(port)); + port = htons(100); + memcpy(&m_sendBuffer2[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + port = htons(10); + memcpy(&m_sendBuffer3[IPV6_SRC_PORT_OFFSET], &port, sizeof(port)); + + return true; + }// ModifyPacktes () +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test060: IPV4 filtering test, non hashed priority higher than hashed priority */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest060 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest060() + { + m_name = "IpaFilteringBlockTest060"; + m_description = + "Filtering block test 060 - Rules prioritization hashable vs non-hashable rule, both rules match the same packet but non hashable has higher priority\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 - non hashable\ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 1 - hashable\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 0; // non hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + + } + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize - 1, sentBufferSize - 1, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + recievedBuffer[0] = '\0'; + print_packets(receivedSize2, m_sendSize2, recievedBufferSize - 1, sentBufferSize - 1, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + recievedBuffer[0] = '\0'; + print_packets(receivedSize3, m_sendSize3, recievedBufferSize - 1, sentBufferSize - 1, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test061: IPV4 filtering test, hashed priority higher than non hashed priority + cache hit */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest061 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest061() + { + m_name = "IpaFilteringBlockTest061"; + m_description = + "Filtering block test 061 - Rules prioritization hashable vs non-hashable rule, both rules match the same packet but hashable has higher priority\ + two identical packets are sent and should be catched by the hashable rule, second one shuld be hit the cache\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 - hashable\ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 1 - non hashable\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + + } + + bool Setup() + { + /* we want statuses on this test */ + return IpaFilteringBlockTestFixture::Setup(true); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 0; // non hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 3 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheHit(m_sendSize2,receivedSize2,rxBuff2); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test062: IPV4 filtering test, hashed rule match, non hash doesn't match expect cache miss */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest062 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest062() + { + m_name = "IpaFilteringBlockTest062"; + m_description = + "Filtering block test 062 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two packets with different tuple are sent and should match the hashable rule, no cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.2 & 255.0.0.255)traffic goes to routing table 0 - non hashable\ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 1 - hashable\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 127.0.0.1 port 546\ + DST_IP == 127.0.0.1 port 547\ + DST_IP == 192.168.1.2"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + /* we want statuses on this test */ + return IpaFilteringBlockTestFixture::Setup(true); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.2. + flt_rule_entry.rule.hashable = 0; // non hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 3 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + + } + + virtual bool ModifyPackets() + { + int address; + unsigned short port; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(547);//DHCP Server Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer2.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheMiss(m_sendSize2,receivedSize2,rxBuff2); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test063: IPV4 filtering test, hashed rule match, non hash doesn't match expect cache miss */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest063 : public IpaFilteringBlockTestFixture +{ +public: + + IpaFilteringBlockTest063() + { + m_name = "IpaFilteringBlockTest063"; + m_description = + "Filtering block test 063 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two packets with different tuple are sent and should match the hashable rule, no cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 - hashable\ + All DST_IP == (127.0.0.2 & 255.0.0.255)traffic goes to routing table 1 - non hashable\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 127.0.0.1 port 546\ + DST_IP == 127.0.0.1 port 547\ + DST_IP == 192.168.1.2"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + /* we want statuses on this test */ + return IpaFilteringBlockTestFixture::Setup(true); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.2. + flt_rule_entry.rule.hashable = 0; // non hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 3 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + int address; + unsigned short port; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(547);//DHCP Server Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheMiss(m_sendSize2,receivedSize2,rxBuff2); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + + +/*----------------------------------------------------------------------------------------------*/ +/* Test064: IPV4 filtering test, hashed rule match, non hash doesn't match expect cache hit */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest064 : public IpaFilteringBlockTestFixture +{ +public: + + IpaFilteringBlockTest064() + { + m_name = "IpaFilteringBlockTest064"; + m_description = + "Filtering block test 064 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two identical packets are sent and should match the hashable rule, cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.2 & 255.0.0.255)traffic goes to routing table 0 - non hashable\ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 1 - hashable\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 127.0.0.1 \ + DST_IP == 127.0.0.1 \ + DST_IP == 192.168.1.2"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + /* we want statuses on this test */ + return IpaFilteringBlockTestFixture::Setup(true); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.2. + flt_rule_entry.rule.hashable = 0; // non hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 3 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + int address; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer2.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheHit(m_sendSize2,receivedSize2,rxBuff2); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test065: IPV4 filtering test, non hashable rule match with max priority vs hashable */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest065 : public IpaFilteringBlockTestFixture +{ +public: + + IpaFilteringBlockTest065() + { + m_name = "IpaFilteringBlockTest065"; + m_description = + "Filtering block test 065 - Rules prioritization hashable vs non-hashable rule, both rules match the packets\ + two identical packets are sent, non hashed with max priority should catch both\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 - hashable\ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 1 - non hashable max prio\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 127.0.0.1 \ + DST_IP == 127.0.0.1 \ + DST_IP == 192.168.1.2"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.max_prio = 1; // max prioirty, should overcome all other rules + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 3 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + int address; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer2.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + + isSuccess &= CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test066: IPV4 filtering test, hashed rule match, non hash doesn't match expect cache hit */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest066 : public IpaFilteringBlockTestFixture +{ +public: + bool IsSecondTime; + + IpaFilteringBlockTest066(): IsSecondTime(false) + { + m_name = "IpaFilteringBlockTest066"; + m_description = + "Filtering block test 066 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two identical packets are sent and should match the hashable rule, cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IP == (127.0.0.1 & 255.0.0.255)traffic goes to routing table 0 - hashable\ + All DST_IP == (127.0.0.2 & 255.0.0.255)traffic goes to routing table 1 - non hashable\ + All DST_IP == (192.169.1.2 & 255.0.0.255)traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 127.0.0.1 \ + DST_IP == 127.0.0.1 \ + DST_IP == 192.168.1.2"; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + /* we want statuses on this test */ + return IpaFilteringBlockTestFixture::Setup(true); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("route table %s has the handle %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("route table %s has the handle %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("route table %s has the handle %u\n", bypass2, routing_table2.hdl); + + struct ipa_flt_rule_add flt_rule_entry; + if (!IsSecondTime) { + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 3); + printf("FilterTable*.Init Completed Successfully..\n"); + IsSecondTime = true; + + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.2. + flt_rule_entry.rule.hashable = 1; // hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 on lower priority (second in list) + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.1. + flt_rule_entry.rule.hashable = 0; // non hashed + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; //put here the handle corresponding to Routing Rule 3 + flt_rule_entry.rule.hashable = 0; // non hashed + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + } else { + printf("in the second time, just commit again\n"); + if (!m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + bool RemoveLastRule() + { + struct ipa_ioc_del_flt_rule *pDeleteRule = (struct ipa_ioc_del_flt_rule *) + calloc(1, sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del)); + + pDeleteRule->commit = 1; + pDeleteRule->ip = IPA_IP_v4; + pDeleteRule->num_hdls = 1; + pDeleteRule->hdl[0].hdl = FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl; + pDeleteRule->hdl[0].status = FilterTable0.ReadRuleFromTable(2)->status; + + if (!m_filtering.DeleteFilteringRule(pDeleteRule)) + { + printf ("%s::Error Deleting Rule from Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + return true; + } + + virtual bool ModifyPackets() + { + int address; + + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheHit(m_sendSize2,receivedSize2,rxBuff2); + + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + + bool ReceiveAndCompareSpecial() + { + size_t receivedSize = 0; + + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + size_t j; + + if ((3 * m_sendSize) > sentBufferSize) + printf("Failed to stringify sent packet. Buffer too small\n"); + else + for(j = 0; j < m_sendSize; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - 3 * j, + " %02X", m_sendBuffer[j]); + if ((3 * receivedSize) > recievedBufferSize) + printf("Failed to stringify recieved packet. Buffer too small\n"); + else + for(j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - 3 * j, + " %02X", rxBuff1[j]); + printf("Expected Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n",m_sendSize,sentBuffer,receivedSize,recievedBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + delete[] rxBuff1; + return isSuccess; + + } + +private: + IPAFilteringTable FilterTable0; +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test067: IPV4 filtering test, hash/cache invalidation on add test */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest067 : public IpaFilteringBlockTest066 +{ +public: + IpaFilteringBlockTest067() + { + m_name = "IpaFilteringBlockTest067"; + m_description = + "Filtering block test 067 - this test first perfroms test 066 and then commits another rule\ + another identical packet is sent: DST_IP == 127.0.0.1 and expected to get cache miss"; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + // untill here test 066 was run, now let's test the invalidation + + // commit the same rules again, this should clear the cache + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // send packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceiveAndCompareSpecial(); + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__,isSuccess); + + return isSuccess; + } // Run() + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test068: IPV4 filtering test, hash/cache invalidation on delete test */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest068 : public IpaFilteringBlockTest066 +{ +public: + IpaFilteringBlockTest068() + { + m_name = "IpaFilteringBlockTest068"; + m_description = + "Filtering block test 068 - this test first perfroms test 066 and then removes last rule\ + another identical packet is sent: DST_IP == 127.0.0.1 and expected to get cache miss"; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + // until here test 066 was run, now let's test the invalidation + + // delete the last rule, this should clear the cache + res = RemoveLastRule(); + if (false == res) { + printf("Failed removing filtering rules.\n"); + return false; + } + + // send packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceiveAndCompareSpecial(); + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__,isSuccess); + + return isSuccess; + } // Run() + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test070: IPV6 filtering test, non hashed priority higher than hashed priority */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest070 : public IpaFilteringBlockTest060 +{ +public: + + IpaFilteringBlockTest070() + { + m_name = "IpaFilteringBlockTest070"; + m_description = + "Filtering block test 070 - Rules prioritization hashable vs non-hashable rule, both rules match the same packet but non hashable has higher priority\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 0 - non hashable\ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 - hashable\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - non hashable - don't care for this specific test"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 0; // non hashable + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test071: IPV6 filtering test, hashed priority higher than non hashed priority + cache hit */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest071: public IpaFilteringBlockTest061 +{ +public: + + IpaFilteringBlockTest071() + { + m_name = "IpaFilteringBlockTest071"; + m_description = + "Filtering block test 071 - Rules prioritization hashable vs non-hashable rule, both rules match the same packet but hashable has higher priority\ + two identical packets are sent and should be catched by the hashable rule, second one should be hit the cache\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 0 - hashable\ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 - non hashable\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - don't care for this specific test"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + // TODO: Add verification that we access only allocated addresses + // TODO: Fix this, doesn't match the Rule's Requirements + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test072: IPV6 filtering test, hashed rule match, non hash doesn't match expect cache miss */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest072 : public IpaFilteringBlockTest062 +{ +public: + + IpaFilteringBlockTest072() + { + m_name = "IpaFilteringBlockTest072"; + m_description = + "Filtering block test 072 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two packets with different tuple are sent and should match the hashable rule, no cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...BB traffic goes to routing table 0 - non hashable\ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 - hashable\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 0x...AA port 546\ + DST_IP == 0x...AA port 547\ + DST_IP == 0x...CC"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677BB; + flt_rule_entry.rule.hashable = 0; // non hashable + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + + port = ntohs(547);//DHCP Client Port + memcpy (&m_sendBuffer2[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test073: IPV4 filtering test, hashed rule match, non hash doesn't match expect cache miss */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest073 : public IpaFilteringBlockTest063 +{ +public: + + IpaFilteringBlockTest073() + { + m_name = "IpaFilteringBlockTest073"; + m_description = + "Filtering block test 073 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two packets with different tuple are sent and should match the hashable rule, no cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 0 - hashable\ + All DST_IPv6 == 0x...BB traffic goes to routing table 1 - non hashable\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 0x...AA port 546\ + DST_IP == 0x...AA port 547\ + DST_IP == 0x...CC"; + + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677BB; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + + unsigned short port; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + + port = ntohs(547);//DHCP Client Port + memcpy (&m_sendBuffer2[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test074: IPV6 filtering test, hashed rule match, non hash doesn't match expect cache hit */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest074 : public IpaFilteringBlockTest064 +{ +public: + + IpaFilteringBlockTest074() + { + m_name = "IpaFilteringBlockTest074"; + m_description = + "Filtering block test 074 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two identical packets are sent and should match the hashable rule, cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...BB traffic goes to routing table 0 - non hashable\ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 - hashable\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 0x...AA \ + DST_IP == 0x...AA \ + DST_IP == 0x...CC"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677BB; + flt_rule_entry.rule.hashable = 0; // non hashable + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test075: IPV6 filtering test, non hashable rule match with max priority vs hashable */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest075 : public IpaFilteringBlockTest065 +{ +public: + + IpaFilteringBlockTest075() + { + m_name = "IpaFilteringBlockTest075"; + m_description = + "Filtering block test 075 - Rules prioritization hashable vs non-hashable rule, both rules match the packets\ + two identical packets are sent, non hashed with max priority should catch both\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 0 - hashable\ + All DST_IPv6 == 0x...AA traffic goes to routing table 1 - non hashable max prio\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 0x...AA \ + DST_IP == 0x...AA \ + DST_IP == 0x...CC"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6,IPA_CLIENT_TEST_PROD,false,3); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + printf ("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 0; // non hashable + flt_rule_entry.rule.max_prio = 1; // max priority + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding RuleTable(2) to Filtering, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test076: IPV6 filtering test, hashed rule match, non hash doesn't match expect cache hit */ +/*----------------------------------------------------------------------------------------------*/ + +class IpaFilteringBlockTest076 : public IpaFilteringBlockTest066 +{ +public: + + bool IsSecondTime; + + IpaFilteringBlockTest076() :IsSecondTime(false) + { + m_name = "IpaFilteringBlockTest076"; + m_description = + "Filtering block test 076 - Rules prioritization hashable vs non-hashable rule, only hashable matches the packets\ + two identical packets are sent and should match the hashable rule, cache hit expected\ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit three filtering rules: (DST & Mask Match). \ + All DST_IPv6 == 0x...AA traffic goes to routing table 0 - hashable\ + All DST_IPv6 == 0x...BB traffic goes to routing table 1 - non hashable\ + All DST_IPv6 == 0x...CC traffic goes to routing table 2 - don't care for this specific test\ + 3. send three packets:\ + DST_IP == 0x...AA \ + DST_IP == 0x...AA \ + DST_IP == 0x...CC"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + uint32_t Hndl0, Hndl1, Hndl2; + + if(!GetThreeIPv6BypassRoutingTables(&Hndl0,&Hndl1,&Hndl2)){ + printf("failed to get three IPV6 routing tables!\n"); + return false; + } + + struct ipa_flt_rule_add flt_rule_entry; + if (!IsSecondTime) { + FilterTable0.Init(IPA_IP_v6, IPA_CLIENT_TEST_PROD, false, 3); + IsSecondTime = true; + + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = Hndl0; //put here the handle corresponding to Routing Rule 0 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x000000FF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF020000; // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x11223344; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677AA; + flt_rule_entry.rule.hashable = 1; // hashable + + printf("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl = Hndl1; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677BB; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl = Hndl2; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X556677CC; + flt_rule_entry.rule.hashable = 0; // non hashable + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) { + printf("%s::Error Adding RuleTable(2) to Filtering, aborting...\n", __FUNCTION__); + return false; + } else { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(2)->status); + } + } else { + printf("in the second time, just commit again\n"); + if (!m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) { + printf("%s::Error commiting rules second time, aborting...\n", __FUNCTION__); + return false; + } + } + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + bool RemoveLastRule() + { + struct ipa_ioc_del_flt_rule *pDeleteRule = (struct ipa_ioc_del_flt_rule *) + calloc(1, sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del)); + + pDeleteRule->commit = 1; + pDeleteRule->ip = IPA_IP_v6; + pDeleteRule->num_hdls = 1; + pDeleteRule->hdl[0].hdl = FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl; + pDeleteRule->hdl[0].status = FilterTable0.ReadRuleFromTable(2)->status; + + if (!m_filtering.DeleteFilteringRule(pDeleteRule)) + { + printf ("%s::Error Deleting Rule from Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + return true; + } + + virtual bool ModifyPackets() + { + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV6] = 0xCC; + return true; + }// ModifyPacktes () + +private: + IPAFilteringTable FilterTable0; +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test077: IPV6 filtering test, hash/cache invalidation on add test */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest077 : public IpaFilteringBlockTest076 +{ +public: + IpaFilteringBlockTest077() + { + m_name = "IpaFilteringBlockTest077"; + m_description = + "Filtering block test 077 - this test first perfroms test 076 and then commits another rule\ + another identical packet is sent: DST_IP == 127.0.0.1 and expected to get cache miss"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + // until here test 076 was run, now let's test the invalidation + + // commit the same rules again, this should clear the cache + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // send packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceiveAndCompareSpecial(); + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__,isSuccess); + + return isSuccess; + } // Run() + +}; + +/*----------------------------------------------------------------------------------------------*/ +/* Test078: IPV6 filtering test, hash/cache invalidation on add test */ +/*----------------------------------------------------------------------------------------------*/ +class IpaFilteringBlockTest078 : public IpaFilteringBlockTest076 +{ +public: + IpaFilteringBlockTest078() + { + m_name = "IpaFilteringBlockTest078"; + m_description = + "Filtering block test 078 - this test first perfroms test 076 and then removes last rule\ + another identical packet is sent: DST_IP == 127.0.0.1 and expected to get cache miss"; + m_minIPAHwType = IPA_HW_v3_0; + m_IpaIPType = IPA_IP_v6; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + // until here test 076 was run, now let's test the invalidation + + // delete the last rule, this should clear the cache + res = RemoveLastRule(); + if (false == res) { + printf("Failed removing filtering rules.\n"); + return false; + } + + // send packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceiveAndCompareSpecial(); + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__,isSuccess); + + return isSuccess; + } // Run() + +}; + +/*---------------------------------------------------------------------------*/ +/* Test081: Type-of-service IP header field match */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest081 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest081() + { + m_name = "IpaFilteringBlockTest081"; + m_description = " \ + Filtering block test 081 - Source and Destination address and TOS exact match (End-Point specific Filtering Table, Insert all rules in a single commit) \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: \ + All DST_IP == (127.0.0.1 & 255.0.0.255) and TOS == 0xFB traffic goes to routing table 0 \ + All DST_IP == (192.168.1.1 & 255.0.0.255) and TOS == 0x10 traffic goes to routing table 1 \ + All DST_IP == (192.168.1.2 & 255.0.0.255) and SRC_IP == (192.168.1.FF & 255.0.0.255) TOS == 0x25 traffic goes to routing table 2"; + m_IpaIPType = IPA_IP_v4; + Register(*this); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("%s route table handle = %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // out param + flt_rule_entry.status = -1; // out param + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR | IPA_FLT_TOS; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1 + flt_rule_entry.rule.attrib.u.v4.tos = 0xFB; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1 + flt_rule_entry.rule.attrib.u.v4.tos = 0x10; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2 + flt_rule_entry.rule.attrib.u.v4.src_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.attrib.u.v4.src_addr = 0xC0A801FF; // Filter DST_IP == 192.168.1.255 + flt_rule_entry.rule.attrib.u.v4.tos = 0x25; + + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + address = ntohl(0x7F000001);//127.0.0.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + m_sendBuffer[IP4_TOS_FIELD_OFFSET] = 0xFB; + + address = ntohl(0xC0A80101);//192.168.1.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + m_sendBuffer2[IP4_TOS_FIELD_OFFSET] = 0x10; + + address = ntohl(0xC0A80102);//192.168.1.2 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + address = ntohl(0xC0A801FF);//192.168.1.255 + memcpy(&m_sendBuffer3[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + m_sendBuffer3[IP4_TOS_FIELD_OFFSET] = 0x25; + + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test082: Pure Ack packet match */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest082 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest082() + { + m_name = "IpaFilteringBlockTest082"; + m_description = " \ + Filtering block test 082 - Pure Ack packet match \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: \ + All IS_PURE_ACK traffic goes to routing table 0 \ + All DST_IP == (192.168.1.5 & 255.0.0.255) goes to routing table 1\ + All other traffic goes to routing table 2"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v4_5; + Register(*this); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0,routing_table1,routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables (bypass0,bypass1,bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + printf("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n",&routing_table1); + return false; + } + printf("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n",&routing_table2); + return false; + } + printf("%s route table handle = %u\n", bypass2, routing_table2.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4,IPA_CLIENT_TEST_PROD,false,3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // out param + flt_rule_entry.status = -1; // out param + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_IS_PURE_ACK; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl=routing_table1.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80105; // Filter DST_IP == 192.168.1.5 + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl=routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + printf ("%s::Error Adding Rule to Filter Table, aborting...\n",__FUNCTION__); + return false; + } else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool LoadFiles(enum ipa_ip_type ip) + { + string fileName; + + if (!LoadNoPayloadPacket(ip, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed loading no payload Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to m_sendBuffer\n",m_sendSize); + + if (!LoadNoPayloadPacket(ip, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed loading no payload Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to m_sendBuffer2\n",m_sendSize2); + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed loading default Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to m_sendBuffer3\n",m_sendSize3); + + return true; + } + + virtual bool ModifyPackets() + { + int address; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) + { + printf ("Error : %s was called with NULL Buffers\n",__FUNCTION__); + return false; + } + + m_sendBuffer[IPv4_TCP_FLAGS_OFFSET] |= TCP_ACK_FLAG_MASK; + address = ntohl(0xC0A80105);//192.168.1.5 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + address = ntohl(0xC0A80105);//192.168.1.5 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + m_sendBuffer3[IPv4_TCP_FLAGS_OFFSET] |= TCP_ACK_FLAG_MASK; + return true; + }// ModifyPacktes () +}; + +/*---------------------------------------------------------------------------*/ +/* Test090: VLAN ID filtering - IPv4 */ +/*---------------------------------------------------------------------------*/ +class IpaFilteringBlockTest090 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest090() + { + m_name = "IpaFilteringBlockTest090"; + m_description = " \ + Filtering block test 090 - VLAN ID packet match - IPv4 \ + 1. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit Three filtering rules: \ + All VLAN ID == 5 goes to routing table 0 \ + All VLAN ID == 6 goes to routing table 1\ + All other traffic goes to routing table 2"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0, routing_table1, routing_table2; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + printf("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) { + printf("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n", &routing_table1); + return false; + } + printf("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + routing_table2.ip = IPA_IP_v4; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) { + printf("m_routing.GetRoutingTable(&routing_table2=0x%p) Failed.\n", &routing_table2); + return false; + } + printf("%s route table handle = %u\n", bypass2, routing_table2.hdl); + + // note here we are using the VLAN pipe TEST2_PROD + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST2_PROD, false, 3); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // out param + flt_rule_entry.status = -1; // out param + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.retain_hdr = 1; // retain header so we can compare the VID + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_VLAN_ID; + flt_rule_entry.rule.attrib.vlan_id = 5; //filter all packets with vlan id == 5 + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl = routing_table1.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_VLAN_ID; + flt_rule_entry.rule.attrib.vlan_id = 6; //filter all packets with vlan id == 6 + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + + // Configuring Filtering Rule No.2 + flt_rule_entry.rule.rt_tbl_hdl = routing_table2.hdl; + flt_rule_entry.rule.attrib.attrib_mask = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } else { + printf("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + printf("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(1)->status); + printf("flt rule hdl2=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(2)->status); + } + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } + + virtual bool LoadFiles(enum ipa_ip_type ip) + { + string fileName; + if (!LoadDefault802_1Q(ip, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed loading first VLAN Packet\n"); + return false; + } + printf("Loaded %zu Bytes to m_sendBuffer\n", m_sendSize); + + if (!LoadDefault802_1Q(ip, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed loading second VLAN Packet\n"); + return false; + } + printf("Loaded %zu Bytes to m_sendBuffer2\n", m_sendSize2); + + if (!LoadDefault802_1Q(ip, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed loading default Packet\n"); + return false; + } + printf("Loaded %zu Bytes to m_sendBuffer3\n", m_sendSize3); + + return true; + } + + virtual bool ModifyPackets() + { + uint32_t vlan_802_1Q_tag; + if ( + (NULL == m_sendBuffer) || + (NULL == m_sendBuffer2) || + (NULL == m_sendBuffer3) + ) { + printf("Error : %s was called with NULL Buffers\n", __FUNCTION__); + return false; + } + + vlan_802_1Q_tag = ntohl(0x81002005); //VLAN ID == 5 + memcpy(&m_sendBuffer[TAG_802_1Q_OFFSET], &vlan_802_1Q_tag, sizeof(vlan_802_1Q_tag)); + + vlan_802_1Q_tag = ntohl(0x81002006); //VLAN ID == 6 + memcpy(&m_sendBuffer2[TAG_802_1Q_OFFSET], &vlan_802_1Q_tag, sizeof(vlan_802_1Q_tag)); + + // default packet has vlan id == 3, assign it anyway + vlan_802_1Q_tag = ntohl(0x81002003); //VLAN ID == 3 + memcpy(&m_sendBuffer3[TAG_802_1Q_OFFSET], &vlan_802_1Q_tag, sizeof(vlan_802_1Q_tag)); + return true; + }// ModifyPacktes () + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer2.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer2.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer2.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + printf("Leaving %s, %s(), Returning %d\n", __FUNCTION__, __FILE__, isSuccess); + + return isSuccess; + } // Run() +}; + +/*---------------------------------------------------------------------------*/ +/* Test100: Cache LRU behavior test */ +/*---------------------------------------------------------------------------*/ +#define CHACHE_ENTRIES 64 +#define CHACHE_PLUS_ONE (CHACHE_ENTRIES +1) +class IpaFilteringBlockTest100 : public IpaFilteringBlockTestFixture +{ +public: + IpaFilteringBlockTest100() + { + m_name = "IpaFilteringBlockTest100"; + m_description = " \ + Filtering block test 100 - Cache LRU behavior test \ + 1. Preload the cache by sending 64 packets for different connections \ + 2. Send another packet for 65th connection \ + 3. Send packets for first 64 connections \ + 4. Verify that 1st connection’s entry was reclaimed"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + bool Setup() + { + /* we want statuses on this test */ + return IpaFilteringBlockTestFixture::Setup(true); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + int i; + struct ipa_ioc_get_rt_tbl routing_table0; + const char bypass0[20] = "Bypass0"; + + if (!CreateBypassRoutingTable(&m_routing, + m_IpaIPType, + bypass0, + IPA_CLIENT_TEST2_CONS, + 0, + &routing_table0.hdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + return false; + } + + routing_table0.ip = m_IpaIPType; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n",&routing_table0); + return false; + } + + printf("Creating Bypass Routing Table completed successfully\n"); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, CHACHE_PLUS_ONE); + printf("FilterTable*.Init Completed Successfully..\n"); + + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + flt_rule_entry.rule.hashable = 1; + + for (i = 0; i < CHACHE_PLUS_ONE; i++) { + // Configuring Filtering Rule No.i + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xC0A80101 + i; // Filter DST_IP == 192.168.1.(1+i). + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + } + + if (!m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + printf ("%s::Error Adding RuleTable(%d) to Filtering, aborting...\n", __FUNCTION__, i); + return false; + } else { + for (i = 0; i < CHACHE_PLUS_ONE; i++) { + printf("flt rule hdl=0x%x, status=0x%x\n", + FilterTable0.ReadRuleFromTable(i)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(i)->status); + } + } + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + virtual bool ModifyPackets() { + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send the first CHACHE_ENTRIES packets + // Receive packets and compare results + // All rules should be cache miss + for (int i = 0; i < CHACHE_ENTRIES; i++) { + res = __ModifyPackets(i); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, false); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + } + + // Send again the first CHACHE_ENTRIES packets + // Receive packets and compare results + // All rules should be cache hit + for (int i = 0; i < CHACHE_ENTRIES; i++) { + res = __ModifyPackets(i); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, true); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + } + + // Send a packet to a new filter entry, this should trigger the LRU clear + res = __ModifyPackets(CHACHE_ENTRIES); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, false); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + + // send the first packet again + res = __ModifyPackets(0); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, false); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__, isSuccess); + + return isSuccess; + } // Run() + +private: + bool __ModifyPackets(int i) + { + int address; + if (NULL == m_sendBuffer) + { + printf ("Error : %s was called with NULL Buffer\n", __FUNCTION__); + return false; + } + + address = ntohl(0xC0A80101 + i); // 192.168.1.(1+i) + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + + return true; + } + +}; + +static class IpaFilteringBlockTest001 ipaFilteringBlockTest001;//Global Filtering Test +static class IpaFilteringBlockTest002 ipaFilteringBlockTest002;//Global Filtering Test +static class IpaFilteringBlockTest003 ipaFilteringBlockTest003;//Global Filtering Test +static class IpaFilteringBlockTest004 ipaFilteringBlockTest004;//Global Filtering Test +static class IpaFilteringBlockTest005 ipaFilteringBlockTest005;//Global Filtering Test +static class IpaFilteringBlockTest006 ipaFilteringBlockTest006;//Global Filtering Test +static class IpaFilteringBlockTest007 ipaFilteringBlockTest007;//Global Filtering Test +static class IpaFilteringBlockTest008 ipaFilteringBlockTest008;//Global Filtering Test +static class IpaFilteringBlockTest009 ipaFilteringBlockTest009;//Global Filtering Test +static class IpaFilteringBlockTest010 ipaFilteringBlockTest010;//Global Filtering Test + +static class IpaFilteringBlockTest021 ipaFilteringBlockTest021;//End point Specific Filtering Table +static class IpaFilteringBlockTest022 ipaFilteringBlockTest022;//End point Specific Filtering Table +static class IpaFilteringBlockTest023 ipaFilteringBlockTest023;//End point Specific Filtering Table +static class IpaFilteringBlockTest024 ipaFilteringBlockTest024;//End point Specific Filtering Table +static class IpaFilteringBlockTest025 ipaFilteringBlockTest025;//End point Specific Filtering Table +static class IpaFilteringBlockTest026 ipaFilteringBlockTest026;//End point Specific Filtering Table +static class IpaFilteringBlockTest027 ipaFilteringBlockTest027;//End point Specific Filtering Table +static class IpaFilteringBlockTest028 ipaFilteringBlockTest028;//End point Specific Filtering Table +static class IpaFilteringBlockTest029 ipaFilteringBlockTest029;//End point Specific Filtering Table +static class IpaFilteringBlockTest030 ipaFilteringBlockTest030;//End point Specific Filtering Table +static class IpaFilteringBlockTest031 ipaFilteringBlockTest031;//End point Specific Filtering Table + +static class IpaFilteringBlockTest050 ipaFilteringBlockTest050;// IPv6 Test, Global Filtering Table +static class IpaFilteringBlockTest051 ipaFilteringBlockTest051;// IPv6 Test, End point Specific Filtering Table +static class IpaFilteringBlockTest052 ipaFilteringBlockTest052;// IPv6 Test, Global Filtering Table +static class IpaFilteringBlockTest053 ipaFilteringBlockTest053;// IPv6 Test, End point Specific Filtering Table +static class IpaFilteringBlockTest054 ipaFilteringBlockTest054;// IPv6 Test, End point Specific Filtering Table + +static class IpaFilteringBlockTest060 ipaFilteringBlockTest060; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest061 ipaFilteringBlockTest061; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest062 ipaFilteringBlockTest062; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest063 ipaFilteringBlockTest063; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest064 ipaFilteringBlockTest064; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest065 ipaFilteringBlockTest065; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest066 ipaFilteringBlockTest066; // Hashed non hashed tests IPv4 +static class IpaFilteringBlockTest067 ipaFilteringBlockTest067; // Cache/Hash invalidation on add test +static class IpaFilteringBlockTest068 ipaFilteringBlockTest068; // Cache/Hash invalidation on delete test + +static class IpaFilteringBlockTest070 ipaFilteringBlockTest070; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest071 ipaFilteringBlockTest071; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest072 ipaFilteringBlockTest072; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest073 ipaFilteringBlockTest073; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest074 ipaFilteringBlockTest074; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest075 ipaFilteringBlockTest075; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest076 ipaFilteringBlockTest076; // Hashed non hashed tests IPV6 +static class IpaFilteringBlockTest077 ipaFilteringBlockTest077; // Cache/Hash invalidation on add test +static class IpaFilteringBlockTest078 ipaFilteringBlockTest078; // Cache/Hash invalidation on delete test + +static class IpaFilteringBlockTest081 ipaFilteringBlockTest081; // Type-of-service Filter rule test +static class IpaFilteringBlockTest082 ipaFilteringBlockTest082; // IPv4 Pure Ack Filter rule test + +static class IpaFilteringBlockTest090 ipaFilteringBlockTest090; // VLAN filtering test IPv4 + +static class IpaFilteringBlockTest100 ipaFilteringBlockTest100; // Cache LRU behavior test + diff --git a/kernel-tests/HeaderInsertion.cpp b/kernel-tests/HeaderInsertion.cpp new file mode 100644 index 0000000000..4d92e8b77f --- /dev/null +++ b/kernel-tests/HeaderInsertion.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2017 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 "HeaderInsertion.h" + +/*All interaction through the driver are + * made through this inode. + */ +static const char* DEVICE_NAME = "/dev/ipa"; + +#define LOG_IOCTL_RETURN_VALUE(nRetVal) \ + printf("%s()- %s\n", __func__, \ + (-1 == nRetVal) ? "Fail" : "Success"); + +HeaderInsertion::HeaderInsertion() +{ + m_fd = open(DEVICE_NAME, O_RDWR); + if (-1 == m_fd) + { + printf( + "Failed to open %s in HeaderInsertion test application constructor.\n", + DEVICE_NAME); + } +} + +HeaderInsertion::~HeaderInsertion() +{ + if (-1 != m_fd) + { + close(m_fd); + } +} + +bool HeaderInsertion::DeviceNodeIsOpened() +{ + return (-1 != m_fd); +} + +bool HeaderInsertion::AddHeader(struct ipa_ioc_add_hdr *pHeaderTableToAdd) +{ + int nRetVal = 0; + /*call the Driver ioctl in order to add header*/ + nRetVal = ioctl(m_fd, IPA_IOC_ADD_HDR, pHeaderTableToAdd); + LOG_IOCTL_RETURN_VALUE(nRetVal); + return (-1 != nRetVal); +} + +bool HeaderInsertion::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete) +{ + int nRetVal = 0; + /*call the Driver ioctl in order to remove header*/ + nRetVal = ioctl(m_fd, IPA_IOC_DEL_HDR , pHeaderTableToDelete); + LOG_IOCTL_RETURN_VALUE(nRetVal); + return (-1 != nRetVal); +} + +bool HeaderInsertion::AddProcCtx(struct ipa_ioc_add_hdr_proc_ctx *procCtxTable) +{ + int retval = 0; + + retval = ioctl(m_fd, IPA_IOC_ADD_HDR_PROC_CTX, procCtxTable); + if (retval) { + printf("%s(), failed adding ProcCtx rule table %p\n", __FUNCTION__, procCtxTable); + return false; + } + + printf("%s(), Added ProcCtx rule to table %p\n", __FUNCTION__, procCtxTable); + return true; +} + +bool HeaderInsertion::DeleteProcCtx(struct ipa_ioc_del_hdr_proc_ctx *procCtxTable) +{ + int retval = 0; + + retval = ioctl(m_fd, IPA_IOC_DEL_HDR_PROC_CTX, procCtxTable); + if (retval) { + printf("%s(), failed deleting ProcCtx rule in table %p\n", __FUNCTION__, procCtxTable); + return false; + } + + printf("%s(), Deleted ProcCtx rule in table %p\n", __FUNCTION__, procCtxTable); + return true; +} + +bool HeaderInsertion::Commit() +{ + int nRetVal = 0; + nRetVal = ioctl(m_fd, IPA_IOC_COMMIT_HDR); + LOG_IOCTL_RETURN_VALUE(nRetVal); + return true; +} + +bool HeaderInsertion::Reset() +{ + int nRetVal = 0; + + nRetVal = ioctl(m_fd, IPA_IOC_RESET_HDR); + nRetVal |= ioctl(m_fd, IPA_IOC_COMMIT_HDR); + LOG_IOCTL_RETURN_VALUE(nRetVal); + return true; +} + +bool HeaderInsertion::GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_GET_HDR, pHeaderStruct); + if (retval) { + printf( + "%s(), IPA_IOC_GET_HDR ioctl failed, routingTable =0x%p, retval=0x%x.\n" + , __func__, + pHeaderStruct, + retval); + return false; + } + + printf( + "%s(), IPA_IOC_GET_HDR ioctl issued to IPA header insertion block.\n", + __func__); + return true; +} + +bool HeaderInsertion::CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_COPY_HDR, pCopyHeaderStruct); + if (retval) { + printf( + "%s(), IPA_IOC_COPY_HDR ioctl failed, retval=0x%x.\n", + __func__, + retval); + return false; + } + + printf( + "%s(), IPA_IOC_COPY_HDR ioctl issued to IPA header insertion block.\n", + __func__); + return true; +} + diff --git a/kernel-tests/HeaderInsertion.h b/kernel-tests/HeaderInsertion.h new file mode 100644 index 0000000000..613aec5339 --- /dev/null +++ b/kernel-tests/HeaderInsertion.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 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 HEADER_INSERTION_H_ +#define HEADER_INSERTION_H_ + +#include +#include "linux/msm_ipa.h" + +class HeaderInsertion +{ +private: + int m_fd; + +public: + bool AddHeader(struct ipa_ioc_add_hdr *pHeaderTable); + bool DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTable); + bool GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct); + bool CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct); + + // Processing context + bool AddProcCtx(struct ipa_ioc_add_hdr_proc_ctx *procCtxTable); + bool DeleteProcCtx(struct ipa_ioc_del_hdr_proc_ctx *procCtxTable); + + bool Commit(); + bool Reset(); + + HeaderInsertion(); + ~HeaderInsertion(); + bool DeviceNodeIsOpened(); +}; + +#endif diff --git a/kernel-tests/HeaderInsertionTests.cpp b/kernel-tests/HeaderInsertionTests.cpp new file mode 100644 index 0000000000..299f616205 --- /dev/null +++ b/kernel-tests/HeaderInsertionTests.cpp @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2017-2018 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 "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" +#include "hton.h" // for htonl +#include "TestsUtils.h" +#include + +#define IPV4_DST_ADDR_OFFSET (16) + +class IPAHeaderInsertionTestFixture: public TestBase { +public: + + IPAHeaderInsertionTestFixture() : m_uBufferSize(0) + { + memset(m_aBuffer, 0, sizeof(m_aBuffer)); + m_testSuiteName.push_back("Insertion"); + } + + virtual bool AddRules() = 0; + virtual bool ModifyPackets() = 0; + virtual bool TestLogic() = 0; + + bool Setup() + { + + ConfigureScenario(PHASE_FIVE_TEST_CONFIGURATION); + + m_producer.Open(INTERFACE0_TO_IPA_DATA_PATH, + INTERFACE0_FROM_IPA_DATA_PATH); + m_Consumer1.Open(INTERFACE1_TO_IPA_DATA_PATH, + INTERFACE1_FROM_IPA_DATA_PATH); + m_Consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, + INTERFACE2_FROM_IPA_DATA_PATH); + m_Consumer3.Open(INTERFACE3_TO_IPA_DATA_PATH, + INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_Routing.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Routing block is not ready for immediate commands!\n"); + return false; + } + if (!m_Filtering.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Filtering block is not ready for immediate commands!\n"); + return false; + } + if (!m_HeaderInsertion.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Header Insertion block is not ready for immediate commands!\n"); + return false; + } + m_HeaderInsertion.Reset();// resetting this component will reset both Routing and Filtering tables. + + return true; + } // Setup() + + bool Run() + { + m_uBufferSize = BUFF_MAX_SIZE; + LOG_MSG_STACK("Entering Function"); + + // Add the relevant filtering rules + if (!AddRules()) { + LOG_MSG_ERROR("Failed adding filtering rules."); + return false; + } + // Load input data (IP packet) from file + if (!LoadDefaultPacket(m_eIP, m_aBuffer, m_uBufferSize)) { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + if (!ModifyPackets()) { + LOG_MSG_ERROR("Failed to modify packets."); + return false; + } + if (!TestLogic()) { + LOG_MSG_ERROR("Test failed, Input and expected output mismatch."); + return false; + } + + LOG_MSG_STACK("Leaving Function (Returning True)"); + return true; + } // Run() + + bool Teardown() + { + m_HeaderInsertion.Reset();// resetting this component will reset both Routing and Filtering tables. + m_producer.Close(); + m_Consumer1.Close(); + m_Consumer2.Close(); + m_Consumer3.Close(); + return true; + } // Teardown() + + ~IPAHeaderInsertionTestFixture() {} + + static RoutingDriverWrapper m_Routing; + static Filtering m_Filtering; + static HeaderInsertion m_HeaderInsertion; + InterfaceAbstraction m_producer; + InterfaceAbstraction m_Consumer1; + InterfaceAbstraction m_Consumer2; + InterfaceAbstraction m_Consumer3; + +protected: + static const size_t BUFF_MAX_SIZE = 1024; + static const uint8_t MAX_HEADER_SIZE = 64; // 64Bytes - Max Header Length + enum ipa_ip_type m_eIP; + uint8_t m_aBuffer[BUFF_MAX_SIZE]; // Input file \ IP packet + size_t m_uBufferSize; + +}; +RoutingDriverWrapper IPAHeaderInsertionTestFixture::m_Routing; +Filtering IPAHeaderInsertionTestFixture::m_Filtering; +HeaderInsertion IPAHeaderInsertionTestFixture::m_HeaderInsertion; + +//---------------------------------------------------------------------------/ +// Test002: Test that 802.3 header was inserted Correctly / +//---------------------------------------------------------------------------/ +class IPAHeaderInsertionTest001: public IPAHeaderInsertionTestFixture { +public: + IPAHeaderInsertionTest001() { + m_name = "IPAHeaderInsertionTest001"; + m_description = + "Header Insertion Test 001 - Test RMNet Header Insertion\ + 1. Generate and commit RMNet.3 header Insertion \ + 2. Generate and commit routing table containing bypass rule. \ + 3. Generate and commit bypass filtering rule. \ + 4. Send a packet, and verify that the RMNet.3 Header was inserted correctly."; + Register(*this); + uint8_t aRMNetHeader[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; + m_nHeadertoAddSize = sizeof(aRMNetHeader); + memcpy(m_aHeadertoAdd, aRMNetHeader, m_nHeadertoAddSize); + } + + // Test Description: + // 1. Generate and commit single bypass routing table. + virtual bool AddRules() { + m_eIP = IPA_IP_v4; + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl sRoutingTable; + bool bRetVal = true; + struct ipa_ioc_get_hdr sRetHeader; + IPAFilteringTable cFilterTable; + struct ipa_flt_rule_add sFilterRuleEntry; + uint32_t nRTTableHdl=0; + memset(&sRoutingTable, 0, sizeof(sRoutingTable)); + memset(&sRetHeader, 0, sizeof(sRetHeader)); + strlcpy(sRetHeader.name, "IEEE802_3", sizeof(sRetHeader.name)); + + LOG_MSG_STACK("Entering Function"); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + strlcpy(pHeaderDescriptor->hdr[0].name, sRetHeader.name, sizeof(pHeaderDescriptor->hdr[0].name)); + memcpy(pHeaderDescriptor->hdr[0].hdr, m_aHeadertoAdd, + m_nHeadertoAddSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = m_nHeadertoAddSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + strlcpy(sRetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sRetHeader.name)); + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + if (!m_HeaderInsertion.GetHeaderHandle(&sRetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, bypass0, IPA_CLIENT_TEST2_CONS, + sRetHeader.hdl,&nRTTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("CreateBypassRoutingTable completed successfully"); + sRoutingTable.ip = m_eIP; + strlcpy(sRoutingTable.name, bypass0, sizeof(sRoutingTable.name)); + if (!m_Routing.GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&sRoutingTable=0x%p) Failed.", &sRoutingTable); + bRetVal = false; + goto bail; + } + // Creating Filtering Rules + cFilterTable.Init(m_eIP,IPA_CLIENT_TEST_PROD,false,1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable.GeneratePresetRule(0,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl = -1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action = IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nRTTableHdl; //put here the handle corresponding to Routing Rule 1 + if ( + ((uint8_t)-1 == cFilterTable.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable.ReadRuleFromTable(0)->status); + } + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + // This test doesn't modify the original IP Packet. + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + m_aExpectedBufSize = 0; + + memcpy(m_aExpectedBuffer, m_aHeadertoAdd, m_nHeadertoAddSize); + memcpy(m_aExpectedBuffer+m_nHeadertoAddSize,m_aBuffer,m_uBufferSize); + m_aExpectedBufSize = m_nHeadertoAddSize + m_uBufferSize; + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Consumer1, m_aExpectedBuffer, m_aExpectedBufSize)) { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + return false; + } + return true; + } +private: + uint8_t m_aExpectedBuffer[BUFF_MAX_SIZE]; // Input file / IP packet + size_t m_aExpectedBufSize; + uint8_t m_aHeadertoAdd[MAX_HEADER_SIZE]; + size_t m_nHeadertoAddSize; +}; + +//---------------------------------------------------------------------------/ +// Test002: Test that 802.3 header was inserted Correctly / +//---------------------------------------------------------------------------/ +class IPAHeaderInsertionTest002: public IPAHeaderInsertionTestFixture { +public: + IPAHeaderInsertionTest002() { + m_name = "IPAHeaderInsertionTest002"; + m_description = + "Header Insertion Test 002 - Test IEEE802.3 Header Insertion\ + 1. Generate and commit IEEE802.3 header Insertion \ + 2. Generate and commit routing table containing bypass rule. \ + 3. Generate and commit bypass filtering rule. \ + 4. Send a packet, and verify that the IEEE802.3 Header was inserted correctly \ + and that the header Length was updated as well"; + Register(*this); + uint8_t aIEEE802_3Header[22] = { 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0x00, 0x46, 0xAE, 0xAF, 0xB0,// the correct size (00 46) is inserted here. + 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6 }; + m_nHeadertoAddSize = sizeof(aIEEE802_3Header); + memcpy(m_aHeadertoAdd, aIEEE802_3Header, m_nHeadertoAddSize); + } + + // Test Description: + // 1. Generate and commit single bypass routing table. + virtual bool AddRules() { + m_eIP = IPA_IP_v4; + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl sRoutingTable; + bool bRetVal = true; + struct ipa_ioc_get_hdr sRetHeader; + IPAFilteringTable cFilterTable; + struct ipa_flt_rule_add sFilterRuleEntry; + uint32_t nRTTableHdl=0; + memset(&sRoutingTable, 0, sizeof(sRoutingTable)); + memset(&sRetHeader, 0, sizeof(sRetHeader)); + strlcpy(sRetHeader.name, "IEEE802_3", sizeof(sRetHeader.name)); + + LOG_MSG_STACK("Entering Function"); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + strlcpy(pHeaderDescriptor->hdr[0].name, sRetHeader.name, sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, m_aHeadertoAdd, + m_nHeadertoAddSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr[12] = 0x00; //set length to zero, to confirm if ipa updates or not + pHeaderDescriptor->hdr[0].hdr_len = m_nHeadertoAddSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + strlcpy(sRetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sRetHeader.name)); + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + if (!m_HeaderInsertion.GetHeaderHandle(&sRetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, bypass0, IPA_CLIENT_TEST3_CONS, + sRetHeader.hdl,&nRTTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("CreateBypassRoutingTable completed successfully"); + sRoutingTable.ip = m_eIP; + strlcpy(sRoutingTable.name, bypass0, sizeof(sRoutingTable.name)); + if (!m_Routing.GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&sRoutingTable=0x%p) Failed.", &sRoutingTable); + bRetVal = false; + goto bail; + } + // Creating Filtering Rules + cFilterTable.Init(m_eIP,IPA_CLIENT_TEST_PROD,false,1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable.GeneratePresetRule(0,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl = -1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action = IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nRTTableHdl; //put here the handle corresponding to Routing Rule 1 + if ( + ((uint8_t)-1 == cFilterTable.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable.ReadRuleFromTable(0)->status); + } + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + // This test doesn't modify the original IP Packet. + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + m_aExpectedBufSize = 0; + + memcpy(m_aExpectedBuffer, m_aHeadertoAdd, m_nHeadertoAddSize); + memcpy(m_aExpectedBuffer+m_nHeadertoAddSize,m_aBuffer,m_uBufferSize); + m_aExpectedBufSize = m_nHeadertoAddSize + m_uBufferSize; + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Consumer2, m_aExpectedBuffer, m_aExpectedBufSize)) { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + return false; + } + return true; + } +private: + uint8_t m_aExpectedBuffer[BUFF_MAX_SIZE]; // Input file / IP packet + size_t m_aExpectedBufSize; + uint8_t m_aHeadertoAdd[MAX_HEADER_SIZE]; + size_t m_nHeadertoAddSize; +}; + +//---------------------------------------------------------------------------/ +// Test003: Test Three Different Header Insertions / +//---------------------------------------------------------------------------/ +class IPAHeaderInsertionTest003: public IPAHeaderInsertionTestFixture { +public: + IPAHeaderInsertionTest003() : + m_aExpectedBufSize(BUFF_MAX_SIZE), + m_nHeadertoAddSize1(0), + m_nHeadertoAddSize2(0), + m_nHeadertoAddSize3(0) + { + m_name = "IPAHeaderInsertionTest003"; + m_description = + "Header Insertion Test 003 - Test RmNet,IEEE802.3 and IEEE802.3 with const (1) addition to the length field\ + 1. Generate and commit two types of header Insertion RmNet and IEE802.3 \ + 2. Generate and commit three routing tables. \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + Routing table 1 is used to add RmNet Header \ + Routing table 2 is used to add IEEE802.3 Header (requires update of the Length field) \ + Routing table 3 is used to add IEEE802.3 Header with additional const (1) to the length field \ + 3. Generate and commit Three filtering rules (MASK = 0xFF..FF). \ + All DST_IP == 127.0.0.1 traffic goes to routing table 1 \ + All DST_IP == 192.169.1.1 traffic goes to routing table 2 \ + All DST_IP == 192.169.1.2 traffic goes to routing table 3"; + + Register(*this); + uint8_t aRMNetHeader[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; + uint8_t aIEEE802_3Header1[22] = { 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0x00, 0x46, 0xAE, 0xAF, 0xB0, + 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6 }; + uint8_t aIEEE802_3Header2[22] = { 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0x00, 0x47, 0xAE, 0xAF, 0xB0, + 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6 }; + m_nHeadertoAddSize1 = sizeof(aRMNetHeader); + memcpy(m_aHeadertoAdd1, aRMNetHeader, m_nHeadertoAddSize1); + m_nHeadertoAddSize2 = sizeof(aIEEE802_3Header1); + memcpy(m_aHeadertoAdd2, aIEEE802_3Header1, m_nHeadertoAddSize2); + m_nHeadertoAddSize3 = sizeof(aIEEE802_3Header2); + memcpy(m_aHeadertoAdd3, aIEEE802_3Header2, m_nHeadertoAddSize3); + } + + // Test Description: + // 1. Generate and commit single bypass routing table. + virtual bool AddRules() { + m_eIP = IPA_IP_v4; + const char aBypass1[20] = "Bypass1"; + const char aBypass2[20] = "Bypass2"; + const char aBypass3[20] = "Bypass3"; + uint32_t nTableHdl01, nTableHdl02, nTableHdl03; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader1,sGetHeader2; + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader1, 0, sizeof(sGetHeader1)); + memset(&sGetHeader2, 0, sizeof(sGetHeader2)); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 2 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 2; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RMNet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, m_aHeadertoAdd1, + m_nHeadertoAddSize1); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = m_nHeadertoAddSize1; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + // Adding Header No2. + strlcpy(pHeaderDescriptor->hdr[1].name, "IEEE_802_3", sizeof(pHeaderDescriptor->hdr[1].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[1].hdr, m_aHeadertoAdd2, + m_nHeadertoAddSize2); //Header's Data + pHeaderDescriptor->hdr[1].hdr_len = m_nHeadertoAddSize2; + pHeaderDescriptor->hdr[1].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[1].is_partial = false; + pHeaderDescriptor->hdr[1].status = -1; // Return Parameter + + strlcpy(sGetHeader1.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader1.name)); + strlcpy(sGetHeader2.name, pHeaderDescriptor->hdr[1].name, sizeof(sGetHeader2.name)); + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader1)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header1 Handle = 0x%x",sGetHeader1.hdl); + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader2)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header2 Handle = 0x%x",sGetHeader2.hdl); + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass1, IPA_CLIENT_TEST2_CONS, + sGetHeader1.hdl,&nTableHdl01)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass2, IPA_CLIENT_TEST3_CONS, + sGetHeader2.hdl,&nTableHdl02)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass3, IPA_CLIENT_TEST4_CONS, + sGetHeader2.hdl,&nTableHdl03)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("Creation of three bypass routing tables completed successfully TblHdl1=0x%x, TblHdl2=0x%x, TblHdl3=0x%x", + nTableHdl01,nTableHdl02,nTableHdl03); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD,false,3); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl01; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering table Failed."); + bRetVal = false; + goto bail; + } + + // Configuring Filtering Rule No.2 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return Value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl02; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) + { + LOG_MSG_ERROR ("Adding Rule(1) to Filtering table Failed."); + bRetVal = false; + goto bail; + } + + // Configuring Filtering Rule No.3 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl03; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + if ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) + { + LOG_MSG_ERROR ("Adding Rule(2) to Filtering table Failed."); + bRetVal = false; + goto bail; + } + + if (!m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable())) { + LOG_MSG_ERROR ("Failed to commit Filtering rules"); + bRetVal = false; + goto bail; + } + + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(1)->status); + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(2)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(2)->status); + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + // This test doesn't modify the original IP Packet. + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + bool bRetVal = true; + m_aExpectedBufSize = 0; + uint32_t nIPv4DSTAddr; + + LOG_MSG_STACK("Entering Function"); + + //Packet No. 1 + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&m_aBuffer[IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr,sizeof(nIPv4DSTAddr)); + memcpy(m_aExpectedBuffer, m_aHeadertoAdd1, m_nHeadertoAddSize1); + memcpy(m_aExpectedBuffer+m_nHeadertoAddSize1,m_aBuffer,m_uBufferSize); + m_aExpectedBufSize = m_nHeadertoAddSize1 + m_uBufferSize; + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Consumer1, m_aExpectedBuffer, m_aExpectedBufSize)) + { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + bRetVal=false; + } + + //Packet No. 2 + memset(m_aExpectedBuffer, 0, sizeof(m_aExpectedBuffer)); + nIPv4DSTAddr = ntohl(0xC0A80101);//192.168.1.1 + memcpy (&m_aBuffer[IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr,sizeof(nIPv4DSTAddr)); + memcpy(m_aExpectedBuffer, m_aHeadertoAdd2, m_nHeadertoAddSize2); + memcpy(m_aExpectedBuffer+m_nHeadertoAddSize2,m_aBuffer,m_uBufferSize); + m_aExpectedBufSize = m_nHeadertoAddSize2 + m_uBufferSize; + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Consumer2, m_aExpectedBuffer, m_aExpectedBufSize)) + { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + bRetVal=false; + } + + //Packet No. 3 + nIPv4DSTAddr = ntohl(0xC0A80102);//192.168.1.2 + memcpy (&m_aBuffer[IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr,sizeof(nIPv4DSTAddr)); + memcpy(m_aExpectedBuffer, m_aHeadertoAdd3, m_nHeadertoAddSize3); + memcpy(m_aExpectedBuffer+m_nHeadertoAddSize3,m_aBuffer,m_uBufferSize); + m_aExpectedBufSize = m_nHeadertoAddSize3 + m_uBufferSize; + if (!SendReceiveAndCompare(&m_producer, m_aBuffer, m_uBufferSize, + &m_Consumer3, m_aExpectedBuffer, m_aExpectedBufSize)) + { + LOG_MSG_ERROR("SendReceiveAndCompare failed."); + bRetVal=false; + } + + LOG_MSG_STACK("Leaving Function (Returning %s)",bRetVal?"True":"False"); + return bRetVal; + } +private: + uint8_t m_aExpectedBuffer[BUFF_MAX_SIZE]; // Input file / IP packet + size_t m_aExpectedBufSize; + uint8_t m_aHeadertoAdd1[MAX_HEADER_SIZE],m_aHeadertoAdd2[MAX_HEADER_SIZE],m_aHeadertoAdd3[MAX_HEADER_SIZE]; + size_t m_nHeadertoAddSize1,m_nHeadertoAddSize2,m_nHeadertoAddSize3; +}; + +class IPAHeaderInsertionTest004: public IPAHeaderInsertionTestFixture { +public: + IPAHeaderInsertionTest004() { + m_name = "IPAHeaderInsertionTest004"; + m_description = + "Header Insertion Test 004 - Test header insertion with bad len values."; + Register(*this); + uint8_t aRMNetHeader[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; + m_nHeadertoAddSize = sizeof(aRMNetHeader); + memcpy(m_aHeadertoAdd, aRMNetHeader, m_nHeadertoAddSize); + } + + virtual bool AddRules() { + // Not adding any rules here. + return true; + } // AddRules() + + virtual bool ModifyPackets() { + // This test doesn't modify the original IP Packet. + return true; + } // ModifyPacktes () + + bool AddSingleHeaderAndCheck(uint8_t len) { + m_eIP = IPA_IP_v4; + bool bRetVal = true; + struct ipa_ioc_get_hdr sRetHeader; + memset(&sRetHeader, 0, sizeof(sRetHeader)); + strlcpy(sRetHeader.name, "Generic", sizeof(sRetHeader.name)); + + LOG_MSG_STACK("Entering Function"); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + strlcpy(pHeaderDescriptor->hdr[0].name, sRetHeader.name, sizeof(pHeaderDescriptor->hdr[0].name)); + memcpy(pHeaderDescriptor->hdr[0].hdr, m_aHeadertoAdd, + m_nHeadertoAddSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + strlcpy(sRetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sRetHeader.name)); + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sRetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddSingleHeaderAndCheck() + + virtual bool TestLogic() { + + // Try to add headers with invalid values. + // Valid values are between 1 to IPA_HDR_MAX_SIZE (64). + // We expect the below functions to fail. + if (AddSingleHeaderAndCheck(0)) { + LOG_MSG_ERROR("This is unexpected, this can't succeed"); + return false; + } + + if (AddSingleHeaderAndCheck(MAX_HEADER_SIZE + 1)) { + LOG_MSG_ERROR("This is unexpected, this can't succeed"); + return false; + } + + // Add one header which is OK + if (!AddSingleHeaderAndCheck(m_nHeadertoAddSize)) { + LOG_MSG_ERROR("This is unexpected, this can't succeed"); + return false; + } + return true; + } + +private: + uint8_t m_aHeadertoAdd[MAX_HEADER_SIZE]; + size_t m_nHeadertoAddSize; +}; + +class IPAHeaderInsertionTest005: public IPAHeaderInsertionTestFixture { +public: + IPAHeaderInsertionTest005() { + m_name = "IPAHeaderInsertionTest005"; + m_description = + "Header Insertion Test 005 - Test Multiple RMNet Header Insertion\ + - Stress test - Generate and commit multiple header Insertion"; + this->m_runInRegression = false; + Register(*this); + uint8_t aRMNetHeader[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; + m_nHeadertoAddSize = sizeof(aRMNetHeader); + memcpy(m_aHeadertoAdd, aRMNetHeader, m_nHeadertoAddSize); + } + + // Test Description: + // 1. Generate and commit single bypass routing table. + virtual bool AddRules() { + m_eIP = IPA_IP_v4; + bool bRetVal = true; + struct ipa_ioc_get_hdr sRetHeader; + char Name[] = "IEEE802_3\0"; + + memset(&sRetHeader, 0, sizeof(sRetHeader)); + strlcpy (sRetHeader.name, Name, sizeof(sRetHeader.name)); + LOG_MSG_STACK("Entering Function"); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + strlcpy(pHeaderDescriptor->hdr[0].name, sRetHeader.name, sizeof(pHeaderDescriptor->hdr[0].name)); + memcpy(pHeaderDescriptor->hdr[0].hdr, m_aHeadertoAdd, + m_nHeadertoAddSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = m_nHeadertoAddSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + strlcpy(sRetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sRetHeader.name)); + + // stress test to check if the target crashes, failure is expected before reaching 500 + for (int i = 0; i < 500; i++) { + LOG_MSG_DEBUG("IPAHeaderInsertionTest005::AddRules iter=%d\n",i); + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed on %d iteration.\n",i); + goto bail; + } + } + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + virtual bool ModifyPackets() { + // This test doesn't modify the original IP Packet. + return true; + } // ModifyPacktes () + + virtual bool TestLogic() { + return true; + } +private: + uint8_t m_aHeadertoAdd[MAX_HEADER_SIZE]; + size_t m_nHeadertoAddSize; +}; + +static IPAHeaderInsertionTest001 ipaHeaderInsertionTest001; +static IPAHeaderInsertionTest002 ipaHeaderInsertionTest002; +static IPAHeaderInsertionTest003 ipaHeaderInsertionTest003; +static IPAHeaderInsertionTest004 ipaHeaderInsertionTest004; +static IPAHeaderInsertionTest005 ipaHeaderInsertionTest005; + diff --git a/kernel-tests/HeaderProcessingContextTestFixture.cpp b/kernel-tests/HeaderProcessingContextTestFixture.cpp new file mode 100644 index 0000000000..08c3a6de6c --- /dev/null +++ b/kernel-tests/HeaderProcessingContextTestFixture.cpp @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "HeaderProcessingContextTestFixture.h" +#include "TestsUtils.h" + +const Byte IpaHdrProcCtxTestFixture::WLAN_ETH2_HDR[WLAN_ETH2_HDR_SIZE] = +{ + // WLAN hdr - 4 bytes + 0xa1, 0xb2, 0xc3, 0xd4, + + // ETH2 - 14 bytes + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +const Byte IpaHdrProcCtxTestFixture::ETH2_HDR[ETH_HLEN] = +{ + // ETH2 - 14 bytes + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +const Byte IpaHdrProcCtxTestFixture::ETH2_8021Q_HDR[ETH8021Q_HEADER_LEN] = +{ + // 802_1Q - 18 bytes + // src and dst MAC - 6 + 6 bytes + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // 802_1Q tag - VLAN ID 3 + 0x81, 0x00, 0x00, 0x03, + // ethertype + 0x00, 0x00 +}; + +const Byte IpaHdrProcCtxTestFixture::WLAN_802_3_HDR[WLAN_802_3_HDR_SIZE] = +{ + // WLAN hdr - 4 bytes + 0x0a, 0x0b, 0x0c, 0x0d, + + // 802_3 - 26 bytes + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +IpaHdrProcCtxTestFixture::IpaHdrProcCtxTestFixture(): + m_procCtxHandleId(PROC_CTX_HANDLE_ID_MAX), + m_pCurrentProducer(NULL), + m_pCurrentConsumer(NULL), + m_sendSize1 (m_BUFF_MAX_SIZE), + m_sendSize2 (m_BUFF_MAX_SIZE), + m_expectedBufferSize1(0), + m_IpaIPType(IPA_IP_v4) +{ + memset(m_headerHandles, 0, sizeof(m_headerHandles)); + memset(m_procCtxHHandles, 0, sizeof(m_procCtxHHandles)); + memset(m_sendBuffer1, 0, sizeof(m_sendBuffer1)); + memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2)); + memset(m_expectedBuffer1, 0, sizeof(m_expectedBuffer1)); + m_testSuiteName.push_back("HdrProcCtx"); +} + +bool IpaHdrProcCtxTestFixture::Setup() +{ + ConfigureScenario(PHASE_TWENTY_TEST_CONFIGURATION); + + // init producers + m_rndisEth2Producer.Open(INTERFACE0_TO_IPA_DATA_PATH, + INTERFACE0_FROM_IPA_DATA_PATH); + m_wlanEth2producer.Open(INTERFACE4_TO_IPA_DATA_PATH, + INTERFACE4_FROM_IPA_DATA_PATH); + m_eth2Producer.Open(INTERFACE5_TO_IPA_DATA_PATH, + INTERFACE5_FROM_IPA_DATA_PATH); + + // init consumers + m_defaultConsumer.Open(INTERFACE1_TO_IPA_DATA_PATH, + INTERFACE1_FROM_IPA_DATA_PATH); + m_rndisEth2Consumer.Open(INTERFACE2_TO_IPA_DATA_PATH, + INTERFACE2_FROM_IPA_DATA_PATH); + + if (!m_headerInsertion.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("HeaderInsertion block is not ready " + "for immediate commands!\n"); + return false; + } + + if (!m_routing.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Routing block is not ready " + "for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Filtering block is not ready " + "for immediate commands!\n"); + return false; + } + + // resetting this component will reset + // both Routing and Filtering tables + m_headerInsertion.Reset(); + + return true; +} // Setup() + +bool IpaHdrProcCtxTestFixture::Teardown() +{ + m_rndisEth2Producer.Close(); + m_wlanEth2producer.Close(); + m_eth2Producer.Close(); + m_defaultConsumer.Close(); + m_rndisEth2Consumer.Close(); + return true; +} // Teardown() + +void IpaHdrProcCtxTestFixture::AddAllHeaders() +{ + for (int i = 0; i < HEADER_HANDLE_ID_MAX; i++) { + AddHeader(static_cast(i)); + } +} + +// Insert a single header +void IpaHdrProcCtxTestFixture::AddHeader(HeaderHandleId handleId) +{ + static const int NUM_OF_HEADERS = 1; + struct ipa_ioc_add_hdr *hdrTable = NULL; + struct ipa_hdr_add *hdr = NULL; + + // init hdr table + hdrTable = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + NUM_OF_HEADERS * sizeof(struct ipa_hdr_add)); + if (!hdrTable) + { + LOG_MSG_ERROR( + "calloc failed to allocate pHeaderDescriptor"); + return; + } + hdrTable->commit = true; + hdrTable->num_hdrs = NUM_OF_HEADERS; + + // init the hdr common fields + hdr = &hdrTable->hdr[0]; + hdr->hdr_hdl = -1; //Return Value + hdr->is_partial = false; + hdr->status = -1; // Return Parameter + + // init hdr specific fields + switch (handleId) + { + case HEADER_HANDLE_ID_WLAN_ETH2: + memcpy(hdr->hdr, WLAN_ETH2_HDR, WLAN_ETH2_HDR_SIZE); + hdr->hdr_len = WLAN_ETH2_HDR_SIZE; + + strlcpy(hdr->name, "WLAN_ETH2", sizeof(hdr->name)); + hdr->type = IPA_HDR_L2_ETHERNET_II; + break; + + case HEADER_HANDLE_ID_RNDIS_ETH2: + if (!RNDISAggregationHelper::LoadRNDISEth2IP4Header( + hdr->hdr, + IPA_HDR_MAX_SIZE, + 0, + (size_t*)&hdr->hdr_len)) + return; + + strlcpy(hdr->name, "RNDIS_ETH2", sizeof(hdr->name)); + hdr->type = IPA_HDR_L2_ETHERNET_II; + break; + + case HEADER_HANDLE_ID_ETH2: + strlcpy(hdr->name, "ETH2", sizeof(hdr->name)); + memcpy(hdr->hdr, ETH2_HDR, ETH_HLEN); + hdr->type = IPA_HDR_L2_ETHERNET_II; + hdr->hdr_len = ETH_HLEN; + + break; + + case HEADER_HANDLE_ID_WLAN_802_3: + strlcpy(hdr->name, "WLAN_802_3", sizeof(hdr->name)); + memcpy(hdr->hdr, WLAN_802_3_HDR, WLAN_802_3_HDR_SIZE); + hdr->type = IPA_HDR_L2_802_3; + hdr->hdr_len = WLAN_802_3_HDR_SIZE; + + LOG_MSG_DEBUG( + "HEADER_HANDLE_ID_WLAN_802_3 NOT supported for now"); + return; + + break; + case HEADER_HANDLE_ID_VLAN_802_1Q: + strlcpy(hdr->name, "VLAN_8021Q", sizeof(hdr->name)); + memcpy(hdr->hdr, ETH2_8021Q_HDR, ETH8021Q_HEADER_LEN); + hdr->type = IPA_HDR_L2_802_1Q; + hdr->hdr_len = ETH8021Q_HEADER_LEN; + break; + + default: + LOG_MSG_ERROR("header handleId not supported."); + return; + } + + // commit header to HW + if (!m_headerInsertion.AddHeader(hdrTable)) + { + LOG_MSG_ERROR("m_headerInsertion.AddHeader() failed."); + return; + } + + // save header handle + m_headerHandles[handleId] = hdr->hdr_hdl; +} + +void IpaHdrProcCtxTestFixture::AddAllProcCtx() +{ + for (int i = 0; i (i)); + } +} + +// Insert a single proc_ctx +void IpaHdrProcCtxTestFixture::AddProcCtx(ProcCtxHandleId handleId) +{ + static const int NUM_OF_PROC_CTX = 1; + struct ipa_ioc_add_hdr_proc_ctx *procCtxTable = NULL; + struct ipa_hdr_proc_ctx_add *procCtx = NULL; + + // init proc ctx table + procCtxTable = (struct ipa_ioc_add_hdr_proc_ctx *)calloc(1, + sizeof(struct ipa_ioc_add_hdr_proc_ctx) + + NUM_OF_PROC_CTX * + sizeof(struct ipa_hdr_proc_ctx_add)); + if (!procCtxTable) + { + LOG_MSG_ERROR("calloc failed to allocate procCtxTable"); + return; + } + + procCtxTable->commit = true; + procCtxTable->num_proc_ctxs = NUM_OF_PROC_CTX; + + // init proc_ctx common fields + procCtx = &procCtxTable->proc_ctx[0]; + procCtx->proc_ctx_hdl = -1; // return value + procCtx->status = -1; // Return parameter + + // init proc_ctx specific fields + switch (handleId) + { + case PROC_CTX_HANDLE_ID_ETH2_2_WLAN_ETH2: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_WLAN_ETH2]; + break; + + case PROC_CTX_HANDLE_ID_ETH2_2_RNDIS_ETH2: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_RNDIS_ETH2]; + break; + + case PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_ETH2]; + break; + + case PROC_CTX_HANDLE_ID_WLAN_ETH2_2_802_3: + procCtx->type = IPA_HDR_PROC_ETHII_TO_802_3; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_WLAN_802_3]; + break; + + case PROC_CTX_HANDLE_ID_RNDIS_802_3_2_ETH2: + procCtx->type = IPA_HDR_PROC_802_3_TO_ETHII; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_RNDIS_ETH2]; + break; + + case PROC_CTX_HANDLE_ID_WLAN_802_3_2_ETH2: + procCtx->type = IPA_HDR_PROC_802_3_TO_802_3; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_WLAN_802_3]; + break; + case PROC_CTX_HANDLE_ID_802_1Q_2_802_1Q: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_VLAN_802_1Q]; + procCtx->generic_params.input_ethhdr_negative_offset = 18; + procCtx->generic_params.output_ethhdr_negative_offset = 18; + break; + case PROC_CTX_HANDLE_ID_802_1Q_2_ETH2: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_ETH2]; + procCtx->generic_params.input_ethhdr_negative_offset = 18; + procCtx->generic_params.output_ethhdr_negative_offset = 14; + break; + case PROC_CTX_HANDLE_ID_ETH2_2_802_1Q: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_VLAN_802_1Q]; + procCtx->generic_params.input_ethhdr_negative_offset = 14; + procCtx->generic_params.output_ethhdr_negative_offset = 18; + break; + case PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2_EX: + procCtx->type = IPA_HDR_PROC_ETHII_TO_ETHII_EX; + procCtx->hdr_hdl = + m_headerHandles[HEADER_HANDLE_ID_ETH2]; + procCtx->generic_params.input_ethhdr_negative_offset = 14; + procCtx->generic_params.output_ethhdr_negative_offset = 14; + break; + + default: + LOG_MSG_ERROR("proc ctx handleId %d not supported.", handleId); + return; + } + + if (!m_headerInsertion.AddProcCtx(procCtxTable)) + { + LOG_MSG_ERROR("m_headerInsertion.AddProcCtx(procCtxTable) failed."); + return; + } + + // save proc_ctx handle + m_procCtxHHandles[handleId] = procCtx->proc_ctx_hdl; +} + +void IpaHdrProcCtxTestFixture::AddRtBypassRule(uint32_t hdrHdl, uint32_t procCtxHdl) +{ + static const char bypass0[] = "bypass0"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateIPv4BypassRoutingTable ( + bypass0, + hdrHdl, + procCtxHdl)) + { + LOG_MSG_ERROR("CreateIPv4BypassRoutingTable Failed\n"); + return; + } + + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable() Failed."); + return; + } + + m_routingTableHdl = routing_table0.hdl; +} + +void IpaHdrProcCtxTestFixture::AddFltBypassRule() +{ + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + + FilterTable0.Init(IPA_IP_v4,m_currProducerClient,false,1); + printf("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl=m_routingTableHdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Mask - Bypass rule + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x12345678; // Filter is irrelevant. + if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule( + FilterTable0.GetFilteringTable())) + { + LOG_MSG_ERROR( + "%s::m_filtering.AddFilteringRule() failed", + __FUNCTION__); + return; + } + else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", + FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, + FilterTable0.ReadRuleFromTable(0)->status); + } +} + +bool IpaHdrProcCtxTestFixture::ReceivePacketsAndCompare() +{ + size_t receivedBufferSize1 = 0; + bool isSuccess = true; + + // Receive results + Byte *receivedBuffer1 = new Byte[m_BUFF_MAX_SIZE]; + + if (NULL == receivedBuffer1) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedBufferSize1 = m_pCurrentConsumer->ReceiveData( + receivedBuffer1, + m_BUFF_MAX_SIZE); + printf("Received %zu bytes on %s.\n", + receivedBufferSize1, + m_pCurrentConsumer->m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGolden( + m_expectedBuffer1, + m_expectedBufferSize1, + receivedBuffer1, + receivedBufferSize1)) + { + printf("Comparison of Buffer Failed!\n"); + isSuccess = false; + } + + printf("Expected buffer 1 - %zu bytes\n", m_expectedBufferSize1); + print_buff(m_expectedBuffer1, m_expectedBufferSize1); + + printf("Received buffer 1 - %zu bytes\n", receivedBufferSize1); + print_buff(receivedBuffer1, receivedBufferSize1); + + delete[] receivedBuffer1; + + return isSuccess; +} + +// Create 1 IPv4 bypass routing entry and commits it +bool IpaHdrProcCtxTestFixture::CreateIPv4BypassRoutingTable ( + const char *name, + uint32_t hdrHdl, + uint32_t procCtxHdl) +{ + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + struct ipa_ioc_add_rt_rule *rt_table = 0; + struct ipa_rt_rule_add *rt_rule_entry = NULL; + + // Verify that only one is nonzero + if ((hdrHdl == 0 && procCtxHdl == 0) || + (hdrHdl != 0 && procCtxHdl != 0)) + { + LOG_MSG_ERROR("Error: hdrHdl = %u, procCtxHdl = %u\n"); + return false; + } + + rt_table = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if(!rt_table) { + LOG_MSG_ERROR("calloc failed to allocate rt_table\n"); + return false; + } + + rt_table->num_rules = 1; + rt_table->ip = IPA_IP_v4; + rt_table->commit = true; + strlcpy(rt_table->rt_tbl_name, name, sizeof(rt_table->rt_tbl_name)); + + rt_rule_entry = &rt_table->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = m_currConsumerPipeNum; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + + // All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000; + rt_rule_entry->rule.hdr_hdl = hdrHdl; + rt_rule_entry->rule.hdr_proc_ctx_hdl = procCtxHdl; + if (false == m_routing.AddRoutingRule(rt_table)) + { + printf("Routing rule addition(rt_table) failed!\n"); + Free (rt_table); + return false; + } + + Free (rt_table); + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; +} + +bool IpaHdrProcCtxTestFixture::AddRules() +{ + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + if (m_procCtxHandleId == PROC_CTX_HANDLE_ID_MAX) + { + LOG_MSG_ERROR("Test developer didn't implement " + "AddRules() or didn't set m_procCtxHandleId"); + return false; + } + + AddAllHeaders(); + + AddAllProcCtx(); + + AddRtBypassRule(0, m_procCtxHHandles[m_procCtxHandleId]); + + AddFltBypassRule(); + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + +}// AddRules() + +bool IpaHdrProcCtxTestFixture::SendPackets() +{ + + bool isSuccess = false; + + // Send first packet + isSuccess = m_pCurrentProducer->SendData( + m_sendBuffer1, + m_sendSize1); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendPackets Buffer1 failed on client %d\n", m_currProducerClient); + return false; + } + + return true; +} + +bool IpaHdrProcCtxTestFixture::Run() +{ + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data - IP packets + res = LoadPackets(m_IpaIPType); + if (false == res) { + printf("Failed loading packets.\n"); + return false; + } + + res = GenerateExpectedPackets(); + if (false == res) { + printf("GenerateExpectedPackets failed\n"); + return false; + } + + res = SendPackets(); + if (false == res) { + printf("SendPackets failed\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + printf("Leaving %s, %s(), Returning %d\n", + __FUNCTION__, + __FILE__, + isSuccess); + + return isSuccess; +} // Run() + +IpaHdrProcCtxTestFixture::~IpaHdrProcCtxTestFixture() +{ + m_sendSize1 = 0; +} + +RoutingDriverWrapper IpaHdrProcCtxTestFixture::m_routing; +Filtering IpaHdrProcCtxTestFixture::m_filtering; +HeaderInsertion IpaHdrProcCtxTestFixture::m_headerInsertion; + diff --git a/kernel-tests/HeaderProcessingContextTestFixture.h b/kernel-tests/HeaderProcessingContextTestFixture.h new file mode 100644 index 0000000000..1667b8cd99 --- /dev/null +++ b/kernel-tests/HeaderProcessingContextTestFixture.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#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 "Filtering.h" +#include "HeaderInsertion.h" +#include "RoutingDriverWrapper.h" +#include "IPAFilteringTable.h" + +/* +Processing context test design: + +1. 1 Producer with RNDIS de-aggregation and ETH2 header removal. +2. 1 Producer with WLAN and ETH2 header removal. +3. 1 default consumer. +4. 1 RNDIS aggregation consumer. +5. 1 FLT rule – accept all - points to 1 RT rule. +6. 1 RT rule – accept all - points to specific test relevant proc_ctx. +7. All tests add all proc_ctx (for all tests). +8. Proc_ctx to be added: 1 for each test – 3 altogether. + Proc_ctx of test 01 and 03 are the same. +9. Each test will send 1 packet and check that the packet is good + except test 03. +10. Test 03 the same as Test 01 but will send multiple packets + and expect 1 (RNDIS aggregation test). + +List of tests: +00. Header insertion scenario of [RNDIS][ETH_II][IP] -> [WLAN][ETH_II][IP] +01. Header insertion scenario of [WLAN][ETH_II][IP] -> [RNDIS][ETH_II][IP] +02. Header insertion scenario of [WLAN][ETH_II][IP] -> [WLAN’][ETH_II][IP] +03. Header insertion of [WLAN][ETH_II][IP] -> [RNDIS][ETH_II][IP] + with RNDIS aggregation. +04. Header insertion scenario when adding total header sizes > 2048 +05. Header insertion scenario of [ETH_II][IP] -> [WLAN][ETH_II][IP] +06. Header insertion scenario of [WLAN][ETH_II][IP] -> [ETH_II][IP +07. Header insertion scenario of [ETH_II][IP] -> [ETH_II][IP] +08. Header insertion scenario of [RNDIS][ETH_II][IP] -> [WLAN][802.3][IP] +09. Header insertion scenario of [WLAN][802.3][IP] -> [RNDIS][ETH_II][IP] +10. Header insertion scenario of [ETH_II][IP] -> [WLAN][802.3][IP] +11. Header insertion scenario of [WLAN][802.3][IP] -> [WLAN’][802.3][IP] +*/ +class IpaHdrProcCtxTestFixture : public TestBase +{ +public: + enum HeaderHandleId + { + HEADER_HANDLE_ID_WLAN_ETH2, + HEADER_HANDLE_ID_RNDIS_ETH2, + HEADER_HANDLE_ID_ETH2, + HEADER_HANDLE_ID_WLAN_802_3, + HEADER_HANDLE_ID_VLAN_802_1Q, + HEADER_HANDLE_ID_MAX + }; + + enum ProcCtxHandleId + { + PROC_CTX_HANDLE_ID_ETH2_2_WLAN_ETH2, + PROC_CTX_HANDLE_ID_ETH2_2_RNDIS_ETH2, + PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2, + PROC_CTX_HANDLE_ID_WLAN_ETH2_2_802_3, + PROC_CTX_HANDLE_ID_RNDIS_802_3_2_ETH2, + PROC_CTX_HANDLE_ID_WLAN_802_3_2_ETH2, + PROC_CTX_HANDLE_ID_802_1Q_2_802_1Q, + PROC_CTX_HANDLE_ID_ETH2_2_802_1Q, + PROC_CTX_HANDLE_ID_802_1Q_2_ETH2, + PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2_EX, + PROC_CTX_HANDLE_ID_MAX + }; + + // header table consist of 9 bits and 4B units -> 2048 + static const int m_ALL_HEADER_SIZE_LIMIT = 2048; + + static const size_t m_BUFF_MAX_SIZE = + 2 * RNDISAggregationHelper::RNDIS_AGGREGATION_BYTE_LIMIT; + + // [WLAN][ETH2] header + static const Byte WLAN_ETH2_HDR[WLAN_ETH2_HDR_SIZE]; + + // [ETH2] header + static const Byte ETH2_HDR[ETH_HLEN]; + + // [ETH2_802_1Q] vlan header + static const Byte ETH2_8021Q_HDR[ETH8021Q_HEADER_LEN]; + + // [WLAN][802.3] header + static const Byte WLAN_802_3_HDR[WLAN_802_3_HDR_SIZE]; + + static Filtering m_filtering; + static RoutingDriverWrapper m_routing; + static HeaderInsertion m_headerInsertion; + + // For each header type the handle is saved + // to be used by the processing context + uint32_t m_headerHandles[HEADER_HANDLE_ID_MAX]; + + // For each prco_ctx type the handle is saved + // to be used by the routing rule + uint32_t m_procCtxHHandles[PROC_CTX_HANDLE_ID_MAX]; + + // proc_ctx handle ID + ProcCtxHandleId m_procCtxHandleId; + + // routing table handle + uint32_t m_routingTableHdl; + + // Pipe with RNDIS and ETH2 header removal + InterfaceAbstraction m_rndisEth2Producer; + + // Pipe with WLAN and ETH2 header removal + InterfaceAbstraction m_wlanEth2producer; + + // Pipe with ETH2 header removal + InterfaceAbstraction m_eth2Producer; + + // TODO: Pipe with WLAN and 802.3 header removal + InterfaceAbstraction m_wlan802_3producer; + + // Pointer to current producer pipe used in the test + InterfaceAbstraction *m_pCurrentProducer; + ipa_client_type m_currProducerClient; + + // Pipe of the WLAN ETH2 consumer + InterfaceAbstraction m_defaultConsumer; + + // Pipe of the RNDIS ETH2 consumer + InterfaceAbstraction m_rndisEth2Consumer; + + // Pointer to current consumer pipe used in the test + InterfaceAbstraction *m_pCurrentConsumer; + ipa_client_type m_currConsumerPipeNum; + + // First input packet + Byte m_sendBuffer1[m_BUFF_MAX_SIZE]; + size_t m_sendSize1; + + // Second input packet + Byte m_sendBuffer2[m_BUFF_MAX_SIZE]; + size_t m_sendSize2; + + // First expected packet + Byte m_expectedBuffer1[m_BUFF_MAX_SIZE]; + size_t m_expectedBufferSize1; + + enum ipa_ip_type m_IpaIPType; + + IpaHdrProcCtxTestFixture(); + + virtual bool Setup(); + virtual bool Teardown(); + virtual void AddAllHeaders(); + + // Insert a single header + virtual void AddHeader(HeaderHandleId handleId); + virtual void AddAllProcCtx(); + + // Insert a single proc_ctx + virtual void AddProcCtx(ProcCtxHandleId handleId); + virtual void AddRtBypassRule(uint32_t hdrHdl, uint32_t procCtxHdl); + virtual void AddFltBypassRule(); + virtual bool LoadPackets(enum ipa_ip_type ip) = 0; + + virtual bool ReceivePacketsAndCompare(); + + // Create 1 IPv4 bypass routing entry and commits it + virtual bool CreateIPv4BypassRoutingTable ( + const char *name, + uint32_t hdrHdl, + uint32_t procCtxHdl); + + virtual bool GenerateExpectedPackets() = 0; + + virtual bool AddRules(); + + virtual bool SendPackets(); + + virtual bool Run(); + + ~IpaHdrProcCtxTestFixture(); + +private: +}; + diff --git a/kernel-tests/HeaderProcessingContextTests.cpp b/kernel-tests/HeaderProcessingContextTests.cpp new file mode 100644 index 0000000000..bfed1b99e5 --- /dev/null +++ b/kernel-tests/HeaderProcessingContextTests.cpp @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "HeaderProcessingContextTestFixture.h" + +/*----------------------------------------------------------------------------*/ +/* Test00: Header insertion scenario of [RNDIS][ETH_II][IP] -> */ +/* [WLAN][ETH_II][IP] */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest00 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest00() + { + m_name = "IpaHdrProcCtxTest00"; + m_description = + "Processing Context test 00 - \ + of [RNDIS][ETH_II][IP] -> [WLAN][ETH_II][IP] \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use processing context ETH2_2_WLAN_ETH2 \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + m_pCurrentProducer = &m_rndisEth2Producer; + m_currProducerClient = IPA_CLIENT_TEST_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_ETH2_2_WLAN_ETH2; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + if (!RNDISAggregationHelper::LoadRNDISPacket( + ip, + m_sendBuffer1, + m_sendSize1)) + { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf ("Loaded %zu Bytes to Packet 1\n",m_sendSize1); + + add_buff(m_sendBuffer1+RNDIS_HDR_SIZE, ETH_HLEN, 2); + print_buff(m_sendBuffer1, m_sendSize1); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + m_expectedBufferSize1 = WLAN_ETH2_HDR_SIZE + + IP4_PACKET_SIZE; + + // copy WLAN header to the beginning of the buffer + memcpy(m_expectedBuffer1, WLAN_ETH2_HDR, WLAN_HDR_SIZE); + + // copy ETH+IP packet right after WLAN header + memcpy(m_expectedBuffer1 + WLAN_HDR_SIZE, + m_sendBuffer1 + RNDIS_HDR_SIZE, + ETH_HLEN + IP4_PACKET_SIZE); + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test01: Header insertion scenario of [WLAN][ETH_II][IP] -> */ +/* [RNDIS][ETH_II][IP] */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest01 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest01() + { + m_name = "IpaHdrProcCtxTest01"; + m_description = + "Processing context test 01 - \ + of [WLAN][ETH_II][IP] -> [RNDIS][ETH_II][IP] \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST3. \ + Routing rule will use processing context ETH2_2_RNDIS_ETH2 \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + m_pCurrentProducer = &m_wlanEth2producer; + m_currProducerClient = IPA_CLIENT_TEST2_PROD; + m_pCurrentConsumer = &m_rndisEth2Consumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST3_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_ETH2_2_RNDIS_ETH2; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + // load WLAN ETH2 IP4 packet of size 1kB + 1 byte + // This size will trigger RNDIS aggregation later + m_sendSize1 = + RNDISAggregationHelper::RNDIS_AGGREGATION_BYTE_LIMIT + 1; + + if (!WlanHelper::LoadWlanEth2IP4PacketByLength( + m_sendBuffer1, + m_BUFF_MAX_SIZE, + m_sendSize1, + 0x01)) + return false; + + printf ("Loaded %zu Bytes to Packet 1\n",m_sendSize1); + + add_buff(m_sendBuffer1+WLAN_HDR_SIZE, ETH_HLEN, 3); + + print_buff(m_sendBuffer1, m_sendSize1); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + size_t len = 0; + size_t eth2PacketSize = m_sendSize1 - WLAN_HDR_SIZE; + + m_expectedBufferSize1 = eth2PacketSize + RNDIS_HDR_SIZE; + + // copy RNDIS header + if (!RNDISAggregationHelper::LoadRNDISHeader( + m_expectedBuffer1, + m_BUFF_MAX_SIZE, + m_expectedBufferSize1, + &len)) + { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + + // copy ETH2 packet after RNDIS header + memcpy(m_expectedBuffer1 + len, + m_sendBuffer1 + WLAN_HDR_SIZE, + eth2PacketSize); + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test02: Header insertion scenario of [WLAN][ETH_II][IP] -> */ +/* [WLAN'][ETH_II][IP] */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest02 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest02() + { + m_name = "IpaHdrProcCtxTest02"; + m_description = + "Processing context test 02 - \ + of [WLAN][ETH_II][IP] -> [WLAN'][ETH_II][IP] \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use processing context ETH2_2_WLAN_ETH2 \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + m_pCurrentProducer = &m_wlanEth2producer; + m_currProducerClient = IPA_CLIENT_TEST2_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_ETH2_2_WLAN_ETH2; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + // load WLAN ETH2 IP4 packet of size 1kB + // This size will trigger RNDIS aggregation later + if (!WlanHelper::LoadWlanEth2IP4Packet( + m_sendBuffer1, + m_BUFF_MAX_SIZE, + &m_sendSize1)) + return false; + + printf ("Loaded %zu Bytes to Packet 1\n",m_sendSize1); + + add_buff(m_sendBuffer1+WLAN_HDR_SIZE, ETH_HLEN, 5); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + m_expectedBufferSize1 = m_sendSize1; + memcpy(m_expectedBuffer1, m_sendBuffer1, m_expectedBufferSize1); + memcpy(m_expectedBuffer1, WLAN_ETH2_HDR, WLAN_HDR_SIZE); + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test03: Header insertion scenario of [WLAN][ETH_II][IP] -> */ +/* [RNDIS][ETH_II][IP] with RNDIS aggregation */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest03 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest03() + { + m_name = "IpaHdrProcCtxTest03"; + m_description = + "Processing Context test 03 - \ + of [RNDIS][ETH_II][IP] -> [WLAN][ETH_II][IP] \ + with RNDIS aggregation \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST3. \ + Routing rule will use processing context ETH2_2_RNDIS_ETH2 \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + m_pCurrentProducer = &m_wlanEth2producer; + m_currProducerClient = IPA_CLIENT_TEST2_PROD; + m_pCurrentConsumer = &m_rndisEth2Consumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST3_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_ETH2_2_RNDIS_ETH2; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + // choose this size so that 2 such buffers would be aggregated + m_sendSize1 = RNDISAggregationHelper:: + RNDIS_AGGREGATION_BYTE_LIMIT / 2 + 200; + + if (!WlanHelper::LoadWlanEth2IP4PacketByLength( + m_sendBuffer1, + m_BUFF_MAX_SIZE, + m_sendSize1, + 1)) + return false; + + printf ("Loaded %zu Bytes to Packet 1\n", m_sendSize1); + + add_buff(m_sendBuffer1+WLAN_HDR_SIZE, ETH_HLEN, 7); + + // choose this size so that 2 such buffers would be aggregated + m_sendSize2 = RNDISAggregationHelper:: + RNDIS_AGGREGATION_BYTE_LIMIT / 2 + 200; + + if (!WlanHelper::LoadWlanEth2IP4PacketByLength( + m_sendBuffer2, + m_BUFF_MAX_SIZE, + m_sendSize2, + 2)) + return false; + + printf ("Loaded %zu Bytes to Packet 2\n", m_sendSize2); + + add_buff(m_sendBuffer2+WLAN_HDR_SIZE, ETH_HLEN, 11); + + return true; + } + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send packet 1 + isSuccess = m_pCurrentProducer->SendData( + m_sendBuffer1, + m_sendSize1); + if (false == isSuccess) + { + LOG_MSG_ERROR( + "SendData Buffer 1 failed on producer %d\n", m_currProducerClient); + return false; + } + + // Send packet 2 + isSuccess = m_pCurrentProducer->SendData( + m_sendBuffer2, + m_sendSize2); + if (false == isSuccess) + { + LOG_MSG_ERROR( + "SendData Buffer 2 failed on producer %d\n", m_currProducerClient); + return false; + } + + return true; + } + + virtual bool GenerateExpectedPackets() + { + size_t len = 0; + size_t eth2PacketSize1 = m_sendSize1 - WLAN_HDR_SIZE; + size_t rndisPacketSize1 = eth2PacketSize1 + RNDIS_HDR_SIZE; + size_t eth2PacketSize2 = m_sendSize2 - WLAN_HDR_SIZE; + size_t rndisPacketSize2 = eth2PacketSize2 + RNDIS_HDR_SIZE; + Byte *currBuffLocation = NULL; + + m_expectedBufferSize1 = rndisPacketSize1 + rndisPacketSize2; + + currBuffLocation = m_expectedBuffer1; + + // copy first RNDIS header + if (!RNDISAggregationHelper::LoadRNDISHeader( + currBuffLocation, + m_BUFF_MAX_SIZE, + rndisPacketSize1, + &len)) + return false; + + // copy ETH2 packet 1 after RNDIS header + currBuffLocation += len; + memcpy(currBuffLocation, + m_sendBuffer1 + WLAN_HDR_SIZE, + eth2PacketSize1); + + // copy second RNDIS header + currBuffLocation += eth2PacketSize1; + if (!RNDISAggregationHelper::LoadRNDISHeader( + currBuffLocation, + m_BUFF_MAX_SIZE - rndisPacketSize1, + rndisPacketSize2, + &len)) + return false; + + // copy ETH2 packet 2 after RNDIS header + currBuffLocation += len; + memcpy(currBuffLocation, + m_sendBuffer2 + WLAN_HDR_SIZE, + eth2PacketSize2); + + return true; + } // GenerateExpectedPackets() +}; + + +/*----------------------------------------------------------------------------*/ +/* Test04: Header insertion scenario when adding total header sizes > 2048 */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest04 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest04() + { + m_name = "IpaHdrProcCtxTest04"; + m_description = + "Processing context test 04 - \ + Header insertion scenario when adding \ + total header sizes > 2048 \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use header WLAN_ETH2 \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + m_pCurrentProducer = &m_wlanEth2producer; + m_currProducerClient = IPA_CLIENT_TEST2_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_minIPAHwType = IPA_HW_v2_5; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual void AddAllHeaders() + { + int cnt = 0; + int allHeadersSize = 0; + + while (allHeadersSize <= m_ALL_HEADER_SIZE_LIMIT) + { + AddHeader(HEADER_HANDLE_ID_ETH2); + /* header bins are power of 2 */ + allHeadersSize += ETH_HLEN + 2; + cnt++; + } + + AddHeader(HEADER_HANDLE_ID_WLAN_ETH2); + } + + virtual bool AddRules() + { + printf("Entering %s, %s()\n",__FUNCTION__, __FILE__); + + AddAllHeaders(); + + AddRtBypassRule(m_headerHandles[HEADER_HANDLE_ID_WLAN_ETH2], 0); + + AddFltBypassRule(); + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + + }// AddRules() + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + // load WLAN ETH2 IP4 packet of size 1kB + // This size will trigger RNDIS aggregation later + if (!WlanHelper::LoadWlanEth2IP4Packet( + m_sendBuffer1, + m_BUFF_MAX_SIZE, + &m_sendSize1)) + return false; + + printf ("Loaded %zu Bytes to Packet 1\n",m_sendSize1); + + add_buff(m_sendBuffer1+WLAN_HDR_SIZE, ETH_HLEN, 13); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + m_expectedBufferSize1 = m_sendSize1; + memcpy(m_expectedBuffer1, m_sendBuffer1, m_expectedBufferSize1); + memcpy(m_expectedBuffer1, WLAN_ETH2_HDR, WLAN_ETH2_HDR_SIZE); + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test05: Header insertion scenario of [ETH_II_802_1Q][IP] -> */ +/* [ETH_II_802_1Q][IP] */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest05 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest05() + { + m_name = "IpaHdrProcCtxTest05"; + m_description = + "Processing Context test 05 - \ + of [ETH_II_802_1Q][IP] -> [ETH_II_802_1Q][IP] \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use processing context 802_1Q_2_802_1Q \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + /* + * NOTE: we use the wlan + ETH header prod pipe since the header + * length shall be equal to 8021Q ETH_II length + */ + m_pCurrentProducer = &m_wlanEth2producer; + m_currProducerClient = IPA_CLIENT_TEST2_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_802_1Q_2_802_1Q; + m_minIPAHwType = IPA_HW_v4_0; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + if (!LoadDefault802_1Q(ip, + m_sendBuffer1, + m_sendSize1)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf("Loaded %zu Bytes to Packet 1\n", m_sendSize1); + + // modify the MAC addresses only + add_buff(m_sendBuffer1, 12, 14); + + //change vlan ID to 9 + m_sendBuffer1[15] = 0x9; + + print_buff(m_sendBuffer1, m_sendSize1); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + m_expectedBufferSize1 = m_sendSize1; + + // we actually expect the same packet to come out (but after uCP) + memcpy(m_expectedBuffer1, m_sendBuffer1, m_expectedBufferSize1); + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test06: Header insertion scenario of [ETH_II][IP] -> */ +/* [ETH_II_802_1Q][IP] */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest06 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest06() + { + m_name = "IpaHdrProcCtxTest06"; + m_description = + "Processing Context test 06 - \ + of [ETH_II][IP] -> [ETH_II_802_1Q][IP] \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use processing context ETH2_2_802_1Q \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + + m_pCurrentProducer = &m_eth2Producer; + m_currProducerClient = IPA_CLIENT_TEST3_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_ETH2_2_802_1Q; + m_minIPAHwType = IPA_HW_v4_0; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + if (!Eth2Helper::LoadEth2IP4Packet( + m_sendBuffer1, + m_BUFF_MAX_SIZE, + &m_sendSize1)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + + printf("Loaded %zu Bytes to Packet 1\n", m_sendSize1); + + // modify the MAC addresses only + add_buff(m_sendBuffer1, 12, 15); + + print_buff(m_sendBuffer1, m_sendSize1); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + size_t len; + + m_expectedBufferSize1 = ETH8021Q_HEADER_LEN + + IP4_PACKET_SIZE; + // copy the VLAN header to expected buffer + memcpy(m_expectedBuffer1, ETH2_8021Q_HDR, ETH8021Q_HEADER_LEN); + + // fill src and dst mac and ethertype + memcpy(m_expectedBuffer1, m_sendBuffer1, 2 * ETH_ALEN); + memcpy(m_expectedBuffer1 + ETH8021Q_ETH_TYPE_OFFSET, + m_sendBuffer1 + ETH2_ETH_TYPE_OFFSET, ETH2_ETH_TYPE_LEN); + + len = m_BUFF_MAX_SIZE - ETH8021Q_HEADER_LEN; + if (!LoadDefaultPacket(IPA_IP_v4, + m_expectedBuffer1 + ETH8021Q_HEADER_LEN, + len)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test07: Header insertion scenario of [ETH_II_802_1Q][IP] -> */ +/* [ETH_II][IP] */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest07 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest07() + { + m_name = "IpaHdrProcCtxTest07"; + m_description = + "Processing Context test 07 - \ + of [ETH_II_802_1Q][IP] -> [ETH_II][IP] \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use processing context 802_1Q_2_ETH2 \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + + m_pCurrentProducer = &m_wlanEth2producer; + m_currProducerClient = IPA_CLIENT_TEST2_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_802_1Q_2_ETH2; + m_minIPAHwType = IPA_HW_v4_0; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + if (!LoadDefault802_1Q(ip, + m_sendBuffer1, + m_sendSize1)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + + printf("Loaded %zu Bytes to Packet 1\n", m_sendSize1); + + // modify the MAC addresses only + add_buff(m_sendBuffer1, ETH8021Q_METADATA_OFFSET, 16); + + print_buff(m_sendBuffer1, m_sendSize1); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + size_t len; + + m_expectedBufferSize1 = m_sendSize1 - ETH8021Q_8021Q_TAG_LEN; + + // copy the ETH2 header to expected buffer + memcpy(m_expectedBuffer1, ETH2_HDR, ETH_HLEN); + + // fill src and dst mac and ethertype + memcpy(m_expectedBuffer1, m_sendBuffer1, 2 * ETH_ALEN); + memcpy(m_expectedBuffer1 + ETH2_ETH_TYPE_OFFSET, + m_sendBuffer1 + ETH8021Q_ETH_TYPE_OFFSET, + ETH2_ETH_TYPE_LEN); + + len = m_BUFF_MAX_SIZE - ETH_HLEN; + if (!LoadDefaultPacket(IPA_IP_v4, + m_expectedBuffer1 + ETH_HLEN, + len)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + + return true; + } // GenerateExpectedPackets() +}; + +/*----------------------------------------------------------------------------*/ +/* Test08: Header insertion scenario of [ETH_II][IP] -> */ +/* [ETH_II][IP] with generic ucp command */ +/*----------------------------------------------------------------------------*/ +class IpaHdrProcCtxTest08 : public IpaHdrProcCtxTestFixture +{ +public: + IpaHdrProcCtxTest08() + { + m_name = "IpaHdrProcCtxTest08"; + m_description = + "Processing Context test 08 - \ + of [ETH_II][IP] -> [ETH_II][IP] with generic ucp \ + 1. Generate and commit all headers for all tests. \ + 2. Generate and commit all processing context rules \ + for all tests.\ + 3. Generate and commit routing table 0. \ + The table contains 1 \"bypass\" rule. \ + All data goes to output pipe TEST2. \ + Routing rule will use processing context ETH2_2_ETH2_EX \ + 4. Generate and commit 1 filtering rule. \ + All traffic goes to routing table 0"; + + m_pCurrentProducer = &m_eth2Producer; + m_currProducerClient = IPA_CLIENT_TEST3_PROD; + m_pCurrentConsumer = &m_defaultConsumer; + m_currConsumerPipeNum = IPA_CLIENT_TEST2_CONS; + m_procCtxHandleId = PROC_CTX_HANDLE_ID_ETH2_ETH2_2_ETH2_EX; + m_minIPAHwType = IPA_HW_v4_0; + m_maxIPAHwType = IPA_HW_MAX; + m_runInRegression = false; + Register(*this); + } + + virtual bool LoadPackets(enum ipa_ip_type ip) + { + if (!Eth2Helper::LoadEth2IP4Packet( + m_sendBuffer1, + m_BUFF_MAX_SIZE, + &m_sendSize1)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + + printf("Loaded %zu Bytes to Packet 1\n", m_sendSize1); + + // modify the MAC addresses only + add_buff(m_sendBuffer1, 12, 17); + + print_buff(m_sendBuffer1, m_sendSize1); + + return true; + } + + virtual bool GenerateExpectedPackets() + { + m_expectedBufferSize1 = m_sendSize1; + + // we actually expect the same packet to come out (but after uCP) + memcpy(m_expectedBuffer1, m_sendBuffer1, m_expectedBufferSize1); + + return true; + } // GenerateExpectedPackets() +}; + +static IpaHdrProcCtxTest00 ipaHdrProcCtxTest00; +static IpaHdrProcCtxTest01 ipaHdrProcCtxTest01; +static IpaHdrProcCtxTest02 ipaHdrProcCtxTest02; +static IpaHdrProcCtxTest03 ipaHdrProcCtxTest03; +static IpaHdrProcCtxTest04 ipaHdrProcCtxTest04; +static IpaHdrProcCtxTest05 ipaHdrProcCtxTest05; +static IpaHdrProcCtxTest06 ipaHdrProcCtxTest06; +static IpaHdrProcCtxTest07 ipaHdrProcCtxTest07; +static IpaHdrProcCtxTest08 ipaHdrProcCtxTest08; diff --git a/kernel-tests/HeaderRemovalTestFixture.cpp b/kernel-tests/HeaderRemovalTestFixture.cpp new file mode 100644 index 0000000000..3067b95caf --- /dev/null +++ b/kernel-tests/HeaderRemovalTestFixture.cpp @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2017 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 "HeaderRemovalTestFixture.h" + +#include "Constants.h" +#include "Logger.h" +#include "IPAFilteringTable.h" + +#define IPA_TEST_DMUX_HEADER_LENGTH 8 +#define IPA_TEST_META_DATA_IS_VALID 1 +#define IPA_TEST_DMUX_HEADER_META_DATA_OFFSET 4 + +extern Logger g_Logger; + +///////////////////////////////////////////////////////////////////////////////// + +//define the static Pipes which will be used by all derived tests. +Pipe HeaderRemovalTestFixture::m_A2NDUNToIpaPipe(IPA_CLIENT_TEST2_PROD, IPA_TEST_CONFIFURATION_3); +Pipe HeaderRemovalTestFixture::m_IpaToUsbPipe(IPA_CLIENT_TEST_CONS, IPA_TEST_CONFIFURATION_3); +Pipe HeaderRemovalTestFixture::m_IpaToA2NDUNPipe(IPA_CLIENT_TEST2_CONS, IPA_TEST_CONFIFURATION_3); +Pipe HeaderRemovalTestFixture::m_IpaToQ6LANPipe(IPA_CLIENT_TEST4_CONS, IPA_TEST_CONFIFURATION_3); +RoutingDriverWrapper HeaderRemovalTestFixture::m_routing; +Filtering HeaderRemovalTestFixture::m_filtering; +const char HeaderRemovalTestFixture_bypass0[20] = "Bypass0"; +const char HeaderRemovalTestFixture_bypassIPv60[20] = "BypassIPv60"; + +///////////////////////////////////////////////////////////////////////////////// + +HeaderRemovalTestFixture::HeaderRemovalTestFixture() +{ + m_testSuiteName.push_back("Removal"); + Register(*this); +} + +static int SetupKernelModule(void) +{ + int retval; + struct ipa_channel_config from_ipa_channels[3]; + struct test_ipa_ep_cfg from_ipa_cfg[3]; + 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[3]; + + /* From ipa configurations - 3 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(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])); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1])); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2])); + from_ipa_array[2] = &from_ipa_channels[2]; + + /* To ipa configurations - 1 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + to_ipa_cfg[0].hdr.hdr_len = IPA_TEST_DMUX_HEADER_LENGTH; + to_ipa_cfg[0].hdr.hdr_ofst_metadata_valid = IPA_TEST_META_DATA_IS_VALID; + to_ipa_cfg[0].hdr.hdr_ofst_metadata = + IPA_TEST_DMUX_HEADER_META_DATA_OFFSET; + prepare_channel_struct(&to_ipa_channels[0], + header.to_ipa_channels_num++, + IPA_CLIENT_TEST2_PROD, + (void *)&to_ipa_cfg[0], + sizeof(to_ipa_cfg[0])); + to_ipa_array[0] = &to_ipa_channels[0]; + + header.head_marker = IPA_TEST_CONFIG_MARKER; + header.tail_marker = IPA_TEST_CONFIG_MARKER; + + prepare_header_struct(&header, from_ipa_array, to_ipa_array); + + retval = GenericConfigureScenario(&header); + + return retval; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTestFixture::Setup() +{ + bool bRetVal = true; + + //Set the configuration to support USB->IPA and IPA->USB pipes. + //ConfigureScenario(PHASE_THREE_TEST_CONFIGURATION); + + bRetVal = SetupKernelModule(); + if (bRetVal != true) { + return bRetVal; + } + + //Initialize the pipe for all the tests - this will open the inode which represents the pipe. + bRetVal &= m_A2NDUNToIpaPipe.Init(); + bRetVal &= m_IpaToUsbPipe.Init(); + bRetVal &= m_IpaToA2NDUNPipe.Init(); + bRetVal &= m_IpaToQ6LANPipe.Init(); + + // remove default "LAN" routing table (as we want to pass to USB pipe) + m_routing.Reset(IPA_IP_v4); + m_routing.Reset(IPA_IP_v6); + + return bRetVal; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTestFixture::Teardown() +{ + //The Destroy method will close the inode. + m_A2NDUNToIpaPipe.Destroy(); + m_IpaToUsbPipe.Destroy(); + m_IpaToA2NDUNPipe.Destroy(); + m_IpaToQ6LANPipe.Destroy(); + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +Byte* HeaderRemovalTestFixture::CreateA2NDUNPacket( + unsigned int magicNumber, + unsigned int nID, + string sPayloadFileName, + unsigned int *nTotalLength) +{ + size_t nIpv4ByteSize = 1024; + bool bRetVal = false; + Byte *pA2NDUNPacket = 0; + unsigned int nA2NDUNPacketByteSize = 0; + Byte *pIpv4Packet = (Byte*) malloc(1024); + + if(0 == pIpv4Packet) + { + LOG_MSG_ERROR("Cannot allocate the memory for IPv4 packet"); + return 0; + } + + bRetVal = LoadDefaultPacket(IPA_IP_v4, pIpv4Packet, nIpv4ByteSize); + if(false == bRetVal) + { + LOG_MSG_ERROR("Cannot load the packet"); + pA2NDUNPacket = 0; + goto bail; + } + //Magic Number(4 Bytes) Logical Channel ID(2 Bytes) Length(2 Bytes) + nA2NDUNPacketByteSize = m_A2NDUNToIpaPipe.GetHeaderLengthAdd() + nIpv4ByteSize; + + pA2NDUNPacket = new Byte[ nA2NDUNPacketByteSize ]; + + //htobe32 for the magic number: + pA2NDUNPacket[0] = (magicNumber & 0xFF000000) >> 24;//MSB + pA2NDUNPacket[1] = (magicNumber & 0x00FF0000) >> 16; + pA2NDUNPacket[2] = (magicNumber & 0x0000FF00) >> 8; + pA2NDUNPacket[3] = (magicNumber & 0x000000FF) >> 0;//LSB + + //htobe16 for the Logical Channel ID: + pA2NDUNPacket[4] = (nID & 0xFF00) >> 8;//MSB + pA2NDUNPacket[5] = (nID & 0x00FF) >> 0;//LSB + + //htobe16 for the Length of the packet: + pA2NDUNPacket[6] = (nA2NDUNPacketByteSize & 0xFF00) >> 8;//MSB + pA2NDUNPacket[7] = (nA2NDUNPacketByteSize & 0x00FF) >> 0;//LSB + + //add the payload to the A2NDUN packet + memcpy(&pA2NDUNPacket[8], pIpv4Packet, nIpv4ByteSize); + + *nTotalLength = nA2NDUNPacketByteSize; + +/* fall through */ + +bail: + + Free(pIpv4Packet); + + return pA2NDUNPacket; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTestFixture::SetIPATablesToPassAllToSpecificClient( + enum ipa_client_type nClientTypeSrc, + enum ipa_client_type nClientTypeDst) +{ + bool bRetVal = true; + + bRetVal = SetRoutingTableToPassAllToSpecificClient(nClientTypeDst); + if(false == bRetVal) + goto bail; + bRetVal = SetFilterTableToPassAllToSpecificClient(nClientTypeSrc); + if(false == bRetVal) + goto bail; + bRetVal = SetHeaderInsertionTableAddEmptyHeaderForTheClient(nClientTypeSrc); + if(false == bRetVal) + goto bail; +/* fall through */ + +bail: + return bRetVal; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTestFixture::SetFilterTableToPassAllToSpecificClient( + enum ipa_client_type nClientType) +{ + IPAFilteringTable FilterTable; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_rt_tbl sRoutingTable; + + sRoutingTable.ip = IPA_IP_v4; + strlcpy(sRoutingTable.name, "Bypass0", sizeof(sRoutingTable.name)); + + if (false == m_routing.GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR("Configure the routing block first"); + return false; + } + + FilterTable.Init(IPA_IP_v4, nClientType, false, 1); + FilterTable.GeneratePresetRule(0, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = sRoutingTable.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; + if ((-1 == FilterTable.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable.GetFilteringTable())) { + LOG_MSG_INFO ("%s::Error Adding RuleTable(0) to Filtering, aborting..."); + return false; + } else { + LOG_MSG_INFO( "flt rule hdl0=0x%x, status=0x%x", + FilterTable.ReadRuleFromTable(0)->flt_rule_hdl, + FilterTable.ReadRuleFromTable(0)->status); + } + LOG_MSG_INFO("Leaving "); + + return true; +} +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTestFixture::SetRoutingTableToPassAllToSpecificClient( + enum ipa_client_type nClientType) +{ + if (!CreateBypassRoutingTablesIPv4( + HeaderRemovalTestFixture_bypass0, + nClientType)) { + LOG_MSG_INFO("CreateThreeBypassRoutingTables Failed"); + return false; + } + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTestFixture::SetHeaderInsertionTableAddEmptyHeaderForTheClient( + enum ipa_client_type nClientType) +{ + //TODO Header Removal: add header insertion data + return true; +} + +///////////////////////////////////////////////////////////////////////////////// +// This function creates IPv4 bypass routing entry and commits it. +bool HeaderRemovalTestFixture::CreateBypassRoutingTablesIPv4( + const char * bypass0, + enum ipa_client_type nClientType) +{ + struct ipa_ioc_add_rt_rule *rt_rule0 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + LOG_MSG_INFO("Entering"); + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add)); + if (!rt_rule0) { + LOG_MSG_INFO("calloc failed to allocate rt_rule0"); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v4; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = nClientType; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule0)) { + LOG_MSG_INFO("Routing rule addition(rt_rule0) failed!"); + Free (rt_rule0); + return false; + } + + Free (rt_rule0); + LOG_MSG_INFO("Leaving "); + return true; +} + +bool HeaderRemovalTestFixture::ConfigureFilteringBlockWithMetaDataEq( + enum ipa_client_type nClientType, + unsigned int nMetaData, + unsigned int nMetaDataMask) +{ + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl routing_table0; + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + + LOG_MSG_INFO("Entering "); + + if (!CreateBypassRoutingTablesIPv4( + HeaderRemovalTestFixture_bypass0, + nClientType)) { + LOG_MSG_INFO("CreateBypassRoutingTablesIPv4 Failed"); + return false; + } + + LOG_MSG_INFO("CreateBypassRoutingTablesIPv4 completed successfully"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) { + LOG_MSG_INFO( + "m_routing.GetRoutingTable(&routing_table0=0x%p) Failed." + ,&routing_table0); + return false; + } + + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST2_PROD, false, 1); + + LOG_MSG_INFO("FilterTable*.Init Completed Successfully.."); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1,flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_META_DATA; + flt_rule_entry.rule.attrib.meta_data = nMetaData; + flt_rule_entry.rule.attrib.meta_data_mask = nMetaDataMask; + if ( (-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + LOG_MSG_INFO ("%s::Error Adding RuleTable(0) to Filtering, aborting..."); + return false; + } else { + LOG_MSG_INFO("flt rule hdl0=0x%x, status=0x%x", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,FilterTable0.ReadRuleFromTable(0)->status); + } + + LOG_MSG_INFO("Leaving "); + + return true; +} diff --git a/kernel-tests/HeaderRemovalTestFixture.h b/kernel-tests/HeaderRemovalTestFixture.h new file mode 100644 index 0000000000..38e6761b47 --- /dev/null +++ b/kernel-tests/HeaderRemovalTestFixture.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017 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 _IPA_LINUX_TESTS_HR_TEST_FIXTURE_H_ +#define _IPA_LINUX_TESTS_HR_TEST_FIXTURE_H_ + + +#include +#include +#include +#include +#include + +#include "Constants.h" +#include "Logger.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "TestBase.h" +#include "Pipe.h" +#include "RoutingDriverWrapper.h" +#include "Filtering.h" + +/*This class will be the base class of all HeaderRemoval tests. + *Any method other than the test case itself can + *be declared in this Fixture thus allowing the derived classes to + *implement only the test case. + *All the test of the HeaderRemovalTestFixture + *uses one input and two output. + */ +class HeaderRemovalTestFixture:public TestBase +{ +public: + /*This Constructor will register each instance + * that it creates.*/ + HeaderRemovalTestFixture(); + + /*This method will create and initialize two Pipe object for the USB + *(Ethernet) Pipes, one as input and the other as output. + */ + virtual bool Setup(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + /*The client type are set from the peripheral perspective + *(TODO Pipe:in case the Driver will change its perspective + *of ipa_connect this should be changed). + */ + static Pipe m_A2NDUNToIpaPipe; + /*from the test application into the IPA(DMUX header)*/ + static Pipe m_IpaToUsbPipe; + /*from the IPA back to the test application(Ethernet header)*/ + static Pipe m_IpaToA2NDUNPipe; + /*from the IPA back to the test application(DMUX header)*/ + static Pipe m_IpaToQ6LANPipe; + + static RoutingDriverWrapper m_routing; + static Filtering m_filtering; + +protected: + unsigned char *CreateA2NDUNPacket(unsigned int magicNumber, + unsigned int ID, + string sPayloadFileName, + unsigned int *nTotalLength); + bool SetIPATablesToPassAllToSpecificClient( + enum ipa_client_type nClientTypeSrc, + enum ipa_client_type nClientTypeDst); + bool SetFilterTableToPassAllToSpecificClient( + enum ipa_client_type nClientType); + bool SetRoutingTableToPassAllToSpecificClient( + enum ipa_client_type nClientType); + bool SetHeaderInsertionTableAddEmptyHeaderForTheClient( + enum ipa_client_type nClientType); + bool CreateBypassRoutingTablesIPv4( + const char *bypass0, + enum ipa_client_type nClientType + ); + bool ConfigureFilteringBlockWithMetaDataEq( + enum ipa_client_type nClientType, + unsigned int nMetaData, + unsigned int nMetaDataMask); +}; + +#endif + diff --git a/kernel-tests/HeaderRemovalTests.cpp b/kernel-tests/HeaderRemovalTests.cpp new file mode 100644 index 0000000000..a45e503add --- /dev/null +++ b/kernel-tests/HeaderRemovalTests.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017 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 "HeaderRemovalTests.h" +#include "TestsUtils.h" +#include + +///////////////////////////////////////////////////////////////////////////////// + +static const unsigned int HEADER_REMOVAL_TEST_MAX_PACKET_BYTE_SIZE = 1024; + +///////////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + +HeaderRemovalTOSCheck::HeaderRemovalTOSCheck() +{ + m_name = "HeaderRemovalTOSCheck"; + m_description = "HeaderRemovalTOSCheck: Remove the header from the A2NDUN pipe and check the TOS field of the IP packet"; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalTOSCheck::Run() +{ + bool bTestResult = true; + Byte pPacketReceiveBuffer[HEADER_REMOVAL_TEST_MAX_PACKET_BYTE_SIZE] = {0};//This buffer will be used in order to store the received packet. + + unsigned int nMagicNumber = 0x12345678; //arbitrary number + unsigned int nChannelID = 0xABCD;//arbitrary number + unsigned int nA2NDUNPacketByteSize = 0; + unsigned int nBytesSent = 0; + int nBytesReceived = 0; + Byte *pA2NDUNPacket = CreateA2NDUNPacket(nMagicNumber, nChannelID, IPV4_FILE_PATH, &nA2NDUNPacketByteSize); + if(0 == pA2NDUNPacket) { + LOG_MSG_ERROR("Cannot load file to memory, exiting"); + return false; + } + LOG_MSG_INFO("A2 Packet was successfully created (%d bytes)", nA2NDUNPacketByteSize); + + if ( false == SetIPATablesToPassAllToSpecificClient(IPA_CLIENT_TEST2_PROD, IPA_CLIENT_TEST_CONS)) { + LOG_MSG_ERROR("SetIPATablesToPassAllToSpecificClient failed, exiting test case"); + bTestResult = false; + goto bail; + } + + LOG_MSG_INFO("All tables were configured in order to output the packet to the correct pipe"); + + LOG_MSG_INFO("Sending packet into the A2NDUN pipe(%d bytes) and the Pipe will add an header", + nA2NDUNPacketByteSize); + + nBytesSent = m_A2NDUNToIpaPipe.Send(pA2NDUNPacket, nA2NDUNPacketByteSize); + if (nA2NDUNPacketByteSize != nBytesSent) + { + bTestResult = false; + goto bail; + } + //Receive the raw IP packet(which is a 4 arbitrary bytes) without header removal by the Pipe + LOG_MSG_INFO("Reading packet from the USB pipe"); + + nBytesReceived = m_IpaToUsbPipe.Receive(pPacketReceiveBuffer, HEADER_REMOVAL_TEST_MAX_PACKET_BYTE_SIZE); + //TODO Header Removal: at this point the success scenario is that data came to the correct pipe - change this to + //packet memory compare after header insertion is enabled. + if (0 == nBytesReceived) + { + bTestResult = false; + goto bail; + } + + LOG_MSG_INFO("Read buffer : "); + //Print the output + for (int i = 0 ; i < nBytesReceived ; i++) + { + printf("0x%02x", pPacketReceiveBuffer[i]); + } + LOG_MSG_INFO("End of Read buffer."); + + if(0 != memcmp((const void *)pPacketReceiveBuffer, + (const void *)(pA2NDUNPacket + (nBytesSent - nBytesReceived)), + nBytesReceived)) { + LOG_MSG_ERROR("Memory contains don't match"); + bTestResult = false; + goto bail; + } +/* fall through */ + +bail: + + delete pA2NDUNPacket; + return bTestResult; +} + +HeaderRemovalMetaDataFiltering::HeaderRemovalMetaDataFiltering() +{ + m_name = "HeaderRemovalMetaDataFiltering"; + m_description = + "HeaderRemovalMetaDataFiltering: check meta data based filtering"; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool HeaderRemovalMetaDataFiltering::Run() +{ + bool bTestResult = true; + Byte pPacketReceiveBuffer[HEADER_REMOVAL_TEST_MAX_PACKET_BYTE_SIZE] = {0};//This buffer will be used in order to store the received packet. + + unsigned int nMagicNumber = 0x12345678; //arbitrary number + unsigned int nChannelID = 0xABCD;//arbitrary number + unsigned int nA2NDUNPacketByteSize = 0; + unsigned int nMetaData = 0; + unsigned int nMetaDataMask = 0xFFFF; + unsigned int nBytesSent = 0; + int nBytesReceived = 0; + + + Byte *pA2NDUNPacket = CreateA2NDUNPacket(nMagicNumber, nChannelID, IPV4_FILE_PATH, &nA2NDUNPacketByteSize); + if(0 == pA2NDUNPacket) { + LOG_MSG_ERROR("Cannot load file to memory, exiting"); + return false; + } + + nMetaData = (nChannelID << 16) | (0xFFFF & nA2NDUNPacketByteSize); + LOG_MSG_INFO("*************nMetaData == (0x%x)", nMetaData); + + LOG_MSG_INFO("A2 Packet was successfully created (%d bytes)", nA2NDUNPacketByteSize); + + SetRoutingTableToPassAllToSpecificClient(IPA_CLIENT_TEST_CONS); + SetHeaderInsertionTableAddEmptyHeaderForTheClient(IPA_CLIENT_TEST_CONS); + + LOG_MSG_INFO("Configuring Filtering module..."); + + if (false == + ConfigureFilteringBlockWithMetaDataEq( + IPA_CLIENT_TEST_CONS, + nMetaData, + nMetaDataMask)) { + bTestResult = false; + goto bail; + } + + LOG_MSG_INFO("Sending packet into the A2NDUN pipe(%d bytes) and the Pipe will add an header", + nA2NDUNPacketByteSize); + nBytesSent = m_A2NDUNToIpaPipe.Send(pA2NDUNPacket, nA2NDUNPacketByteSize); + if (nA2NDUNPacketByteSize != nBytesSent) { + bTestResult = false; + goto bail; + } + + //Receive the raw IP packet(which is a 4 arbitrary bytes) without header removal by the Pipe + LOG_MSG_INFO("Reading packet from the USB pipe"); + nBytesReceived = m_IpaToUsbPipe.Receive(pPacketReceiveBuffer, HEADER_REMOVAL_TEST_MAX_PACKET_BYTE_SIZE); + //TODO Header Removal: at this point the success scenario is that data came to the correct pipe - change this to + //packet memory compare after header insertion is enabled. + if (0 == nBytesReceived) { + bTestResult = false; + goto bail; + } + + LOG_MSG_INFO("Read buffer : "); + //Print the output + for (int i = 0 ; i < nBytesReceived ; i++) { + printf("0x%02x", pPacketReceiveBuffer[i]); + } + LOG_MSG_INFO("End of Read buffer."); + + if(0 != memcmp((const void *)pPacketReceiveBuffer, + (const void *)(pA2NDUNPacket + (nBytesSent - nBytesReceived)), + nBytesReceived)) { + LOG_MSG_ERROR("Memory contains don't match"); + bTestResult = false; + goto bail; + } + +/* fall through */ + +bail: + + delete pA2NDUNPacket; + return bTestResult; +} + +static HeaderRemovalTOSCheck headerRemovalTOSCheck; +static HeaderRemovalMetaDataFiltering headerRemovalMetaDataFiltering; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + diff --git a/kernel-tests/HeaderRemovalTests.h b/kernel-tests/HeaderRemovalTests.h new file mode 100644 index 0000000000..8bc6967ef1 --- /dev/null +++ b/kernel-tests/HeaderRemovalTests.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017 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 _IPA_LINUX_TESTS_HR_TESTS_H_ +#define _IPA_LINUX_TESTS_HR_TESTS_H_ + +#include +#include +#include +#include +#include + +#include "Constants.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "HeaderRemovalTestFixture.h" + +/*This test will send a DMUX with IP packet and check it TOS field thus + *validating the the header was removed. + */ +class HeaderRemovalTOSCheck:public HeaderRemovalTestFixture +{ +public: + /*This Constructor will be use to specify some test description.*/ + HeaderRemovalTOSCheck(); + + /*This method will send a an IP packet with + * DMUX header and create a rule + * */ + virtual bool Run(); +}; + +/*This test will send a DMUX with IP packet and see if it filtered + *by meta data contained in link layer header as expected + */ +class HeaderRemovalMetaDataFiltering:HeaderRemovalTestFixture +{ +public: + /* his Constructor will be use to specify + * some test description.*/ + HeaderRemovalMetaDataFiltering(); + + virtual bool Run(); + +}; + +#endif diff --git a/kernel-tests/IPAFilteringTable.cpp b/kernel-tests/IPAFilteringTable.cpp new file mode 100644 index 0000000000..ec14a85555 --- /dev/null +++ b/kernel-tests/IPAFilteringTable.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2017,2020 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 "IPAFilteringTable.h" +#include +#include "TestsUtils.h" + +IPAFilteringTable::IPAFilteringTable () : // C'tor + m_pFilteringTable(NULL), + nextRuleIndex(0) {} + +bool IPAFilteringTable::Init(ipa_ip_type ipFamily, ipa_client_type pipeNo, uint8_t isGlobal, uint8_t numOfRulesInTable, uint8_t commit) +{ + if (NULL != m_pFilteringTable) { + char message[256] = {0}; + snprintf(message, sizeof(message), "Error in Function %s, m_pFilteringTable==0x%p, must be NULL, Please call D'tor prior to calling () %s.", + __FUNCTION__,m_pFilteringTable,__FUNCTION__); + ReportError(message); + return false; + } + + if (numOfRulesInTable < 1) { + char message[256] = {0}; + snprintf(message, sizeof(message),"Error in Function %s, numberOfRulesInTable==%d must be > 0", + __FUNCTION__,numOfRulesInTable); + ReportError(message); + return false; + } + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_flt_rule) + + numOfRulesInTable *sizeof(struct ipa_flt_rule_add)); + + if (NULL == m_pFilteringTable) { + char message[256] = {0}; + snprintf(message, sizeof(message),"Error in Function %s, Failed to allocate %d filter rules in Filtering Table",__FUNCTION__,numOfRulesInTable); + ReportError(message); + return false; + } + + m_pFilteringTable->commit = commit; + m_pFilteringTable->ep = pipeNo; + m_pFilteringTable->global = isGlobal; + m_pFilteringTable->ip = ipFamily; + m_pFilteringTable->num_rules = (uint8_t)(numOfRulesInTable); + + return true; +} + +bool IPAFilteringTable::GeneratePresetRule(uint8_t preset,ipa_flt_rule_add &flt_rule_entry) +{ + memset(&flt_rule_entry,0,sizeof(ipa_flt_rule_add)); // Zero All Fields + + switch (preset) + { + case 0: // in Preset 0 the Filtering Rule is matches all (bypass) + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + break; + case 1: + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl=-1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action=IPA_PASS_TO_ROUTING; + //flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = 17; // Filter only UDP Packets. + break; + default: + char message[256] = {0}; + snprintf(message, sizeof(message),"Error in Function %s, preset=%d, is not supported.",__FUNCTION__,preset); + ReportError(message); + return false; + } + return true; +} + +uint8_t IPAFilteringTable::AddRuleToTable(ipa_flt_rule_add flt_rule_entry) +{ + if (NULL == m_pFilteringTable) { + char message[256] = {0}; + snprintf(message, sizeof(message),"Error in Function %s, m_pFilteringTable==NULL, Please call Init() prior to calling %s().",__FUNCTION__,__FUNCTION__); + ReportError(message); + return -1; + } + + if (nextRuleIndex >= m_pFilteringTable->num_rules) { + char message[256] = {0}; + snprintf(message, sizeof(message),"Error in Function %s, ruleIindex==%d while, No. of Rules in Filtering Table is %d. Please use IPAFilteringTable::WriteRule().", + __FUNCTION__,nextRuleIndex,m_pFilteringTable->num_rules); + ReportError(message); + return -1; + } + struct ipa_flt_rule_add *pFilteringRule = &(m_pFilteringTable->rules[nextRuleIndex]); + memcpy(pFilteringRule,&flt_rule_entry,sizeof(ipa_flt_rule_add)); + nextRuleIndex++; + return(nextRuleIndex-1); +} + +const ipa_flt_rule_add * IPAFilteringTable::ReadRuleFromTable(uint8_t index) +{ + if (index < nextRuleIndex) + return (&(m_pFilteringTable->rules[index])); + return NULL; +} + +// Function Not Implemented - Always returns FALSE +bool IPAFilteringTable::WriteRuleToTable(uint8_t index,ipa_flt_rule_add flt_rule_entry) {return false;} + +//This Function Frees the Filtering Table and all it's content. +//This Function will always return TRUE; +void IPAFilteringTable::Destructor() +{ + if (NULL != m_pFilteringTable) { + free (m_pFilteringTable); + printf("Filtering Table Freed\n"); + } + m_pFilteringTable = NULL; + nextRuleIndex = 0; +} + +IPAFilteringTable::~IPAFilteringTable() +{ + Destructor(); +} + +/* V2 */ + +IPAFilteringTable_v2::IPAFilteringTable_v2() : // C'tor + m_pFilteringTable_v2(NULL), + nextRuleIndex(0) +{ +} + +bool IPAFilteringTable_v2::Init(ipa_ip_type ipFamily, ipa_client_type pipeNo, uint8_t isGlobal, uint8_t numOfRulesInTable, uint8_t commit) +{ + if (NULL != m_pFilteringTable_v2) { + char message[256] = { 0 }; + snprintf(message, sizeof(message), "Error in Function %s, m_pFilteringTable_v2==0x%p, must be NULL, Please call D'tor prior to calling () %s.", + __FUNCTION__, m_pFilteringTable_v2, __FUNCTION__); + ReportError(message); + return false; + } + + if (numOfRulesInTable < 1) { + char message[256] = { 0 }; + snprintf(message, sizeof(message), "Error in Function %s, numberOfRulesInTable==%d must be > 0", + __FUNCTION__, numOfRulesInTable); + ReportError(message); + return false; + } + + m_pFilteringTable_v2 = (struct ipa_ioc_add_flt_rule_v2 *) + calloc(1, sizeof(struct ipa_ioc_add_flt_rule_v2)); + m_pFilteringTable_v2->rules = (uint64_t)calloc(numOfRulesInTable, sizeof(struct ipa_flt_rule_add_v2)); + + if (NULL == m_pFilteringTable_v2) { + char message[256] = { 0 }; + snprintf(message, sizeof(message), "Error in Function %s, Failed to allocate %d filter rules in Filtering Table V2", __FUNCTION__, numOfRulesInTable); + ReportError(message); + return false; + } + + m_pFilteringTable_v2->commit = commit; + m_pFilteringTable_v2->ep = pipeNo; + m_pFilteringTable_v2->global = isGlobal; + m_pFilteringTable_v2->ip = ipFamily; + m_pFilteringTable_v2->num_rules = (uint8_t)(numOfRulesInTable); + m_pFilteringTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2); + return true; +} + +bool IPAFilteringTable_v2::GeneratePresetRule(uint8_t preset, ipa_flt_rule_add_v2 &flt_rule_entry) +{ + memset(&flt_rule_entry, 0, sizeof(ipa_flt_rule_add_v2)); // Zero All Fields + + switch (preset) { + case 0: // in Preset 0 the Filtering Rule is matches all (bypass) + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + break; + case 1: + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + //flt_rule_entry.rule.rt_tbl_hdl=routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = 17; // Filter only UDP Packets. + break; + default: + char message[256] = { 0 }; + snprintf(message, sizeof(message), "Error in Function %s, preset=%d, is not supported.", __FUNCTION__, preset); + ReportError(message); + return false; + } + return true; +} + +uint8_t IPAFilteringTable_v2::AddRuleToTable(ipa_flt_rule_add_v2 flt_rule_entry) +{ + if (NULL == m_pFilteringTable_v2) { + char message[256] = { 0 }; + snprintf(message, sizeof(message), "Error in Function %s, m_pFilteringTable_v2==NULL, Please call Init() prior to calling %s().", __FUNCTION__, __FUNCTION__); + ReportError(message); + return -1; + } + + if (nextRuleIndex >= m_pFilteringTable_v2->num_rules) { + char message[256] = { 0 }; + snprintf(message, sizeof(message), "Error in Function %s, ruleIindex==%d while, No. of Rules in Filtering Table is %d. Please use IPAFilteringTable::WriteRule().", + __FUNCTION__, nextRuleIndex, m_pFilteringTable_v2->num_rules); + ReportError(message); + return -1; + } + struct ipa_flt_rule_add_v2 *pFilteringRule = &(((struct ipa_flt_rule_add_v2 *)(m_pFilteringTable_v2->rules))[nextRuleIndex]); + memcpy(pFilteringRule, &flt_rule_entry, sizeof(ipa_flt_rule_add_v2)); + nextRuleIndex++; + return(nextRuleIndex - 1); +} + +const ipa_flt_rule_add_v2 *IPAFilteringTable_v2::ReadRuleFromTable(uint8_t index) +{ + if (index < nextRuleIndex) + return (&(((struct ipa_flt_rule_add_v2*)m_pFilteringTable_v2->rules)[index])); + return NULL; +} + +// Function Not Implemented - Always returns FALSE +bool IPAFilteringTable_v2::WriteRuleToTable(uint8_t index, ipa_flt_rule_add_v2 flt_rule_entry) { return false; } + +//This Function Frees the Filtering Table and all it's content. +//This Function will always return TRUE; +void IPAFilteringTable_v2::Destructor() +{ + if (NULL != m_pFilteringTable_v2) { + free(m_pFilteringTable_v2); + printf("Filtering Table Freed\n"); + } + m_pFilteringTable_v2 = NULL; + nextRuleIndex = 0; +} + +IPAFilteringTable_v2::~IPAFilteringTable_v2() +{ + Destructor(); +} + diff --git a/kernel-tests/IPAFilteringTable.h b/kernel-tests/IPAFilteringTable.h new file mode 100644 index 0000000000..0b6354bf0b --- /dev/null +++ b/kernel-tests/IPAFilteringTable.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017,2020 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 _FILTERING_TABLE_ +#define _FILTERING_TABLE_ + +#include "Constants.h" +#include "Filtering.h" + + +/*This Class Encapsulate Filtering Table and Filtering Rules. + *It allows the user to easily manipulate rules and Tables. + */ +class IPAFilteringTable +{ +public: + IPAFilteringTable(); + ~IPAFilteringTable(); + + bool Init(ipa_ip_type ipFamily, + ipa_client_type pipeNo, + uint8_t isGlobal, + uint8_t numOfRulesInTable, + uint8_t commit = true); + + /*This Function Frees the Filtering Table and all it's content. + *This Function will always return TRUE; + */ + void Destructor(); + + + bool GeneratePresetRule( + uint8_t preset, + ipa_flt_rule_add & flt_rule_entry); + bool GeneratePresetRule( + uint8_t preset, + ipa_flt_rule_add_v2 &flt_rule_entry); + uint8_t AddRuleToTable( + ipa_flt_rule_add flt_rule_entry); + uint8_t AddRuleToTable( + ipa_flt_rule_add_v2 flt_rule_entry); + bool WriteRuleToTable( + uint8_t index, + ipa_flt_rule_add flt_rule_entry); + + /*Warning!!! + *Take care when using this function. + *The Returned pointer existence is guaranteed only as + *long as no other method of this class is called. + */ + const ipa_flt_rule_add *ReadRuleFromTable(uint8_t index); + + /*Warning!!! + *Take care when using this function + *The Returned pointer existence is guaranteed only + *as long as no other method of this class is called. + */ + const ipa_ioc_add_flt_rule *GetFilteringTable() + { + return m_pFilteringTable; + } + +private: + void ReportError(char *message) + { + printf("%s\n", message); + } + ipa_ioc_add_flt_rule *m_pFilteringTable; + uint8_t nextRuleIndex; +}; + +class IPAFilteringTable_v2 { +public: + IPAFilteringTable_v2(); + ~IPAFilteringTable_v2(); + + bool Init(ipa_ip_type ipFamily, + ipa_client_type pipeNo, + uint8_t isGlobal, + uint8_t numOfRulesInTable, + uint8_t commit = true); + + /*This Function Frees the Filtering Table and all it's content. + *This Function will always return TRUE; + */ + void Destructor(); + + bool GeneratePresetRule( + uint8_t preset, + ipa_flt_rule_add_v2 &flt_rule_entry); + uint8_t AddRuleToTable( + ipa_flt_rule_add_v2 flt_rule_entry); + bool WriteRuleToTable( + uint8_t index, + ipa_flt_rule_add_v2 flt_rule_entry); + + /*Warning!!! + *Take care when using this function. + *The Returned pointer existence is guaranteed only as + *long as no other method of this class is called. + */ + const ipa_flt_rule_add_v2 *ReadRuleFromTable(uint8_t index); + + /*Warning!!! + *Take care when using this function + *The Returned pointer existence is guaranteed only + *as long as no other method of this class is called. + */ + const ipa_ioc_add_flt_rule_v2 *GetFilteringTable() + { + return m_pFilteringTable_v2; + } + +private: + void ReportError(char *message) + { + printf("%s\n", message); + } + ipa_ioc_add_flt_rule_v2 *m_pFilteringTable_v2; + uint8_t nextRuleIndex; +}; + +#endif diff --git a/kernel-tests/IPAInterruptsTestFixture.cpp b/kernel-tests/IPAInterruptsTestFixture.cpp new file mode 100644 index 0000000000..c7b1815ec5 --- /dev/null +++ b/kernel-tests/IPAInterruptsTestFixture.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017 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 "IPAInterruptsTestFixture.h" + +/*define the static Pipes which will be used by all derived tests.*/ +Pipe IPAInterruptsTestFixture::m_IpaToUsbPipe(IPA_CLIENT_TEST_CONS, IPA_TEST_CONFIGURATION_19); +Pipe IPAInterruptsTestFixture::m_UsbToIpaPipe(IPA_CLIENT_TEST_PROD, IPA_TEST_CONFIGURATION_19); + +IPAInterruptsTestFixture::IPAInterruptsTestFixture() +{ + m_testSuiteName.push_back("Interrupts"); +} + +bool IPAInterruptsTestFixture::Setup() +{ + return true; +} + +bool IPAInterruptsTestFixture::Run() +{ + bool bTestResult = true; + Byte pIpPacket[] = { 0x01, 0x02, 0x03, 0x04 }; //This packet will be sent(It can be replaced by a real IP packet). + Byte pIpPacketReceive[sizeof(pIpPacket)] = { 0 }; //This buffer will be used in order to store the received packet. + + //Send the raw IP packet(which is a 4 arbitrary bytes) without header addition by the Pipe + LOG_MSG_DEBUG( + "Sending packet into the USB pipe(%d bytes)\n", sizeof(pIpPacket)); + int nBytesSent = m_UsbToIpaPipe.Send(pIpPacket, sizeof(pIpPacket)); + if (sizeof(pIpPacket) != nBytesSent) { + return false; + } + + //Receive the raw IP packet(which is a 4 arbitrary bytes) without header removal by the Pipe + LOG_MSG_DEBUG( + "Reading packet from the USB pipe(%d bytes should be there)\n", sizeof(pIpPacketReceive)); + int nBytesReceived = m_IpaToUsbPipe.Receive(pIpPacketReceive, + sizeof(pIpPacketReceive)); + if (sizeof(pIpPacketReceive) != nBytesReceived) { + LOG_MSG_DEBUG("sizes mismatch\n"); + for (int i = 0; i < nBytesReceived && i < (int)sizeof(pIpPacketReceive) ; i++) { + LOG_MSG_DEBUG("0x%02x\n", pIpPacketReceive[i]); + } + return false; + } + for (int i = 0; i < nBytesReceived; i++) { + LOG_MSG_DEBUG("0x%02x\n", pIpPacketReceive[i]); + } + + //Check that the sent IP packet is equal to the received IP packet. + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + bTestResult &= !memcmp(pIpPacket, pIpPacketReceive, sizeof(pIpPacket)); + + return bTestResult; +} + +bool IPAInterruptsTestFixture::Teardown() +{ + /* unregister the test framework suspend handler */ + RegSuspendHandler(false, false, 0); + + /*The Destroy method will close the inode.*/ + m_IpaToUsbPipe.Destroy(); + m_UsbToIpaPipe.Destroy(); + ConfigureScenario(-1); + return true; +} diff --git a/kernel-tests/IPAInterruptsTestFixture.h b/kernel-tests/IPAInterruptsTestFixture.h new file mode 100644 index 0000000000..d2b3dd0ede --- /dev/null +++ b/kernel-tests/IPAInterruptsTestFixture.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017 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 "Constants.h" +#include "Logger.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "TestBase.h" +#include "Pipe.h" + +/*This class will be the base class of all Pipe tests. + *Any method other than the test case itself can be + *declared in this Fixture thus allowing the derived classes to + *implement only the test case. + *All the test of the pipe uses one input and one output in DMA mode. + */ +class IPAInterruptsTestFixture:public TestBase +{ +public: + /*This Constructor will register each instance that it creates.*/ + IPAInterruptsTestFixture(); + + /*This method will create and initialize two Pipe object for the USB + * (Ethernet) Pipes, one as input and the other as output. + */ + virtual bool Setup(); + + /*Run test logic*/ + bool Run(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + /*The client type are set from the peripheral perspective + * (TODO Pipe:in case the Driver will change its perspective + * of ipa_connect this should be changed). + */ + static Pipe m_IpaToUsbPipe; + static Pipe m_UsbToIpaPipe; +}; diff --git a/kernel-tests/IPAInterruptsTests.cpp b/kernel-tests/IPAInterruptsTests.cpp new file mode 100644 index 0000000000..196ca68653 --- /dev/null +++ b/kernel-tests/IPAInterruptsTests.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017 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 "IPAInterruptsTestFixture.h" +#include "Constants.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class SuspendTestDeferred: public IPAInterruptsTestFixture { +public: + + SuspendTestDeferred() { + m_name = "SuspendTestDeferred"; + m_description = "This test will send data on a suspended pipe(Deferred context) "; + Register(*this); + } + + bool Setup() + { + bool bRetVal = true; + + /*Set the configuration to support USB->IPA and IPA->USB pipes.*/ + ConfigureScenario(IPA_TEST_CONFIGURATION_19); + + RegSuspendHandler(true,true,0); + + /*Initialize the pipe for all the tests - + * this will open the inode which represents the pipe. + */ + bRetVal &= m_IpaToUsbPipe.Init(); + bRetVal &= m_UsbToIpaPipe.Init(); + return bRetVal; + } +}; + + +class SuspendTest: public IPAInterruptsTestFixture { +public: + + SuspendTest() { + m_name = "SuspendTest"; + m_description = "This test will send data on a suspended pipe"; + Register(*this); + } + + bool Setup() + { + bool bRetVal = true; + + /*Set the configuration to support USB->IPA and IPA->USB pipes.*/ + ConfigureScenario(IPA_TEST_CONFIGURATION_19); + + RegSuspendHandler(false,true,0); + + /*Initialize the pipe for all the tests - + * this will open the inode which represents the pipe. + */ + bRetVal &= m_IpaToUsbPipe.Init(); + bRetVal &= m_UsbToIpaPipe.Init(); + return bRetVal; + } +}; + +static SuspendTest suspendTest; +static SuspendTestDeferred suspendTestDeferred; +///////////////////////////////////////////////////////////////////////////////// +// EOF //// +///////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/IPv4Packet.cpp b/kernel-tests/IPv4Packet.cpp new file mode 100644 index 0000000000..62aa2082f8 --- /dev/null +++ b/kernel-tests/IPv4Packet.cpp @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2017-2018 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 "TestsUtils.h" +#include "IPv4Packet.h" +#include "memory.h" + +using namespace IPA; + +static const unsigned char TCP_IP_PACKET_DUMP[] = { 0x45, // IPv4, IHL = 5 + 0x00, // ToS = 0 + 0x00, 0x28, // Total length + 0x11, 0xc2, // ID + 0x40, 0x00, //ID + Fragment Offset + 0x80, // TTL + 0x06, // Protocol = TCP + 0x70, 0x3a, //Checksum + 0x0a, 0x05, 0x07, 0x46, // Source IP 10.5.7.70 + 0x81, 0x2e, 0xe6, 0x5a, // Destination IP 129.46.230.90 + 0xf3, 0xa2, // Source Port 62370 + 0x01, 0xbd, // Destination Port 445 + 0x26, 0x26, 0x1d, 0x7d, // Seq Number + 0x15, 0xaa, 0xbc, 0xdb, // Ack Num + 0x50, 0x10, 0x80, 0xd4, // TCP Params + 0xaa, 0xa3, // TCP Checksum + 0x00, 0x00 // Urgent PTR + }; + +static const unsigned char UDP_IP_PACKET_DUMP[] = { + 0x45, // IPv4, IHL = 5 + 0x00, // ToS = 0 + 0x00, + 0x34, // Total Length + 0x12, + 0xa2, // ID + 0x00, + 0x00, //ID + fragment offset + 0x80, // TTL + 0x11, // Protocol = UDP + 0xe4, + 0x92, // Checksum + 0x0a, 0x05, 0x07, + 0x46, // Source IP 10.5.7.70 + 0x0a, 0x2b, 0x28, + 0x0f, // Destination IP 10.43.40.15 + 0x03, + 0x4a, // Source port 842 + 0x1b, + 0x4f, // Destination Port 6991 + 0x00, + 0x20, // UDP length + 0x36, + 0xac, // UDP checksum + 0x00, 0x05, 0x20, + 0x6d, // Data + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x13, 0x05, 0x20, 0x6c }; +static unsigned char ICMP_IP_PACKET_DUMP[] = { + //IP + 0x45, 0x00, 0x00, 0xdc, 0x03, 0xfe, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x81, 0x2e, 0xe4, 0xf6, 0x81, 0x2e, 0xe6, 0xd4, + //ICMP + 0x00, 0x00, 0xa9, 0xcd, 0x28, 0xa3, 0x01, 0x00, + //DATA + 0xee, 0x7c, 0xf7, 0x90, 0x39, 0x06, 0xd4, 0x41, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51 }; + +static void LittleToBigEndianUint32(unsigned char *pBigEndianBuffer, + unsigned int nUint32LittleEndianValue) { + unsigned char nLsb = nUint32LittleEndianValue & 0xff; + unsigned char nLsbMsbLow = (nUint32LittleEndianValue >> 8) & 0xff; + unsigned char nLsbMsbHigh = (nUint32LittleEndianValue >> 16) & 0xff; + unsigned char nMsb = (nUint32LittleEndianValue >> 24) & 0xff; + + pBigEndianBuffer[0] = nMsb; + pBigEndianBuffer[1] = nLsbMsbHigh; + pBigEndianBuffer[2] = nLsbMsbLow; + pBigEndianBuffer[3] = nLsb; +} + +static unsigned short BigToLittleEndianUint16(unsigned char *pBigEndianStart) { + unsigned char nMsb = pBigEndianStart[0]; + unsigned char nLsb = pBigEndianStart[1]; + + return (nMsb << 8 | nLsb << 0); +} + +static unsigned int BigToLittleEndianUint32(unsigned char *pBigEndianStart) { + unsigned char nMsb = pBigEndianStart[0]; + unsigned char nMsbLsbHigh = pBigEndianStart[1]; + unsigned char nMsbLsbLow = pBigEndianStart[2]; + unsigned char nLsb = pBigEndianStart[3]; + + return (nMsb << 24 | nMsbLsbHigh << 16 | nMsbLsbLow << 8 | nLsb << 0); +} + +static void LittleToBigEndianUint16(unsigned char *pBigEndianBuffer, + unsigned int nUint16LittleEndianValue) { + unsigned char nLsb = nUint16LittleEndianValue & 0xff; + unsigned char nMsb = (nUint16LittleEndianValue >> 8) & 0xff; + + pBigEndianBuffer[0] = nMsb; + pBigEndianBuffer[1] = nLsb; +} + +static unsigned short Get2BBIGEndian(const unsigned char *pBuff, int offset) { + unsigned char upperByte = 0; + unsigned char lowerByte = 0; + + memcpy(&upperByte, pBuff + offset, 1); + memcpy(&lowerByte, pBuff + offset + 1, 1); + + return (upperByte << 8 | lowerByte); +} + +IPv4Packet::IPv4Packet(unsigned int size) : + m_PacketSize(size) { +} + +IPv4Packet::~IPv4Packet(void) { + if (0 != m_Packet) { + delete[] m_Packet; + m_Packet = 0; + } +} + +void IPv4Packet::ToNetworkByteStream(unsigned char *buffer) { + if (0 == buffer) { + LOG_MSG_ERROR("IPv4Packet::ToNetworkByteStream : NULL arguments"); + return; + } + + memcpy(buffer, m_Packet, GetSize()); +} + +unsigned int IPv4Packet::GetSrcAddr(void) { + return BigToLittleEndianUint32(m_Packet + 12); +} + +void IPv4Packet::SetSrcAddr(unsigned int addr) { + LittleToBigEndianUint32(m_Packet + 12, addr); + RecalculateChecksum(); +} + +unsigned int IPv4Packet::GetDstAddr(void) { + + return BigToLittleEndianUint32(m_Packet + 16); +} + +void IPv4Packet::SetDstAddr(unsigned int addr) { + LittleToBigEndianUint32(m_Packet + 16, addr); + RecalculateChecksum(); +} + +unsigned char IPv4Packet::GetProtocol(void) { + unsigned char retVal = 0; + memcpy(&retVal, m_Packet + 9, sizeof(unsigned char)); + return retVal; +} + +unsigned short IPv4Packet::GetSrcPort(void) { + return BigToLittleEndianUint16(m_Packet + 20); +} + +unsigned short IPv4Packet::GetDstPort(void) { + return BigToLittleEndianUint16(m_Packet + 22); +} + +void IPv4Packet::SetDstPort(unsigned short port) { + + LittleToBigEndianUint16(m_Packet + 22, port); + RecalculateChecksum(); +} + +void IPv4Packet::SetSrcPort(unsigned short port) { + LittleToBigEndianUint16(m_Packet + 20, port); + RecalculateChecksum(); +} + +/////////////////////////////////////////////////////////////////////////////// + +//Set the third MSB bit of the IPV4_FLAGS_BYTE_OFFSET's byte +void IPv4Packet::SetMF(bool bValue) { + + Byte * pFlags = m_Packet + IPV4_FLAGS_BYTE_OFFSET; + //clear the bit + if (true == bValue) { + *pFlags |= (0x20); + } else { + *pFlags &= (~0x20); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void IPv4Packet::RecalculateChecksum(void) { + RecalculateIPChecksum(); + RecalculateTCPChecksum(); + RecalculateUDPChecksum(); +} + +void IPv4Packet::RecalculateIPChecksum(void) { + unsigned short pUint16[100]; + int headerLen = (m_Packet[0] & 0x0F) * 2; + int checksum = 0; + unsigned short result = 0; + + memset(&pUint16, 0, 100 * sizeof(unsigned short)); + + //clear the IP checksum field first + memset(m_Packet + 10, 0, sizeof(unsigned short)); + + memcpy(&pUint16, m_Packet, headerLen * sizeof(unsigned short)); + + for (int i = 0; i < headerLen; i++) { + checksum += pUint16[i]; + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + result = (~checksum & 0xFFFF); + + memcpy(m_Packet + 10, &result, sizeof(unsigned short)); + + return; +} + +void TCPPacket::RecalculateTCPChecksum(void) { + unsigned short *pUint16 = new unsigned short[100]; + int checksum = 0; + int headerLen = 0; + unsigned short *pTemp = 0; + unsigned short result = 0; + + headerLen = Get2BBIGEndian(m_Packet, 2) - (m_Packet[0] & 0x0F) * 4; + + memset(pUint16, 0, 100); + + //clear the TCP checksum field first + memset(m_Packet + 36, 0, sizeof(unsigned short)); + + memcpy(pUint16, m_Packet, headerLen * sizeof(unsigned short)); + + pTemp = pUint16; + + // Pseudo Header + pUint16 += 6; // Source IP + for (int i = 0; i < 4; i++) { + checksum += pUint16[i]; + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + checksum += 0x0600; // TCP Protocol + checksum += Get2BBIGEndian((unsigned char*) &headerLen, 0); + + pUint16 = pTemp + (m_Packet[0] & 0x0F) * 2; + headerLen /= 2; + for (int i = 0; i < headerLen; i++) { + checksum += pUint16[i]; + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + result = (~checksum & 0xFFFF); + + memcpy(m_Packet + 36, &result, sizeof(unsigned short)); + + delete[] pTemp; + + return; +} + +void UDPPacket::RecalculateUDPChecksum(void) { + unsigned short *pUint16 = new unsigned short[100]; + int checksum = 0; + int headerLen = 0; + unsigned short *pTemp = 0; + unsigned short result = 0; + + headerLen = Get2BBIGEndian(m_Packet, (m_Packet[0] & 0x0F) * 4 + 4); + + memset(pUint16, 0, 100); + + //clear the UDP checksum field first + memset(m_Packet + 26, 0, sizeof(unsigned short)); + + memcpy(pUint16, m_Packet, headerLen * sizeof(unsigned short)); + + pTemp = pUint16; + + // Pseudo Header + pUint16 += 6; // Source IP + for (int i = 0; i < 4; i++) { + checksum += pUint16[i]; + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + checksum += 0x1100; // UDP Protocol + checksum += Get2BBIGEndian((unsigned char*) &headerLen, 0); + + pUint16 = pTemp + (m_Packet[0] & 0x0F) * 2; + headerLen /= 2; + for (int i = 0; i < headerLen; i++) { + checksum += pUint16[i]; + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + + result = (~checksum & 0xFFFF); + + memcpy(m_Packet + 26, &result, sizeof(unsigned short)); + + delete[] pTemp; + return; +} + +TCPPacket::TCPPacket(void) : + IPv4Packet(sizeof(TCP_IP_PACKET_DUMP)) { + size_t length = GetSize(); + + m_Packet = new unsigned char[length]; + if (0 == m_Packet) { + LOG_MSG_ERROR("TCPPacket : packet allocation failed"); + return; + } + + memcpy(m_Packet, TCP_IP_PACKET_DUMP, length); +} + +UDPPacket::UDPPacket(void) : + IPv4Packet(sizeof(UDP_IP_PACKET_DUMP)) { + size_t length = GetSize(); + + m_Packet = new unsigned char[length]; + if (0 == m_Packet) { + LOG_MSG_ERROR("UDPPacket : packet allocation failed"); + return; + } + + memcpy(m_Packet, UDP_IP_PACKET_DUMP, length); +} + +ICMPPacket::ICMPPacket(void) : + IPv4Packet(sizeof(ICMP_IP_PACKET_DUMP)) { + size_t length = GetSize(); + + m_Packet = new unsigned char[length]; + if (0 == m_Packet) { + LOG_MSG_ERROR("ICMPPacket : packet allocation failed"); + return; + } + + memcpy(m_Packet, ICMP_IP_PACKET_DUMP, length); +} + +unsigned short ICMPPacket::GetSrcPort(void) { + return 0; +} + +unsigned short ICMPPacket::GetDstPort(void) { + return 0; +} + +void ICMPPacket::SetDstPort(unsigned short port) { + (void) port; + return; +} + +void ICMPPacket::SetSrcPort(unsigned short port) { + (void) port; + return; +} diff --git a/kernel-tests/IPv4Packet.h b/kernel-tests/IPv4Packet.h new file mode 100644 index 0000000000..d0a3451971 --- /dev/null +++ b/kernel-tests/IPv4Packet.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017 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 __IPA_TESTS_IPV4_PACKET__H__ +#define __IPA_TESTS_IPV4_PACKET__H__ + +namespace IPA +{ + +#define IPV4_FLAGS_BYTE_OFFSET 6 + +/** + @brief + IPv4Packet abstract class. + + @details + new setters should call to RecalculateChecksum(); + */ +class IPv4Packet +{ +public: + + IPv4Packet(unsigned int size); + + virtual ~IPv4Packet(void) = 0; + + void ToNetworkByteStream(unsigned char *addr); + + unsigned int GetSrcAddr(void); + + void SetSrcAddr(unsigned int addr); + + unsigned int GetDstAddr(void); + + void SetDstAddr(unsigned int addr); + + unsigned char GetProtocol(void); + + unsigned int GetSize(void) + { + return m_PacketSize; + } + + virtual unsigned short GetSrcPort(void); + + virtual unsigned short GetDstPort(void); + + virtual void SetDstPort(unsigned short port); + + virtual void SetSrcPort(unsigned short port); + + void SetMF(bool bValue); + +protected: + + virtual void RecalculateTCPChecksum(void) {} + + virtual void RecalculateUDPChecksum(void) {} + + virtual void RecalculateICMPChecksum(void) {} + + unsigned char *m_Packet; + +private: + + unsigned int m_PacketSize; + + void RecalculateChecksum(void); + + void RecalculateIPChecksum(void); +}; + +/** + @brief + TCPPacket implementation. + + @details + new setters should call to RecalculateChecksum(); + */ +class TCPPacket:public IPv4Packet +{ +public: + + TCPPacket(void); + + ~TCPPacket(void) {} + +protected: + + virtual void RecalculateTCPChecksum(void); +}; + +/** + @brief + UDPPacket implementation. + + @details + new setters should call to RecalculateChecksum(); + */ +class UDPPacket:public IPv4Packet +{ +public: + UDPPacket(void); + + ~UDPPacket(void) {} + +protected: + + virtual void RecalculateUDPChecksum(void); +}; + +/** + @brief + ICMPPacket implementation. + + @details + new setters should call to RecalculateChecksum(); + */ +class ICMPPacket:public IPv4Packet +{ +public: + ICMPPacket(void); + + ~ICMPPacket(void) {} + + virtual unsigned short GetSrcPort(void); + + virtual unsigned short GetDstPort(void); + + virtual void SetDstPort(unsigned short port); + + virtual void SetSrcPort(unsigned short port); + +protected: + + /** + @brief + RecalculateICMPChecksum method. + + @details + ICMP checksum recalculation is not needed now + and by so is not implemented yet + TODO: implement if needed + */ + virtual void RecalculateICMPChecksum(void) + { + return; + } +}; + +} /* namespace IPA */ + +#endif diff --git a/kernel-tests/IPv6CTTest.cpp b/kernel-tests/IPv6CTTest.cpp new file mode 100644 index 0000000000..207b03f316 --- /dev/null +++ b/kernel-tests/IPv6CTTest.cpp @@ -0,0 +1,1781 @@ +/* + * Copyright (c) 2018 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 "Filtering.h" +#include "RoutingDriverWrapper.h" +#include "IPAFilteringTable.h" +extern "C" { +#include "ipa_ipv6ct.h" +} + +#define IPV6_SRC_PORT_OFFSET (40) +#define IPV6_SRC_ADDRESS_MSB_OFFSET (8) +#define IPV6_SRC_ADDRESS_LSB_OFFSET (16) +#define IPV6_DST_ADDRESS_MSB_OFFSET (24) +#define IPV6_DST_ADDRESS_LSB_OFFSET (32) +#define IPV6_DST_PORT_OFFSET (40+2) + +#define IPV6_LOW_32_MASK (0xFFFFFFFF) +#define IPV6_HIGH_32_MASK (0xFFFFFFFF00000000) + +#define IPV6_BITS_IN_BYTE 8 + +inline uint32_t GetHigh32(uint64_t in) +{ + return static_cast((in & IPV6_HIGH_32_MASK) >> 32); +} + +inline uint32_t GetLow32(uint64_t in) +{ + return static_cast(in & IPV6_LOW_32_MASK); +} + +template +T HostToNetwork(T in) +{ + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + if (1 == htons(1)) + { + return in; + } + + static const T mask = 0xff; + T ret; + uint8_t* p = reinterpret_cast(&ret + 1); + while (in) + { + *--p = static_cast(in & mask); + in >>= IPV6_BITS_IN_BYTE; + } + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return ret; +} + +extern Logger g_Logger; + +class IpaIPv6CTBlockTestFixture : public TestBase +{ +public: + + IpaIPv6CTBlockTestFixture() : + m_sendSize(BUFF_MAX_SIZE), + m_sendSize2(BUFF_MAX_SIZE), + m_sendSize3(BUFF_MAX_SIZE), + m_outbound_dst_addr_msb(0XFF02000000000000), + m_outbound_dst_addr_lsb(0x11223344556677AA), + m_outbound_dst_port(1000), + m_outbound_src_addr_msb(m_outbound_dst_addr_msb), + m_outbound_src_addr_lsb(0x11223344556677CC), + m_outbound_src_port(1001), + m_direction_settings(IPA_IPV6CT_DIRECTION_ALLOW_ALL), + m_tableHandle(0) + { + memset(m_sendBuffer, 0, sizeof(m_sendBuffer)); // First input file / IP packet + memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2)); // Second input file / IP packet + memset(m_sendBuffer3, 0, sizeof(m_sendBuffer3)); // Third input file (default) / IP packet + m_minIPAHwType = IPA_HW_v4_0; + m_testSuiteName.push_back("IPv6CT"); + } + + static int SetupKernelModule(bool en_status = false) + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + int retval; + struct ipa_channel_config from_ipa_channels[3]; + struct test_ipa_ep_cfg from_ipa_cfg[3]; + 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[3]; + + /* From ipa configurations - 3 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0])); + prepare_channel_struct(&from_ipa_channels[0], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[0], + sizeof(from_ipa_cfg[0]), + en_status); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST3_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1]), + en_status); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2]), + en_status); + from_ipa_array[2] = &from_ipa_channels[2]; + + /* To ipa configurations - 1 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + 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); + + retval = GenericConfigureScenario(&header); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return retval; + } + + bool Setup() + { + bool bRetVal = true; + + if (SetupKernelModule() != true) + return bRetVal; + + 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); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) + { + printf("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + printf("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); // This will issue a Reset command to the Filtering as well + m_routing.Reset(IPA_IP_v6); // This will issue a Reset command to the Filtering as well + return true; + } // Setup() + + bool Teardown() + { + ipa_ipv6ct_dump_table(m_tableHandle); + ipa_ipv6ct_del_tbl(m_tableHandle); + + m_producer.Close(); + m_consumer.Close(); + m_consumer2.Close(); + m_defaultConsumer.Close(); + + return true; + } // Teardown() + + bool LoadFiles() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + if (!LoadDefaultPacket(IPA_IP_v6, m_extHdrType, m_sendBuffer, m_sendSize)) + { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf("Loaded %zu Bytes to Buffer 1\n", m_sendSize); + + if (!LoadDefaultPacket(IPA_IP_v6, m_extHdrType, m_sendBuffer2, m_sendSize2)) + { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf("Loaded %zu Bytes to Buffer 2\n", m_sendSize2); + + if (!LoadDefaultPacket(IPA_IP_v6, m_extHdrType, m_sendBuffer3, m_sendSize3)) + { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + printf("Loaded %zu Bytes to Buffer 3\n", m_sendSize3); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } + + // This function creates three IPv6 bypass routing entries and commits them. + bool CreateThreeIPv6BypassRoutingTables(const char * bypass0, const char * bypass1, const char * bypass2) + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0, *rt_rule2 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule0) { + printf("calloc failed to allocate rt_rule0 in %s\n", __FUNCTION__); + return false; + } + rt_rule1 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule1) { + printf("calloc failed to allocate rt_rule1 in %s\n", __FUNCTION__); + Free(rt_rule0); + return false; + } + rt_rule2 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule2) { + printf("calloc failed to allocate rt_rule2 in %s\n", __FUNCTION__); + Free(rt_rule0); + Free(rt_rule1); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v6; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + printf("Routing rule addition(rt_rule0) failed!\n"); + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + + rt_rule1->num_rules = 1; + rt_rule1->ip = IPA_IP_v6; + rt_rule1->commit = true; + strlcpy(rt_rule1->rt_tbl_name, bypass1, sizeof(rt_rule1->rt_tbl_name)); + rt_rule_entry = &rt_rule1->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule1)) + { + printf("Routing rule addition(rt_rule1) failed!\n"); + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + + rt_rule2->num_rules = 1; + rt_rule2->ip = IPA_IP_v6; + rt_rule2->commit = true; + strlcpy(rt_rule2->rt_tbl_name, bypass2, sizeof(rt_rule2->rt_tbl_name)); + rt_rule_entry = &rt_rule2->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0xeeff0011; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x22334455; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0x66778899; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;// All Packets will get a "Hit" + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + if (false == m_routing.AddRoutingRule(rt_rule2)) + { + printf("Routing rule addition(rt_rule2) failed!\n"); + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } + + bool GetThreeIPv6BypassRoutingTables(uint32_t *Hndl0, uint32_t *Hndl1, uint32_t *Hndl2) + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0, routing_table1, routing_table2; + + if (!CreateThreeIPv6BypassRoutingTables(bypass0, bypass1, bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + printf("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%pK) Failed.\n", &routing_table0); + return false; + } + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%pK) Failed.\n", &routing_table1); + return false; + } + + routing_table2.ip = IPA_IP_v6; + strlcpy(routing_table2.name, bypass2, sizeof(routing_table2.name)); + if (!m_routing.GetRoutingTable(&routing_table2)) + { + printf("m_routing.GetRoutingTable(&routing_table2=0x%pK) Failed.\n", &routing_table2); + return false; + } + + *Hndl0 = routing_table0.hdl; + *Hndl1 = routing_table1.hdl; + *Hndl2 = routing_table2.hdl; + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } + + bool AddIpv6ctTable() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + const int total_entries = 20; + + int result = ipa_ipv6ct_add_tbl(total_entries, &m_tableHandle); + if (result) + { + printf("Leaving %s, %s(), failed creating IPvC6T table with result %d\n", __FUNCTION__, __FILE__, result); + return false; + } + + printf("IPv6CT table added, hdl %d\n", m_tableHandle); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } + + bool AddIpv6ctRule(ipa_ipv6ct_rule& rule, uint32_t& rule_hdl) const + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + int result = ipa_ipv6ct_add_rule(m_tableHandle, &rule, &rule_hdl); + if (result) + { + printf("Leaving %s, %s(), failed creating IPvC6T rule with result %d\n", __FUNCTION__, __FILE__, result); + return false; + } + printf("IPv6CT rule added:\ndest lsb %llX, dest msb %llX, dest port %d\ndir %d, proto %d\nsrc lsb 0x%llX, src msb 0x%llX, src port %d\n", + (long long unsigned int)rule.dest_ipv6_lsb, (long long unsigned int)rule.dest_ipv6_msb, + rule.dest_port, rule.direction_settings, + rule.protocol, (long long unsigned int)rule.src_ipv6_lsb, (long long unsigned int)rule.src_ipv6_msb, + rule.src_port); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } + + void InitIpv6ctRule(ipa_ipv6ct_rule& rule, uint64_t change_bit) const + { + rule.dest_ipv6_lsb = m_outbound_dst_addr_lsb ^ change_bit; + rule.dest_ipv6_msb = m_outbound_dst_addr_msb; + rule.dest_port = m_outbound_dst_port; + rule.direction_settings = m_direction_settings; + rule.protocol = IPPROTO_TCP; + rule.src_ipv6_lsb = m_outbound_src_addr_lsb ^ change_bit; + rule.src_ipv6_msb = m_outbound_src_addr_msb; + rule.src_port = m_outbound_src_port; + } + + virtual bool AddIpv6ctRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + ipa_ipv6ct_rule rule; + InitIpv6ctRule(rule, 0); + + uint32_t rule_hdl; + bool result = AddIpv6ctRule(rule, rule_hdl); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } + + virtual bool ModifyPackets() = 0; + virtual bool AddRoutingFilteringRules() = 0; + virtual bool ReceivePacketsAndCompare() = 0; + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + res = AddRoutingFilteringRules(); + if (false == res) { + printf("Failed adding routing and filtering rules.\n"); + return false; + } + + res = AddIpv6ctTable(); + if (false == res) + { + printf("Failed adding IPv6 connection tracking table.\n"); + return false; + } + + res = AddIpv6ctRules(); + if (false == res) + { + printf("Failed adding IPv6 connection tracking rules.\n"); + return false; + } + + res = LoadFiles(); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + printf("Failed to modify packets.\n"); + return false; + } + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + printf("Leaving %s, %s(), Returning %d\n", __FUNCTION__, __FILE__, isSuccess); + + return isSuccess; + } // Run() + + void ModifyPackets(uint64_t dstAddrLsb, uint64_t dstAddrMsb, uint16_t dstPort, + uint64_t srcAddrLsb, uint64_t srcAddrMsb, uint16_t srcPort) + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + // destination + uint64_t address = HostToNetwork(dstAddrLsb); + memcpy(&m_sendBuffer[IPV6_DST_ADDRESS_LSB_OFFSET], &address, sizeof(address)); + + address = HostToNetwork(dstAddrMsb); + memcpy(&m_sendBuffer[IPV6_DST_ADDRESS_MSB_OFFSET], &address, sizeof(address)); + + uint16_t port = ntohs(dstPort); + memcpy(&m_sendBuffer[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + + // source + address = HostToNetwork(srcAddrLsb); + memcpy(&m_sendBuffer[IPV6_SRC_ADDRESS_LSB_OFFSET], &address, sizeof(address)); + + address = HostToNetwork(srcAddrMsb); + memcpy(&m_sendBuffer[IPV6_SRC_ADDRESS_MSB_OFFSET], &address, sizeof(address)); + + port = ntohs(srcPort); + memcpy(&m_sendBuffer[IPV6_SRC_PORT_OFFSET], &port, sizeof(port)); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + }// ModifyPacktes () + + virtual bool AddRoutingFilteringRules(enum ipa_flt_action flt_action, uint64_t dst_addr_msb, uint64_t dst_addr_lsb) + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + + if (!CreateThreeIPv6BypassRoutingTables(bypass0, bypass1, bypass2)) + { + printf("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + printf("CreateThreeBypassRoutingTables completed successfully\n"); + + ipa_ioc_get_rt_tbl routing_table0; + routing_table0.ip = IPA_IP_v6; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + printf("m_routing.GetRoutingTable(&routing_table0=0x%pK) Failed.\n", &routing_table0); + return false; + } + + ipa_ioc_get_rt_tbl routing_table1; + routing_table1.ip = IPA_IP_v6; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + printf("m_routing.GetRoutingTable(&routing_table1=0x%pK) Failed.\n", &routing_table1); + return false; + } + + IPAFilteringTable FilterTable0; + ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v6, IPA_CLIENT_TEST_PROD, false, 1); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = flt_action; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;// Exact Match + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = GetHigh32(dst_addr_msb); // Filter DST_IP + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = GetLow32(dst_addr_msb); + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = GetHigh32(dst_addr_lsb); + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = GetLow32(dst_addr_lsb); + + printf("flt_rule_entry was set successfully, preparing for insertion....\n"); + + if (((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable())) + { + printf("%s::Error Adding Rule to Filter Table, aborting...\n", __FUNCTION__); + return false; + } + else + { + printf("flt rule hdl0=0x%x, status=0x%x\n", + FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// AddRoutingFilteringRules() + + virtual bool ReceivePacketsAndCompare(bool packetPassExpected) + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + // Receive results + Byte rxBuff1[0x400]; + size_t receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + bool isSuccess = true; + if (packetPassExpected) + { + // Compare results + if (!CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize)) + { + printf("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + } + else + { + if (receivedSize) + { + isSuccess = false; + printf("got data while expected packet to be blocked, failing\n"); + } + } + + char recievedBuffer[256] = {0}; + char SentBuffer[256] = {0}; + size_t j; + + for (j = 0; j < m_sendSize; j++) + { + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer)-(3 * j + 1), " %02X", m_sendBuffer[j]); + } + + for (j = 0; j < receivedSize; j++) + { + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer)-(3 * j + 1), " %02X", rxBuff1[j]); + } + printf("Expected Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", + m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return isSuccess; + } + +protected: + + static Filtering m_filtering; + static RoutingDriverWrapper m_routing; + InterfaceAbstraction m_producer; + InterfaceAbstraction m_consumer; + InterfaceAbstraction m_consumer2; + InterfaceAbstraction m_defaultConsumer; + + static const size_t BUFF_MAX_SIZE = 1024; + + Byte m_sendBuffer[BUFF_MAX_SIZE]; // First input file / IP packet + Byte m_sendBuffer2[BUFF_MAX_SIZE]; // Second input file / IP packet + Byte m_sendBuffer3[BUFF_MAX_SIZE]; // Third input file (default) / IP packet + size_t m_sendSize; + size_t m_sendSize2; + size_t m_sendSize3; + static const ipv6_ext_hdr_type m_extHdrType = NONE; + + uint64_t m_outbound_dst_addr_msb; + uint64_t m_outbound_dst_addr_lsb; + uint16_t m_outbound_dst_port; + uint64_t m_outbound_src_addr_msb; + uint64_t m_outbound_src_addr_lsb; + uint16_t m_outbound_src_port; + ipa_ipv6_ct_direction_settings_type m_direction_settings; + + uint32_t m_tableHandle; +}; + +RoutingDriverWrapper IpaIPv6CTBlockTestFixture::m_routing; +Filtering IpaIPv6CTBlockTestFixture::m_filtering; + +/*---------------------------------------------------------------------------------------------*/ +/* Test001: IPv6CT send outbound packet */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest001 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest001() + { + m_name = "IpaIPV6CTBlockTest001"; + m_description = + "IPv6CT block test 001 - IPv6CT passes successfully one packet in outbound direction\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test002: IPv6CT send inbound packet */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest002 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest002() + { + m_name = "IpaIPV6CTBlockTest002"; + m_description = + "IPv6CT block test 002 - IPv6CT passes successfully one packet in inbound direction\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test003: IPv6CT send outbound packet - without IPV6CT rule */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest003 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest003() + { + m_name = "IpaIPV6CTBlockTest003"; + m_description = + "IPv6CT block test 003 - IPv6CT blocks one packet in outbound direction due to rule absence\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n"; + Register(*this); + } + + virtual bool AddIpv6ctRules() + { + printf("not adding IPv6CT rule for packet - blocking expected %s %s\n", __FUNCTION__, __FILE__); + return true; + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test004: IPv6CT send inbound packet - without IPV6CT rule */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest004 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest004() + { + m_name = "IpaIPV6CTBlockTest004"; + m_description = + "IPv6CT block test 004 - IPv6CT blocks one packet in inbound direction due to rule absence\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n"; + Register(*this); + } + + virtual bool AddIpv6ctRules() + { + printf("not adding IPv6CT rule for packet - blocking expected %s %s\n", __FUNCTION__, __FILE__); + return true; + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test005: IPv6CT send outbound packet with inbound filtering rule */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest005 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest005() + { + m_name = "IpaIPV6CTBlockTest005"; + m_description = + "IPv6CT block test 005 - IPv6CT blocks one packet in outbound direction, because the filtering rule\n" + " action is inbound\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test006: IPv6CT send inbound packet with outbound filtering rule */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest006 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest006() + { + m_name = "IpaIPV6CTBlockTest006"; + m_description = + "IPv6CT block test 006 - IPv6CT blocks one packet in inbound direction, because the filtering rule\n" + " action is outbound\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test007: IPv6CT block outbound packet while disabled outbound direction */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest007 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest007() + { + m_name = "IpaIPV6CTBlockTest007"; + m_description = + "IPv6CT block test 007 - IPv6CT blocks one packet in outbound direction, because the outbound direction\n" + " is disabled\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet with disabled outbound direction\n"; + m_direction_settings = IPA_IPV6CT_DIRECTION_ALLOW_IN; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test008: IPv6CT block inbound packet with disabled inbound direction */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest008 : public IpaIPv6CTBlockTestFixture +{ +public: + + IpaIPV6CTBlockTest008() + { + m_name = "IpaIPV6CTBlockTest008"; + m_description = + "IPv6CT block test 008 - IPv6CT blocks one packet in inbound direction, because the inbound direction\n" + " is disabled\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet with disabled inbound direction\n"; + m_direction_settings = IPA_IPV6CT_DIRECTION_ALLOW_OUT; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +class IpaIPv6CTBlockExpansionTableTestFixture : public IpaIPv6CTBlockTestFixture +{ +public: + + virtual bool AddIpv6ctRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + ipa_ipv6ct_rule rule; + InitIpv6ctRule(rule, 8); + + uint32_t rule_hdl; + if (!AddIpv6ctRule(rule, rule_hdl)) + { + return false; + } + + bool result = IpaIPv6CTBlockTestFixture::AddIpv6ctRules(); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test009: IPv6CT send outbound packet with rule in expansion table */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest009 : public IpaIPv6CTBlockExpansionTableTestFixture +{ +public: + + IpaIPV6CTBlockTest009() + { + m_name = "IpaIPV6CTBlockTest009"; + m_description = + "IPv6CT block test 009 - IPv6CT passes successfully one packet in outbound direction with rule in\n" + " expansion table\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add an IPv6CT rule to occupy base table. This rule is not supposed to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test010: IPv6CT send inbound packet with rule in expansion table */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest010 : public IpaIPv6CTBlockExpansionTableTestFixture +{ +public: + + IpaIPV6CTBlockTest010() + { + m_name = "IpaIPV6CTBlockTest010"; + m_description = + "IPv6CT block test 010 - IPv6CT passes successfully one packet in inbound direction with rule in\n" + " expansion table\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add an IPv6CT rule to occupy base table. This rule is not supposed to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +class IpaIPv6CTBlockRuleDeleteTestFixture : public IpaIPv6CTBlockTestFixture +{ +public: + + virtual bool AddIpv6ctRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + ipa_ipv6ct_rule rule; + InitIpv6ctRule(rule, 0); + + uint32_t rule_hdl; + if (!AddIpv6ctRule(rule, rule_hdl)) + { + return false; + } + + int result = ipa_ipv6ct_del_rule(m_tableHandle, rule_hdl); + if (result) + { + printf("Leaving %s, %s(), failed delete IPvC6T rule %d with result %d\n", __FUNCTION__, __FILE__, + rule_hdl, result); + return false; + } + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test011: IPv6CT block outbound packet while the rule was deleted */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest011 : public IpaIPv6CTBlockRuleDeleteTestFixture +{ +public: + + IpaIPV6CTBlockTest011() + { + m_name = "IpaIPV6CTBlockTest011"; + m_description = + "IPv6CT block test 011 - IPv6CT blocks one packet in outbound direction due to the rule deletion\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet\n" + "4. Delete IPv6CT rule for the packet\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test012: IPv6CT block inbound packet while the rule was deleted */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest012 : public IpaIPv6CTBlockRuleDeleteTestFixture +{ +public: + + IpaIPV6CTBlockTest012() + { + m_name = "IpaIPV6CTBlockTest012"; + m_description = + "IPv6CT block test 012 - IPv6CT blocks one packet in inbound direction due to the rule deletion\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add IPv6CT rule for the packet\n" + "4. Delete IPv6CT rule for the packet\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +class IpaIPv6CTBlockRuleDeleteExpansionTableTestFixture : public IpaIPv6CTBlockRuleDeleteTestFixture +{ +public: + + virtual bool AddIpv6ctRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + ipa_ipv6ct_rule rule; + InitIpv6ctRule(rule, 8); + + uint32_t rule_hdl; + if (!AddIpv6ctRule(rule, rule_hdl)) + { + return false; + } + + bool result = IpaIPv6CTBlockRuleDeleteTestFixture::AddIpv6ctRules(); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test013: IPv6CT block outbound packet while the rule in expansion table was deleted */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest013 : public IpaIPv6CTBlockRuleDeleteExpansionTableTestFixture +{ +public: + + IpaIPV6CTBlockTest013() + { + m_name = "IpaIPV6CTBlockTest013"; + m_description = + "IPv6CT block test 013 - IPv6CT blocks one packet in outbound direction due to the rule deletion from\n" + " the expansion table\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add an IPv6CT rule to occupy base table. This rule is not supposed to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n" + "5. Delete IPv6CT rule for the packet from the expansion table\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------*/ +/* Test014: IPv6CT block inbound packet while the rule in expansion table was deleted */ +/*---------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest014 : public IpaIPv6CTBlockRuleDeleteExpansionTableTestFixture +{ +public: + + IpaIPV6CTBlockTest014() + { + m_name = "IpaIPV6CTBlockTest014"; + m_description = + "IPv6CT block test 014 - IPv6CT blocks one packet in inbound direction due to the rule deletion from\n" + " the expansion table\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add an IPv6CT rule to occupy base table. This rule is not supposed to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n" + "5. Delete IPv6CT rule for the packet from the expansion table\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(false); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +class IpaIPv6CTBlockHeadRuleDeleteTestFixture : public IpaIPv6CTBlockTestFixture +{ +public: + + virtual bool AddIpv6ctRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + ipa_ipv6ct_rule rule; + InitIpv6ctRule(rule, 8); + + uint32_t rule_hdl; + if (!AddIpv6ctRule(rule, rule_hdl)) + { + return false; + } + + if (!IpaIPv6CTBlockTestFixture::AddIpv6ctRules()) + { + return false; + } + + int result = ipa_ipv6ct_del_rule(m_tableHandle, rule_hdl); + if (result) + { + printf("Leaving %s, %s(), failed delete IPvC6T rule %d with result %d\n", __FUNCTION__, __FILE__, + rule_hdl, result); + return false; + } + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + } +}; + +/*---------------------------------------------------------------------------------------------------------------*/ +/* Test015: IPv6CT send outbound packet with rule in expansion table while the rule in the list head was deleted */ +/*---------------------------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest015 : public IpaIPv6CTBlockHeadRuleDeleteTestFixture +{ +public: + + IpaIPV6CTBlockTest015() + { + m_name = "IpaIPV6CTBlockTest015"; + m_description = + "IPv6CT block test 015 - IPv6CT passes successfully one packet in outbound direction with rule in\n" + " expansion table, while the list head was deleted\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add an IPv6CT rule to occupy base table. This rule is not supposed to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n" + "5. Delete IPv6CT rule in the list head\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*---------------------------------------------------------------------------------------------------------------*/ +/* Test016: IPv6CT send inbound packet with rule in expansion table while the rule in the list head was deleted */ +/*---------------------------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest016 : public IpaIPv6CTBlockHeadRuleDeleteTestFixture +{ +public: + + IpaIPV6CTBlockTest016() + { + m_name = "IpaIPV6CTBlockTest016"; + m_description = + "IPv6CT block test 016 - IPv6CT passes successfully one packet in inbound direction with rule in\n" + " expansion table, while the list head was deleted\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add an IPv6CT rule to occupy base table. This rule is not supposed to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n" + "5. Delete IPv6CT rule in the list head\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +class IpaIPv6CTBlockMiddleRuleDeleteTestFixture : public IpaIPv6CTBlockHeadRuleDeleteTestFixture +{ +public: + + virtual bool AddIpv6ctRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + ipa_ipv6ct_rule rule; + InitIpv6ctRule(rule, 1); + + uint32_t rule_hdl; + if (!AddIpv6ctRule(rule, rule_hdl)) + { + return false; + } + + bool result = IpaIPv6CTBlockHeadRuleDeleteTestFixture::AddIpv6ctRules(); + + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*------------------------------------------------------------------------------------------------------------*/ +/* Test017: IPv6CT send outbound packet with rule in expansion table while the rule in the middle of the list */ +/* was deleted */ +/*------------------------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest017 : public IpaIPv6CTBlockMiddleRuleDeleteTestFixture +{ +public: + + IpaIPV6CTBlockTest017() + { + m_name = "IpaIPV6CTBlockTest017"; + m_description = + "IPv6CT block test 017 - IPv6CT passes successfully one packet in outbound direction with rule in\n" + " expansion table, while the rule in the middle of the list was deleted\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one outbound filtering rule: Destination IP Exactly Match.\n" + "3. Add two IPv6CT rules: one to base table and other to expansion table. These rules are not supposed\n" + " to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n" + "5. Delete IPv6CT rule in the middle of the list\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_SRC_NAT, + m_outbound_dst_addr_msb, m_outbound_dst_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port, + m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +/*------------------------------------------------------------------------------------------------------------*/ +/* Test018: IPv6CT send inbound packet with rule in expansion table while the rule in the middle of the list */ +/* was deleted */ +/*------------------------------------------------------------------------------------------------------------*/ +class IpaIPV6CTBlockTest018 : public IpaIPv6CTBlockMiddleRuleDeleteTestFixture +{ +public: + + IpaIPV6CTBlockTest018() + { + m_name = "IpaIPV6CTBlockTest018"; + m_description = + "IPv6CT block test 018 - IPv6CT passes successfully one packet in inbound direction with rule in\n" + " expansion table, while the rule in the middle of the list was deleted\n" + "1. Generate and commit three routing tables.\n" + " Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly))\n" + "2. Generate and commit one inbound filtering rule: Destination IP Exactly Match.\n" + "3. Add two IPv6CT rules to occupy base table and the middle of the list. These rules are not supposed\n" + " to match a packet\n" + "4. Add IPv6CT rule for the packet to the expansion table\n" + "5. Delete IPv6CT rule in the middle of the list\n"; + Register(*this); + } + + virtual bool AddRoutingFilteringRules() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::AddRoutingFilteringRules(IPA_PASS_TO_DST_NAT, + m_outbound_src_addr_msb, m_outbound_src_addr_lsb); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + }// AddRoutingFilteringRules() + + virtual bool ModifyPackets() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + IpaIPv6CTBlockTestFixture::ModifyPackets(m_outbound_src_addr_lsb, m_outbound_src_addr_msb, m_outbound_src_port, + m_outbound_dst_addr_lsb, m_outbound_dst_addr_msb, m_outbound_dst_port); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return true; + }// ModifyPackets() + + virtual bool ReceivePacketsAndCompare() + { + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + bool result = IpaIPv6CTBlockTestFixture::ReceivePacketsAndCompare(true); + printf("Leaving %s, %s()\n", __FUNCTION__, __FILE__); + return result; + } +}; + +// IPv6CT outbound packet test +static class IpaIPV6CTBlockTest001 IpaIPV6CTBlockTest001; + +// IPv6CT inbound packet test +static class IpaIPV6CTBlockTest002 IpaIPV6CTBlockTest002; + +// IPv6CT block outbound packet test +static class IpaIPV6CTBlockTest003 IpaIPV6CTBlockTest003; + +// IPv6CT block inbound packet test +static class IpaIPV6CTBlockTest004 IpaIPV6CTBlockTest004; + +// IPv6CT block outbound packet on inbound filtering rule test +static class IpaIPV6CTBlockTest005 IpaIPV6CTBlockTest005; + +// IPv6CT block inbound packet on outbound filtering rule test +static class IpaIPV6CTBlockTest006 IpaIPV6CTBlockTest006; + +// IPv6CT block outbound packet while disabled outbound direction +static class IpaIPV6CTBlockTest007 IpaIPV6CTBlockTest007; + +// IPv6CT block inbound packet with disabled inbound direction +static class IpaIPV6CTBlockTest008 IpaIPV6CTBlockTest008; + +// IPv6CT send outbound packet with rule in expansion table +static class IpaIPV6CTBlockTest009 IpaIPV6CTBlockTest009; + +// IPv6CT send inbound packet with rule in expansion table +static class IpaIPV6CTBlockTest010 IpaIPV6CTBlockTest010; + +// IPv6CT block outbound packet while the rule was deleted +static class IpaIPV6CTBlockTest011 IpaIPV6CTBlockTest011; + +// IPv6CT block inbound packet while the rule was deleted +static class IpaIPV6CTBlockTest012 IpaIPV6CTBlockTest012; + +// IPv6CT block outbound packet while the rule in expansion table was deleted +static class IpaIPV6CTBlockTest013 IpaIPV6CTBlockTest013; + +// IPv6CT block inbound packet while the rule in expansion table was deleted +static class IpaIPV6CTBlockTest014 IpaIPV6CTBlockTest014; + +// IPv6CT send outbound packet with rule in expansion table while the rule in list head was deleted +static class IpaIPV6CTBlockTest015 IpaIPV6CTBlockTest015; + +// IPv6CT send inbound packet with rule in expansion table while the rule in list head was deleted +static class IpaIPV6CTBlockTest016 IpaIPV6CTBlockTest016; + +// IPv6CT send outbound packet with rule in expansion table while the rule in the middle of the list was deleted +static class IpaIPV6CTBlockTest017 IpaIPV6CTBlockTest017; + +// IPv6CT send inbound packet with rule in expansion table while the rule in the middle of the list was deleted +static class IpaIPV6CTBlockTest018 IpaIPV6CTBlockTest018; + diff --git a/kernel-tests/InterfaceAbstraction.cpp b/kernel-tests/InterfaceAbstraction.cpp new file mode 100644 index 0000000000..f690d203df --- /dev/null +++ b/kernel-tests/InterfaceAbstraction.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2017 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 "InterfaceAbstraction.h" + +#define MAX_OPEN_RETRY 10000 + +bool InterfaceAbstraction::Open(const char * toIPAPath, const char * fromIPAPath) +{ + int tries_cnt = MAX_OPEN_RETRY; + if (NULL == toIPAPath && NULL == fromIPAPath) + { + printf("InterfaceAbstraction constructor got 2 null arguments.\n"); + exit(0); + } + + if (NULL != toIPAPath) { + while (tries_cnt > 0) { + printf("trying to open %s %d/%d\n", toIPAPath, MAX_OPEN_RETRY - tries_cnt, MAX_OPEN_RETRY); + // Sleep for 5 msec + usleep(5000); + m_toIPADescriptor = open(toIPAPath, O_WRONLY); + if (-1 != m_toIPADescriptor) { + printf("Success!\n"); + break; + } + tries_cnt--; + } + printf("open retries_cnt=%d\n", MAX_OPEN_RETRY - tries_cnt); + if (-1 == m_toIPADescriptor) { + printf("InterfaceAbstraction failed while opening %s.\n", toIPAPath); + exit(0); + } + m_toChannelName = toIPAPath; + printf("%s device node opened, fd = %d.\n", toIPAPath, m_toIPADescriptor); + } + tries_cnt = MAX_OPEN_RETRY; + if (NULL != fromIPAPath) { + while (tries_cnt > 0) { + printf("trying to open %s %d/%d\n", fromIPAPath, MAX_OPEN_RETRY - tries_cnt, MAX_OPEN_RETRY); + // Sleep for 5 msec + usleep(5000); + m_fromIPADescriptor = open(fromIPAPath, O_RDONLY); + if (-1 != m_fromIPADescriptor) { + printf("Success!\n"); + break; + } + tries_cnt--; + } + printf("open retries_cnt=%d\n", MAX_OPEN_RETRY - tries_cnt); + if (-1 == m_fromIPADescriptor) + { + printf("InterfaceAbstraction failed on opening %s.\n", fromIPAPath); + exit(0); + } + m_fromChannelName = fromIPAPath; + printf("%s device node opened, fd = %d.\n", fromIPAPath, m_fromIPADescriptor); + } + + return true; +}/*Ctor*/ + +void InterfaceAbstraction::Close() +{ + close(m_toIPADescriptor); + close(m_fromIPADescriptor); +} + +bool InterfaceAbstraction::SendData(unsigned char *buf, size_t size) +{ + int bytesWritten = 0; + + printf("Trying to write %zu bytes to %d.\n", size, m_toIPADescriptor); + + bytesWritten = write(m_toIPADescriptor, buf, size); + if (-1 == bytesWritten) + { + int err = errno; + printf( + "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); + printf( + "Failed to execute command\n write(m_toIPADescriptor, buf, size);\n " + "m_toIPADescriptor=%d, buf=0x%p, size=%zu",m_toIPADescriptor, + buf, + size); + printf("Error on write execution, errno=%d, Quitting!\n", err); + printf( + "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); + exit(-1); + } + + printf("bytesWritten = %d.\n", bytesWritten); + + return bytesWritten; +} + +int InterfaceAbstraction::ReceiveData(unsigned char *buf, size_t size) +{ + size_t bytesRead = 0; + size_t totalBytesRead = 0; + bool continueRead = false; + + do + { + 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); + totalBytesRead += bytesRead; + if (bytesRead == size) + continueRead = true; + else + continueRead = false; + } while (continueRead); + + return totalBytesRead; +} + +InterfaceAbstraction::~InterfaceAbstraction() +{ + close(m_fromIPADescriptor); + m_fromChannelName = ""; + + close(m_toIPADescriptor); + m_toChannelName = ""; +} diff --git a/kernel-tests/InterfaceAbstraction.h b/kernel-tests/InterfaceAbstraction.h new file mode 100644 index 0000000000..074eb09c01 --- /dev/null +++ b/kernel-tests/InterfaceAbstraction.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 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 INTERFACE_ABSTRACTION_H_ +#define INTERFACE_ABSTRACTION_H_ + +#include +#include +#include + +typedef unsigned char Byte; + +using namespace std; + +class InterfaceAbstraction +{ + +public: + ~InterfaceAbstraction(); + bool Open(const char *toIPAPath, const char *fromIPAPath); + void Close(); + bool SendData(unsigned char *buffer, size_t size); + int ReceiveData(unsigned char *buf, size_t size); + + string m_toChannelName; + string m_fromChannelName; + +private: + int m_toIPADescriptor; + int m_fromIPADescriptor; +}; + +#endif diff --git a/kernel-tests/Logger.cpp b/kernel-tests/Logger.cpp new file mode 100644 index 0000000000..5b226c51d0 --- /dev/null +++ b/kernel-tests/Logger.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 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 "Logger.h" + +//////////////////////////////////////////////////////////////////////////// + +//The trace level of the system will be used to choose the system printing level +Logger::Logger(TraceLevel nTraceLevel) +{ + m_nTraceLevelToPresent = nTraceLevel; +} + +//////////////////////////////////////////////////////////////////////////// + +//This method will be use to print messages. it will also gie a trace level for each message. +void Logger::AddMessage(TraceLevel nTraceLevel, const char *format, ...) +{ + + //in case the trace level is not "high" no print should be made. + if (nTraceLevel < m_nTraceLevelToPresent) + { + return; + } + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +//////////////////////////////////////////////////////////////////////////// + diff --git a/kernel-tests/Logger.h b/kernel-tests/Logger.h new file mode 100644 index 0000000000..9e991f50e2 --- /dev/null +++ b/kernel-tests/Logger.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017 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 LOGGER_H_ +#define LOGGER_H_ + +#include +#include + +using namespace std; + +typedef enum{ + LOG_DEVELOPMENT = 0, + LOG_ERROR = 0, + LOG_VERBOSE = 1 +} TraceLevel; + +/*This class will controll all the printing in the test application + *In each test there will be many printing while each + *specific print will define it's "importancy"(TraceLevel) + *During the development of the test it is + *strongly suggested to use LOG_DEVELOPMENT. + */ + +class Logger +{ +public: + Logger(TraceLevel nTraceLevelToPresent); + void AddMessage(TraceLevel nTraceLevel, const char *format, ...); +private: + int m_nTraceLevelToPresent; +}; + +#endif /* LOGGER_H_ */ diff --git a/kernel-tests/MBIMAggregationTestFixtureConf11.cpp b/kernel-tests/MBIMAggregationTestFixtureConf11.cpp new file mode 100644 index 0000000000..7462d9bf91 --- /dev/null +++ b/kernel-tests/MBIMAggregationTestFixtureConf11.cpp @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2017-2018,2020 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 "MBIMAggregationTestFixtureConf11.h" +#include "TestManager.h" + +///////////////////////////////////////////////////////////////////////////////// + +//define the static Pipes which will be used by all derived tests. +Pipe MBIMAggregationTestFixtureConf11::m_IpaToUsbPipeAgg(IPA_CLIENT_TEST2_CONS, + IPA_TEST_CONFIGURATION_11); +Pipe MBIMAggregationTestFixtureConf11::m_UsbToIpaPipe(IPA_CLIENT_TEST_PROD, + IPA_TEST_CONFIGURATION_11); +Pipe MBIMAggregationTestFixtureConf11::m_IpaToUsbPipe(IPA_CLIENT_TEST3_CONS, + IPA_TEST_CONFIGURATION_11); +Pipe MBIMAggregationTestFixtureConf11::m_UsbToIpaPipeDeagg(IPA_CLIENT_TEST2_PROD, + IPA_TEST_CONFIGURATION_11); +Pipe MBIMAggregationTestFixtureConf11::m_IpaToUsbPipeAggTime(IPA_CLIENT_TEST_CONS, + IPA_TEST_CONFIGURATION_11); +Pipe MBIMAggregationTestFixtureConf11::m_IpaToUsbPipeAgg0Limits(IPA_CLIENT_TEST4_CONS, + IPA_TEST_CONFIGURATION_11); + +RoutingDriverWrapper MBIMAggregationTestFixtureConf11::m_Routing; +Filtering MBIMAggregationTestFixtureConf11::m_Filtering; +HeaderInsertion MBIMAggregationTestFixtureConf11::m_HeaderInsertion; + +///////////////////////////////////////////////////////////////////////////////// + +MBIMAggregationTestFixtureConf11::MBIMAggregationTestFixtureConf11(bool generic_agg) +: mGenericAgg(generic_agg) +{ + if (mGenericAgg) { + m_testSuiteName.push_back("GenMbimAgg"); + m_minIPAHwType = IPA_HW_v4_0; + } else { + m_testSuiteName.push_back("Mbim16Agg"); + m_maxIPAHwType = IPA_HW_v3_5_1; + } + Register(*this); +} + +///////////////////////////////////////////////////////////////////////////////// + +int MBIMAggregationTestFixtureConf11::SetupKernelModule() +{ + int retval; + struct ipa_channel_config from_ipa_channels[4]; + struct test_ipa_ep_cfg from_ipa_cfg[4]; + struct ipa_channel_config to_ipa_channels[2]; + struct test_ipa_ep_cfg to_ipa_cfg[2]; + + struct ipa_test_config_header header = {0}; + struct ipa_channel_config *to_ipa_array[2]; + struct ipa_channel_config *from_ipa_array[4]; + + /* From ipa configurations - 4 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0])); + from_ipa_cfg[0].aggr.aggr_en = IPA_ENABLE_AGGR; + from_ipa_cfg[0].aggr.aggr = IPA_MBIM_16; + from_ipa_cfg[0].aggr.aggr_byte_limit = 1; + from_ipa_cfg[0].aggr.aggr_time_limit = 0; + if (mGenericAgg) { + from_ipa_cfg[0].hdr.hdr_len = 4; + from_ipa_cfg[0].hdr_ext.hdr_pad_to_alignment = 2; + } else { + from_ipa_cfg[0].hdr.hdr_len = 1; + } + + prepare_channel_struct(&from_ipa_channels[0], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[0], + sizeof(from_ipa_cfg[0]), + false); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST3_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1]), + false); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + from_ipa_cfg[2].aggr.aggr_en = IPA_ENABLE_AGGR; + from_ipa_cfg[2].aggr.aggr = IPA_MBIM_16; + from_ipa_cfg[2].aggr.aggr_byte_limit = 1; + from_ipa_cfg[2].aggr.aggr_time_limit = 30; + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v4_2) + from_ipa_cfg[2].aggr.aggr_time_limit *= 1000; + if (mGenericAgg) { + from_ipa_cfg[2].hdr.hdr_len = 4; + from_ipa_cfg[2].hdr_ext.hdr_pad_to_alignment = 2; + } else { + from_ipa_cfg[2].hdr.hdr_len = 1; + } + + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2]), + false); + from_ipa_array[2] = &from_ipa_channels[2]; + + memset(&from_ipa_cfg[3], 0, sizeof(from_ipa_cfg[3])); + from_ipa_cfg[3].aggr.aggr_en = IPA_ENABLE_AGGR; + from_ipa_cfg[3].aggr.aggr = IPA_MBIM_16; + from_ipa_cfg[3].aggr.aggr_byte_limit = 0; + from_ipa_cfg[3].aggr.aggr_time_limit = 0; + if (mGenericAgg) { + from_ipa_cfg[3].hdr.hdr_len = 4; + from_ipa_cfg[3].hdr_ext.hdr_pad_to_alignment = 2; + } else { + from_ipa_cfg[3].hdr.hdr_len = 1; + } + + prepare_channel_struct(&from_ipa_channels[3], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[3], + sizeof(from_ipa_cfg[3]), + false); + from_ipa_array[3] = &from_ipa_channels[3]; + + /* To ipa configurations - 2 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + 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]; + + memset(&to_ipa_cfg[1], 0, sizeof(to_ipa_cfg[1])); + to_ipa_cfg[1].aggr.aggr_en = IPA_ENABLE_DEAGGR; + to_ipa_cfg[1].aggr.aggr = IPA_MBIM_16; + prepare_channel_struct(&to_ipa_channels[1], + header.to_ipa_channels_num++, + IPA_CLIENT_TEST2_PROD, + (void *)&to_ipa_cfg[1], + sizeof(to_ipa_cfg[1])); + to_ipa_array[1] = &to_ipa_channels[1]; + + prepare_header_struct(&header, from_ipa_array, to_ipa_array); + + retval = GenericConfigureScenario(&header); + + return retval; +} + +bool MBIMAggregationTestFixtureConf11::Setup() +{ + bool bRetVal = true; + + //Set the configuration to support USB->IPA and IPA->USB pipes. + if (SetupKernelModule() != true) { + LOG_MSG_ERROR("fail to configure kernel module!\n"); + return false; + } + + //Initialize the pipe for all the tests - this will open the inode which represents the pipe. + bRetVal &= m_IpaToUsbPipeAgg.Init(); + bRetVal &= m_UsbToIpaPipe.Init(); + bRetVal &= m_IpaToUsbPipe.Init(); + bRetVal &= m_UsbToIpaPipeDeagg.Init(); + bRetVal &= m_IpaToUsbPipeAggTime.Init(); + bRetVal &= m_IpaToUsbPipeAgg0Limits.Init(); + + if (!m_Routing.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Routing block is not ready for immediate commands!\n"); + return false; + } + if (!m_Filtering.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Filtering block is not ready for immediate commands!\n"); + return false; + } + if (!m_HeaderInsertion.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Header Insertion block is not ready for immediate commands!\n"); + return false; + } + m_HeaderInsertion.Reset();// resetting this component will reset both Routing and Filtering tables. + + return bRetVal; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationTestFixtureConf11::Teardown() +{ + //The Destroy method will close the inode. + m_IpaToUsbPipeAgg.Destroy(); + m_UsbToIpaPipe.Destroy(); + m_IpaToUsbPipe.Destroy(); + m_UsbToIpaPipeDeagg.Destroy(); + m_IpaToUsbPipeAggTime.Destroy(); + m_IpaToUsbPipeAgg0Limits.Destroy(); + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationTestFixtureConf11::Run() +{ + LOG_MSG_STACK("Entering Function"); + + // Add the relevant filtering rules + if (!AddRules()) { + LOG_MSG_ERROR("Failed adding filtering rules."); + return false; + } + if (!TestLogic()) { + LOG_MSG_ERROR("Test failed, Input and expected output mismatch."); + return false; + } + + LOG_MSG_STACK("Leaving Function (Returning True)"); + return true; +} // Run() + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationTestFixtureConf11::AddRules1HeaderAggregation() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + uint32_t nTableHdl; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + IPAFilteringTable cFilterTable1; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0]= 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, aHeadertoAdd, hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST2_CONS, + sGetHeader.hdl,&nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table for IPA_CLIENT_TEST_PROD completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + + // Creating Filtering Rule for De-aggregation PROD + cFilterTable1.Init(m_eIP,IPA_CLIENT_TEST2_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table for IPA_CLIENT_TEST2_PROD completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable1.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable1.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable1.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable1.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool MBIMAggregationTestFixtureConf11::AddRules1HeaderAggregation(bool bAggForceClose) { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + uint32_t nTableHdl; + bool bRetVal = true; + IPAFilteringTable_v2 cFilterTable0; + IPAFilteringTable_v2 cFilterTable1; + struct ipa_flt_rule_add_v2 sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0]= 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, aHeadertoAdd, hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST2_CONS, + sGetHeader.hdl, &nTableHdl, 0)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table for IPA_CLIENT_TEST_PROD completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = bAggForceClose; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + + // Creating Filtering Rule for De-aggregation PROD + cFilterTable1.Init(m_eIP,IPA_CLIENT_TEST2_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table for IPA_CLIENT_TEST2_PROD completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable1.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = bAggForceClose; + if ( + ((uint8_t)-1 == cFilterTable1.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable1.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable1.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable1.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationTestFixtureConf11::AddRulesDeaggregation() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + uint32_t nTableHdl; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0] = 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } + else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&aHeadertoAdd, + hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST3_CONS, + sGetHeader.hdl,&nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST2_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationTestFixtureConf11::AddRules1HeaderAggregationTime() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + uint32_t nTableHdl; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0] = 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } + else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&aHeadertoAdd, + hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST_CONS, + sGetHeader.hdl,&nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationTestFixtureConf11::AddRules1HeaderAggregation0Limits() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + uint32_t nTableHdl; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0] = 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } + else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&aHeadertoAdd, + hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST4_CONS, + sGetHeader.hdl,&nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool MBIMAggregationTestFixtureConf11::AddRulesAggDualFC(Pipe *input, Pipe *output1, Pipe *output2) { + m_eIP = IPA_IP_v4; + const char aBypass[2][20] = {"BypassTest2", "BypassTest4"}; + uint32_t nTableHdl[2]; + bool bRetVal = true; + IPAFilteringTable_v2 cFilterTable0; + struct ipa_flt_rule_add_v2 sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0]= 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, aHeadertoAdd, hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[0], + output1->GetClientType(), + sGetHeader.hdl, &nTableHdl[0], 0)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[1], + output2->GetClientType(), + sGetHeader.hdl, &nTableHdl[1], 0)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + LOG_MSG_INFO("Creation of bypass routing tables completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,input->GetClientType(), false, 2); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[0]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 1; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[1]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 0; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (1) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl1=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(1)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRulesAggDualFC() + +bool MBIMAggregationTestFixtureConf11::AddRulesAggDualFcRoutingBased(Pipe *input, Pipe *output1, Pipe *output2) { + m_eIP = IPA_IP_v4; + const char aBypass[2][20] = {"BypassTest2", "BypassTest4"}; + uint32_t nTableHdl[2]; + bool bRetVal = true; + IPAFilteringTable_v2 cFilterTable0; + struct ipa_flt_rule_add_v2 sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint8_t aHeadertoAdd[4]; + int hdrSize; + + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[0]= 0x49; + aHeadertoAdd[1] = 0x50; + aHeadertoAdd[2] = 0x53; + aHeadertoAdd[3] = 0x00; + } else { + hdrSize = 1; + aHeadertoAdd[0] = 0x00; + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, aHeadertoAdd, hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[0], + output1->GetClientType(), + sGetHeader.hdl, &nTableHdl[0], 1)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[1], + output2->GetClientType(), + sGetHeader.hdl, &nTableHdl[1], 0)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + LOG_MSG_INFO("Creation of bypass routing tables completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,input->GetClientType(), false, 2); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[0]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 0; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[1]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 0; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (1) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl1=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(1)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRulesAggDualFC() diff --git a/kernel-tests/MBIMAggregationTestFixtureConf11.h b/kernel-tests/MBIMAggregationTestFixtureConf11.h new file mode 100644 index 0000000000..f1c90731fe --- /dev/null +++ b/kernel-tests/MBIMAggregationTestFixtureConf11.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017,2020 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 "Constants.h" +#include "Logger.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "TestBase.h" +#include "Pipe.h" +#include "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" + + +#define NUM_PACKETS 5 +#define NUM_PACKETS_FC 4 +#define MAX_PACKET_SIZE 1024 +#define MAX_PACKETS_IN_MBIM_TESTS 10 +#define MAX_PACKETS_IN_NDP 8 +#define MAX_NDPS_IN_PACKET 8 + +/*This class will be the base class of MBIM Aggregation tests. + *Any method other than the test case itself + *can be declared in this Fixture thus allowing the derived classes to + *implement only the test case. + *All the test of the Aggregation uses one input and one output in DMA mode. + */ +class MBIMAggregationTestFixtureConf11:public TestBase +{ +public: + /*This Constructor will register each instance that it creates.*/ + MBIMAggregationTestFixtureConf11(bool generic_agg); + + virtual int SetupKernelModule(); + + /*This method will create and initialize two Pipe object + *for the USB (Ethernet) Pipes, one + *for as input and the other as output. + */ + virtual bool Setup(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + virtual bool Run(); + + virtual bool AddRules() = 0; + + virtual bool TestLogic() = 0; + + bool AddRules1HeaderAggregation(); + + bool AddRules1HeaderAggregation(bool bAggForceClose); + + bool AddRulesDeaggregation(); + + bool AddRules1HeaderAggregationTime(); + + bool AddRules1HeaderAggregation0Limits(); + + bool AddRulesAggDualFC(Pipe *input, Pipe *output1, Pipe *output2); + + bool AddRulesAggDualFcRoutingBased(Pipe *input, Pipe *output1, Pipe *output2); + + /*The client type are set from the + * peripheral perspective + */ + static Pipe m_IpaToUsbPipeAgg; + static Pipe m_UsbToIpaPipe; + static Pipe m_IpaToUsbPipe; + static Pipe m_UsbToIpaPipeDeagg; + static Pipe m_IpaToUsbPipeAggTime; + static Pipe m_IpaToUsbPipeAgg0Limits; + + static RoutingDriverWrapper m_Routing; + static Filtering m_Filtering; + static HeaderInsertion m_HeaderInsertion; + +protected: + enum ipa_ip_type m_eIP; + bool mGenericAgg; +}; diff --git a/kernel-tests/MBIMAggregationTests.cpp b/kernel-tests/MBIMAggregationTests.cpp new file mode 100644 index 0000000000..bd21434e0b --- /dev/null +++ b/kernel-tests/MBIMAggregationTests.cpp @@ -0,0 +1,3366 @@ +/* + * Copyright (c) 2017,2020 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 "hton.h" // for htonl +#include "MBIMAggregationTestFixtureConf11.h" +#include "Constants.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" + +#define AGGREGATION_LOOP 4 +#define IPV4_DST_ADDR_OFFSET (16) + +///////////////////////////////////////////////////////////////////////////////// +// MBIM Aggregation scenarios // +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationScenarios { +public: + //MBIM Aggregation test - sends 5 packets and receives 1 aggregated packet + static bool MBIMAggregationTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Deaggregation test - sends an aggregated packet made from 5 packets + //and receives 5 packets + static bool MBIMDeaggregationTest(Pipe* input, + Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Deaggregation one packet test - sends an aggregated packet made from + //1 packet and receives 1 packet + static bool MBIMDeaggregationOnePacketTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Deaggregation and Aggregation test - sends an aggregated packet made + //from 5 packets and receives the same aggregated packet + static bool MBIMDeaggregationAndAggregationTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM multiple Deaggregation and Aggregation test - sends 5 aggregated + //packets each one made of 1 packet and receives an aggregated packet made + //of the 5 packets + static bool MBIMMultipleDeaggregationAndAggregationTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP); + //MBIM Aggregation Loop test - sends 5 packets and expects to receive 1 + //aggregated packet a few times + static bool MBIMAggregationLoopTest(Pipe* input, + Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation time limit test - sends 1 small packet smaller than the + //byte limit and receives 1 aggregated packet + static bool MBIMAggregationTimeLimitTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation byte limit test - sends 2 packets that together are + //larger than the byte limit + static bool MBIMAggregationByteLimitTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + static bool MBIMAggregationByteLimitTestFC(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + static bool MBIMAggregationDualDpTestFC(Pipe* input, Pipe* output1, Pipe* output2, enum ipa_ip_type m_eIP); + //MBIM Deaggregation multiple NDP test - sends an aggregated packet made + //from 5 packets and 2 NDPs and receives 5 packets + static bool MBIMDeaggregationMultipleNDPTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation 2 pipes test - sends 3 packets from one pipe and an + //aggregated packet made of 2 packets from another pipe and receives 1 + //aggregated packet made of all 5 packets + static bool MBIMAggregation2PipesTest(Pipe* input1, Pipe* input2, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation time limit loop test - sends 5 small packet smaller than + //the byte limit and receives 5 aggregated packet + static bool MBIMAggregationTimeLimitLoopTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation 0 limits test - sends 5 packets and expects to get each + //packet back aggregated (both size and time limits are 0) + static bool MBIMAggregation0LimitsTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation multiple packets test - sends 9 packets with same stream + //ID and receives 1 aggregated packet with 2 NDPs + static bool MBIMAggregationMultiplePacketsTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation different stream IDs test - sends 5 packets with + //different stream IDs and receives 1 aggregated packet made of 5 NDPs + static bool MBIMAggregationDifferentStreamIdsTest(Pipe* input, Pipe* output, enum ipa_ip_type m_eIP); + //MBIM Aggregation no interleaving stream IDs test - sends 5 packets with + //interleaving stream IDs (0, 1, 0, 1, 0) and receives 1 aggregated packet + //made of 5 NDPs + static bool MBIMAggregationNoInterleavingStreamIdsTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP); + +private: + //This method will deaggregate an aggregated packet and compare the packets + //to the expected packets + static bool DeaggragateAndComparePackets( + Byte pAggregatedPacket[MAX_PACKET_SIZE], + Byte pExpectedPackets[MAX_PACKETS_IN_MBIM_TESTS][MAX_PACKET_SIZE], + int pPacketsSizes[MAX_PACKETS_IN_MBIM_TESTS], int nNumPackets, + int nAggregatedPacketSize); + //This method will aggregate packets + static void AggregatePackets( + Byte pAggregatedPacket[MAX_PACKET_SIZE]/*ouput*/, + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE], + int pPacketsSizes[NUM_PACKETS], int nNumPackets, + int nAggregatedPacketSize); + //This method will aggregate packets and take into consideration their + //stream id to seperate them into different NDPs + static void AggregatePacketsWithStreamId( + Byte pAggregatedPacket[MAX_PACKET_SIZE]/*ouput*/, + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE], + int pPacketsSizes[NUM_PACKETS], int nNumPackets, + int nAggregatedPacketSize, Byte pPacketsStreamId[NUM_PACKETS]); + //This method will deaggregate an aggregated packet made of one packet and + //compare the packet to the expected packet + static bool DeaggragateAndCompareOnePacket( + Byte pAggregatedPacket[MAX_PACKET_SIZE], + Byte pExpectedPacket[MAX_PACKET_SIZE], int nPacketsSize, + int nAggregatedPacketSize); + //This method will deaggregate an aggregated packet and compare the packets + //to the expected packets + static bool DeaggragateAndComparePacketsWithStreamId( + Byte pAggregatedPacket[MAX_PACKET_SIZE], + Byte pExpectedPackets[][MAX_PACKET_SIZE], int pPacketsSizes[], + int nNumPackets, int nAggregatedPacketSize, + Byte pPacketsStreamId[NUM_PACKETS]); +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationTest( + Pipe* input, Pipe* output, enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + { + pPacketsSizes[i]++; + } + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + + } + + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)" + "\n", MAX_PACKET_SIZE); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + //deaggregating the aggregated packet + return DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, NUM_PACKETS, nBytesReceived); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMDeaggregationTest( + Pipe* input, Pipe* output, enum ipa_ip_type m_eIP) +{ + bool bTestResult = true; + //The packets that the aggregated packet will be made of + Byte pExpectedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[NUM_PACKETS]; + //Buffers for the packets that will be received + Byte pReceivedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //Total size of all the packets that the aggregated packet will be made of + //(this is the max size of the aggregated packet + //minus the size of the header and the NDP) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + { + pPacketsSizes[i]++; + } + nTotalPacketsSize -= pPacketsSizes[i]; + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pExpectedPackets[i], + pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pExpectedPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pExpectedPackets[i][size] = i; + size++; + } + } + + //initializing the aggregated packet + AggregatePackets(pAggregatedPacket, pExpectedPackets, pPacketsSizes, + NUM_PACKETS, MAX_PACKET_SIZE); + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)\n", + sizeof(pAggregatedPacket)); + int nBytesSent = input->Send(pAggregatedPacket, sizeof(pAggregatedPacket)); + if (sizeof(pAggregatedPacket) != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes) " + "failed!\n", sizeof(pAggregatedPacket)); + return false; + } + + //receive the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Reading packet %d from the USB pipe(%d bytes should be " + "there)\n", i, pPacketsSizes[i]); + int nBytesReceived = output->Receive(pReceivedPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving packet %d from the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + print_buff(pReceivedPackets[i], nBytesReceived); + return false; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + for (int i = 0; i < NUM_PACKETS; i++) + bTestResult &= !memcmp(pExpectedPackets[i], pReceivedPackets[i], + pPacketsSizes[i]); + + return bTestResult; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMDeaggregationOnePacketTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + bool bTestResult = true; + //The packets that the aggregated packet will be made of + Byte pExpectedPackets[1][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[1] = {100}; + //Buffers for the packets that will be received + Byte pReceivedPackets[1][MAX_PACKET_SIZE]; + //Total size of the aggregated packet + //(this is the max size of the aggregated packet + //minus the size of the header and the NDP) + int nTotalAggregatedPacketSize = 100 + 12 + 16; + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[1]; + + // Load input data (IP packet) from file + pIpPacketsSizes[0] = 100; + if (!LoadDefaultPacket(m_eIP, pExpectedPackets[0], pIpPacketsSizes[0])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pExpectedPackets[0][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[0]; + while (size < pPacketsSizes[0]) + { + pExpectedPackets[0][size] = 0; + size++; + } + + + //initializing the aggregated packet + AggregatePackets(pAggregatedPacket, pExpectedPackets, pPacketsSizes, 1, + nTotalAggregatedPacketSize); + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)\n", + nTotalAggregatedPacketSize); + int nBytesSent = input->Send(pAggregatedPacket, nTotalAggregatedPacketSize); + if (nTotalAggregatedPacketSize != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes) " + "failed!\n", nTotalAggregatedPacketSize); + return false; + } + + //receive the packet + for (int i = 0; i < 1; i++) + { + LOG_MSG_DEBUG("Reading packet %d from the USB pipe(%d bytes should be " + "there)\n", i, pPacketsSizes[i]); + int nBytesReceived = output->Receive(pReceivedPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving packet %d from the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + print_buff(pReceivedPackets[i], nBytesReceived); + return false; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + for (int i = 0; i < 1; i++) + bTestResult &= !memcmp(pExpectedPackets[i], pReceivedPackets[i], + pPacketsSizes[i]); + + return bTestResult; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMDeaggregationAndAggregationTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that the aggregated packet will be made of + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[NUM_PACKETS]; + //Buffers for the packets that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all the packets that the aggregated packet will be made of + //(this is the max size of the aggregated packet + //minus the size of the header and the NDP) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + pPacketsSizes[i]++; + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + //initializing the aggregated packet + AggregatePackets(pAggregatedPacket, pPackets, pPacketsSizes, NUM_PACKETS, + MAX_PACKET_SIZE); + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)\n", + MAX_PACKET_SIZE); + int nBytesSent = input->Send(pAggregatedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE); + return false; + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading aggregated packet from the USB pipe(%d bytes should " + "be there)\n", MAX_PACKET_SIZE); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE); + LOG_MSG_DEBUG("Received %d bytes\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + return DeaggragateAndComparePackets(pReceivedPacket, pPackets, pPacketsSizes, + NUM_PACKETS, nBytesReceived); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMMultipleDeaggregationAndAggregationTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that the aggregated packets will be made of + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[NUM_PACKETS]; + //Buffers for the packets that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all the packets that the aggregated packet will be made of + //(this is the max size of the aggregated packet + //minus the size of the header and the NDP) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + //The aggregated packet that will be sent + Byte pAggregatedPacket[NUM_PACKETS][MAX_PACKET_SIZE]; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + pPacketsSizes[i]++; + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + + } + + //initializing the aggregated packets + for (int i = 0; i < NUM_PACKETS; i++) + AggregatePackets(pAggregatedPacket[i], &pPackets[i], &pPacketsSizes[i], + 1, pPacketsSizes[i] + 12 + 16); + + //send the aggregated packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending aggregated packet %d into the USB pipe(%d " + "bytes)\n", i, pPacketsSizes[i] + 12 + 16); + int nBytesSent = input->Send(pAggregatedPacket[i], + pPacketsSizes[i] + 12 + 16); + if (pPacketsSizes[i] + 12 + 16 != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet %d into the USB pipe(%d " + "bytes) failed!\n", i, pPacketsSizes[i] + 12 + 16); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading aggregated packet from the USB pipe(%d bytes should " + "be there)\n", MAX_PACKET_SIZE); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE); + LOG_MSG_DEBUG("Received %d bytes\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + return DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, NUM_PACKETS, nBytesReceived); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationLoopTest( + Pipe* input, Pipe* output, enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + pPacketsSizes[i]++; + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + int num_iters = AGGREGATION_LOOP - 1; + for (int j = 0; j < num_iters; j++) + { + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + memset(pReceivedPacket, 0, sizeof(pReceivedPacket)); + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", MAX_PACKET_SIZE); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + if (false == DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, NUM_PACKETS, nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + return false; + } + + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationTimeLimitTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[1][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[1] = {0}; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[1]; + + //initialize the packets + for (int i = 0; i < 1 ; i++) + { + pPacketsSizes[i] = 52 + 4*i; + nTotalPacketsSize += pPacketsSizes[i] + 4; //size of the packet + 4 bytes for index and length + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + int nAllPacketsSizes = 0; + for (int i = 0; i < 1; i++) + nAllPacketsSizes += pPacketsSizes[i]; + while (0 != nAllPacketsSizes % 4) + { + nAllPacketsSizes++; + nTotalPacketsSize++; //zero padding for NDP offset to be 4x + } + + //send the packets + for (int i = 0; i < 1; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", nTotalPacketsSize); + int nBytesReceived = output->Receive(pReceivedPacket, nTotalPacketsSize); + // IPA HW may add padding to the packets to align to 4B + if (nTotalPacketsSize > nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nTotalPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + if (false == DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, 1, nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationByteLimitTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[2][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[2]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[2]; + + //initialize the packets + for (int i = 0; i < 2; i++) + { + pPacketsSizes[i] = (MAX_PACKET_SIZE / 2) + 10; + nTotalPacketsSize += pPacketsSizes[i] + 4; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + + //send the packets + for (int i = 0; i < 2; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", nTotalPacketsSize); + int nBytesReceived = output->Receive(pReceivedPacket, nTotalPacketsSize); + // IPA HW may add padding to the packets to align to 4B + if (nTotalPacketsSize > nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nTotalPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + if (false == DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, 2, nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + return false; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationByteLimitTestFC( + Pipe *input, Pipe *output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[2][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[2]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2][MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 24 + (MAX_PACKET_SIZE / 2) + 8 + 4; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[2]; + int nBytesReceived; + + for (int i = 0; i < 2; i++) + { + pPacketsSizes[i] = (MAX_PACKET_SIZE / 2) + 8; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + + //send the packets + for (int i = 0; i < 2; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + /* receive the packet */ + LOG_MSG_DEBUG( + "Reading packets from the USB pipe(%d bytes for each)" + "\n", nTotalPacketsSize); + for (int i = 0; i < 2; i++) + { + nBytesReceived = output->Receive(pReceivedPacket[i], MAX_PACKET_SIZE); + if (nTotalPacketsSize != nBytesReceived) + { + LOG_MSG_ERROR( + "Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket[i], nBytesReceived); + return false; + } + } + + //comparing the received packets to the aggregated packets + LOG_MSG_DEBUG("Checking sent.vs.received packets\n"); + for (int i = 0; i < 2; i++) + { + if (false == DeaggragateAndComparePackets(pReceivedPacket[i], + &pPackets[i], + (int *)&pPacketsSizes[i], + 1, + nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + return false; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// +#define DUAL_FC_IP_PACKET_L ((MAX_PACKET_SIZE / 2) + 8) +#define DUAL_FC_1_AGG_PACKET_L (12 + DUAL_FC_IP_PACKET_L + 12 + 4) +#define DUAL_FC_2_AGG_PACKET_L (12 + DUAL_FC_IP_PACKET_L + DUAL_FC_IP_PACKET_L + 12 + 4 + 4) +bool MBIMAggregationScenarios::MBIMAggregationDualDpTestFC( + Pipe *input, Pipe *output1, Pipe *output2, + enum ipa_ip_type m_eIP) +{ + int i; + //The packets that will be sent + Byte pPackets[4][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[4]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2 * MAX_PACKET_SIZE] = {0}; + Byte pReceivedPacketFC[2][MAX_PACKET_SIZE] = {0}; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[4]; + int nBytesReceived; + + for (i = 0; i < 4; i++) + { + pPacketsSizes[i] = DUAL_FC_IP_PACKET_L; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001 + (i & 0x1)); + memcpy(&pPackets[i][IPV4_DST_ADDR_OFFSET], &nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = 0xAA; + size++; + } + } + + //send the packets + for (int i = 0; i < 4; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + /* receive the packets from FC pipe */ + LOG_MSG_DEBUG( + "Reading packets from the FC pipe (%d bytes for each)" + "\n", DUAL_FC_1_AGG_PACKET_L); + for (i = 0; i < 2; i++) + { + nBytesReceived = output1->Receive(pReceivedPacketFC[i], MAX_PACKET_SIZE); + if (DUAL_FC_1_AGG_PACKET_L != nBytesReceived) + { + LOG_MSG_ERROR( + "Receiving aggregated packet from the USB pipe (%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacketFC[i], nBytesReceived); + return false; + } + } + + for (i = 0; i < 2; i++) + { + if (false == DeaggragateAndComparePackets(pReceivedPacketFC[i], + &pPackets[i * 2], + (int *)&pPacketsSizes[i * 2], + 1, + nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + return false; + } + } + + /* receive the packet from non-FC pipe */ + LOG_MSG_DEBUG( + "Reading packet from the non-FC pipe (%d bytes)" + "\n", DUAL_FC_2_AGG_PACKET_L); + nBytesReceived = output2->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (DUAL_FC_2_AGG_PACKET_L != nBytesReceived) + { + LOG_MSG_ERROR( + "Receiving aggregated packet from the USB pipe (%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + // Setting all source packets IP to 127.0.0.2 for comparison + nIPv4DSTAddr = ntohl(0x7F000002); + memcpy(&pPackets[0][IPV4_DST_ADDR_OFFSET], &nIPv4DSTAddr, sizeof(nIPv4DSTAddr)); + memcpy(&pPackets[2][IPV4_DST_ADDR_OFFSET], &nIPv4DSTAddr, sizeof(nIPv4DSTAddr)); + + if (false == DeaggragateAndComparePackets(&pReceivedPacket[0], pPackets, + (int *)&pPacketsSizes, 2, nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMDeaggregationMultipleNDPTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + bool bTestResult = true; + //The packets that the aggregated packet will be made of + Byte pExpectedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[NUM_PACKETS]; + //Buffers for the packets that will be received + Byte pReceivedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //Total size of all the packets that the aggregated packet will be made of + //(this is the max size of the aggregated packet + //minus the size of the header and the 2 NDPs) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 36; + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + //The stream Id byte for every packet - this will determine on which NDP the + //packet will appear + Byte pPacketsStreamId[NUM_PACKETS] = {0}; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else { + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + pPacketsSizes[i] += (pPacketsSizes[i] % 4 == 0 ? 0 : + 4 - pPacketsSizes[i] % 4); + } + nTotalPacketsSize -= pPacketsSizes[i]; + pPacketsStreamId[i] = i < 3 ? 0 : 1; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pExpectedPackets[i], + pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pExpectedPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pExpectedPackets[i][size] = i; + size++; + } + } + + //initializing the aggregated packet + AggregatePacketsWithStreamId(pAggregatedPacket, pExpectedPackets, + pPacketsSizes, NUM_PACKETS, MAX_PACKET_SIZE, pPacketsStreamId); + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)\n", + sizeof(pAggregatedPacket)); + int nBytesSent = input->Send(pAggregatedPacket, sizeof(pAggregatedPacket)); + if (sizeof(pAggregatedPacket) != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes) " + "failed!\n", sizeof(pAggregatedPacket)); + return false; + } + + //receive the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Reading packet %d from the USB pipe(%d bytes should be " + "there)\n", i, pPacketsSizes[i]); + int nBytesReceived = output->Receive(pReceivedPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving packet %d from the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + print_buff(pReceivedPackets[i], nBytesReceived); + return false; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + for (int i = 0; i < NUM_PACKETS; i++) + bTestResult &= !memcmp(pExpectedPackets[i], pReceivedPackets[i], + pPacketsSizes[i]); + + return bTestResult; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregation2PipesTest( + Pipe* input1, Pipe* input2, Pipe* output, enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + //The aggregated packet that will be sent + Byte pAggregatedPacket[2][MAX_PACKET_SIZE]; + //The size of the sent aggregated packet + int nAggregatedPacketSize[2] = {0}; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + pPacketsSizes[i]++; + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + + nAggregatedPacketSize[0] += pPacketsSizes[0] + pPacketsSizes[1]; //adding the packets + nAggregatedPacketSize[0] += 12; //adding the header + nAggregatedPacketSize[0] += 12 + 4*2; //adding the NDP + //initializing the aggregated packet + AggregatePackets(pAggregatedPacket[0], pPackets, pPacketsSizes, 2, + nAggregatedPacketSize[0]); + + //send the aggregated packet + + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d " + "bytes)\n", nAggregatedPacketSize[0]); + int nBytesSent = input1->Send(pAggregatedPacket[0], + nAggregatedPacketSize[0]); + if (nAggregatedPacketSize[0] != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes) " + "failed!\n", nAggregatedPacketSize[0]); + return false; + } + + //send the packets + for (int i = 2; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input2->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //deaggregating the aggregated packet + return DeaggragateAndComparePackets(pReceivedPacket, pPackets, pPacketsSizes, NUM_PACKETS, nBytesReceived); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationTimeLimitLoopTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[1][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[1] = {0}; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < 1 ; i++) + { + pPacketsSizes[i] = 52 + 4*i; + nTotalPacketsSize += pPacketsSizes[i] + 4; //size of the packet + 4 bytes for index and length + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + int nAllPacketsSizes = 0; + for (int i = 0; i < 1; i++) + nAllPacketsSizes += pPacketsSizes[i]; + while (0 != nAllPacketsSizes % 4) + { + nAllPacketsSizes++; + nTotalPacketsSize++; //zero padding for NDP offset to be 4x + } + + for (int k = 0; k < AGGREGATION_LOOP; k++) + { + //send the packets + for (int i = 0; i < 1; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", nTotalPacketsSize); + int nBytesReceived = output->Receive(pReceivedPacket, + nTotalPacketsSize); + // IPA HW may add padding to the packets to align to 4B + if (nTotalPacketsSize > nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", nTotalPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + if (false == DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, 1, nBytesReceived)) + { + LOG_MSG_DEBUG("Comparing aggregated packet failed!\n"); + return false; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregation0LimitsTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The expected aggregated packets sizes + int pAggragatedPacketsSizes[NUM_PACKETS] = {0}; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS ; i++) + { + pPacketsSizes[i] = 52 + 4*i; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + //calculate aggregated packets sizes + for (int i = 0; i < NUM_PACKETS; i++) + { + pAggragatedPacketsSizes[i] += pPacketsSizes[i]; + while (0 != pAggragatedPacketsSizes[i] % 4) + pAggragatedPacketsSizes[i]++; //zero padding for NDP offset to be 4x + pAggragatedPacketsSizes[i] += 28; //header + NDP + } + + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Reading packet %d from the USB pipe(%d bytes should be " + "there)\n", i, pAggragatedPacketsSizes[i]); + int nBytesReceived = output->Receive(pReceivedPackets[i], + pAggragatedPacketsSizes[i]); + // IPA HW may add padding to the packets to align to 4B + if (pAggragatedPacketsSizes[i] > nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet %d from the USB pipe(%d " + "bytes) failed!\n", i, pAggragatedPacketsSizes[i]); + print_buff(pReceivedPackets[i], nBytesReceived); + return false; + } + pAggragatedPacketsSizes[i] = nBytesReceived; + } + + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + for (int i = 0; i < NUM_PACKETS; i++) + { + if (false == DeaggragateAndCompareOnePacket(pReceivedPackets[i], + pPackets[i], pPacketsSizes[i], pAggragatedPacketsSizes[i])) + { + LOG_MSG_DEBUG("Comparing aggregated packet %d failed!\n", i); + return false; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationMultiplePacketsTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[MAX_PACKETS_IN_NDP + 1][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[MAX_PACKETS_IN_NDP + 1]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[MAX_PACKETS_IN_NDP + 1]; + //Total size of all sent packets (this is the max size of the aggregated packet + //minus the size of the header and the 2 NDPs) + int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * (MAX_PACKETS_IN_NDP + 1)) - 24; + + //initialize the packets + for (int i = 0; i < MAX_PACKETS_IN_NDP + 1; i++) + { + if (MAX_PACKETS_IN_NDP == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + { + pPacketsSizes[i] = nTotalPacketsSize / (MAX_PACKETS_IN_NDP + 1); + pPacketsSizes[i] += (pPacketsSizes[i] % 4 == 0 ? 0 : + 4 - pPacketsSizes[i] % 4); + } + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + //send the packets + for (int i = 0; i < MAX_PACKETS_IN_NDP + 1; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //deaggregating the aggregated packet + return DeaggragateAndComparePackets(pReceivedPacket, pPackets, + pPacketsSizes, MAX_PACKETS_IN_NDP+1, nBytesReceived); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationDifferentStreamIdsTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDPs) + int nTotalPacketsSize = MAX_PACKET_SIZE - (16 * NUM_PACKETS) - 12; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + Byte pPacketsStreamId[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + pPacketsStreamId[i] = i; + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize + 12; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + pPacketsSizes[i]++; + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[0][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0xC0A80101); + memcpy (&pPackets[1][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0xC0A80102); + memcpy (&pPackets[2][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0xC0A80103); + memcpy (&pPackets[3][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0xC0A80104); + memcpy (&pPackets[4][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE + 12); + int nBytesReceived = output->Receive(pReceivedPacket, MAX_PACKET_SIZE + 12); + if (MAX_PACKET_SIZE + 12 != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", MAX_PACKET_SIZE + 12); + print_buff(pReceivedPacket, nBytesReceived + 12); + return false; + } + + //deaggregating the aggregated packet + return DeaggragateAndComparePacketsWithStreamId(pReceivedPacket, pPackets, + pPacketsSizes, NUM_PACKETS, nBytesReceived, pPacketsStreamId); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::MBIMAggregationNoInterleavingStreamIdsTest( + Pipe* input, Pipe* output, + enum ipa_ip_type m_eIP) +{ + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated packet + //minus the size of the header and the NDPs) + int nTotalPacketsSize = MAX_PACKET_SIZE - (16 * NUM_PACKETS) - 12; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + Byte pPacketsStreamId[NUM_PACKETS]; + + //initialize the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + pPacketsStreamId[i] = i % 2; + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize + 12; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + while (0 != pPacketsSizes[i] % 4) + pPacketsSizes[i]++; + nTotalPacketsSize -= pPacketsSizes[i]; + + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + int size = pIpPacketsSizes[i]; + while (size < pPacketsSizes[i]) + { + pPackets[i][size] = i; + size++; + } + } + + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[0][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0xC0A80101); + memcpy (&pPackets[1][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[2][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0xC0A80101); + memcpy (&pPackets[3][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[4][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = input->Send(pPackets[i], pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE + 12); + int nBytesReceived = output->Receive(pReceivedPacket, + MAX_PACKET_SIZE + 12); + if (MAX_PACKET_SIZE + 12 != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d bytes)" + " failed!\n", MAX_PACKET_SIZE + 12); + print_buff(pReceivedPacket, nBytesReceived + 12); + return false; + } + + //deaggregating the aggregated packet + return DeaggragateAndComparePacketsWithStreamId(pReceivedPacket, pPackets, + pPacketsSizes, NUM_PACKETS, nBytesReceived, pPacketsStreamId); +} + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::DeaggragateAndComparePackets( + Byte pAggregatedPacket[MAX_PACKET_SIZE], + Byte pExpectedPackets[MAX_PACKETS_IN_MBIM_TESTS][MAX_PACKET_SIZE], + int pPacketsSizes[MAX_PACKETS_IN_MBIM_TESTS], int nNumPackets, int nAggregatedPacketSize) +{ + int nPacketNum = 0; + int i = 0; + int nNdpStart = 0; + Byte pNdpIndex[2] = {0}; + Byte pNdpLen[2] = {0}; + if (0x4e != pAggregatedPacket[i] || 0x43 != pAggregatedPacket[i+1] || + 0x4d != pAggregatedPacket[i+2]|| 0x48 != pAggregatedPacket[i+3]) + { + LOG_MSG_DEBUG("Error: Wrong NTH16 signature: 0x%02x 0x%02x 0x%02x " + "0x%02x(should be 0x4e, 0x43, 0x4d, 0x48)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1], + pAggregatedPacket[i+2], pAggregatedPacket[i+3]); + return false; + } + i += 4; + if (0x0c != pAggregatedPacket[i] || 0x00 != pAggregatedPacket[i+1]) + { + LOG_MSG_DEBUG("Error: Wrong header length: 0x%02x 0x%02x(should be 0x0c, " + "0x00)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1]); + return false; + } + i += 4; //ignoring sequence number + if ((nAggregatedPacketSize & 0x00FF) != pAggregatedPacket[i] || + (nAggregatedPacketSize >> 8) != pAggregatedPacket[i+1]) + { + LOG_MSG_DEBUG("Error: Wrong aggregated packet length: 0x%02x 0x%02x" + "(should be 0x%02x, 0x%02x)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1], + nAggregatedPacketSize & 0x00FF, nAggregatedPacketSize >> 8); + return false; + } + i += 2; + pNdpIndex[0] = pAggregatedPacket[i]; //least significant byte + pNdpIndex[1] = pAggregatedPacket[i+1]; //most significant byte + //reading the NDP + while (0x00 != pNdpIndex[0] || 0x00 != pNdpIndex[1]) + { + i = pNdpIndex[0] + 256*pNdpIndex[1]; //NDP should begin here + nNdpStart = i; + + if (0x49 != pAggregatedPacket[i] || 0x50 != pAggregatedPacket[i + 1] || + 0x53 != pAggregatedPacket[i + 2] || 0x00 != pAggregatedPacket[i + 3]) + { + LOG_MSG_DEBUG("Error: Wrong NDP16 signature: 0x%02x 0x%02x " + "0x%02x 0x%02x(should be 0x49, 0x50, 0x53, 0x00)\n", + pAggregatedPacket[i], pAggregatedPacket[i + 1], + pAggregatedPacket[i + 2], pAggregatedPacket[i + 3]); + return false; + } + i += 4; + pNdpLen[0] = pAggregatedPacket[i]; //least significant byte + pNdpLen[1] = pAggregatedPacket[i+1]; //most significant byte + if (0x00 != pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2] || + 0x00 != pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] -1]) + { + LOG_MSG_DEBUG("Error: Wrong end of NDP: 0x%02x 0x%02x(should be 0x00," + " 0x00)\n", + pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2], + pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 1]); + return false; + } + i += 2; + pNdpIndex[0] = pAggregatedPacket[i]; //least significant byte + pNdpIndex[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + while (i <= nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2) + { //going over all the datagrams in this NDP + Byte pDatagramIndex[2] = {0}; + Byte pDatagramLen[2] = {0}; + int packetIndex = 0; + pDatagramIndex[0] = pAggregatedPacket[i]; //least significant byte + pDatagramIndex[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + if (0x00 == pDatagramIndex[0] && 0x00 == pDatagramIndex[1]) + break; //zero padding after all datagrams + if (nPacketNum >= nNumPackets) + { + LOG_MSG_DEBUG("Error: wrong number of packets: %d(should be %d)\n", + nPacketNum, nNumPackets); + return false; + } + pDatagramLen[0] = pAggregatedPacket[i]; //least significant byte + pDatagramLen[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + packetIndex = pDatagramIndex[0] + 256*pDatagramIndex[1]; + if (pDatagramLen[0] + 256*pDatagramLen[1] != pPacketsSizes[nPacketNum]) + { + LOG_MSG_DEBUG("Error: Wrong packet %d length: 0x%02x 0x%02x" + "(should be %d)\n", nPacketNum, pDatagramLen[0], + pDatagramLen[1], pPacketsSizes[nPacketNum]); + return false; + } + if (0 != memcmp(pExpectedPackets[nPacketNum], + &pAggregatedPacket[packetIndex], pPacketsSizes[nPacketNum])) + { + LOG_MSG_DEBUG("Error: Comparison of packet %d failed!\n", + nPacketNum); + + return false; + } + nPacketNum++; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +void MBIMAggregationScenarios::AggregatePackets( + Byte pAggregatedPacket[MAX_PACKET_SIZE]/*ouput*/, + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE], + int pPacketsSizes[NUM_PACKETS], int nNumPackets, + int nAggregatedPacketSize) +{ + int i = 0; + int pDatagramIndexes[NUM_PACKETS] = {0}; + int nNdpIndex = 0; + int nNdpLen = 0; + //NTH16 signature + pAggregatedPacket[i] = 0x4e; + pAggregatedPacket[i+1] = 0x43; + pAggregatedPacket[i+2] = 0x4d; + pAggregatedPacket[i+3] = 0x48; + i += 4; + //header length + pAggregatedPacket[i] = 0x0c; + pAggregatedPacket[i+1] = 0x00; + i += 2; + //sequence number + pAggregatedPacket[i] = 0x00; + pAggregatedPacket[i+1] = 0x00; + i += 2; + //aggregated packet length + pAggregatedPacket[i] = nAggregatedPacketSize & 0x00FF; + pAggregatedPacket[i+1] = nAggregatedPacketSize >> 8; + i += 2; + //NDP index + for (int j = 0; j < nNumPackets; j++) + nNdpIndex += pPacketsSizes[j]; + nNdpIndex += i + 2; + while (0 != nNdpIndex % 4) + nNdpIndex++; + pAggregatedPacket[i] = nNdpIndex & 0x00FF; + pAggregatedPacket[i+1] = nNdpIndex >> 8; + i += 2; + //packets + for (int j = 0; j < nNumPackets; j++) + { + pDatagramIndexes[j] = i; + for (int k = 0; k < pPacketsSizes[j]; k++) + { + pAggregatedPacket[i] = pPackets[j][k]; + i++; + } + } + while (i < nNdpIndex) + { + pAggregatedPacket[i] = 0x00; + i++; + } + + //NDP16 signature + pAggregatedPacket[i] = 0x49; + pAggregatedPacket[i+1] = 0x50; + pAggregatedPacket[i+2] = 0x53; + pAggregatedPacket[i+3] = 0x00; + i += 4; + //NDP length + nNdpLen = 4*nNumPackets + 8 + 2; + while (nNdpLen % 4 != 0) + nNdpLen += 2; + pAggregatedPacket[i] = nNdpLen & 0x00FF; + pAggregatedPacket[i+1] = nNdpLen >> 8; + i += 2; + //next NDP + pAggregatedPacket[i] = 0x00; + pAggregatedPacket[i+1] = 0x00; + i += 2; + for (int j = 0; j < nNumPackets; j++) + { + //datagram index + pAggregatedPacket[i] = pDatagramIndexes[j] & 0x00FF; + pAggregatedPacket[i+1] = pDatagramIndexes[j] >> 8; + i += 2; + //datagram length + pAggregatedPacket[i] = pPacketsSizes[j] & 0x00FF; + pAggregatedPacket[i+1] = pPacketsSizes[j] >> 8; + i += 2; + } + //zeros in the end of NDP + while (i < nAggregatedPacketSize) + { + pAggregatedPacket[i] = 0x00; + i++; + } +} + +///////////////////////////////////////////////////////////////////////////////// + +void MBIMAggregationScenarios::AggregatePacketsWithStreamId( + Byte pAggregatedPacket[MAX_PACKET_SIZE]/*ouput*/, + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE], + int pPacketsSizes[NUM_PACKETS], int nNumPackets, int nAggregatedPacketSize, + Byte pPacketsStreamId[NUM_PACKETS]) +{ + int i = 0; + int n = 0; + int pDatagramIndexes[NUM_PACKETS] = {0}; + int nNdpIndex[NUM_PACKETS] = {0}; + int nNdpLen = 0; + Byte currStreamId = pPacketsStreamId[0]; + int nNdpFirstPacket[NUM_PACKETS] = {0}; + int nNdpAfterLastPacket[NUM_PACKETS] = {0}; + int nNumNDPs = 0; + for (n = 0; n < nNumPackets; n++) + { + if (currStreamId != pPacketsStreamId[n]) + { + nNdpAfterLastPacket[nNumNDPs] = n; + nNumNDPs++; + nNdpFirstPacket[nNumNDPs] = n; + currStreamId = pPacketsStreamId[n]; + } + } + nNdpAfterLastPacket[nNumNDPs] = n; + nNumNDPs++; + //calculate NDP indexes + nNdpIndex[0] += 12; //adding the header + for (int j = 0; j < nNumNDPs; j++) + { + for (n = nNdpFirstPacket[j]; n < nNdpAfterLastPacket[j]; n++) + nNdpIndex[j] += pPacketsSizes[n]; //adding the packets + while (0 != nNdpIndex[j] % 4) + nNdpIndex[j]++; + if (j < nNumNDPs - 1) + nNdpIndex[j+1] += nNdpIndex[j] + 12 + 4*(nNdpAfterLastPacket[j] - + nNdpFirstPacket[j]); //adding the location after the current NDP to the next NDP + } + //start building the aggregated packet + //NTH16 signature + pAggregatedPacket[i] = 0x4e; + pAggregatedPacket[i+1] = 0x43; + pAggregatedPacket[i+2] = 0x4d; + pAggregatedPacket[i+3] = 0x48; + i += 4; + //header length + pAggregatedPacket[i] = 0x0c; + pAggregatedPacket[i+1] = 0x00; + i += 2; + //sequence number + pAggregatedPacket[i] = 0x00; + pAggregatedPacket[i+1] = 0x00; + i += 2; + //aggregated packet length + pAggregatedPacket[i] = nAggregatedPacketSize & 0x00FF; + pAggregatedPacket[i+1] = nAggregatedPacketSize >> 8;; + i += 2; + //first NDP index + pAggregatedPacket[i] = nNdpIndex[0] & 0x00FF; + pAggregatedPacket[i+1] = nNdpIndex[0] >> 8; + i += 2; + for (n = 0; n < nNumNDPs; n++) + { + //packets + for (int j = nNdpFirstPacket[n]; j < nNdpAfterLastPacket[n]; j++) + { + pDatagramIndexes[j] = i; + for (int k = 0; k < pPacketsSizes[j]; k++) + { + pAggregatedPacket[i] = pPackets[j][k]; + i++; + } + } + while (i < nNdpIndex[n]) + { + pAggregatedPacket[i] = 0x00; + i++; + } + //NDP signature + pAggregatedPacket[i] = 0x49; + pAggregatedPacket[i+1] = 0x50; + pAggregatedPacket[i+2] = 0x53; + pAggregatedPacket[i+3] = pPacketsStreamId[nNdpFirstPacket[n]]; + i += 4; + //NDP length + nNdpLen = 4*(nNdpAfterLastPacket[n] - nNdpFirstPacket[n]) + 8 + 2; + while (nNdpLen % 4 != 0) + nNdpLen += 2; + pAggregatedPacket[i] = nNdpLen & 0x00FF; + pAggregatedPacket[i+1] = nNdpLen >> 8; + i += 2; + //next NDP + pAggregatedPacket[i] = nNdpIndex[n+1] & 0x00FF; + pAggregatedPacket[i+1] = nNdpIndex[n+1] >> 8; + i += 2; + for (int j = nNdpFirstPacket[n]; j < nNdpAfterLastPacket[n]; j++) + { + //datagram index + pAggregatedPacket[i] = pDatagramIndexes[j] & 0x00FF; + pAggregatedPacket[i+1] = pDatagramIndexes[j] >> 8; + i += 2; + //datagram length + pAggregatedPacket[i] = pPacketsSizes[j] & 0x00FF; + pAggregatedPacket[i+1] = pPacketsSizes[j] >> 8; + i += 2; + } + //zeros in the end of NDP + while (i < nNdpIndex[n] + nNdpLen) + { + pAggregatedPacket[i] = 0x00; + i++; + } + } +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::DeaggragateAndCompareOnePacket( + Byte pAggregatedPacket[MAX_PACKET_SIZE], + Byte pExpectedPacket[MAX_PACKET_SIZE], int nPacketsSize, + int nAggregatedPacketSize) +{ + int nPacketNum = 0; + int i = 0; + int nNdpStart = 0; + Byte pNdpIndex[2] = {0}; + Byte pNdpLen[2] = {0}; + if (0x4e != pAggregatedPacket[i] || 0x43 != pAggregatedPacket[i+1] || + 0x4d != pAggregatedPacket[i+2]|| 0x48 != pAggregatedPacket[i+3]) + { + LOG_MSG_DEBUG("Error: Wrong NTH16 signature: 0x%02x 0x%02x 0x%02x " + "0x%02x(should be 0x4e, 0x43, 0x4d, 0x48)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1], + pAggregatedPacket[i+2], pAggregatedPacket[i+3]); + return false; + } + i += 4; + if (0x0c != pAggregatedPacket[i] || 0x00 != pAggregatedPacket[i+1]) + { + LOG_MSG_DEBUG("Error: Wrong header length: 0x%02x 0x%02x(should be 0x0c," + " 0x00)\n", pAggregatedPacket[i], pAggregatedPacket[i+1]); + return false; + } + i += 4; //ignoring sequence number + if ((nAggregatedPacketSize & 0x00FF) != pAggregatedPacket[i] || + (nAggregatedPacketSize >> 8) != pAggregatedPacket[i+1]) + { + LOG_MSG_DEBUG("Error: Wrong aggregated packet length: 0x%02x 0x%02x" + "(should be 0x%02x, 0x%02x)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1], + nAggregatedPacketSize & 0x00FF, nAggregatedPacketSize >> 8); + return false; + } + i += 2; + pNdpIndex[0] = pAggregatedPacket[i]; //least significant byte + pNdpIndex[1] = pAggregatedPacket[i+1]; //most significant byte + //reading the NDP + while (0x00 != pNdpIndex[0] || 0x00 != pNdpIndex[1]) + { + i = pNdpIndex[0] + 256*pNdpIndex[1]; //NDP should begin here + nNdpStart = i; + + if (0x49 != pAggregatedPacket[i] || 0x50 != pAggregatedPacket[i+1] || + 0x53 != pAggregatedPacket[i+2] || 0x00 != pAggregatedPacket[i+3]) + { + LOG_MSG_DEBUG("Error: Wrong NDP16 signature: 0x%02x 0x%02x " + "0x%02x 0x%02x(should be 0x49, 0x50, 0x53, 0x00)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1], + pAggregatedPacket[i+2], pAggregatedPacket[i+3]); + return false; + } + i += 4; + pNdpLen[0] = pAggregatedPacket[i]; //least significant byte + pNdpLen[1] = pAggregatedPacket[i+1]; //most significant byte + if (0x00 != pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2] || + 0x00 != pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] -1]) + { + LOG_MSG_DEBUG("Error: Wrong end of NDP: 0x%02x 0x%02x(should be " + "0x00, 0x00)\n", + pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2], + pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 1]); + return false; + } + i += 2; + pNdpIndex[0] = pAggregatedPacket[i]; //least significant byte + pNdpIndex[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + while (i <= nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2) + { //going over all the datagrams in this NDP + Byte pDatagramIndex[2] = {0}; + Byte pDatagramLen[2] = {0}; + int packetIndex = 0; + pDatagramIndex[0] = pAggregatedPacket[i]; //least significant byte + pDatagramIndex[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + if (0x00 == pDatagramIndex[0] && 0x00 == pDatagramIndex[1]) + break; //zero padding after all datagrams + if (nPacketNum > 1) + { + LOG_MSG_DEBUG("Error: wrong number of packets: %d(should be %d)\n", + nPacketNum, 1); + return false; + } + pDatagramLen[0] = pAggregatedPacket[i]; //least significant byte + pDatagramLen[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + packetIndex = pDatagramIndex[0] + 256*pDatagramIndex[1]; + if (pDatagramLen[0] + 256*pDatagramLen[1] != nPacketsSize) + { + LOG_MSG_DEBUG("Error: Wrong packet %d length: 0x%02x 0x%02x" + "(should be %d)\n", nPacketNum, pDatagramLen[0], + pDatagramLen[1], nPacketsSize); + return false; + } + if (0 != memcmp(pExpectedPacket, &pAggregatedPacket[packetIndex], + nPacketsSize)) + { + LOG_MSG_DEBUG("Error: Comparison of packet %d failed!\n", + nPacketNum); + return false; + } + nPacketNum++; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool MBIMAggregationScenarios::DeaggragateAndComparePacketsWithStreamId( + Byte pAggregatedPacket[MAX_PACKET_SIZE], + Byte pExpectedPackets[][MAX_PACKET_SIZE], int pPacketsSizes[], + int nNumPackets, int nAggregatedPacketSize, + Byte pPacketsStreamId[NUM_PACKETS]) +{ + int nPacketNum = 0; + int i = 0; + int nNdpStart = 0; + Byte pNdpIndex[2] = {0}; + Byte pNdpLen[2] = {0}; + if (0x4e != pAggregatedPacket[i] || 0x43 != pAggregatedPacket[i+1] || + 0x4d != pAggregatedPacket[i+2]|| 0x48 != pAggregatedPacket[i+3]) + { + LOG_MSG_DEBUG("Error: Wrong NTH16 signature: 0x%02x 0x%02x 0x%02x " + "0x%02x(should be 0x4e, 0x43, 0x4d, 0x48)\n", + pAggregatedPacket[i], pAggregatedPacket[i+1], + pAggregatedPacket[i+2], pAggregatedPacket[i+3]); + return false; + } + i += 4; + if (0x0c != pAggregatedPacket[i] || 0x00 != pAggregatedPacket[i+1]) + { + LOG_MSG_DEBUG("Error: Wrong header length: 0x%02x 0x%02x(should be " + "0x0c, 0x00)\n",pAggregatedPacket[i], pAggregatedPacket[i+1]); + return false; + } + i += 4; //ignoring sequence number + if ((nAggregatedPacketSize & 0x00FF) != pAggregatedPacket[i] || + (nAggregatedPacketSize >> 8) != pAggregatedPacket[i+1]) + { + LOG_MSG_DEBUG("Error: Wrong aggregated packet length: 0x%02x 0x%02x" + "(should be 0x%02x, 0x%02x)\n", pAggregatedPacket[i], + pAggregatedPacket[i+1], nAggregatedPacketSize & 0x00FF, + nAggregatedPacketSize >> 8); + return false; + } + i += 2; + pNdpIndex[0] = pAggregatedPacket[i]; //least significant byte + pNdpIndex[1] = pAggregatedPacket[i+1]; //most significant byte + //reading the NDP + while (0x00 != pNdpIndex[0] || 0x00 != pNdpIndex[1]) + { + i = pNdpIndex[0] + 256*pNdpIndex[1]; //NDP should begin here + nNdpStart = i; + if (0x49 != pAggregatedPacket[i] || 0x50 != pAggregatedPacket[i+1] || + 0x53 != pAggregatedPacket[i+2]) + { + LOG_MSG_DEBUG("Error: Wrong NDP16 signature: 0x%02x 0x%02x 0x%02x" + "(should be 0x49, 0x50, 0x53)\n", pAggregatedPacket[i], + pAggregatedPacket[i+1], pAggregatedPacket[i+2]); + return false; + } + if (pPacketsStreamId[nPacketNum] != pAggregatedPacket[i+3]) + { + LOG_MSG_DEBUG("Error: Wrong NDP stream id: 0x%02x(should be 0x%02x)\n", + pAggregatedPacket[i+3], pPacketsStreamId[nPacketNum]); + return false; + } + i += 4; + pNdpLen[0] = pAggregatedPacket[i]; //least significant byte + pNdpLen[1] = pAggregatedPacket[i+1]; //most significant byte + if (0x00 != pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2] || + 0x00 != pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] -1]) + { + LOG_MSG_DEBUG("Error: Wrong end of NDP: 0x%02x 0x%02x(should be 0x00, " + "0x00)\n", + pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2], + pAggregatedPacket[nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 1]); + return false; + } + i += 2; + pNdpIndex[0] = pAggregatedPacket[i]; //least significant byte + pNdpIndex[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + while (i <= nNdpStart + pNdpLen[0] + 256*pNdpLen[1] - 2) + { //going over all the datagrams in this NDP + Byte pDatagramIndex[2] = {0}; + Byte pDatagramLen[2] = {0}; + int packetIndex = 0; + pDatagramIndex[0] = pAggregatedPacket[i]; //least significant byte + pDatagramIndex[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + if (0x00 == pDatagramIndex[0] && 0x00 == pDatagramIndex[1]) + break; //zero padding after all datagrams + if (nPacketNum >= nNumPackets) + { + LOG_MSG_DEBUG("Error: wrong number of packets: %d(should be %d)\n", + nPacketNum, nNumPackets); + return false; + } + pDatagramLen[0] = pAggregatedPacket[i]; //least significant byte + pDatagramLen[1] = pAggregatedPacket[i+1]; //most significant byte + i += 2; + packetIndex = pDatagramIndex[0] + 256*pDatagramIndex[1]; + if (pDatagramLen[0] + 256*pDatagramLen[1] != (int)pPacketsSizes[nPacketNum]) + { + LOG_MSG_DEBUG("Error: Wrong packet %d length: 0x%02x 0x%02x" + "(should be %d)\n", nPacketNum, pDatagramLen[0], + pDatagramLen[1], pPacketsSizes[nPacketNum]); + return false; + } + if (0 != memcmp(pExpectedPackets[nPacketNum], + &pAggregatedPacket[packetIndex], pPacketsSizes[nPacketNum])) + { + LOG_MSG_DEBUG("Error: Comparison of packet %d failed!\n", + nPacketNum); + return false; + } + nPacketNum++; + } + } + + return true; +} + + +class MBIMAggregationTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationTest(bool generic_agg) : + MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationTest"; + else + m_name = "MBIMAggregationTest"; + m_description = "MBIM Aggregation test - sends 5 packets and receives 1 " + "aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationTest(&m_UsbToIpaPipe, + &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMDeaggregationTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMDeaggregationTest(bool generic_agg) : + MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMDeaggregationTest"; + else + m_name = "MBIMDeaggregationTest"; + m_description = "MBIM Deaggregation test - sends an aggregated packet made from" + "5 packets and receives 5 packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesDeaggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMDeaggregationTest(&m_UsbToIpaPipeDeagg, &m_IpaToUsbPipe, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +class MBIMDeaggregationOnePacketTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMDeaggregationOnePacketTest(bool generic_agg) : + MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMDeaggregationOnePacketTest"; + else + m_name = "MBIMDeaggregationOnePacketTest"; + m_description = "MBIM Deaggregation one packet test - sends an aggregated packet made" + "of 1 packet and receives 1 packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesDeaggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMDeaggregationOnePacketTest(&m_UsbToIpaPipeDeagg, &m_IpaToUsbPipe, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + +class MBIMDeaggregationAndAggregationTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMDeaggregationAndAggregationTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMDeaggregationAndAggregationTest"; + else + m_name = "MBIMDeaggregationAndAggregationTest"; + m_description = "MBIM Deaggregation and Aggregation test - sends an aggregated " + "packet made from 5 packets and receives the same aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMDeaggregationAndAggregationTest( + &m_UsbToIpaPipeDeagg, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// + +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + +class MBIMMultipleDeaggregationAndAggregationTest: + public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMMultipleDeaggregationAndAggregationTest(bool generic_agg) : + MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMMultipleDeaggregationAndAggregationTest"; + else + m_name = "MBIMMultipleDeaggregationAndAggregationTest"; + m_description = "MBIM Multiple Deaggregation and Aggregation test - sends 5 aggregated " + "packets each one made of 1 packet and receives an aggregated packet made of the" + "5 packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMMultipleDeaggregationAndAggregationTest( + &m_UsbToIpaPipeDeagg, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// + +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationLoopTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationLoopTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMggregationLoopTest"; + else + m_name = "MBIMggregationLoopTest"; + m_description = "MBIM Aggregation Loop test - sends 5 packets and expects to" + "receives 1 aggregated packet a few times"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationLoopTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationTimeLimitTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationTimeLimitTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationTimeLimitTest"; + else + m_name = "MBIMAggregationTimeLimitTest"; + m_description = "MBIM Aggregation time limit test - sends 1 small packet " + "smaller than the byte limit and receives 1 aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregationTime(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationTimeLimitTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAggTime, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationByteLimitTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationByteLimitTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationByteLimitTest"; + else + m_name = "MBIMAggregationByteLimitTest"; + m_description = "MBIM Aggregation byte limit test - sends 2 packets that together " + "are larger than the byte limit "; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationByteLimitTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationByteLimitTestFC: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationByteLimitTestFC(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) { + if (generic_agg) + m_name = "GenMBIMAggregationByteLimitTestFC"; + else + m_name = "MBIMAggregationByteLimitTestFC"; + m_description = "MBIMAggregationByteLimitTestFC - Send 4 IP packet with FC" + "and expect 4 aggregated MBIM packets."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() { + return AddRules1HeaderAggregation(true); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationByteLimitTestFC( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } +}; + +class MBIMAggregationDualDpTestFC : public MBIMAggregationTestFixtureConf11 +{ +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationDualDpTestFC(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) m_name = "GenMBIMAggregationDualDpTestFC"; + else m_name = "MBIMAggregationDualDpTestFC"; + m_description = "MBIMAggregationDualDpTestFC - Send IP packets " + "on two datapathes: one with FC and one without. " + "Expect 2 aggregated MBIM packets on pipe with FC. " + "Expect one aggregated MBIM packet on pipe without FC. "; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesAggDualFC(&m_UsbToIpaPipe, + &m_IpaToUsbPipeAggTime, + &m_IpaToUsbPipeAgg); + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationDualDpTestFC( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAggTime, &m_IpaToUsbPipeAgg, m_eIP); + } +}; + +class MBIMAggregationDualDpTestFcRoutingBased : public MBIMAggregationTestFixtureConf11 +{ +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationDualDpTestFcRoutingBased(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) m_name = "GenMBIMAggregationDualDpTestFcRoutingBased"; + else m_name = "MBIMAggregationDualDpTestFcRoutingBased"; + m_description = "MBIMAggregationDualDpTestFcRoutingBased - Send IP packets " + "on two datapathes: one with RT based FC and one without. " + "Expect 2 aggregated MBIM packets on pipe with RT based FC. " + "Expect one aggregated MBIM packet on pipe without RT based FC. "; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesAggDualFcRoutingBased(&m_UsbToIpaPipe, + &m_IpaToUsbPipeAggTime, + &m_IpaToUsbPipeAgg); + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationDualDpTestFC( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAggTime, &m_IpaToUsbPipeAgg, m_eIP); + } +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMDeaggregationMultipleNDPTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMDeaggregationMultipleNDPTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMDeaggregationMultipleNDPTest"; + else + m_name = "MBIMDeaggregationMultipleNDPTest"; + m_description = "MBIM Deaggregation multiple NDP test - sends an aggregated" + "packet made from 5 packets and 2 NDPs and receives 5 packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesDeaggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMDeaggregationMultipleNDPTest( + &m_UsbToIpaPipeDeagg, &m_IpaToUsbPipe, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregation2PipesTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregation2PipesTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregation2PipesTest"; + else + m_name = "MBIMAggregation2PipesTest"; + m_description = "MBIM Aggregation 2 pipes test - sends 3 packets from one pipe" + "and an aggregated packet made of 2 packets from another pipe and " + "receives 1 aggregated packet made of all 5 packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregation2PipesTest( + &m_UsbToIpaPipeDeagg, &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationTimeLimitLoopTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationTimeLimitLoopTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationTimeLimitLoopTest"; + else + m_name = "MBIMAggregationTimeLimitLoopTest"; + m_description = "MBIM Aggregation time limit loop test - sends 5 small packet " + "smaller than the byte limit and receives 5 aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregationTime(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationTimeLimitLoopTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAggTime, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationMultiplePacketsTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationMultiplePacketsTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationMultiplePacketsTest"; + else + m_name = "MBIMAggregationMultiplePacketsTest"; + m_description = "MBIM Aggregation multiple packets test - sends 9 packets " + "with same stream ID and receives 1 aggregated packet with 2 NDPs"; + this->m_runInRegression = false; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationMultiplePacketsTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregation0LimitsTest: public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregation0LimitsTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregation0LimitsTest"; + else + m_name = "MBIMAggregation0LimitsTest"; + m_description = "MBIM Aggregation 0 limits test - sends 5 packets and expects" + "to get each packet back aggregated (both size and time limits are 0)"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRules1HeaderAggregation0Limits(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregation0LimitsTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg0Limits, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationDifferentStreamIdsTest: + public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationDifferentStreamIdsTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationDifferentStreamIdsTest"; + else + m_name = "MBIMAggregationDifferentStreamIdsTest"; + m_description = "MBIM Aggregation different stream IDs test - sends 5 packets" + "with different stream IDs and receives 1 aggregated packet made of 5" + "NDPs"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + m_eIP = IPA_IP_v4; + const char aBypass[NUM_PACKETS][20] = {{"Bypass1"}, {"Bypass2"}, {"Bypass3"}, + {"Bypass4"}, {"Bypass5"}}; + uint32_t nTableHdl[NUM_PACKETS]; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader[NUM_PACKETS]; + uint8_t aHeadertoAdd[NUM_PACKETS][4]; + int hdrSize; + + for (int i = 0; i < NUM_PACKETS; i++) { + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[i][0] = 0x49; + aHeadertoAdd[i][1] = 0x50; + aHeadertoAdd[i][2] = 0x53; + aHeadertoAdd[i][3] = (uint8_t)i; + } else { + hdrSize = 1; + aHeadertoAdd[i][0] = (uint8_t)i; + } + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + for (int i = 0; i < NUM_PACKETS; i++) + memset(&sGetHeader[i], 0, sizeof(sGetHeader[i])); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + NUM_PACKETS * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) + { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = NUM_PACKETS; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&aHeadertoAdd[0], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + // Adding Header No2. + strlcpy(pHeaderDescriptor->hdr[1].name, "StreamId1", sizeof(pHeaderDescriptor->hdr[1].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[1].hdr, (void*)&aHeadertoAdd[1], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[1].hdr_len = hdrSize; + pHeaderDescriptor->hdr[1].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[1].is_partial = false; + pHeaderDescriptor->hdr[1].status = -1; // Return Parameter + + // Adding Header No3. + strlcpy(pHeaderDescriptor->hdr[2].name, "StreamId2", sizeof(pHeaderDescriptor->hdr[2].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[2].hdr, (void*)&aHeadertoAdd[2], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[2].hdr_len = hdrSize; + pHeaderDescriptor->hdr[2].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[2].is_partial = false; + pHeaderDescriptor->hdr[2].status = -1; // Return Parameter + + // Adding Header No4. + strlcpy(pHeaderDescriptor->hdr[3].name, "StreamId3", sizeof(pHeaderDescriptor->hdr[3].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[3].hdr, (void*)&aHeadertoAdd[3], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[3].hdr_len = hdrSize; + pHeaderDescriptor->hdr[3].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[3].is_partial = false; + pHeaderDescriptor->hdr[3].status = -1; // Return Parameter + + // Adding Header No5. + strlcpy(pHeaderDescriptor->hdr[4].name, "StreamId4", sizeof(pHeaderDescriptor->hdr[4].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[4].hdr, (void*)&aHeadertoAdd[4], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[4].hdr_len = hdrSize; + pHeaderDescriptor->hdr[4].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[4].is_partial = false; + pHeaderDescriptor->hdr[4].status = -1; // Return Parameter + + for (int i = 0; i < NUM_PACKETS; i++) + strlcpy(sGetHeader[i].name, pHeaderDescriptor->hdr[i].name, sizeof(sGetHeader[i].name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + for (int i = 0; i < NUM_PACKETS; i++) + { + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader[i])) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header %d Handle = 0x%x", i, sGetHeader[i].hdl); + } + + for (int i = 0; i < NUM_PACKETS; i++) + { + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass[i], + IPA_CLIENT_TEST2_CONS, sGetHeader[i].hdl,&nTableHdl[i])) + { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + } + + LOG_MSG_INFO("Creation of 5 bypass routing tables completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, NUM_PACKETS); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[0]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return Value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[1]; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule(1) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(1)->status); + } + + // Configuring Filtering Rule No.3 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[2]; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80102; // Filter DST_IP == 192.168.1.2. + + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule(2) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(2)->status); + } + + // Configuring Filtering Rule No.4 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[3]; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80103; // Filter DST_IP == 192.168.1.3. + + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule(3) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(2)->status); + } + + // Configuring Filtering Rule No.5 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[4]; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80104; // Filter DST_IP == 192.168.1.4. + + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule(4) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(2)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(2)->status); + } + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationDifferentStreamIdsTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class MBIMAggregationNoInterleavingStreamIdsTest: + public MBIMAggregationTestFixtureConf11 { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + MBIMAggregationNoInterleavingStreamIdsTest(bool generic_agg) + : MBIMAggregationTestFixtureConf11(generic_agg) + { + if (generic_agg) + m_name = "GenMBIMAggregationNoInterleavingStreamIdsTest"; + else + m_name = "MBIMAggregationNoInterleavingStreamIdsTest"; + m_description = "MBIM Aggregation no interleaving stream IDs test - sends 5 packets" + "with interleaving stream IDs (0, 1, 0, 1, 0) and receives 1 aggregated " + "packet made of 5 NDPs"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + m_eIP = IPA_IP_v4; + const char aBypass[2][20] = {{"Bypass1"}, {"Bypass2"}}; + uint32_t nTableHdl[2]; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader[2]; + uint8_t aHeadertoAdd[2][4]; + int hdrSize; + + for (int i = 0; i < 2; i++) { + if (mGenericAgg) { + hdrSize = 4; + aHeadertoAdd[i][0] = 0x49; + aHeadertoAdd[i][1] = 0x50; + aHeadertoAdd[i][2] = 0x53; + aHeadertoAdd[i][3] = (uint8_t)i; + } + else { + hdrSize = 1; + aHeadertoAdd[i][0] = (uint8_t)i; + } + } + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + for (int i = 0; i < 2; i++) + memset(&sGetHeader[i], 0, sizeof(sGetHeader[i])); + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 2 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) + { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 2; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "StreamId0", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&aHeadertoAdd[0], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = hdrSize; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + // Adding Header No2. + strlcpy(pHeaderDescriptor->hdr[1].name, "StreamId1", sizeof(pHeaderDescriptor->hdr[1].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[1].hdr, (void*)&aHeadertoAdd[1], + hdrSize); //Header's Data + pHeaderDescriptor->hdr[1].hdr_len = hdrSize; + pHeaderDescriptor->hdr[1].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[1].is_partial = false; + pHeaderDescriptor->hdr[1].status = -1; // Return Parameter + + for (int i = 0; i < 2; i++) + strlcpy(sGetHeader[i].name, pHeaderDescriptor->hdr[i].name, sizeof(sGetHeader[i].name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + for (int i = 0; i < 2; i++) + { + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader[i])) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header %d Handle = 0x%x", i, sGetHeader[i].hdl); + } + + for (int i = 0; i < 2; i++) + { + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass[i], + IPA_CLIENT_TEST2_CONS, sGetHeader[i].hdl,&nTableHdl[i])) + { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + } + + LOG_MSG_INFO("Creation of 2 bypass routing tables completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, 2); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[0]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return Value + sFilterRuleEntry.rule.rt_tbl_hdl=nTableHdl[1]; //put here the handle corresponding to Routing Rule 2 + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0xC0A80101; // Filter DST_IP == 192.168.1.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule(1) to Filtering block Failed."); + bRetVal = false; + goto bail; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", + cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, + cFilterTable0.ReadRuleFromTable(1)->status); + } + + bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + return MBIMAggregationScenarios::MBIMAggregationNoInterleavingStreamIdsTest( + &m_UsbToIpaPipe, &m_IpaToUsbPipeAgg, m_eIP); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +/* Legacy MBIM tests */ + +static MBIMAggregationTest mbimAggregationTest(false); +static MBIMDeaggregationTest mbimDeaggregationTest(false); +static MBIMDeaggregationOnePacketTest mbimDeaggregationOnePacketTest(false); +static MBIMDeaggregationAndAggregationTest mbimDeaggregationAndAggregationTest(false); +static MBIMMultipleDeaggregationAndAggregationTest + mbimMultipleDeaggregationAndAggregationTest(false); +static MBIMAggregationLoopTest mbimAggregationLoopTest(false); +static MBIMDeaggregationMultipleNDPTest mbimDeaggregationMultipleNDPTest(false); +static MBIMAggregationMultiplePacketsTest mbimAggregationMultiplePacketsTest(false); +static MBIMAggregation2PipesTest mbimAggregation2PipesTest(false); +static MBIMAggregationNoInterleavingStreamIdsTest + mbimAggregationNoInterleavingStreamIdsTest(false); +static MBIMAggregationDifferentStreamIdsTest mbimAggregationDifferentStreamIdsTest(false); +static MBIMAggregationTimeLimitTest mbimAggregationTimeLimitTest(false); +static MBIMAggregationByteLimitTest mbimAggregationByteLimitTest(false); +static MBIMAggregationTimeLimitLoopTest mbimAggregationTimeLimitLoopTest(false); +static MBIMAggregation0LimitsTest mbimAggregation0LimitsTest(false); + +/* Generic Aggregation MBIM tests */ + +static MBIMAggregationTest genMbimAggregationTest(true); +static MBIMDeaggregationTest genMbimDeaggregationTest(true); +static MBIMDeaggregationOnePacketTest genMbimDeaggregationOnePacketTest(true); +static MBIMDeaggregationAndAggregationTest genMbimDeaggregationAndAggregationTest(true); +static MBIMMultipleDeaggregationAndAggregationTest genMbimMultipleDeaggregationAndAggregationTest(true); +static MBIMAggregationLoopTest genMbimAggregationLoopTest(true); +static MBIMDeaggregationMultipleNDPTest genMbimDeaggregationMultipleNDPTest(true); +static MBIMAggregationMultiplePacketsTest genMbimAggregationMultiplePacketsTest(true); +static MBIMAggregation2PipesTest genMbimAggregation2PipesTest(true); +static MBIMAggregationNoInterleavingStreamIdsTest genMbimAggregationNoInterleavingStreamIdsTest(true); +static MBIMAggregationDifferentStreamIdsTest genMbimAggregationDifferentStreamIdsTest(true); +static MBIMAggregationTimeLimitTest genMbimAggregationTimeLimitTest(true); +static MBIMAggregationByteLimitTest genMbimAggregationByteLimitTest(true); +static MBIMAggregationByteLimitTestFC genMbimAggregationByteLimitTestFC(true); +static MBIMAggregationDualDpTestFC genMBIMAggregationDualDpTestFC(true); +static MBIMAggregationDualDpTestFcRoutingBased genMBIMAggregationDualDpTestFcRoutingBased(true); +static MBIMAggregationTimeLimitLoopTest genMbimAggregationTimeLimitLoopTest(true); +static MBIMAggregation0LimitsTest genMbimAggregation0LimitsTest(true); + +///////////////////////////////////////////////////////////////////////////////// +// EOF //// +///////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/Makefile.am b/kernel-tests/Makefile.am new file mode 100644 index 0000000000..8a3a8e79fb --- /dev/null +++ b/kernel-tests/Makefile.am @@ -0,0 +1,51 @@ +ACLOCAL_AMFLAGS = -Im4 +EXTRA_CFLAGS = -DDEBUG +AM_CXXFLAGS = -Wall -Wundef -Wno-trigraphs -Werror + +if USE_GLIB + ipa_kernel_tests_CPPFLAGS = $(AM_CFLAGS) -DUSE_GLIB -Dstrlcpy=g_strlcpy @GLIB_CFLAGS@ + ipa_kernel_tests_LDFLAGS = -lpthread @GLIB_LIBS@ +endif + +requiredlibs = -lipanat +ipa_kernel_tests_LDADD = $(requiredlibs) + +ipa_kernel_testsdir = $(prefix) +ipa_kernel_tests_PROGRAMS = ipa_kernel_tests +dist_ipa_kernel_tests_SCRIPTS = run.sh +ipa_kernel_tests_SOURCES =\ + TestManager.cpp \ + TestBase.cpp \ + InterfaceAbstraction.cpp \ + Pipe.cpp \ + PipeTestFixture.cpp \ + PipeTests.cpp \ + TLPAggregationTestFixture.cpp \ + TLPAggregationTests.cpp \ + MBIMAggregationTestFixtureConf11.cpp \ + MBIMAggregationTests.cpp \ + Logger.cpp \ + RoutingDriverWrapper.cpp \ + RoutingTests.cpp \ + IPAFilteringTable.cpp \ + Filtering.cpp \ + FilteringTest.cpp \ + HeaderInsertion.cpp \ + HeaderInsertionTests.cpp \ + TestsUtils.cpp \ + HeaderRemovalTestFixture.cpp \ + HeaderRemovalTests.cpp \ + IPv4Packet.cpp \ + RNDISAggregationTestFixture.cpp \ + RNDISAggregationTests.cpp \ + DataPathTestFixture.cpp \ + DataPathTests.cpp \ + IPAInterruptsTestFixture.cpp \ + IPAInterruptsTests.cpp \ + HeaderProcessingContextTestFixture.cpp \ + HeaderProcessingContextTests.cpp \ + FilteringEthernetBridgingTestFixture.cpp \ + FilteringEthernetBridgingTests.cpp \ + NatTest.cpp \ + IPv6CTTest.cpp \ + main.cpp diff --git a/kernel-tests/NOTICE b/kernel-tests/NOTICE new file mode 100644 index 0000000000..6b493a6ba7 --- /dev/null +++ b/kernel-tests/NOTICE @@ -0,0 +1,26 @@ +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. \ No newline at end of file diff --git a/kernel-tests/NatTest.cpp b/kernel-tests/NatTest.cpp new file mode 100644 index 0000000000..71d491a69a --- /dev/null +++ b/kernel-tests/NatTest.cpp @@ -0,0 +1,4288 @@ +/* + * Copyright (c) 2017-2020 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 "Filtering.h" +#include "RoutingDriverWrapper.h" +#include "IPAFilteringTable.h" +extern "C" { +#include "ipa_nat_drv.h" +} + +//IP offsets +#define IPV4_PROTOCOL_OFFSET (9) +#define IPV4_IP_CHECKSUM_OFFSET (10) +#define IPV4_SRC_ADDR_OFFSET (12) +#define IPV4_DST_ADDR_OFFSET (16) + +//TCP offsets +#define IPV4_SRC_PORT_OFFSET (20) +#define IPV4_DST_PORT_OFFSET (20+2) +#define IPV4_TCP_FLAGS_OFFSET (33) +#define IPV4_TCP_CHECKSUM_OFFSET (36) + +#define IPA_16BIT_ROUND_UP(val) \ + do { \ + if (val >> 16) { \ + val = (val & 0x0000FFFF);\ + val += 1;\ + } \ + } while(0) + +extern Logger g_Logger; + +class IpaNatBlockTestFixture : public TestBase +{ +public: + + IpaNatBlockTestFixture() : + m_sendSize(BUFF_MAX_SIZE), + m_sendSize2(BUFF_MAX_SIZE), + m_sendSize3(BUFF_MAX_SIZE), + m_IpaIPType(IPA_IP_v4), + m_extHdrType(NONE) + { + memset(m_sendBuffer, 0, sizeof(m_sendBuffer)); // First input file / IP packet + memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2)); // Second input file / IP packet + memset(m_sendBuffer3, 0, sizeof(m_sendBuffer3)); // Third input file (default) / IP packet + m_testSuiteName.push_back("Nat"); + } + + static int SetupKernelModule(bool en_status = 0) + { + int retval; + struct ipa_channel_config from_ipa_channels[3]; + struct test_ipa_ep_cfg from_ipa_cfg[3]; + struct ipa_channel_config to_ipa_channels[2]; + struct test_ipa_ep_cfg to_ipa_cfg[2]; + + struct ipa_test_config_header header = { 0 }; + struct ipa_channel_config *to_ipa_array[2]; + struct ipa_channel_config *from_ipa_array[3]; + + /* From ipa configurations - 3 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0])); + prepare_channel_struct(&from_ipa_channels[0], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[0], + sizeof(from_ipa_cfg[0]), + en_status); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST3_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1]), + en_status); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2]), + en_status); + from_ipa_array[2] = &from_ipa_channels[2]; + + /* To ipa configurations - 2 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + 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]; + + /* header removal for Ethernet header + 8021Q header */ + memset(&to_ipa_cfg[1], 0, sizeof(to_ipa_cfg[1])); + to_ipa_cfg[1].hdr.hdr_len = ETH8021Q_HEADER_LEN; + to_ipa_cfg[1].hdr.hdr_ofst_metadata_valid = 1; + to_ipa_cfg[1].hdr.hdr_ofst_metadata = + ETH8021Q_METADATA_OFFSET; + prepare_channel_struct(&to_ipa_channels[1], + header.to_ipa_channels_num++, + IPA_CLIENT_TEST2_PROD, + (void *)&to_ipa_cfg[1], + sizeof(to_ipa_cfg[1])); + to_ipa_array[1] = &to_ipa_channels[1]; + + prepare_header_struct(&header, from_ipa_array, to_ipa_array); + + retval = GenericConfigureScenario(&header); + + return retval; + } + + bool Setup() + { + bool bRetVal = true; + + if (SetupKernelModule() != true) + return bRetVal; + + m_producer.Open(INTERFACE0_TO_IPA_DATA_PATH, INTERFACE0_FROM_IPA_DATA_PATH); + m_producer2.Open(INTERFACE4_TO_IPA_DATA_PATH, INTERFACE4_FROM_IPA_DATA_PATH); + + m_consumer.Open(INTERFACE1_TO_IPA_DATA_PATH, INTERFACE1_FROM_IPA_DATA_PATH); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); // This will issue a Reset command to the Filtering as well + m_routing.Reset(IPA_IP_v6); // This will issue a Reset command to the Filtering as well + return true; + } // Setup() + + bool Setup(bool en_status = false) + { + bool bRetVal = true; + + if (SetupKernelModule(en_status) != true) + return bRetVal; + + 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); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); // This will issue a Reset command to the Filtering as well + m_routing.Reset(IPA_IP_v6); // This will issue a Reset command to the Filtering as well + return true; + } // Setup() + + bool Teardown() + { + ipa_nat_dump_ipv4_table(m_tbl_hdl); + ipa_nat_del_ipv4_tbl(m_tbl_hdl); + + m_producer.Close(); + m_producer2.Close(); + m_consumer.Close(); + m_consumer2.Close(); + m_defaultConsumer.Close(); + return true; + } // Teardown() + + virtual bool LoadFiles(enum ipa_ip_type ip) + { + string fileName; + + if (IPA_IP_v4 == ip) { + fileName = "Input/IPv4_1"; + } + else { + fileName = "Input/IPv6"; + } + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + LOG_MSG_DEBUG("Loaded %zu Bytes to Buffer 1\n", m_sendSize); + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + LOG_MSG_DEBUG("Loaded %zu Bytes to Buffer 2\n", m_sendSize2); + + if (!LoadDefaultPacket(ip, m_extHdrType, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed default Packet\n"); + return false; + } + LOG_MSG_DEBUG("Loaded %zu Bytes to Buffer 3\n", m_sendSize3); + + return true; + } + + inline bool VerifyStatusReceived(size_t SendSize, size_t RecvSize) + { + size_t stts_size = sizeof(struct ipa3_hw_pkt_status); + + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) { + stts_size = sizeof(struct ipa3_hw_pkt_status_hw_v5_0); + } + + if ((RecvSize <= SendSize) || + ((RecvSize - SendSize) != stts_size)) { + LOG_MSG_ERROR("received buffer size does not match! sent:receive [%zu]:[%zu]\n", SendSize, RecvSize); + return false; + } + + return true; + } + + inline bool IsCacheHit(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status *pStatus = (struct ipa3_hw_pkt_status *)Buff; + + if (VerifyStatusReceived(SendSize, RecvSize) == false) { + return false; + } + + if ((bool)pStatus->route_hash) { + LOG_MSG_DEBUG("cache hit!! \n"); + return true; + } + + LOG_MSG_ERROR("cache miss!! \n"); + return false; + + } + + inline bool IsCacheHit_v5_0(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status_hw_v5_0 *pStatus = (struct ipa3_hw_pkt_status_hw_v5_0 *)Buff; + + if (VerifyStatusReceived(SendSize, RecvSize) == false) { + return false; + } + + if ((bool)pStatus->route_hash) { + LOG_MSG_DEBUG("cache hit!! \n"); + return true; + } + + LOG_MSG_ERROR("cache miss!! \n"); + return false; + + } + + inline bool IsCacheMiss(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status *pStatus = (struct ipa3_hw_pkt_status *)Buff; + + if (VerifyStatusReceived(SendSize, RecvSize) == false) { + return false; + } + + if (!((bool)pStatus->route_hash)) { + LOG_MSG_DEBUG("cache miss!! \n"); + return true; + } + + LOG_MSG_ERROR("cache hit!! \n"); + return false; + } + + inline bool IsCacheMiss_v5_0(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status_hw_v5_0 *pStatus = (struct ipa3_hw_pkt_status_hw_v5_0 *)Buff; + + if (VerifyStatusReceived(SendSize, RecvSize) == false) { + return false; + } + + if (!((bool)pStatus->route_hash)) { + LOG_MSG_DEBUG("cache miss!! \n"); + return true; + } + + LOG_MSG_ERROR("cache hit!! \n"); + return false; + } + + bool CompareResultVsGoldenNat(Byte *goldenBuffer, unsigned int goldenSize, + Byte *receivedBuffer, unsigned int receivedSize, int private_ip, int public_ip, + int private_port, int public_port, bool src_nat, int IPv4_offset = 0, bool with_status = false) + { + bool result; + uint32_t address; + uint16_t port; + uint32_t val; + uint16_t ip_checksum_diff, tcp_checksum_diff; + uint32_t ip_checksum, tcp_checksum; + int recv_offset = 0; + size_t stts_size = sizeof(struct ipa3_hw_pkt_status); + + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) { + stts_size = sizeof(struct ipa3_hw_pkt_status_hw_v5_0); + } + + if (with_status) + recv_offset += stts_size; + + ip_checksum_diff = calc_ip_cksum_diff(public_ip, private_ip); + tcp_checksum_diff = calc_tcp_udp_cksum_diff(public_ip, public_port, private_ip, private_port); + + //calculate new ip checksum, old checksum + 1's compliment of checksum diff + ip_checksum = *((uint16_t *)&goldenBuffer[IPV4_IP_CHECKSUM_OFFSET + IPv4_offset]); + ip_checksum = ntohs(ip_checksum); + + if(src_nat) + ip_checksum += (uint16_t)(~ip_checksum_diff); + else + ip_checksum += (uint16_t)ip_checksum_diff; + + IPA_16BIT_ROUND_UP(ip_checksum); + + //return to network format + ip_checksum = htons(ip_checksum); + + //calculate new tcp checksum, old checksum + 1's compliment of checksum diff + tcp_checksum = *((uint16_t *)&goldenBuffer[IPV4_TCP_CHECKSUM_OFFSET + IPv4_offset]); + tcp_checksum = ntohs(tcp_checksum); + + if(src_nat) + tcp_checksum += (uint16_t)(~tcp_checksum_diff); + else + tcp_checksum += (uint16_t)tcp_checksum_diff; + + IPA_16BIT_ROUND_UP(tcp_checksum); + + //return to network format + tcp_checksum = htons(tcp_checksum); + + if ((receivedSize - recv_offset) != goldenSize) { + g_Logger.AddMessage(LOG_VERBOSE, "%s Buffers sizes are different.\n", __FUNCTION__); + return false; + } + + Byte *tmp_buff = new Byte[goldenSize]; + + memcpy(tmp_buff, goldenBuffer, goldenSize); + + if (src_nat) { + address = htonl(public_ip); + port = htons(public_port); + + memcpy(&tmp_buff[IPV4_SRC_ADDR_OFFSET + IPv4_offset], &address, sizeof(address)); + memcpy(&tmp_buff[IPV4_SRC_PORT_OFFSET + IPv4_offset], &port, sizeof(port)); + + val = (*(uint32_t*)(&receivedBuffer[IPV4_SRC_ADDR_OFFSET + IPv4_offset + recv_offset])); + if (address != val) + LOG_MSG_ERROR("received src ip 0x%X != 0x%X\n", val, address); + + val = (*(uint16_t*)(&receivedBuffer[IPV4_SRC_PORT_OFFSET + IPv4_offset + recv_offset])); + if (port != val) + LOG_MSG_ERROR("received src port %d != %d\n", val, port); + } + else { + address = htonl(private_ip); + port = htons(private_port); + + memcpy(&tmp_buff[IPV4_DST_ADDR_OFFSET + IPv4_offset], &address, sizeof(address)); + memcpy(&tmp_buff[IPV4_DST_PORT_OFFSET + IPv4_offset], &port, sizeof(port)); + + val = (*(uint32_t*)(&receivedBuffer[IPV4_DST_ADDR_OFFSET + IPv4_offset + +recv_offset])); + if (address != val) + LOG_MSG_ERROR("received dst ip 0x%X != 0x%X\n", val, address); + val = (*(uint16_t*)(&receivedBuffer[IPV4_DST_PORT_OFFSET + IPv4_offset + recv_offset])); + if (port != val) + LOG_MSG_ERROR("received dst port %d != %d\n", val, port); + } + + memcpy(&tmp_buff[IPV4_IP_CHECKSUM_OFFSET + IPv4_offset], &ip_checksum, sizeof(uint16_t)); + val = (*(uint16_t*)(&receivedBuffer[IPV4_IP_CHECKSUM_OFFSET + IPv4_offset + recv_offset])); + if (ip_checksum != val) + LOG_MSG_ERROR("received checksum %d != %d\n", val, ip_checksum); + + memcpy(&tmp_buff[IPV4_TCP_CHECKSUM_OFFSET + IPv4_offset], &tcp_checksum, sizeof(uint16_t)); + val = (*(uint16_t*)(&receivedBuffer[IPV4_TCP_CHECKSUM_OFFSET + IPv4_offset + recv_offset])); + if (tcp_checksum != val) + LOG_MSG_ERROR("received checksum %d != %d\n", val, tcp_checksum); + + size_t j; + char tmpBuffer[512] = { 0 }; + + for (j = 0; j < receivedSize; j++) + snprintf(&tmpBuffer[3 * j], sizeof(tmpBuffer) - (3 * j + 1), " %02X", tmp_buff[j]); + LOG_MSG_STACK("expected packet should be (%zu)\n%s\n", receivedSize, tmpBuffer); + + result = !memcmp((void*)tmp_buff, (void*)(receivedBuffer + recv_offset), goldenSize); + if (!result) + LOG_MSG_ERROR("buffers comparison failed!!\n"); + + delete[] tmp_buff; + + return result; + } + + bool CreateMetdataRoutingRule(const char * bypass0) + { + LOG_MSG_DEBUG("Entering\n"); + struct ipa_ioc_add_rt_rule *rt_rule0 = NULL; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule0) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule0\n"); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v4; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_META_DATA; + rt_rule_entry->rule.attrib.meta_data = m_metadata; + rt_rule_entry->rule.attrib.meta_data_mask = 0xFFFFFFFF;// Filter exact metadata value + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule0) failed!\n"); + Free(rt_rule0); + return false; + } + + Free(rt_rule0); + LOG_MSG_DEBUG("Leaving\n"); + return true; + } + + bool CreateHashableRoutingRules(const char * bypass0) + { + LOG_MSG_DEBUG("Entering\n"); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 2 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule0) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule0\n"); + return false; + } + + rt_rule0->num_rules = 2; + rt_rule0->ip = IPA_IP_v4; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = m_private_ip; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;// Exact match + rt_rule_entry->rule.hashable = 1; + + rt_rule_entry = &rt_rule0->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = m_private_ip2; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;// Exact match + rt_rule_entry->rule.hashable = 1; + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule0) failed!\n"); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + Free(rt_rule0); + LOG_MSG_DEBUG("Leaving\n"); + return true; + } + + // This function creates three IPv4 bypass routing entries and commits them. + bool CreateThreeIPv4BypassRoutingTables(const char * bypass0, const char * bypass1, const char * bypass2) + { + LOG_MSG_DEBUG("Entering\n"); + struct ipa_ioc_add_rt_rule *rt_rule0 = 0, *rt_rule1 = 0, *rt_rule2 = 0; + struct ipa_rt_rule_add *rt_rule_entry; + + rt_rule0 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule0) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule0\n"); + return false; + } + rt_rule1 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule1) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule1\n"); + Free(rt_rule0); + return false; + } + rt_rule2 = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1 * sizeof(struct ipa_rt_rule_add) + ); + if (!rt_rule2) { + LOG_MSG_ERROR("calloc failed to allocate rt_rule2\n"); + Free(rt_rule0); + Free(rt_rule1); + return false; + } + + rt_rule0->num_rules = 1; + rt_rule0->ip = IPA_IP_v4; + rt_rule0->commit = true; + strlcpy(rt_rule0->rt_tbl_name, bypass0, sizeof(rt_rule0->rt_tbl_name)); + + rt_rule_entry = &rt_rule0->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule0)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule0) failed!\n"); + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + + rt_rule1->num_rules = 1; + rt_rule1->ip = IPA_IP_v4; + rt_rule1->commit = true; + strlcpy(rt_rule1->rt_tbl_name, bypass1, sizeof(rt_rule1->rt_tbl_name)); + rt_rule_entry = &rt_rule1->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule1)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule1) failed!\n"); + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + + rt_rule2->num_rules = 1; + rt_rule2->ip = IPA_IP_v4; + rt_rule2->commit = true; + strlcpy(rt_rule2->rt_tbl_name, bypass2, sizeof(rt_rule2->rt_tbl_name)); + rt_rule_entry = &rt_rule2->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xaabbccdd; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x00000000;// All Packets will get a "Hit" + if (false == m_routing.AddRoutingRule(rt_rule2)) + { + LOG_MSG_ERROR("Routing rule addition(rt_rule2) failed!\n"); + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + return false; + } + + + Free(rt_rule2); + Free(rt_rule1); + Free(rt_rule0); + LOG_MSG_DEBUG("Leaving\n"); + return true; + } + + void Load8021QPacket() + { + m_sendSize = sizeof(m_sendBuffer); + LoadDefault802_1Q(IPA_IP_v4, m_sendBuffer, m_sendSize); + } + + virtual bool ModifyPackets() = 0; + virtual bool AddRules() = 0; + virtual bool SendPackets() = 0; + virtual bool ReceivePacketsAndCompare() = 0; + + bool Run() + { + bool res = false; + bool isSuccess = false; + + LOG_MSG_DEBUG("Entering\n"); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + LOG_MSG_ERROR("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(m_IpaIPType); + if (false == res) { + LOG_MSG_ERROR("Failed loading files.\n"); + return false; + } + + res = ModifyPackets(); + if (false == res) { + LOG_MSG_ERROR("Failed to modify packets.\n"); + return false; + } + + res = SendPackets(); + if (res == false) { + LOG_MSG_ERROR("failed to send packets\n"); + return false; + } + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + LOG_MSG_DEBUG("Returning %d\n", isSuccess); + + return isSuccess; + } // Run() + + /** + * calc_ip_cksum_diff() - Calculate the source nat + * IP checksum diff + * @pub_ip_addr: [in] public ip address + * @priv_ip_addr: [in] Private ip address + * + * source nat ip checksum different is calculated as + * public_ip_addr - private_ip_addr + * Here we are using 1's complement to represent -negative number. + * So take 1's complement of private ip addr and add it + * to public ip addr. + * + * Returns: >0 ip checksum diff + */ + uint16_t calc_ip_cksum_diff(uint32_t pub_ip_addr, + uint32_t priv_ip_addr) + { + uint16_t ret; + uint32_t cksum = 0; + + /* Add LSB(2 bytes) of public ip address to cksum */ + cksum += (pub_ip_addr & 0xFFFF); + + /* Add MSB(2 bytes) of public ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (pub_ip_addr >> 16); + IPA_16BIT_ROUND_UP(cksum); + + /* Calculate the 1's complement of private ip address */ + priv_ip_addr = (~priv_ip_addr); + + /* Add LSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr & 0xFFFF); + IPA_16BIT_ROUND_UP(cksum); + + /* Add MSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr >> 16); + IPA_16BIT_ROUND_UP(cksum); + + /* Return the LSB(2 bytes) of checksum */ + ret = (uint16_t)cksum; + return ret; + } + + /** + * calc_tcp_udp_cksum() - Calculate the source nat + * TCP/UDP checksum diff + * @pub_ip_addr: [in] public ip address + * @pub_port: [in] public tcp/udp port + * @priv_ip_addr: [in] Private ip address + * @priv_port: [in] Private tcp/udp prot + * + * source nat tcp/udp checksum is calculated as + * (pub_ip_addr + pub_port) - (priv_ip_addr + priv_port) + * Here we are using 1's complement to represent -ve number. + * So take 1's complement of prviate ip addr &private port + * and add it public ip addr & public port. + * + * Returns: >0 tcp/udp checksum diff + */ + uint16_t calc_tcp_udp_cksum_diff(uint32_t pub_ip_addr, + uint16_t pub_port, + uint32_t priv_ip_addr, + uint16_t priv_port) + { + uint16_t ret = 0; + uint32_t cksum = 0; + + /* Add LSB(2 bytes) of public ip address to cksum */ + cksum += (pub_ip_addr & 0xFFFF); + + /* Add MSB(2 bytes) of public ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (pub_ip_addr >> 16); + IPA_16BIT_ROUND_UP(cksum); + + /* Add public port to cksum and + check for carry forward(CF), if any add it */ + cksum += pub_port; + IPA_16BIT_ROUND_UP(cksum); + + /* Calculate the 1's complement of private ip address */ + priv_ip_addr = (~priv_ip_addr); + + /* Add LSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr & 0xFFFF); + IPA_16BIT_ROUND_UP(cksum); + + /* Add MSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add + */ + cksum += (priv_ip_addr >> 16); + IPA_16BIT_ROUND_UP(cksum); + + /* Calculate the 1's complement of private port */ + priv_port = (~priv_port); + + /* Add public port to cksum and + check for carry forward(CF), if any add it */ + cksum += priv_port; + IPA_16BIT_ROUND_UP(cksum); + + /* return the LSB(2 bytes) of checksum */ + ret = (uint16_t)cksum; + return ret; + } + + ~IpaNatBlockTestFixture() + { + m_sendSize = 0; + m_sendSize2 = 0; + m_sendSize3 = 0; + } + + static Filtering m_filtering; + static RoutingDriverWrapper m_routing; + InterfaceAbstraction m_producer; + InterfaceAbstraction m_producer2; + InterfaceAbstraction m_consumer; + InterfaceAbstraction m_consumer2; + InterfaceAbstraction m_defaultConsumer; + + static const size_t BUFF_MAX_SIZE = 1024; + + Byte m_sendBuffer[BUFF_MAX_SIZE]; // First input file / IP packet + Byte m_sendBuffer2[BUFF_MAX_SIZE]; // Second input file / IP packet + Byte m_sendBuffer3[BUFF_MAX_SIZE]; // Third input file (default) / IP packet + size_t m_sendSize; + size_t m_sendSize2; + size_t m_sendSize3; + enum ipa_ip_type m_IpaIPType; + enum ipv6_ext_hdr_type m_extHdrType; + uint32_t m_tbl_hdl; + uint32_t m_nat_rule_hdl1; + uint32_t m_public_ip; + uint32_t m_public_ip2; + uint32_t m_private_ip; + uint32_t m_private_ip2; + uint32_t m_target_ip; + uint16_t m_public_port; + uint16_t m_public_port2; + uint16_t m_private_port; + uint16_t m_private_port2; + uint16_t m_target_port; + uint32_t m_metadata; +private: +}; + +RoutingDriverWrapper IpaNatBlockTestFixture::m_routing; +Filtering IpaNatBlockTestFixture::m_filtering; + +/*---------------------------------------------------------------------------*/ +/* Test001: Single PDN src NAT test */ +/* NOTE: other classes are derived from this class - change carefully */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest001 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest001() + { + m_name = "IpaNatBlockTest001"; + m_description = + "NAT block test 001 - single PDN src NAT test\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to src NAT \ + All DST_IP == (193.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit one NAT rule:\ + private ip 194.23.22.1 --> public ip 192.23.22.1"; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00FFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_target_ip; // Filter DST_IP == 193.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + + ret = ipa_nat_add_ipv4_tbl(m_public_ip, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_DEBUG("failed creating NAT table\n"); + return false; + } + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + m_public_ip); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("failed adding NAT rule 0\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + address = htonl(m_target_ip);//193.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip);/* 194.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET],&flags , sizeof(flags)); + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully one packet\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test002: Single PDN dst NAT test */ +/* NOTE: other classes are derived from this class - change carefully */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest002 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest002() + { + m_name = "IpaNatBlockTest002"; + m_description = + "NAT block test 002 - single PDN dst NAT test\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block (public IP filtering) \ + 3. generate and commit one NAT rule:\ + public ip 192.23.22.1 --> private ip 194.23.22.1 "; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 3); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00FFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_public_ip; // Filter DST_IP == 192.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + uint32_t pub_ip_add = m_public_ip; + + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + pub_ip_add); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + address = htonl(m_public_ip);//192.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_public_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_target_ip);/* 193.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully one packet\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + false)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test003: Multi PDN src NAT test */ +/* NOTE: other classes are derived from this class - change carefully */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest003 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest003() + { + m_name = "IpaNatBlockTest003"; + m_description = + "NAT block test 003 - Multi PDN src NAT test\ + 1. Generate and commit three routing tables (two are used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit two filtering rule: (DST & Mask Match). \ + - action go to src NAT \ + All SRC_IP == (194.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All SRC_IP == (197.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit two NAT rules:\ + private ip 194.23.22.1 --> public ip 192.23.22.1 \ + private ip 197.23.22.1 --> public ip 195.23.22.1"; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_private_ip2 = 0xC5171601; /* 197.23.22.1 */ + m_private_port2 = 5679; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_public_ip2 = 0xC3171601; /* "195.23.22.1" */ + m_public_port2 = 9051; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0, routing_table1; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n", &routing_table1); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 2); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.src_addr = m_private_ip; // Filter SRC_IP == 194.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl = routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.src_addr = m_private_ip2; // Filter SRC_IP == 197.23.22.1 + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + LOG_MSG_DEBUG("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(1)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + uint32_t pub_ip_add = m_public_ip; + ipa_nat_pdn_entry pdn_info; + + // first create the NAT table + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + pub_ip_add); + + // modify the PDN entries that will be pointed by the NAT rules + pdn_info.public_ip = m_public_ip; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 0, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 0 \n"); + return false; + } + + pdn_info.public_ip = m_public_ip2; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 1, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 1 \n"); + return false; + } + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + ipv4_rule.private_ip = m_private_ip2; + ipv4_rule.private_port = m_private_port2; + ipv4_rule.public_port = m_public_port2; + ipv4_rule.pdn_index = 1; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 1\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 2 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + //first packet private ip 194.23.22.1 --> public ip 192.23.22.1 + address = htonl(m_target_ip);//193.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip);/* 194.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + // second packet private ip 197.23.22.1 --> public ip 195.23.22.1 + address = htonl(m_target_ip);//193.23.22.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip2);/* 197.23.22.1 */ + memcpy(&m_sendBuffer2[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port2); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer2[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + LOG_MSG_DEBUG("sending first packet\n"); + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + // Send second packet + LOG_MSG_DEBUG("sending second packet\n"); + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully two packets\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + + if (rxBuff1 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + if (rxBuff2) + delete[] rxBuff2; + return false; + } + + if (rxBuff2 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + delete[] rxBuff1; + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + char recievedBuffer2[256] = { 0 }; + char SentBuffer2[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer2, m_sendSize2, + rxBuff2, receivedSize2, + m_private_ip2, m_public_ip2, + m_private_port2, m_public_port2, + true); + + for (j = 0; j < m_sendSize2; j++) + snprintf(&SentBuffer2[3 * j], sizeof(SentBuffer2) - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for (j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer2[3 * j], sizeof(recievedBuffer2) - (3 * j + 1), " %02X", rxBuff2[j]); + LOG_MSG_STACK("sent Value2 (%zu)\n%s\n, Received Value2(%zu)\n%s\n", m_sendSize2, SentBuffer2, receivedSize2, recievedBuffer2); + + delete[] rxBuff2; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test004: Multi PDN dst NAT test */ +/* NOTE: other classes are derived from this class - change carefully */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest004 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest004() + { + m_name = "IpaNatBlockTest004"; + m_description = + "NAT block test 004 - Multi PDN dst NAT test\ + 1. Generate and commit three routing tables (two are used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit two filtering rule: (DST & Mask Match). \ + - action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All DST_IP == (195.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit two NAT rules:\ + private ip 194.23.22.1 --> public ip 192.23.22.1 \ + private ip 197.23.22.1 --> public ip 195.23.22.1"; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_private_ip2 = 0xC5171601; /* 197.23.22.1 */ + m_private_port2 = 5679; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_public_ip2 = 0xC3171601; /* "195.23.22.1" */ + m_public_port2 = 9051; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0, routing_table1; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n", &routing_table1); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 2); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_public_ip; // Filter DST_IP == 192.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + + // Configuring Filtering Rule No.1 + flt_rule_entry.rule.rt_tbl_hdl = routing_table1.hdl; //put here the handle corresponding to Routing Rule 2 + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_public_ip2; // Filter DST_IP == 195.23.22.1 + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + LOG_MSG_DEBUG("flt rule hdl1=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(1)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(1)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + uint32_t pub_ip_add = m_public_ip; + ipa_nat_pdn_entry pdn_info; + + // first create the NAT table + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + pub_ip_add); + + // modify the PDN entries that will be pointed by the NAT rules + pdn_info.public_ip = m_public_ip; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 0,&pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 0 \n"); + return false; + } + + pdn_info.public_ip = m_public_ip2; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 1, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 1 \n"); + return false; + } + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + ipv4_rule.private_ip = m_private_ip2; + ipv4_rule.private_port = m_private_port2; + ipv4_rule.public_port = m_public_port2; + ipv4_rule.pdn_index = 1; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 2 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + //first packet private ip public ip 192.23.22.1 --> 194.23.22.1 + address = htonl(m_public_ip);//192.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_public_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_target_ip);/* 194.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + // second packet public ip 195.23.22.1--> private ip 197.23.22.1 + address = htonl(m_public_ip2);//193.23.22.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_public_port2); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_target_ip);/* 197.23.22.1 */ + memcpy(&m_sendBuffer2[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer2[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + // Send second packet + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully two packets\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + + if (rxBuff1 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + if (rxBuff2) + delete[] rxBuff2; + return false; + } + + if (rxBuff2 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + delete[] rxBuff1; + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + false)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + char recievedBuffer2[256] = { 0 }; + char SentBuffer2[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer2, m_sendSize2, + rxBuff2, receivedSize2, + m_private_ip2, m_public_ip2, + m_private_port2, m_public_port2, + false); + + for (j = 0; j < m_sendSize2; j++) + snprintf(&SentBuffer2[3 * j], sizeof(SentBuffer2) - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for (j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer2[3 * j], sizeof(recievedBuffer2) - (3 * j + 1), " %02X", rxBuff2[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize2, SentBuffer2, receivedSize2, recievedBuffer2); + + delete[] rxBuff2; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test005: Single PDN src metadata replacement NAT test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest005 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest005() + { + m_name = "IpaNatBlockTest005"; + m_description = + "NAT block test 005 - single PDN src metadata replacement NAT test\ + source metadata will be replaced and the routing rule equation will be done upon replaced value\ + 1. Generate and commit two routing tables (only one is used). \ + the routing table will catch packets with metadata value 0x34567890 (different from original value)\ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to src NAT \ + All DST_IP == (193.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + action parameters metadata replacement = true\ + 3. generate and commit one NAT rule:\ + private ip 194.23.22.1 --> public ip 192.23.22.1\ + source metadata value shall be replaced to 0x34567890 (caught by the routing rule)"; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + m_metadata = 0x34567890; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateMetdataRoutingRule(bypass0)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateMetdataRoutingRule completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST2_PROD, false, 1); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_target_ip; // Filter DST_IP == 193.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 1; + flt_rule_entry.rule.retain_hdr = 1; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + ipa_nat_pdn_entry pdn_info; + + ret = ipa_nat_add_ipv4_tbl(m_public_ip, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + m_public_ip); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + // modify the PDN entries that will be pointed by the NAT rules + pdn_info.public_ip = m_public_ip; + pdn_info.src_metadata = m_metadata; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 0, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed modifying PDN index 0\n"); + return false; + } + LOG_MSG_DEBUG("PDN 0 was modified to hold ip 0x%X, src_metadata 0x%X\n", m_public_ip, m_metadata); + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + Load8021QPacket(); + + address = htonl(m_target_ip);//193.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET + ETH8021Q_HEADER_LEN], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET + ETH8021Q_HEADER_LEN], &port, sizeof(port)); + + address = htonl(m_private_ip);/* 194.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET + ETH8021Q_HEADER_LEN], &address, sizeof(address)); + port = htons(m_private_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET + ETH8021Q_HEADER_LEN], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET + ETH8021Q_HEADER_LEN], &flags, sizeof(flags)); + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer2.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully one packet\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true, ETH8021Q_HEADER_LEN)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test006: Single PDN dst metadata replacement NAT test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest006 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest006() + { + m_name = "IpaNatBlockTest006"; + m_description = + "NAT block test 006 - single PDN dst metadata replacement NAT test\ + destination metadata will be replaced and the routing rule equation will be done upon replaced value\ + 1. Generate and commit two routing tables (only one is used). \ + the routing table will catch packets with metadata value 0x34567890 (different from original value)\ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + action parameters metadata replacement = true\ + 3. generate and commit one NAT rule:\ + public ip 192.23.22.1 --> private ip 194.23.22.1 \ + destination metadata value shall be replaced to 0x34567890 (caught by the routing rule)"; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + m_metadata = 0x34567890; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateMetdataRoutingRule(bypass0)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateMetdataRoutingRule completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST2_PROD, false, 1); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_public_ip; // Filter DST_IP == 193.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 1; + flt_rule_entry.rule.retain_hdr = 1; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + ipa_nat_pdn_entry pdn_info; + + ret = ipa_nat_add_ipv4_tbl(m_public_ip, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + m_public_ip); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + // modify the PDN entries that will be pointed by the NAT rules + pdn_info.public_ip = m_public_ip; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = m_metadata; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 0, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed modifying PDN index 0\n"); + return false; + } + LOG_MSG_DEBUG("PDN 0 was modified to hold ip 0x%X, dst_metadata 0x%X\n", m_public_ip, m_metadata); + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + LOG_MSG_ERROR("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + Load8021QPacket(); + + address = htonl(m_public_ip);//193.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET + ETH8021Q_HEADER_LEN], &address, sizeof(address)); + port = htons(m_public_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET + ETH8021Q_HEADER_LEN], &port, sizeof(port)); + + address = htonl(m_target_ip);/* 194.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET + ETH8021Q_HEADER_LEN], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET + ETH8021Q_HEADER_LEN], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET + ETH8021Q_HEADER_LEN], &flags, sizeof(flags)); + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer2.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully one packet\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + false, ETH8021Q_HEADER_LEN)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test007: Hashable routing rule with dst NAT test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest007 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest007() + { + m_name = "IpaNatBlockTest007"; + m_description = + "NAT block test 007 - single PDN dst NAT with hashable routing rule test\ + test if routing block hash mechanism tests NATed values or pre NAT values\ + 1. Generate and commit routing table with two hashable rules. \ + first routing rule will send packets with ip == 192.168.9.119 to first pipe \ + second routing rule will send packets with ip == 192.168.9.120 to second pipe\ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.168.9.1 & 255.255.255.0)traffic goes to NAT block \ + 3. generate and commit two NAT rules with target ip 211.1.1.4:\ + 1. public ip 5.5.6.120 --> private ip 192.168.9.119 \ + public port 4501 --> private port 4500 \ + 2. public ip 5.5.6.120 --> private ip 192.168.9.119 \ + public port 4502 --> private port 4500"; + m_private_ip = 0xC0A80977; /* 192.168.9.119 */ + m_private_port = 4500; + m_private_ip2 = 0xC0A80978; /* 192.168.9.120 */ + m_private_port2 = 4500; + m_public_ip = 0x05050678; /* 5.5.6.120 */ + m_public_port = 4501; + m_public_port2 = 4502; + m_target_ip = 0xD3010104; /* 211.1.1.4 */ + m_target_port = 1234; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + bool Setup() + { + return IpaNatBlockTestFixture::Setup(true); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateHashableRoutingRules(bypass0)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateHashableRoutingRules completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing table 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; // Mask - catch all + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_public_ip; // Filter DST_IP == 5.5.6.120 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + + ret = ipa_nat_add_ipv4_tbl(m_public_ip, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + m_public_ip); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule 1 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip2; + ipv4_rule.private_port = m_private_port2; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port2; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule 2 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + address = ntohl(m_public_ip);//5.5.6.120 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(m_public_port); // 4501 + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = ntohl(m_target_ip);/* 211.1.1.4 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(m_target_port); // 4500 + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + // second packet + address = ntohl(m_public_ip);//5.5.6.120 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(m_public_port2); // 4502 + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = ntohl(m_target_ip);/* 211.1.1.4 */ + memcpy(&m_sendBuffer2[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = ntohs(m_target_port); // 4500 + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer2[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully the first packet\n"); + + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully two packet\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + + if (rxBuff1 == NULL || rxBuff2 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + false, 0, true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize, receivedSize, rxBuff1); + + char recievedBuffer[0x400] = { 0 }; + char SentBuffer[0x400] = { 0 }; + char recievedBuffer2[0x400] = { 0 }; + char SentBuffer2[0x400] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer2, m_sendSize2, + rxBuff2, receivedSize2, + m_private_ip2, m_public_ip, + m_private_port2, m_public_port2, + false, 0, true); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheMiss(m_sendSize2, receivedSize2, rxBuff2); + + for (j = 0; j < m_sendSize2; j++) + snprintf(&SentBuffer2[3 * j], sizeof(SentBuffer2) - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for (j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer2[3 * j], sizeof(recievedBuffer2) - (3 * j + 1), " %02X", rxBuff2[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize2, SentBuffer2, receivedSize2, recievedBuffer2); + + delete[] rxBuff2; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test008: Multi PDN src NAT test match PDN by input from filtering block */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest008 : public IpaNatBlockTestFixture +{ +public: + IpaNatBlockTest008() + { + m_name = "IpaNatBlockTest008"; + m_description = + "NAT block test 008 - Multi PDN src NAT test match PDN by input from filtering block\ + 1. Generate and commit three routing tables (two are used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + - action go to src NAT + PDN index 2\ + All SRC_IP == (194.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit two NAT rules:\ + private ip 194.23.22.1 --> public ip 192.23.22.1 PDN index 1\ + private ip 194.23.22.1 --> public ip 195.23.22.1 PDN index 2"; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_public_ip2 = 0xC3171601; /* "195.23.22.1" */ + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0, routing_table1; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n", &routing_table1); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 2); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; //put here the handle corresponding to Routing Rule 1 + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.src_addr = m_private_ip; // Filter SRC_IP == 194.23.22.1 + flt_rule_entry.rule.pdn_idx = 2; + flt_rule_entry.rule.set_metadata = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_ERROR("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + uint32_t pub_ip_add = m_public_ip; + ipa_nat_pdn_entry pdn_info; + + // first create the NAT table + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + pub_ip_add); + + // modify the PDN entries that will be pointed by the NAT rules + pdn_info.public_ip = m_public_ip; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 1, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 0 \n"); + return false; + } + + pdn_info.public_ip = m_public_ip2; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 2, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 1 \n"); + return false; + } + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 1; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + // the second rule shall be identical to the first on all parameters except PDN index so the filtering + // block action parameter will provide the PDN index. + ipv4_rule.pdn_index = 2; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 1\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 2 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + //first packet private ip 194.23.22.1 --> public ip 195.23.22.1 + address = htonl(m_target_ip);//193.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip);/* 194.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (rxBuff1 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results - verify that the ip of PDN 2 was selected (m_public_ip2) + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip2, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test009: Single PDN src NAT delete rule test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest009 : public IpaNatBlockTest001 +{ +public: + IpaNatBlockTest009() + { + m_name = "IpaNatBlockTest009"; + m_description = + "NAT block test 009 - single PDN src NAT rule deletion test\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to src NAT \ + All DST_IP == (193.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit one NAT rule:\ + private ip 194.23.22.1 --> public ip 192.23.22.1\ + 4. delete the NAT rule and expect NAT miss"; + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + int ret = IpaNatBlockTest001::AddRules(); + if (!ret) { + LOG_MSG_ERROR("Leaving, failed Adding test 001 rules 0\n"); + return false; + } + + ret = ipa_nat_del_ipv4_rule(m_tbl_hdl, m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed deleting NAT rule 0\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule deleted\n"); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + if (receivedSize) { + LOG_MSG_ERROR("Data received - test failed!\n"); + isSuccess = false; + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + } else { + LOG_MSG_ERROR("Comparison of Buffer0 succeeded - NAT rule was hit despite deletion!\n"); + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + } + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test010: Single PDN dst NAT rule deletion test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest010 : public IpaNatBlockTest002 +{ +public: + IpaNatBlockTest010() + { + m_name = "IpaNatBlockTest010"; + m_description = + "NAT block test 010 - single PDN dst NAT rule deletion test\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block (public IP filtering) \ + 3. generate and commit one NAT rule:\ + public ip 192.23.22.1 --> private ip 194.23.22.1 \ + delete rule and verrify NAT miss"; + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + int ret = IpaNatBlockTest002::AddRules(); + if (!ret) { + LOG_MSG_ERROR("Leaving, failed Adding test 002 rules 0\n"); + return false; + } + + ret = ipa_nat_del_ipv4_rule(m_tbl_hdl, m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed deleting NAT rule 0\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule deleted\n"); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + if (receivedSize) { + LOG_MSG_ERROR("Data received - test failed!\n"); + isSuccess = false; + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + false)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + } + else { + LOG_MSG_ERROR("Comparison of Buffer0 succeeded - NAT rule was hit despite deletion!\n"); + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + } + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test011: Multi PDN src NAT - MAX number of PDNs test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest011 : public IpaNatBlockTestFixture +{ + uint32_t m_public_ip3; + uint32_t m_public_ip4; + uint32_t m_private_ip3; + uint32_t m_private_ip4; + uint16_t m_public_port3; + uint16_t m_public_port4; + uint16_t m_private_port3; + uint16_t m_private_port4; + Byte m_sendBuffer4[BUFF_MAX_SIZE]; + size_t m_sendSize4; + +public: + IpaNatBlockTest011() + { + m_name = "IpaNatBlockTest011"; + m_description = + "NAT block test 011 - Multi PDN src NAT test\ + 1. Generate and commit three routing tables (one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + - action go to src NAT \ + All SRC_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All SRC_IP == (194.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All SRC_IP == (196.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All SRC_IP == (198.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit four NAT rules:\ + private ip 192.23.22.1 --> public ip 193.23.22.1 \ + private ip 194.23.22.1 --> public ip 195.23.22.1 \ + private ip 196.23.22.1 --> public ip 197.23.22.1 \ + private ip 198.23.22.1 --> public ip 199.23.22.1"; + m_private_ip = 0xC0171601; /* 192.23.22.1 */ + m_private_port = 5678; + m_public_ip = 0xC1171601; /* "193.23.22.1" */ + m_public_port = 9050; + + m_private_ip2 = 0xC2171601; /* 194.23.22.1 */ + m_private_port2 = 5679; + m_public_ip2 = 0xC3171601; /* "195.23.22.1" */ + m_public_port2 = 9051; + + m_private_ip3 = 0xC4171601; /* 196.23.22.1 */ + m_private_port3 = 5680; + m_public_ip3 = 0xC5171601; /* "197.23.22.1" */ + m_public_port3 = 9052; + + m_private_ip4 = 0xC6171601; /* 198.23.22.1 */ + m_private_port4 = 5681; + m_public_ip4 = 0xC7171601; /* "199.23.22.1" */ + m_public_port4 = 9053; + + m_target_ip = 0xBF171601; /* 191.23.22.1 */ + m_target_port = 1234; + + m_sendSize4 = BUFF_MAX_SIZE; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0, routing_table1; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + routing_table1.ip = IPA_IP_v4; + strlcpy(routing_table1.name, bypass1, sizeof(routing_table1.name)); + if (!m_routing.GetRoutingTable(&routing_table1)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table1=0x%p) Failed.\n", &routing_table1); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass1, routing_table1.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v4.src_addr_mask = 0x00FFFFFF; // Mask - catch all private IPs + flt_rule_entry.rule.attrib.u.v4.src_addr = m_private_ip; // Filter SRC_IP == 192.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + ipa_nat_pdn_entry pdn_info; + + // first create the NAT table + ret = ipa_nat_add_ipv4_tbl(m_public_ip, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + m_public_ip); + + // modify the PDN entries that will be pointed by the NAT rules + pdn_info.public_ip = m_public_ip; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 0, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 0 \n"); + return false; + } + + pdn_info.public_ip = m_public_ip2; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 1, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 1 \n"); + return false; + } + + pdn_info.public_ip = m_public_ip3; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 2, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 2 \n"); + return false; + } + + pdn_info.public_ip = m_public_ip4; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 3, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 3 \n"); + return false; + } + + LOG_MSG_DEBUG("Added 4 PDNs successfully: 0x%X, 0x%X, 0x%X, 0x%X\n", + m_public_ip, m_public_ip2, m_public_ip3, m_public_ip4); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d, $d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port, ipv4_rule.pdn_index); + + ipv4_rule.private_ip = m_private_ip2; + ipv4_rule.private_port = m_private_port2; + ipv4_rule.public_port = m_public_port2; + ipv4_rule.pdn_index = 1; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 1\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 2 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d, $d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port, ipv4_rule.pdn_index); + + ipv4_rule.private_ip = m_private_ip3; + ipv4_rule.private_port = m_private_port3; + ipv4_rule.public_port = m_public_port3; + ipv4_rule.pdn_index = 2; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 2\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 3 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d, $d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port, ipv4_rule.pdn_index); + + ipv4_rule.private_ip = m_private_ip4; + ipv4_rule.private_port = m_private_port4; + ipv4_rule.public_port = m_public_port4; + ipv4_rule.pdn_index = 3; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 3\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 4 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d, $d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port, ipv4_rule.pdn_index); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + if (!LoadDefaultPacket(IPA_IP_v4, m_extHdrType, m_sendBuffer4, m_sendSize4)) { + LOG_MSG_ERROR("Failed default Packet buffer 4\n"); + return false; + } + LOG_MSG_DEBUG("Loaded %zu Bytes to Buffer 4\n", m_sendSize4); + + //first packet private ip 192.23.22.1 --> public ip 193.23.22.1 + address = htonl(m_target_ip);//191.23.22.1 + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip);/* 192.23.22.1 */ + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + // second packet private ip 194.23.22.1 --> public ip 195.23.22.1 + address = htonl(m_target_ip);//191.23.22.1 + memcpy(&m_sendBuffer2[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip2);/* 194.23.22.1 */ + memcpy(&m_sendBuffer2[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port2); + memcpy(&m_sendBuffer2[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer2[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + // third packet private ip 196.23.22.1 --> public ip 197.23.22.1 + address = htonl(m_target_ip);//191.23.22.1 + memcpy(&m_sendBuffer3[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer3[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip3);/* 196.23.22.1 */ + memcpy(&m_sendBuffer3[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port3); + memcpy(&m_sendBuffer3[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer3[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + // third packet private ip 198.23.22.1 --> public ip 199.23.22.1 + address = htonl(m_target_ip);//191.23.22.1 + memcpy(&m_sendBuffer4[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port); + memcpy(&m_sendBuffer4[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_private_ip4);/* 198.23.22.1 */ + memcpy(&m_sendBuffer4[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_private_port4); + memcpy(&m_sendBuffer4[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer4[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + LOG_MSG_DEBUG("sending first packet\n"); + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + // Send second packet + LOG_MSG_DEBUG("sending second packet\n"); + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + // Send third packet + LOG_MSG_DEBUG("sending third packet\n"); + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + // Send fourth packet + LOG_MSG_DEBUG("sending fourth packet\n"); + isSuccess = m_producer.SendData(m_sendBuffer4, m_sendSize4); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully four packets\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + size_t receivedSize4 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + Byte *rxBuff4 = new Byte[0x400]; + + if (rxBuff1 == NULL) + { + LOG_MSG_ERROR("Memory allocation error 1.\n"); + if (rxBuff2) + delete[] rxBuff2; + if (rxBuff3) + delete[] rxBuff3; + if (rxBuff4) + delete[] rxBuff4; + return false; + } + + if (rxBuff2 == NULL) + { + LOG_MSG_ERROR("Memory allocation error 2.\n"); + delete[] rxBuff1; + if (rxBuff3) + delete[] rxBuff3; + if (rxBuff4) + delete[] rxBuff4; + return false; + } + + if (rxBuff3 == NULL) + { + LOG_MSG_ERROR("Memory allocation error 3.\n"); + delete[] rxBuff1; + delete[] rxBuff2; + if (rxBuff4) + delete[] rxBuff4; + return false; + } + + if (rxBuff4 == NULL) + { + LOG_MSG_ERROR("Memory allocation error 4.\n"); + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_consumer.ReceiveData(rxBuff3, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize3, m_consumer.m_fromChannelName.c_str()); + + receivedSize4 = m_consumer.ReceiveData(rxBuff4, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize4, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + char recievedBuffer2[256] = { 0 }; + char SentBuffer2[256] = { 0 }; + char recievedBuffer3[256] = { 0 }; + char SentBuffer3[256] = { 0 }; + char recievedBuffer4[256] = { 0 }; + char SentBuffer4[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer2, m_sendSize2, + rxBuff2, receivedSize2, + m_private_ip2, m_public_ip2, + m_private_port2, m_public_port2, + true); + + for (j = 0; j < m_sendSize2; j++) + snprintf(&SentBuffer2[3 * j], sizeof(SentBuffer2) - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for (j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer2[3 * j], sizeof(recievedBuffer2) - (3 * j + 1), " %02X", rxBuff2[j]); + LOG_MSG_STACK("sent Value2 (%zu)\n%s\n, Received Value2(%zu)\n%s\n", m_sendSize2, SentBuffer2, receivedSize2, recievedBuffer2); + + delete[] rxBuff2; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer3, m_sendSize3, + rxBuff3, receivedSize3, + m_private_ip3, m_public_ip3, + m_private_port3, m_public_port3, + true); + + for (j = 0; j < m_sendSize3; j++) + snprintf(&SentBuffer3[3 * j], sizeof(SentBuffer3) - (3 * j + 1), " %02X", m_sendBuffer3[j]); + for (j = 0; j < receivedSize3; j++) + snprintf(&recievedBuffer3[3 * j], sizeof(recievedBuffer3) - (3 * j + 1), " %02X", rxBuff3[j]); + LOG_MSG_STACK("sent Value3 (%zu)\n%s\n, Received Value3(%zu)\n%s\n", m_sendSize3, SentBuffer3, receivedSize3, recievedBuffer3); + + delete[] rxBuff3; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer4, m_sendSize4, + rxBuff4, receivedSize4, + m_private_ip4, m_public_ip4, + m_private_port4, m_public_port4, + true); + + for (j = 0; j < m_sendSize4; j++) + snprintf(&SentBuffer4[3 * j], sizeof(SentBuffer4) - (3 * j + 1), " %02X", m_sendBuffer4[j]); + for (j = 0; j < receivedSize4; j++) + snprintf(&recievedBuffer4[3 * j], sizeof(recievedBuffer4) - (3 * j + 1), " %02X", rxBuff4[j]); + LOG_MSG_STACK("sent Value4 (%zu)\n%s\n, Received Value4(%zu)\n%s\n", m_sendSize4, SentBuffer4, receivedSize4, recievedBuffer4); + + delete[] rxBuff4; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test012: Single PDN dst NAT test expansion table usage */ +/* NOTE: other classes are derived from this class - change carefully */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest012 : public IpaNatBlockTestFixture +{ + uint32_t m_target_ip2; + uint16_t m_target_port2; +public: + IpaNatBlockTest012() + { + m_name = "IpaNatBlockTest012"; + m_description = + "NAT block test 012 - single PDN dst NAT test - expansion table usage\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block (public IP filtering) \ + 3. generate and commit two NAT rules so second one is located in expansion table:\ + since we use a single public ip this test should work also on pre IPAv4 targets\ + public ip 192.23.22.1 --> private ip 194.23.22.1 "; + m_private_ip = 0xC2171601; /* 194.23.22.1 */ + m_private_port = 5678; + m_private_ip2 = 0xC5171601; /* 197.23.22.1 */ + m_private_port2 = 5679; + m_public_ip = 0xC0171601; /* "192.23.22.1" */ + m_public_port = 9050; + m_target_ip = 0xC1171601; /* 193.23.22.1 */ + m_target_port = 1234; + m_target_ip2 = 0x1601C117; /* swap m_target_ip to get same hash*/ + m_target_port2 = m_target_port; + Register(*this); + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + const char bypass0[20] = "Bypass0"; + const char bypass1[20] = "Bypass1"; + const char bypass2[20] = "Bypass2"; + struct ipa_ioc_get_rt_tbl routing_table0; + + if (!CreateThreeIPv4BypassRoutingTables(bypass0, bypass1, bypass2)) + { + LOG_MSG_ERROR("CreateThreeBypassRoutingTables Failed\n"); + return false; + } + + LOG_MSG_DEBUG("CreateThreeBypassRoutingTables completed successfully\n"); + routing_table0.ip = IPA_IP_v4; + strlcpy(routing_table0.name, bypass0, sizeof(routing_table0.name)); + if (!m_routing.GetRoutingTable(&routing_table0)) + { + LOG_MSG_ERROR("m_routing.GetRoutingTable(&routing_table0=0x%p) Failed.\n", &routing_table0); + return false; + } + LOG_MSG_DEBUG("%s route table handle = %u\n", bypass0, routing_table0.hdl); + + IPAFilteringTable FilterTable0; + struct ipa_flt_rule_add flt_rule_entry; + FilterTable0.Init(IPA_IP_v4, IPA_CLIENT_TEST_PROD, false, 3); + LOG_MSG_DEBUG("FilterTable*.Init Completed Successfully..\n"); + + // Configuring Filtering Rule No.0 + FilterTable0.GeneratePresetRule(1, flt_rule_entry); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; // return Value + flt_rule_entry.status = -1; // return value + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + flt_rule_entry.rule.rt_tbl_hdl = routing_table0.hdl; + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00FFFFFF; // Mask + flt_rule_entry.rule.attrib.u.v4.dst_addr = m_public_ip; // Filter DST_IP == 192.23.22.1 + flt_rule_entry.rule.pdn_idx = 0; + flt_rule_entry.rule.set_metadata = 0; + if ( + ((uint8_t)-1 == FilterTable0.AddRuleToTable(flt_rule_entry)) || + !m_filtering.AddFilteringRule(FilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR("Error Adding Rule to Filter Table, aborting...\n"); + return false; + } + else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", FilterTable0.ReadRuleFromTable(0)->flt_rule_hdl, FilterTable0.ReadRuleFromTable(0)->status); + } + + //NAT table and rules creation + int total_entries = 20; + int ret; + ipa_nat_ipv4_rule ipv4_rule; + uint32_t pub_ip_add = m_public_ip; + + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, m_mem_type, total_entries, &m_tbl_hdl); + if (ret) { + LOG_MSG_ERROR("Leaving, failed creating NAT table\n"); + return false; + } + + LOG_MSG_DEBUG("nat table added, hdl %d, public ip 0x%X\n", m_tbl_hdl, + pub_ip_add); + + ipv4_rule.target_ip = m_target_ip; + ipv4_rule.target_port = m_target_port; + ipv4_rule.private_ip = m_private_ip; + ipv4_rule.private_port = m_private_port; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = m_public_port; + ipv4_rule.pdn_index = 0; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d, $d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port, ipv4_rule.pdn_index); + + ipv4_rule.target_ip = m_target_ip2; + ipv4_rule.target_port = m_target_port2; + + // private IPs are not part of the dst NAT entry hash calculation + ipv4_rule.private_ip = m_private_ip2; + ipv4_rule.private_port = m_private_port2; + + ret = ipa_nat_add_ipv4_rule(m_tbl_hdl, &ipv4_rule, &m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed adding NAT rule 0\n"); + return false; + } + + LOG_MSG_DEBUG("NAT rule 2 added, hdl %d, data: 0x%X, %d, 0x%X, %d, %d, %d, $d\n", + m_nat_rule_hdl1, ipv4_rule.target_ip, ipv4_rule.target_port, + ipv4_rule.private_ip, ipv4_rule.private_port, + ipv4_rule.protocol, ipv4_rule.public_port, ipv4_rule.pdn_index); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ModifyPackets() + { + uint32_t address; + uint16_t port; + char flags = 0x18; + + address = htonl(m_public_ip); + memcpy(&m_sendBuffer[IPV4_DST_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_public_port); + memcpy(&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + + address = htonl(m_target_ip2); + memcpy(&m_sendBuffer[IPV4_SRC_ADDR_OFFSET], &address, sizeof(address)); + port = htons(m_target_port2); + memcpy(&m_sendBuffer[IPV4_SRC_PORT_OFFSET], &port, sizeof(port)); + + //make sure the FIN flag is not set, otherwise we will get a NAT miss + memcpy(&m_sendBuffer[IPV4_TCP_FLAGS_OFFSET], &flags, sizeof(flags)); + + return true; + }// ModifyPacktes () + + virtual bool SendPackets() + { + bool isSuccess = false; + + // Send first packet + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + LOG_MSG_ERROR("SendData failure.\n"); + return false; + } + + LOG_MSG_DEBUG("sent successfully one packet\n"); + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip2, m_public_ip, + m_private_port2, m_public_port, + false)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test013: Single PDN dst NAT expansion rule deletion test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest013 : public IpaNatBlockTest012 +{ +public: + IpaNatBlockTest013() + { + m_name = "IpaNatBlockTest013"; + m_description = + "NAT block test 013 - single PDN dst NAT test - expansion table rule deletion\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block (public IP filtering) \ + 3. generate and commit two NAT rules so second one is located in expansion table:\ + since we use a single public ip this test should work also on pre IPAv4 targets\ + public ip 192.23.22.1 --> private ip 194.23.22.1\ + 4. delete NAT rule and expect NAT miss"; + } + + + virtual bool AddRules() + { + LOG_MSG_DEBUG("Entering\n"); + + int ret = IpaNatBlockTest012::AddRules(); + if (!ret) { + LOG_MSG_ERROR("Leaving, failed Adding test 012 rules 0\n"); + return false; + } + + ret = ipa_nat_del_ipv4_rule(m_tbl_hdl, m_nat_rule_hdl1); + if (ret) { + LOG_MSG_ERROR("Leaving, failed deleting NAT rule 1\n"); + return false; + } + LOG_MSG_DEBUG("NAT rule deleted\n"); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + if (receivedSize) { + LOG_MSG_ERROR("Data received - test failed!\n"); + isSuccess = false; + + // Compare results for debug in the case of failure only + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip2, m_public_ip, + m_private_port2, m_public_port, + false)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + } + else { + LOG_MSG_ERROR("Comparison of Buffer0 succeeded - NAT rule was hit despite deletion!\n"); + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + } + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test014: Single PDN src NAT zero PDN test */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest014 : public IpaNatBlockTest001 +{ +public: + IpaNatBlockTest014() + { + m_name = "IpaNatBlockTest014"; + m_description = + "NAT block test 014 - single PDN src NAT PDN zeroing test\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to src NAT \ + All DST_IP == (193.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit one NAT rule:\ + private ip 194.23.22.1 --> public ip 192.23.22.1\ + 4. modify PDN entry 0 and expect NAT miss"; + m_minIPAHwType = IPA_HW_v4_0; + } + + + virtual bool AddRules() + { + ipa_nat_pdn_entry pdn_info; + + LOG_MSG_DEBUG("Entering\n"); + + int ret = IpaNatBlockTest001::AddRules(); + if (!ret) { + LOG_MSG_ERROR("Leaving, failed Adding test 001 rules 0\n"); + return false; + } + + // modify PDN entry 0 so the NAT rule will get a NAT miss + pdn_info.public_ip = 0; + pdn_info.src_metadata = 0; + pdn_info.dst_metadata = 0; + ret = ipa_nat_modify_pdn(m_tbl_hdl, 0, &pdn_info); + if (ret) { + LOG_MSG_ERROR("Leaving, failed Modifying PDN entry 0 \n"); + return false; + } + + LOG_MSG_DEBUG("PDN modified\n"); + + LOG_MSG_DEBUG("Leaving\n"); + return true; + }// AddRules() + + virtual bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + if (receivedSize) { + LOG_MSG_ERROR("Data received - test failed!\n"); + isSuccess = false; + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + } + else { + LOG_MSG_ERROR("Comparison of Buffer0 succeeded - NAT rule was hit despite deletion!\n"); + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + } + + delete[] rxBuff1; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test015: Single PDN src NAT send two packets that will hit the same rule */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest015 : public IpaNatBlockTest001 +{ +public: + IpaNatBlockTest015() + { + m_name = "IpaNatBlockTest015"; + m_description = + "NAT block test 015 - single PDN src NAT hit the same rule twice\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to src NAT \ + All DST_IP == (193.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit one NAT rule:\ + private ip 194.23.22.1 --> public ip 192.23.22.1\ + 4. send two pakcets and verify NATing"; + } + + virtual bool SendPackets() + { + bool ret = IpaNatBlockTest001::SendPackets(); + if (!ret) + { + LOG_MSG_ERROR("failed sending first pakcket.\n"); + return false; + } + + LOG_MSG_DEBUG("first packet sent succesfully.\n"); + + ret = IpaNatBlockTest001::SendPackets(); + if (!ret) + { + LOG_MSG_ERROR("failed sending second pakcket.\n"); + return false; + } + + LOG_MSG_DEBUG("second packet sent succesfully.\n"); + + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + bool isSuccess = true; + + isSuccess &= IpaNatBlockTest001::ReceivePacketsAndCompare(); + if (!isSuccess) + { + LOG_MSG_ERROR("failed to receive\\compare first packet.\n"); + } + + isSuccess &= IpaNatBlockTest001::ReceivePacketsAndCompare(); + if (!isSuccess) + { + LOG_MSG_ERROR("failed to receive\\compare second packet.\n"); + } + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test016: Single PDN dst NAT send two packets that will hit the same rule */ +/*---------------------------------------------------------------------------*/ +class IpaNatBlockTest016 : public IpaNatBlockTest002 +{ +public: + IpaNatBlockTest016() + { + m_name = "IpaNatBlockTest016"; + m_description = + "NAT block test 016 - single PDN dst NAT hit the same rule twice\ + 1. Generate and commit three routing tables (only one is used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit one filtering rule: (DST & Mask Match). \ + action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + 3. generate and commit one NAT rule:\ + public ip 192.23.22.1 --> private ip 194.23.22.1\ + 4. send two pakcets and verify NATing"; + } + + virtual bool SendPackets() + { + bool ret = IpaNatBlockTest002::SendPackets(); + if (!ret) + { + LOG_MSG_ERROR("failed sending first pakcket.\n"); + return false; + } + + LOG_MSG_DEBUG("first packet sent succesfully.\n"); + + ret = IpaNatBlockTest002::SendPackets(); + if (!ret) + { + LOG_MSG_ERROR("failed sending second pakcket.\n"); + return false; + } + + LOG_MSG_DEBUG("second packet sent succesfully.\n"); + + return true; + } + + virtual bool ReceivePacketsAndCompare() + { + bool isSuccess = true; + + isSuccess &= IpaNatBlockTest002::ReceivePacketsAndCompare(); + if (!isSuccess) + { + LOG_MSG_ERROR("failed to receive\\compare first packet.\n"); + } + + isSuccess &= IpaNatBlockTest002::ReceivePacketsAndCompare(); + if (!isSuccess) + { + LOG_MSG_ERROR("failed to receive\\compare second packet.\n"); + } + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------------*/ +/* Test017: Multi PDN src NAT test with identical private IPs and different ports */ +/*---------------------------------------------------------------------------------*/ +class IpaNatBlockTest017 : public IpaNatBlockTest003 +{ +public: + IpaNatBlockTest017() + { + m_name = "IpaNatBlockTest017"; + m_description = + "NAT block test 017 - Multi PDN src NAT test with identical private IPs\ + 1. Generate and commit three routing tables (two are used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit two filtering rule: (DST & Mask Match). \ + - action go to src NAT \ + All SRC_IP == (194.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All SRC_IP == (197.23.22.1 & 0.255.255.255)traffic goes to NAT block - not relevant for this test \ + 3. generate and commit two NAT rules:\ + private ip 194.23.22.1 && port 5678--> public ip 192.23.22.1 \ + private ip 194.23.22.1 && port 5679--> public ip 195.23.22.1"; + m_private_ip2 = m_private_ip; + } + + virtual bool ReceivePacketsAndCompare() + { + // we cannot just use test 003 ReceivePacketsAndCompare since the filtering rules send the + // packets to two different pipes, but since the private IPs are now equal the second filtering rule + // won't be hit so we need to recive the second packet on the first pipe + + size_t receivedSize = 0; + size_t receivedSize2 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + + if (rxBuff1 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + if (rxBuff2) + delete[] rxBuff2; + return false; + } + + if (rxBuff2 == NULL) + { + LOG_MSG_ERROR("Memory allocation error.\n"); + delete[] rxBuff1; + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + LOG_MSG_DEBUG("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + // Compare results + if (!CompareResultVsGoldenNat( + m_sendBuffer, m_sendSize, + rxBuff1, receivedSize, + m_private_ip, m_public_ip, + m_private_port, m_public_port, + true)) + { + LOG_MSG_ERROR("Comparison of Buffer0 Failed!\n"); + isSuccess = false; + } + + char recievedBuffer[256] = { 0 }; + char SentBuffer[256] = { 0 }; + char recievedBuffer2[256] = { 0 }; + char SentBuffer2[256] = { 0 }; + size_t j; + + for (j = 0; j < m_sendSize; j++) + snprintf(&SentBuffer[3 * j], sizeof(SentBuffer) - (3 * j + 1), " %02X", m_sendBuffer[j]); + for (j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], sizeof(recievedBuffer) - (3 * j + 1), " %02X", rxBuff1[j]); + LOG_MSG_STACK("sent Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n", m_sendSize, SentBuffer, receivedSize, recievedBuffer); + + delete[] rxBuff1; + + isSuccess &= CompareResultVsGoldenNat( + m_sendBuffer2, m_sendSize2, + rxBuff2, receivedSize2, + m_private_ip2, m_public_ip2, + m_private_port2, m_public_port2, + true); + + for (j = 0; j < m_sendSize2; j++) + snprintf(&SentBuffer2[3 * j], sizeof(SentBuffer2) - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for (j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer2[3 * j], sizeof(recievedBuffer2) - (3 * j + 1), " %02X", rxBuff2[j]); + LOG_MSG_STACK("sent Value2 (%zu)\n%s\n, Received Value2(%zu)\n%s\n", m_sendSize2, SentBuffer2, receivedSize2, recievedBuffer2); + + delete[] rxBuff2; + + return isSuccess; + } +}; + +/*---------------------------------------------------------------------------------*/ +/* Test018: Multi PDN dst NAT test with identical private IPs and different ports */ +/*---------------------------------------------------------------------------------*/ +class IpaNatBlockTest018 : public IpaNatBlockTest004 +{ +public: + IpaNatBlockTest018() + { + m_name = "IpaNatBlockTest018"; + m_description = + "NAT block test 018 - Multi PDN dst NAT test with identical private IPs\ + 1. Generate and commit three routing tables (two are used). \ + Each table contains a single \"bypass\" rule (all data goes to output pipe 0, 1 and 2 (accordingly)) \ + 2. Generate and commit two filtering rule: (DST & Mask Match). \ + - action go to dst NAT \ + All DST_IP == (192.23.22.1 & 0.255.255.255)traffic goes to NAT block \ + All DST_IP == (195.23.22.1 & 0.255.255.255)traffic goes to NAT block - not releveant for this test\ + 3. generate and commit two NAT rules:\ + private ip 194.23.22.1 --> public ip 192.23.22.1 && port 9050\ + private ip 194.23.22.1 --> public ip 192.23.22.1 && port 9051"; + m_private_ip2 = m_private_ip; + } +}; + +static class IpaNatBlockTest001 IpaNatBlockTest001;//single PDN src NAT test +static class IpaNatBlockTest002 IpaNatBlockTest002;//single PDN dst NAT test +static class IpaNatBlockTest003 IpaNatBlockTest003;//multi PDN (tuple) src NAT test +static class IpaNatBlockTest004 IpaNatBlockTest004;//multi PDN (tuple) dst NAT test +static class IpaNatBlockTest005 IpaNatBlockTest005;//single PDN src NAT test - src metadata replacement +static class IpaNatBlockTest006 IpaNatBlockTest006;//single PDN dst NAT test - dst metadata replacement +static class IpaNatBlockTest007 IpaNatBlockTest007;//hashable routing rule with dst NAT test +static class IpaNatBlockTest008 IpaNatBlockTest008;//Multi PDN src NAT test match PDN by input from filtering block +static class IpaNatBlockTest009 IpaNatBlockTest009;//single PDN src NAT rule deletion test +static class IpaNatBlockTest010 IpaNatBlockTest010;//single PDN dst NAT rule deletion test +static class IpaNatBlockTest011 IpaNatBlockTest011;//Multi PDN src NAT - MAX number of PDNs test +static class IpaNatBlockTest012 IpaNatBlockTest012;//Single PDN dst NAT test expansion table usage +static class IpaNatBlockTest013 IpaNatBlockTest013;//Single PDN dst NAT test expansion table delete test +static class IpaNatBlockTest014 IpaNatBlockTest014;//single PDN src NAT zero PDN test +static class IpaNatBlockTest015 IpaNatBlockTest015;//single PDN src NAT test - send two packets that will hit the same rule +static class IpaNatBlockTest016 IpaNatBlockTest016;//single PDN dst NAT test - send two packets that will hit the same rule +static class IpaNatBlockTest017 IpaNatBlockTest017;//multi PDN (tuple) src NAT test - identical private IPs different ports +static class IpaNatBlockTest018 IpaNatBlockTest018;//multi PDN (tuple) dst NAT test - identical private IPs different ports + diff --git a/kernel-tests/Pipe.cpp b/kernel-tests/Pipe.cpp new file mode 100644 index 0000000000..84697e7285 --- /dev/null +++ b/kernel-tests/Pipe.cpp @@ -0,0 +1,729 @@ +/* + * Copyright (c) 2017-2018,2020 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 "Pipe.h" +#include "TestsUtils.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Do not change those default values due to the fact that some test may relay on those default values. +//In case you need a change of the field do this in a derived class. + +//Dest MAC(6 bytes) Src MAC(6 Bytes) EtherType(2 Bytes) +unsigned char Pipe::m_pUsbHeader[] = { 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xB1, 0xB2, + 0xB3, 0xB4, 0xB5, 0xB6, 0xC1, 0xC2 }; +unsigned char Pipe::m_pA2NDUNHeader[] = + { 0xA1, 0xA2, 0xA3, 0xA4, 0xB1, 0xB2, 0xC1, 0xC2 }; +//unsigned char Pipe::m_pA2DUNHeader[] = {}; +//unsigned char Pipe::m_pQ6LANHeader[] = {}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Pipe::Pipe(enum ipa_client_type nClientType, + IPATestConfiguration eConfiguration) : + m_Fd(-1), m_nHeaderLengthRemove(0), + m_nHeaderLengthAdd(0), m_pHeader(NULL), m_pInodePath(NULL), + m_bInitialized(false), m_ExceptionPipe(false) { + m_nClientType = nClientType; + m_eConfiguration = eConfiguration; +} + +Pipe::Pipe(IPATestConfiguration eConfiguration) : + m_Fd(-1), m_nHeaderLengthRemove(0), + m_nHeaderLengthAdd(0), m_pHeader(NULL), m_pInodePath(NULL), + m_bInitialized(false), m_ExceptionPipe(true) { + m_eConfiguration = eConfiguration; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Pipe::~Pipe() { + //Nothing to be done at this point... +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool Pipe::Init() { + int tries_cnt = 1; + SetSpecificClientParameters(m_nClientType, m_eConfiguration); + //By examining the Client type we will map the inode device name + while (tries_cnt <= 10000) { + m_Fd = open(m_pInodePath, O_RDWR); + if (-1 != m_Fd) + break; + + // Sleep for 5 msec + usleep(5000); + ++tries_cnt; + } + LOG_MSG_DEBUG("open retries_cnt=%d\n", tries_cnt); + if (-1 == m_Fd) { + LOG_MSG_ERROR("Failed to open %s", m_pInodePath); + return false; + } + m_bInitialized = true; + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Pipe::Destroy() { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return; + } + close(m_Fd); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Pipe::Send(unsigned char * pBuffer, size_t nBytesToSend) { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return 0; + } + size_t nBytesWritten = 0; + nBytesWritten = write(m_Fd, pBuffer, nBytesToSend); + return nBytesWritten; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Pipe::AddHeaderAndSend(unsigned char * pIpPacket, size_t nIpPacketSize) { + int retval; + + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return 0; + } + size_t nBytesToWrite = nIpPacketSize + m_nHeaderLengthAdd; + //Allocate new buffer for the Header and IP packet: + unsigned char *pLinkLayerAndIpPacket = new unsigned char[nBytesToWrite]; + if (!pLinkLayerAndIpPacket) { + LOG_MSG_ERROR("Memory allocation failure."); + return 0; + } + + //put the header first: + memcpy(pLinkLayerAndIpPacket, m_pHeader, m_nHeaderLengthAdd); + //Then add the IP packet: + memcpy(pLinkLayerAndIpPacket + m_nHeaderLengthAdd, pIpPacket, + nIpPacketSize); + //Call the Send method which will send the new created buffer(which contains the IP packet with the Header): + retval = Send(pLinkLayerAndIpPacket, nBytesToWrite); + delete[] pLinkLayerAndIpPacket; + + return retval; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Pipe::Receive(unsigned char *pBuffer, size_t nBytesToReceive) { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return 0; + } + size_t nBytesRead = 0; + nBytesRead = read(m_Fd, (void*) pBuffer, nBytesToReceive); + return nBytesRead; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Pipe::ReceiveAndRemoveHeader(unsigned char *pIpPacket, size_t nIpPacketSize) { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return 0; + } + size_t nBytesToRead = nIpPacketSize + m_nHeaderLengthRemove; + unsigned char *pPacket = new unsigned char[nBytesToRead]; + if (!pPacket) { + LOG_MSG_ERROR("Memory allocation failure."); + return 0; + } + size_t nReceivedBytes = Receive(pPacket, nBytesToRead); + if (nReceivedBytes != nBytesToRead) { + LOG_MSG_ERROR("Pipe was asked to receive an IP packet " + "of size %d, however only %d bytes were read " + "while the header size is %d", + nIpPacketSize, + nReceivedBytes, + m_nHeaderLengthRemove); + delete[] pPacket; + return nReceivedBytes - m_nHeaderLengthRemove; + } + + memcpy(pIpPacket, pPacket + m_nHeaderLengthRemove, nIpPacketSize); + delete[] pPacket; + + return (nReceivedBytes - m_nHeaderLengthRemove); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +enum ipa_client_type Pipe::GetClientType() { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return IPA_CLIENT_HSIC1_PROD; + } + return m_nClientType; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Pipe::SetSpecificClientParameters( + enum ipa_client_type nClientType, + IPATestConfiguration eConfiguration) { + switch (eConfiguration) { + case IPA_TEST_CONFIFURATION_0: + break; + case IPA_TEST_CONFIFURATION_1: + switch (nClientType) { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_1_FROM_USB1_TO_IPA_DMA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD "); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_1_FROM_IPA_TO_USB1_DMA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_1 switch in default " + "nClientType = %d is not supported ", nClientType); + break; + } + break; + case IPA_TEST_CONFIFURATION_2: + switch (nClientType) { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_2_FROM_USB_TO_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD"); + break; + case (IPA_CLIENT_TEST2_CONS): + m_pInodePath = CONFIG_2_FROM_IPA_TO_A2_NDUN; + m_nHeaderLengthAdd = sizeof(m_pA2NDUNHeader); + m_nHeaderLengthRemove = sizeof(m_pA2NDUNHeader); + m_pHeader = m_pA2NDUNHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_2 switch in default " + "nClientType = %d is not supported ", nClientType); + break; + } + break; + case IPA_TEST_CONFIFURATION_3: + switch (nClientType) { + case IPA_CLIENT_TEST2_PROD: + m_pInodePath = CONFIG_3_FROM_A2_NDUN_TO_IPA; + m_nHeaderLengthAdd = sizeof(m_pA2NDUNHeader); + m_nHeaderLengthRemove = sizeof(m_pA2NDUNHeader); + m_pHeader = m_pA2NDUNHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD"); + break; + case IPA_CLIENT_TEST_CONS: + m_pInodePath = CONFIG_3_FROM_IPA_TO_USB1; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + case IPA_CLIENT_TEST2_CONS: + m_pInodePath = CONFIG_3_FROM_IPA_TO_A2_NDUN; + m_nHeaderLengthAdd = sizeof(m_pA2NDUNHeader); + m_nHeaderLengthRemove = sizeof(m_pA2NDUNHeader); + m_pHeader = m_pA2NDUNHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + case IPA_CLIENT_TEST4_CONS: + //TODO add when applicable + m_pInodePath = CONFIG_3_FROM_IPA_TO_Q6_LAN; + m_nHeaderLengthAdd = 0; + m_nHeaderLengthRemove = 0; + m_pHeader = 0; + LOG_MSG_INFO("IPA_CLIENT_TEST4_CONS is not supported yet"); + break; + default: + LOG_MSG_INFO("IPA_TEST_CONFIFURATION_3 switch in default " + "nClientType = %d is not supported ", nClientType); + break; + } + break; + case IPA_TEST_CONFIFURATION_7: + if (m_ExceptionPipe) { + m_pInodePath = CONFIG_7_FROM_IPA_TO_A5_EXCEPTION; + m_nHeaderLengthAdd = 0; //No send + m_nHeaderLengthRemove = 8; //A5Mux header size without retained source header + m_pHeader = NULL; //No header to send + LOG_MSG_INFO("Setting parameters for A5_Exception "); + break; + } + + if (nClientType == IPA_CLIENT_TEST_PROD) { + m_pInodePath = CONFIG_7_FROM_USB1_TO_IPA; + m_nHeaderLengthAdd = 0; + m_nHeaderLengthRemove = 0; + m_pHeader = NULL; + LOG_MSG_INFO( + "Setting parameters for FROM_USB1_TO_IPA - no header addition/removal"); + } else { + LOG_MSG_INFO("IPA_TEST_CONFIFURATION_7 switch in default " + "nClientType = %d is not supported ", nClientType); + } + break; + case IPA_TEST_CONFIGURATION_8: + switch(nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_8_DEAGG_TO_IPA_NO_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD "); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_8_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + case (IPA_CLIENT_TEST3_PROD): + m_pInodePath = CONFIG_8_NO_AGG_TO_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_PROD "); + break; + case (IPA_CLIENT_TEST3_CONS): + m_pInodePath = CONFIG_8_FROM_IPA_NO_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_CONS"); + break; + case (IPA_CLIENT_TEST2_PROD): + m_pInodePath = CONFIG_8_DEAGG_TO_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD"); + break; + case (IPA_CLIENT_TEST2_CONS): + m_pInodePath = CONFIG_8_DEAGG_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + case (IPA_CLIENT_TEST4_PROD): + m_pInodePath = CONFIG_8_NO_AGG_TO_IPA_AGG_TIME; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST4_PROD"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_8 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_9: + switch(nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_9_DEAGG_TO_IPA_NO_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD "); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_9_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + case (IPA_CLIENT_TEST3_PROD): + m_pInodePath = CONFIG_9_NO_AGG_TO_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_PROD "); + break; + case (IPA_CLIENT_TEST3_CONS): + m_pInodePath = CONFIG_9_FROM_IPA_NO_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_CONS"); + break; + case (IPA_CLIENT_TEST2_PROD): + m_pInodePath = CONFIG_9_DEAGG_TO_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD"); + break; + case (IPA_CLIENT_TEST2_CONS): + m_pInodePath = CONFIG_9_DEAGG_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + case (IPA_CLIENT_TEST4_PROD): + m_pInodePath = CONFIG_9_NO_AGG_TO_IPA_AGG_TIME; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST4_PROD"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_9 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_10: + switch(nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_10_TO_IPA_AGG_ZERO_LIMITS; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD"); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_10_FROM_IPA_AGG_ZERO_LIMITS; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_10 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_11: + switch(nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_11_TO_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD"); + break; + case (IPA_CLIENT_TEST2_CONS): + m_pInodePath = CONFIG_11_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + case (IPA_CLIENT_TEST2_PROD): + m_pInodePath = CONFIG_11_TO_IPA_DEAGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD"); + break; + case (IPA_CLIENT_TEST3_CONS): + m_pInodePath = CONFIG_11_FROM_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_CONS"); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_11_FROM_IPA_AGG_TIME; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + case (IPA_CLIENT_TEST4_CONS): + m_pInodePath = CONFIG_11_FROM_IPA_ZERO_LIMITS; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST4_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_11 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_12: + switch(nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_12_TO_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD"); + break; + case (IPA_CLIENT_TEST2_CONS): + m_pInodePath = CONFIG_12_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + case (IPA_CLIENT_TEST2_PROD): + m_pInodePath = CONFIG_12_TO_IPA_DEAGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD"); + break; + case (IPA_CLIENT_TEST3_CONS): + m_pInodePath = CONFIG_12_FROM_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_CONS"); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_12_FROM_IPA_AGG_TIME; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + case (IPA_CLIENT_TEST4_CONS): + m_pInodePath = CONFIG_12_FROM_IPA_ZERO_LIMITS; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST4_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_12 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_17: + switch(nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_17_TO_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD "); + break; + case (IPA_CLIENT_TEST3_PROD): + m_pInodePath = CONFIG_17_TO_IPA_NO_HDR; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_PROD "); + break; + case (IPA_CLIENT_TEST2_CONS): + m_pInodePath = CONFIG_17_FROM_IPA_AGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_CONS"); + break; + case (IPA_CLIENT_TEST2_PROD): + m_pInodePath = CONFIG_17_TO_IPA_DEAGG; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD "); + break; + case (IPA_CLIENT_TEST3_CONS): + m_pInodePath = CONFIG_17_FROM_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST3_CONS"); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_17_FROM_IPA_AGG_TIME; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + case (IPA_CLIENT_TEST4_CONS): + m_pInodePath = CONFIG_17_FROM_IPA_ZERO_LIMITS; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST4_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_17 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_18: + switch (nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_18_TO_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD "); + break; + case (IPA_CLIENT_TEST2_PROD): + m_pInodePath = CONFIG_18_DUMMY_ENDPOINT; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST2_PROD "); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_18_FROM_IPA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_CONS"); + break; + default: + LOG_MSG_ERROR( + "IPA_TEST_CONFIFURATION_18 switch in default " + "nClientType = %d is not supported ", + nClientType); + break; + } + break; + case IPA_TEST_CONFIGURATION_19: + switch (nClientType) + { + case (IPA_CLIENT_TEST_PROD): + m_pInodePath = CONFIG_19_FROM_USB_TO_IPA_DMA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for IPA_CLIENT_TEST_PROD "); + break; + case (IPA_CLIENT_TEST_CONS): + m_pInodePath = CONFIG_19_FROM_IPA_TO_USB_DMA; + m_nHeaderLengthAdd = sizeof(m_pUsbHeader); + m_nHeaderLengthRemove = sizeof(m_pUsbHeader); + m_pHeader = m_pUsbHeader; + LOG_MSG_INFO("Setting parameters for TEST_CONS"); + break; + default: + LOG_MSG_ERROR("IPA_TEST_CONFIFURATION_19 switch in default " + "nClientType = %d is not supported ", nClientType); + break; + } + break; + default: + LOG_MSG_ERROR("Pipe::SetSpecificClientParameters " + "switch in default eConfiguration = %d ", eConfiguration); + break; + } +}/* Pipe::SetSpecificClientParameters() */ + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Pipe::GetHeaderLengthAdd() { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return 0; + } + return m_nHeaderLengthAdd; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Pipe::GetHeaderLengthRemove() { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return 0; + } + return m_nHeaderLengthRemove; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool Pipe::ConfigureHolb(unsigned short enable, unsigned timerValue) { + if (false == m_bInitialized) { + LOG_MSG_ERROR("Pipe is being used without being initialized!"); + return false; + } + + if (IPA_CLIENT_IS_PROD(m_nClientType)) { + LOG_MSG_ERROR("Can't configure HOLB on a producer pipe!"); + return false; + } + + struct ipa_test_holb_config test_holb_config; + + test_holb_config.client = m_nClientType; + test_holb_config.tmr_val = timerValue; + test_holb_config.en = enable; + + LOG_MSG_DEBUG("Sending: client=%d tmr_val=%d en=%d", + test_holb_config.client, + test_holb_config.tmr_val, + test_holb_config.en); + + return configure_holb(&test_holb_config); +} + +bool Pipe::EnableHolb(unsigned timerValue) { + return ConfigureHolb(1, timerValue); +} + +bool Pipe::DisableHolb() { + return ConfigureHolb(0, 0); +} + diff --git a/kernel-tests/Pipe.h b/kernel-tests/Pipe.h new file mode 100644 index 0000000000..e6172bc35f --- /dev/null +++ b/kernel-tests/Pipe.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017,2020 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 _PIPE_H_ +#define _PIPE_H_ + +#include +#include +#include +#include +#include + +#include +#include "linux/msm_ipa.h" +#include "Constants.h" +#include "Logger.h" + +using namespace std; + +/*This class will be used to interact with the system pipes + *by only referring to Client type. + *It will allow "raw" data transfer to/from the IPA and + *will allow a encapsulation of the header addition/ + *removal of a packets thus allowing + *the test to deal only with IP packet. + */ +class Pipe +{ + +public: + /* see Constants.h for nClientType / eConfiguration */ + Pipe(enum ipa_client_type nClientType, + IPATestConfiguration eConfiguration); + /* exception pipe Ctor */ + Pipe(IPATestConfiguration eConfiguration); + ~Pipe(); + + /*In this method the actual inode openning will occur.*/ + bool Init(); + + /*The close of the inode*/ + void Destroy(); + + /*Send the pBuffer(which is an ip[ packet) + *after adding the header to the packet.*/ + int AddHeaderAndSend( + unsigned char *pBuffer, + size_t nIPPacketSize); + + /*Send raw data as is - no header removal + *- nBytesToSend bytes will be added*/ + int Send( + unsigned char *pBuffer, + size_t nBytesToSend); + + /*Receive data from the IPA and remove its header*/ + int ReceiveAndRemoveHeader( + unsigned char *pBuffer, + size_t nIPPacketSize); + + /*Receive data from the IPA as is*/ + int Receive(unsigned char *pBuffer, size_t nBytesToReceive); + + /*return the Client type of this pipe.*/ + enum ipa_client_type GetClientType(); + + /*Return the length of the header to be added to an + *IP packet before it is being sent to the pipe + *(This length will be determine by the Pipe's ClientType). + */ + int GetHeaderLengthAdd(); + + /*Return the length of the header to be removed from a + *packet before it is being sent to the user + *(thus returning only the IP packet). + *(This length will be determine by the Pipe's ClientType). + */ + int GetHeaderLengthRemove(); + + bool EnableHolb(unsigned timerValue); + bool DisableHolb(); + +private: + void SetSpecificClientParameters( + enum ipa_client_type nClientType, + IPATestConfiguration eConfiguration); + + bool ConfigureHolb(unsigned short enable, unsigned timerValue); + +public: + /*efault Headers(Can be changed in Derived classes).*/ + static unsigned char m_pUsbHeader[]; + static unsigned char m_pHSICHeader[]; + static unsigned char m_pA2DUNHeader[]; + static unsigned char m_pA2NDUNHeader[]; + static unsigned char m_pQ6LANHeader[]; + + +private: + int m_Fd; + /*The file descriptor which will be used to transfer data + * via the inode(this inode will be created by the ITAKEM) + */ + enum ipa_client_type m_nClientType; + int m_nHeaderLengthRemove; + /*this length will be set in the + * constructor in corresponds to m_nClientType + */ + int m_nHeaderLengthAdd; + /*this length will be set in the constructor + * in corresponds to m_nClientType + */ + unsigned char *m_pHeader; + /*this pointer will be set to the current pipe used*/ + const char *m_pInodePath; + /*this pointer will be set to the current pipe used*/ + bool m_bInitialized; + IPATestConfiguration m_eConfiguration; + /*The Pipes configuration env*/ + bool m_ExceptionPipe; + /* Is this the exception pipe */ + +}; + +#endif diff --git a/kernel-tests/PipeTestFixture.cpp b/kernel-tests/PipeTestFixture.cpp new file mode 100644 index 0000000000..3c483d2853 --- /dev/null +++ b/kernel-tests/PipeTestFixture.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017,2020 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 "PipeTestFixture.h" + +extern Logger g_Logger; + +/*define the static Pipes which will be used by all derived tests.*/ +Pipe PipeTestFixture::m_IpaToUsbPipe(IPA_CLIENT_TEST_CONS, IPA_TEST_CONFIFURATION_1); +Pipe PipeTestFixture::m_UsbToIpaPipe(IPA_CLIENT_TEST_PROD, IPA_TEST_CONFIFURATION_1); + +PipeTestFixture::PipeTestFixture() +{ + m_testSuiteName.push_back("Pipes"); + Register(*this); +} + +static int SetupKernelModule(void) +{ + int retval; + struct ipa_channel_config from_ipa_0 = {0}; + struct test_ipa_ep_cfg from_ipa_0_cfg; + struct ipa_channel_config to_ipa_0 = {0}; + struct test_ipa_ep_cfg to_ipa_0_cfg; + + 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 pipes */ + memset(&from_ipa_0_cfg, 0 , sizeof(from_ipa_0_cfg)); + prepare_channel_struct(&from_ipa_0, + header.from_ipa_channels_num++, + IPA_CLIENT_TEST_CONS, + (void *)&from_ipa_0_cfg, + sizeof(from_ipa_0_cfg)); + from_ipa_array[0] = &from_ipa_0; + + /* To ipa configurations - 1 pipes */ + memset(&to_ipa_0_cfg, 0 , sizeof(to_ipa_0_cfg)); + to_ipa_0_cfg.mode.mode = IPA_DMA; + to_ipa_0_cfg.mode.dst = IPA_CLIENT_TEST_CONS; + prepare_channel_struct(&to_ipa_0, + header.to_ipa_channels_num++, + IPA_CLIENT_TEST_PROD, + (void *)&to_ipa_0_cfg, + sizeof(to_ipa_0_cfg)); + to_ipa_array[0] = &to_ipa_0; + + prepare_header_struct(&header, from_ipa_array, to_ipa_array); + + retval = GenericConfigureScenario(&header); + + return retval; +} + +bool PipeTestFixture::Setup() +{ + bool bRetVal = true; + + if (SetupKernelModule() == false) + return false; + + /*Initialize the pipe for all the tests - + * this will open the inode which represents the pipe. + */ + bRetVal &= m_IpaToUsbPipe.Init(); + bRetVal &= m_UsbToIpaPipe.Init(); + + return bRetVal; +} + +bool PipeTestFixture::Teardown() +{ + /*The Destroy method will close the inode.*/ + m_IpaToUsbPipe.Destroy(); + m_UsbToIpaPipe.Destroy(); + + return true; +} diff --git a/kernel-tests/PipeTestFixture.h b/kernel-tests/PipeTestFixture.h new file mode 100644 index 0000000000..4544607af1 --- /dev/null +++ b/kernel-tests/PipeTestFixture.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 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 "Constants.h" +#include "Logger.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "TestBase.h" +#include "Pipe.h" + +/*This class will be the base class of all Pipe tests. + *Any method other than the test case itself can be + *declared in this Fixture thus allowing the derived classes to + *implement only the test case. + *All the test of the pipe uses one input and one output in DMA mode. + */ +class PipeTestFixture:public TestBase +{ +public: + /*This Constructor will register each instance that it creates.*/ + PipeTestFixture(); + + /*This method will create and initialize two Pipe object for the USB + * (Ethernet) Pipes, one as input and the other as output. + */ + virtual bool Setup(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + /*The client type are set from the peripheral perspective + * (TODO Pipe:in case the Driver will change its perspective + * of ipa_connect this should be changed). + */ + static Pipe m_IpaToUsbPipe; + static Pipe m_UsbToIpaPipe; +}; diff --git a/kernel-tests/PipeTests.cpp b/kernel-tests/PipeTests.cpp new file mode 100644 index 0000000000..737410e0f8 --- /dev/null +++ b/kernel-tests/PipeTests.cpp @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2017,2020 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 "PipeTestFixture.h" +#include "Constants.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class PipeTestRawTransfer: public PipeTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + PipeTestRawTransfer() { + m_name = "PipeTestRawTransfer"; + m_description = "This test will be using the Pipe raw transfer ability"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() { + bool bTestResult = true; + Byte pIpPacket[] = { 0x01, 0x02, 0x03, 0x04 }; //This packet will be sent(It can be replaced by a real IP packet). + Byte pIpPacketReceive[sizeof(pIpPacket)] = { 0 }; //This buffer will be used in order to store the received packet. + + //Send the raw IP packet(which is a 4 arbitrary bytes) without header addition by the Pipe + LOG_MSG_DEBUG( + "Sending packet into the USB pipe(%d bytes)\n", sizeof(pIpPacket)); + int nBytesSent = m_UsbToIpaPipe.Send(pIpPacket, sizeof(pIpPacket)); + if (sizeof(pIpPacket) != nBytesSent) { + return false; + } + + //Receive the raw IP packet(which is a 4 arbitrary bytes) without header removal by the Pipe + LOG_MSG_DEBUG( + "Reading packet from the USB pipe(%d bytes should be there)\n", sizeof(pIpPacketReceive)); + int nBytesReceived = m_IpaToUsbPipe.Receive(pIpPacketReceive, + sizeof(pIpPacketReceive)); + if (sizeof(pIpPacketReceive) != nBytesReceived) { + return false; + } + for (int i = 0; i < nBytesReceived; i++) { + LOG_MSG_DEBUG("0x%02x\n", pIpPacketReceive[i]); + } + + //Check that the sent IP packet is equal to the received IP packet. + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + bTestResult &= !memcmp(pIpPacket, pIpPacketReceive, sizeof(pIpPacket)); + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +//This test will be using the Pipe Add-Header transfer ability(and not header insertion +class PipeTestAddHeader: public PipeTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + PipeTestAddHeader() { + m_name = "PipeTestAddHeader"; + m_description = "Add header to USB pipe and receive it without removing the header"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() { + Byte pIpPacketSend[4] = { 0x01, 0x02, 0x03, 0x04 }; + int nReceivedPacketSize = sizeof(pIpPacketSend) + + m_IpaToUsbPipe.GetHeaderLengthAdd(); + Byte *pPacketReceive = new Byte[nReceivedPacketSize]; + + LOG_MSG_DEBUG("Sending packet into the USB pipe(%d bytes - no header size)\n", sizeof(pIpPacketSend)); + int nRetValSend = m_UsbToIpaPipe.AddHeaderAndSend(pIpPacketSend, + sizeof(pIpPacketSend)); + LOG_MSG_DEBUG("Result of AddHeaderAndSend = %d\n", nRetValSend); + + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes - including header)\n", nReceivedPacketSize); + int nRetValReceive = m_IpaToUsbPipe.Receive(pPacketReceive, + nReceivedPacketSize); + LOG_MSG_DEBUG("Result of Receive = %d\n", nRetValReceive); + + if (nReceivedPacketSize != nRetValReceive) { + delete[] pPacketReceive; + LOG_MSG_ERROR( + "Size of received packet is not as expected - %d\n", nRetValReceive); + return false; + } + + bool bHeaderCmp = !memcmp(pPacketReceive, Pipe::m_pUsbHeader, + m_IpaToUsbPipe.GetHeaderLengthAdd()); + LOG_MSG_DEBUG("bHeaderCmp - %s\n", bHeaderCmp ? "True" : "False"); + + bool bIpCmp = !memcmp(pPacketReceive + m_IpaToUsbPipe.GetHeaderLengthAdd(), + pIpPacketSend, sizeof(pIpPacketSend)); + LOG_MSG_DEBUG("bIpCmp - %s\n", bIpCmp ? "True" : "False"); + + delete[] pPacketReceive; + return bHeaderCmp && bIpCmp; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +//This test will be using the Pipe Remove-Header transfer ability(and header addition) +class PipeTestAddAndRemoveHeader: public PipeTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + PipeTestAddAndRemoveHeader() { + m_name = "PipeTestAddAndRemoveHeader"; + m_description = "This test will be using the Pipe Remove-Header transfer ability(and header addition)"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() { + Byte pIpPacketSend[4] = { 0x01, 0x02, 0x03, 0x04 }; + int nToBeReceivedPacketSize = sizeof(pIpPacketSend) + + m_IpaToUsbPipe.GetHeaderLengthAdd(); + Byte *pPacketReceive = new Byte[nToBeReceivedPacketSize]; + + LOG_MSG_DEBUG("Sending packet into the USB pipe(%d bytes - no header size)\n", sizeof(pIpPacketSend)); + int nBytesSent = m_UsbToIpaPipe.AddHeaderAndSend(pIpPacketSend, + sizeof(pIpPacketSend)); + LOG_MSG_DEBUG("nBytesSent of AddHeaderAndSend = %d\n", nBytesSent); + + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes - including header)\n", nToBeReceivedPacketSize); + int nBytesReceived = m_IpaToUsbPipe.Receive(pPacketReceive, + nToBeReceivedPacketSize); + LOG_MSG_DEBUG("nBytesReceived = %d\n", nBytesReceived); + + if (nToBeReceivedPacketSize != nBytesReceived) { + delete[] pPacketReceive; + LOG_MSG_ERROR("Size of received packet is not as expected - %d\n", nBytesReceived); + return false; + } + + bool bHeaderCmp = !memcmp(pPacketReceive, Pipe::m_pUsbHeader, + m_IpaToUsbPipe.GetHeaderLengthAdd()); + LOG_MSG_DEBUG("bHeaderCmp - %s\n", bHeaderCmp ? "True" : "False"); + + bool bIpCmp = !memcmp(pPacketReceive + m_IpaToUsbPipe.GetHeaderLengthAdd(), + pIpPacketSend, sizeof(pIpPacketSend)); + LOG_MSG_DEBUG("bIpCmp - %s\n", bIpCmp ? "True" : "False"); + + delete[] pPacketReceive; + return bHeaderCmp && bIpCmp; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +//This test will try to send big chuck of data and check if the Data FIFO is working correct +class PipeTestDataFifoOverflow: public PipeTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + PipeTestDataFifoOverflow() { + m_name = "PipeTestDataFifoOverflow"; + m_description = "Send many big packets over the IPA. there will be toggle of send/receive"; + m_runInRegression = false; // Test is very long thus makes a problem in regression testing + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() { + bool bTestResult = true; + int nPacketByteSize; + int nTotalDataSent = 0; + int nTestsMaxDataSend = 3 * 0x6400; + int nIterationNumber = 0; + Byte *pIpPacket; + Byte *pIpPacketReceive; + srand(123); //set some constant seed value in order to be able to reproduce problems. + + //send and receive many packets(nIterations) + while (nTotalDataSent < nTestsMaxDataSend) { + //get random values for this packet. + nPacketByteSize = (rand() % 400) + 200; + pIpPacket = new Byte[nPacketByteSize]; + + for (int j = 0; j < nPacketByteSize; j++) { + pIpPacket[j] = rand() % 0x100; + } + + //Send the raw IP packet(which is a 4 arbitrary bytes) without header addition by the Pipe + LOG_MSG_DEBUG( + "Iteration number %d(0x%08x/0x%08x data):\n", nIterationNumber++, nTotalDataSent, nTestsMaxDataSend); + LOG_MSG_DEBUG( + "Sending packet into the USB pipe(%d bytes)\n", nPacketByteSize); + int nBytesSent = m_UsbToIpaPipe.Send(pIpPacket, nPacketByteSize); + if (nPacketByteSize != nBytesSent) { + delete[] pIpPacket; + LOG_MSG_ERROR("Could not send the whole packet - nTotalDataSent = 0x%08x\n", nTotalDataSent); + return false; + } + + //Receive the raw IP packet(which is a 4 arbitrary bytes) without header removal by the Pipe + pIpPacketReceive = new Byte[nPacketByteSize]; + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)\n", nPacketByteSize); + int nBytesReceived = m_IpaToUsbPipe.Receive(pIpPacketReceive, + nPacketByteSize); + if (nPacketByteSize != nBytesReceived) { + delete[] pIpPacket; + delete[] pIpPacketReceive; + LOG_MSG_ERROR("Could not read the whole packet - nTotalDataSent = 0x%08x\n", nTotalDataSent); + return false; + } + for (int j = 0; j < nBytesReceived; j++) { + LOG_MSG_DEBUG("0x%02x\n", pIpPacketReceive[j]); + } + + //Check that the sent IP packet is equal to the received IP packet. + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + bTestResult &= !memcmp(pIpPacket, pIpPacketReceive, + nPacketByteSize); + if (true != bTestResult) { + delete[] pIpPacketReceive; + delete[] pIpPacket; + LOG_MSG_ERROR("Send != Received - nTotalDataSent = 0x%08x\n", nTotalDataSent); + return false; + } + nTotalDataSent += nPacketByteSize; + delete[] pIpPacket; + delete[] pIpPacketReceive; + } + LOG_MSG_DEBUG("Great success - nTotalDataSent = 0x%08x\n", nTotalDataSent); + return true; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +//This test will try to many little chuck of data and check if the Descriptor FIFO is working correct +class PipeTestDescriptorFifoOverflow: public PipeTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + PipeTestDescriptorFifoOverflow() { + m_name = "PipeTestDescriptorFifoOverflow"; + m_description = "Send many small packets over the IPA. there will be toggle of send/receive"; + m_runInRegression = false; // Test is very long thus makes a problem in regression testing + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() { + bool bTestResult = true; + int nPacketByteSize; + int nTotalPacketSent = 0; + int nTestsMaxDescriptors = 3 * 0x1000; + int nIterationNumber = 0; + Byte *pIpPacket; + Byte *pIpPacketReceive; + srand(123); //set some constant seed value in order to be able to reproduce problems. + + //send and receive many packets(nIterations) + while (nTotalPacketSent < nTestsMaxDescriptors) { + //get random values for this packet. + nPacketByteSize = (rand() % 10) + 1; + pIpPacket = new Byte[nPacketByteSize]; + + for (int j = 0; j < nPacketByteSize; j++) { + pIpPacket[j] = rand() % 0x100; + } + + //Send the raw IP packet(which is a 4 arbitrary bytes) without header addition by the Pipe + LOG_MSG_DEBUG("Iteration number %d(0x%08x/0x%08x packets):\n", nIterationNumber++, nTotalPacketSent, nTestsMaxDescriptors); + LOG_MSG_DEBUG("Sending packet into the USB pipe(%d bytes)\n", nPacketByteSize); + int nBytesSent = m_UsbToIpaPipe.Send(pIpPacket, nPacketByteSize); + if (nPacketByteSize != nBytesSent) { + delete[] pIpPacket; + LOG_MSG_ERROR("Could not send the whole packet - nTotalPacketSent = 0x%08x\n", nTotalPacketSent); + return false; + } + + //Receive the raw IP packet(which is a 4 arbitrary bytes) without header removal by the Pipe + pIpPacketReceive = new Byte[nPacketByteSize]; + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)\n", nPacketByteSize); + int nBytesReceived = m_IpaToUsbPipe.Receive(pIpPacketReceive, + nPacketByteSize); + if (nPacketByteSize != nBytesReceived) { + delete[] pIpPacketReceive; + LOG_MSG_ERROR("Could not read the whole packet - nTotalPacketSent = 0x%08x\n", nTotalPacketSent); + return false; + } + for (int j = 0; j < nBytesReceived; j++) { + LOG_MSG_DEBUG("0x%02x\n", pIpPacketReceive[j]); + } + + //Check that the sent IP packet is equal to the received IP packet. + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + bTestResult &= !memcmp(pIpPacket, pIpPacketReceive, + nPacketByteSize); + if (true != bTestResult) { + delete[] pIpPacketReceive; + delete[] pIpPacket; + LOG_MSG_ERROR("Send != Received - nTotalPacketSent = 0x%08x\n", nTotalPacketSent); + return false; + } + nTotalPacketSent++; + delete[] pIpPacket; + delete[] pIpPacketReceive; + } + LOG_MSG_DEBUG("Great success - nTotalPacketSent = 0x%08x\n", nTotalPacketSent); + return true; + } + + ///////////////////////////////////////////////////////////////////////////////// + +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +#define HOLB_TEST_PACKETS_MAX_NUM 50 +class PipeTestHolb: public PipeTestFixture { + +public: + + PipeTestHolb() { + m_name = "PipeTestHolb"; + m_description = "This test will check the HOLB function"; + } + + bool Run() { + int nPacketsToSend = HOLB_TEST_PACKETS_MAX_NUM; + int nBytesReceived; + int nBytesSentInLastPacket; + int i; + Byte pIpPacket[] = { 0x01, 0x02, 0x03, 0x04 }; //This packet will be sent(It can be replaced by a real IP packet). + Byte pIpPacketReceive[sizeof(pIpPacket) * HOLB_TEST_PACKETS_MAX_NUM] = { 0 }; //This buffer will be used in order to store the received packet. + + m_IpaToUsbPipe.DisableHolb(); + + //Send the IP packets + LOG_MSG_DEBUG("Sending %d packets of %d bytes into the USB pipe\n", + nPacketsToSend, sizeof(pIpPacket)); + for (i = 0; i < nPacketsToSend; i++) { + nBytesSentInLastPacket = m_UsbToIpaPipe.Send(pIpPacket, sizeof(pIpPacket)); + if (sizeof(pIpPacket) != nBytesSentInLastPacket) { + LOG_MSG_ERROR("Failed sending the packet %d to m_UsbToIpaPipe", i); + return false; + } + } + + //Receive all the raw IP packets (which are a 4 arbitrary bytes) + LOG_MSG_DEBUG( + "Reading packets from the USB pipe (%dx%d bytes should be there)\n", + sizeof(pIpPacket), nPacketsToSend); + for (i = 0; i < nPacketsToSend; i++) { + nBytesReceived = m_IpaToUsbPipe.Receive(pIpPacketReceive, sizeof(pIpPacketReceive)); + if ((int)sizeof(pIpPacket) != nBytesReceived) { + LOG_MSG_ERROR("Failed with HOLB disabled! Packet #%d: Expected %d Bytes, got %d Bytes", + i, sizeof(pIpPacket), nBytesReceived); + return false; + } + } + + // Enable HOLB + m_IpaToUsbPipe.EnableHolb(0); + + //Send the IP packets + LOG_MSG_DEBUG("Sending %d packets of %d bytes into the USB pipe\n", + nPacketsToSend, sizeof(pIpPacket)); + for (i = 0; i < nPacketsToSend; i++) { + nBytesSentInLastPacket = m_UsbToIpaPipe.Send(pIpPacket, sizeof(pIpPacket)); + if (sizeof(pIpPacket) != nBytesSentInLastPacket) { + LOG_MSG_ERROR("Failed sending the packet %d to m_UsbToIpaPipe", i); + return false; + } + } + + // Receive the raw IP packets (which are a 4 arbitrary bytes) + // that fit into the FIFO before the HOLB started dropping + // and fail to receive the rest + LOG_MSG_DEBUG( + "Reading packets from the USB pipe(%dx%d bytes should be there)\n", + sizeof(pIpPacket), nPacketsToSend); + for (i = 0; i < nPacketsToSend; i++) { + int nBytesReceived = m_IpaToUsbPipe.Receive(pIpPacketReceive, + sizeof(pIpPacketReceive)); + if ((int)sizeof(pIpPacket) != nBytesReceived) { + if (i == 0) { + LOG_MSG_ERROR("First packet failed to receive ! Expected %d Bytes, got %d Bytes", + sizeof(pIpPacket), nBytesReceived); + return false; + } else + // Failed to receive a packet, but not the first one. + // This is the desired result. + return true; + } + } + + LOG_MSG_ERROR("All packets were received successfully, which means the HOLB didn't work."); + return false; + } +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +//Those tests should be run with configuration number 1 which has one input pipe and +//one output pipe. +//Please look at the Fixture for more configurations update. +static PipeTestRawTransfer pipeTestRawTransfer; +static PipeTestAddHeader pipeTestAddHeader; +static PipeTestAddAndRemoveHeader pipeTestAddAndRemoveHeader; +static PipeTestHolb pipeTestHolb; + +//DO NOT UNCOMMENT THOSE LINES UNLESS YOU KNOW WHAT YOU ARE DOING!!! +//those test takes 4ever and should be use for specific usecase! +//static PipeTestDataFifoOverflow pipeTestDataFifoOverflow; +//static PipeTestDescriptorFifoOverflow pipeTestDescriptorFifoOverflow; + +///////////////////////////////////////////////////////////////////////////////// +// EOF //// +///////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/README.txt b/kernel-tests/README.txt new file mode 100644 index 0000000000..db60972f22 --- /dev/null +++ b/kernel-tests/README.txt @@ -0,0 +1,11 @@ +Subsystem: ipa-kernel-tests + +Parameters: + -n: Nominal test case (tests all the different use cases for ip_accelerator) + -a: Adversarial test case (Currently holds no tests) + -r: Repeatability test case (Currently holds no tests) + -s: Stress test case (invokes many simultaneous threads that all try and access the device at once) + --help: Specifies the params for run.sh + +Description: +This test module tests IPA driver, it holds a userspace module and a kernel space module. \ No newline at end of file diff --git a/kernel-tests/RNDISAggregationTestFixture.cpp b/kernel-tests/RNDISAggregationTestFixture.cpp new file mode 100644 index 0000000000..803ec2b14c --- /dev/null +++ b/kernel-tests/RNDISAggregationTestFixture.cpp @@ -0,0 +1,1097 @@ +/* + * Copyright (c) 2017-2018,2020 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 "RNDISAggregationTestFixture.h" +#include "TestManager.h" + +///////////////////////////////////////////////////////////////////////////////// + +//define the static Pipes which will be used by all derived tests. +Pipe RNDISAggregationTestFixture::m_IpaToUsbPipeAgg(IPA_CLIENT_TEST2_CONS, + IPA_TEST_CONFIGURATION_17); +Pipe RNDISAggregationTestFixture::m_UsbToIpaPipe(IPA_CLIENT_TEST_PROD, + IPA_TEST_CONFIGURATION_17); +Pipe RNDISAggregationTestFixture::m_IpaToUsbPipe(IPA_CLIENT_TEST3_CONS, + IPA_TEST_CONFIGURATION_17); +Pipe RNDISAggregationTestFixture::m_UsbToIpaPipeDeagg(IPA_CLIENT_TEST2_PROD, + IPA_TEST_CONFIGURATION_17); +Pipe RNDISAggregationTestFixture::m_IpaToUsbPipeAggTime(IPA_CLIENT_TEST_CONS, + IPA_TEST_CONFIGURATION_17); +Pipe RNDISAggregationTestFixture::m_IpaToUsbPipeAggPktLimit(IPA_CLIENT_TEST4_CONS, + IPA_TEST_CONFIGURATION_17); +Pipe RNDISAggregationTestFixture::m_HsicToIpaPipe(IPA_CLIENT_TEST3_PROD, + IPA_TEST_CONFIGURATION_17); + +RoutingDriverWrapper RNDISAggregationTestFixture::m_Routing; +Filtering RNDISAggregationTestFixture::m_Filtering; +HeaderInsertion RNDISAggregationTestFixture::m_HeaderInsertion; + +///////////////////////////////////////////////////////////////////////////////// + +RNDISAggregationTestFixture::RNDISAggregationTestFixture() +{ + m_testSuiteName.push_back("RndisAgg"); + Register(*this); +} + +///////////////////////////////////////////////////////////////////////////////// + +static int SetupKernelModule(void) +{ + int retval; + struct ipa_channel_config from_ipa_channels[4]; + struct test_ipa_ep_cfg from_ipa_cfg[4]; + struct ipa_channel_config to_ipa_channels[3]; + struct test_ipa_ep_cfg to_ipa_cfg[3]; + struct ipa_test_config_header header = {0}; + struct ipa_channel_config *to_ipa_array[3]; + struct ipa_channel_config *from_ipa_array[4]; + bool en_status = false; + + /* From ipa configurations - 4 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0])); + from_ipa_cfg[0].aggr.aggr_en = IPA_ENABLE_AGGR; + from_ipa_cfg[0].aggr.aggr = IPA_GENERIC; + from_ipa_cfg[0].aggr.aggr_byte_limit = 1; + from_ipa_cfg[0].aggr.aggr_time_limit = 0; + from_ipa_cfg[0].hdr.hdr_ofst_pkt_size_valid = true; + from_ipa_cfg[0].hdr.hdr_ofst_pkt_size = 12; + from_ipa_cfg[0].hdr.hdr_additional_const_len = 14; + from_ipa_cfg[0].hdr.hdr_len = 58; + from_ipa_cfg[0].hdr_ext.hdr_little_endian = true; + from_ipa_cfg[0].hdr_ext.hdr_total_len_or_pad_valid = true; + from_ipa_cfg[0].hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN; + from_ipa_cfg[0].hdr_ext.hdr_total_len_or_pad_offset = 4; + + prepare_channel_struct(&from_ipa_channels[0], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[0], + sizeof(from_ipa_cfg[0]), + en_status); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST3_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1]), + en_status); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + from_ipa_cfg[2].aggr.aggr_en = IPA_ENABLE_AGGR; + from_ipa_cfg[2].aggr.aggr = IPA_GENERIC; + from_ipa_cfg[2].aggr.aggr_byte_limit = 1; + from_ipa_cfg[2].aggr.aggr_time_limit = 30; + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v4_2) + from_ipa_cfg[2].aggr.aggr_time_limit *= 1000; + from_ipa_cfg[2].hdr.hdr_ofst_pkt_size_valid = true; + from_ipa_cfg[2].hdr.hdr_ofst_pkt_size = 12; + from_ipa_cfg[2].hdr.hdr_additional_const_len = 14; + from_ipa_cfg[2].hdr.hdr_len = 58; + from_ipa_cfg[2].hdr_ext.hdr_little_endian = true; + from_ipa_cfg[2].hdr_ext.hdr_total_len_or_pad_valid = true; + from_ipa_cfg[2].hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN; + from_ipa_cfg[2].hdr_ext.hdr_total_len_or_pad_offset = 4; + + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2]), + en_status); + from_ipa_array[2] = &from_ipa_channels[2]; + + memset(&from_ipa_cfg[3], 0, sizeof(from_ipa_cfg[3])); + from_ipa_cfg[3].aggr.aggr_en = IPA_ENABLE_AGGR; + from_ipa_cfg[3].aggr.aggr = IPA_GENERIC; + from_ipa_cfg[3].aggr.aggr_byte_limit = 0; + from_ipa_cfg[3].aggr.aggr_time_limit = 0; + from_ipa_cfg[3].aggr.aggr_pkt_limit = 2; + from_ipa_cfg[3].hdr.hdr_ofst_pkt_size_valid = true; + from_ipa_cfg[3].hdr.hdr_ofst_pkt_size = 12; + from_ipa_cfg[3].hdr.hdr_additional_const_len = 14; + from_ipa_cfg[3].hdr.hdr_len = 58; + from_ipa_cfg[3].hdr_ext.hdr_little_endian = true; + from_ipa_cfg[3].hdr_ext.hdr_total_len_or_pad_valid = true; + from_ipa_cfg[3].hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN; + from_ipa_cfg[3].hdr_ext.hdr_total_len_or_pad_offset = 4; + + prepare_channel_struct(&from_ipa_channels[3], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[3], + sizeof(from_ipa_cfg[3]), + en_status); + from_ipa_array[3] = &from_ipa_channels[3]; + + /* to ipa configurations - 3 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + to_ipa_cfg[0].hdr.hdr_len = 14; + + 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]), + en_status); + to_ipa_array[0] = &to_ipa_channels[0]; + + memset(&to_ipa_cfg[1], 0, sizeof(to_ipa_cfg[1])); + prepare_channel_struct(&to_ipa_channels[1], + header.to_ipa_channels_num++, + IPA_CLIENT_TEST3_PROD, + (void *)&to_ipa_cfg[1], + sizeof(to_ipa_cfg[1]), + en_status); + to_ipa_array[1] = &to_ipa_channels[1]; + + memset(&to_ipa_cfg[2], 0, sizeof(to_ipa_cfg[2])); + to_ipa_cfg[2].aggr.aggr_en = IPA_ENABLE_DEAGGR; + to_ipa_cfg[2].aggr.aggr = IPA_GENERIC; + to_ipa_cfg[2].deaggr.deaggr_hdr_len = 44; + to_ipa_cfg[2].deaggr.packet_offset_valid = true; + to_ipa_cfg[2].deaggr.packet_offset_location = 8; + to_ipa_cfg[2].hdr.hdr_len = 14; /* Ethernet header */ + to_ipa_cfg[2].hdr.hdr_ofst_pkt_size = 12; + to_ipa_cfg[2].hdr.hdr_remove_additional = false; + to_ipa_cfg[2].hdr_ext.hdr_little_endian = 1; + to_ipa_cfg[2].hdr_ext.hdr_total_len_or_pad_valid = 1; + to_ipa_cfg[2].hdr_ext.hdr_total_len_or_pad = IPA_HDR_TOTAL_LEN; + to_ipa_cfg[2].hdr_ext.hdr_payload_len_inc_padding = 0; + to_ipa_cfg[2].hdr_ext.hdr_total_len_or_pad_offset = 4; + + prepare_channel_struct(&to_ipa_channels[2], + header.to_ipa_channels_num++, + IPA_CLIENT_TEST2_PROD, + (void *)&to_ipa_cfg[2], + sizeof(to_ipa_cfg[2]), + en_status); + to_ipa_array[2] = &to_ipa_channels[2]; + + prepare_header_struct(&header, from_ipa_array, to_ipa_array); + + retval = GenericConfigureScenario(&header); + + return retval; +} + +bool RNDISAggregationTestFixture::Setup() +{ + bool bRetVal = true; + + //Set the configuration to support USB->IPA and IPA->USB pipes. + bRetVal = SetupKernelModule(); + if (bRetVal != true) { + return bRetVal; + } + + //Initialize the pipe for all the tests - this will open the inode which represents the pipe. + bRetVal &= m_IpaToUsbPipeAgg.Init(); + bRetVal &= m_UsbToIpaPipe.Init(); + bRetVal &= m_HsicToIpaPipe.Init(); + bRetVal &= m_IpaToUsbPipe.Init(); + bRetVal &= m_UsbToIpaPipeDeagg.Init(); + bRetVal &= m_IpaToUsbPipeAggTime.Init(); + bRetVal &= m_IpaToUsbPipeAggPktLimit.Init(); + + if (!m_Routing.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Routing block is not ready for immediate commands!\n"); + return false; + } + if (!m_Filtering.DeviceNodeIsOpened()) { + LOG_MSG_ERROR( + "Filtering block is not ready for immediate commands!\n"); + return false; + } + if (!m_HeaderInsertion.DeviceNodeIsOpened()) + { + LOG_MSG_ERROR("Header Insertion block is not ready for immediate commands!\n"); + return false; + } + m_HeaderInsertion.Reset();// resetting this component will reset both Routing and Filtering tables. + + return bRetVal; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool RNDISAggregationTestFixture::Teardown() +{ + //The Destroy method will close the inode. + m_IpaToUsbPipeAgg.Destroy(); + m_UsbToIpaPipe.Destroy(); + m_HsicToIpaPipe.Destroy(); + m_IpaToUsbPipe.Destroy(); + m_UsbToIpaPipeDeagg.Destroy(); + m_IpaToUsbPipeAggTime.Destroy(); + m_IpaToUsbPipeAggPktLimit.Destroy(); + + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool RNDISAggregationTestFixture::Run() +{ + LOG_MSG_STACK("Entering Function"); + + // Add the relevant filtering rules + if (!AddRules()) { + LOG_MSG_ERROR("Failed adding filtering rules."); + return false; + } + if (!TestLogic()) { + LOG_MSG_ERROR("Test failed, Input and expected output mismatch."); + return false; + } + + LOG_MSG_STACK("Leaving Function (Returning True)"); + return true; +} // Run() + +///////////////////////////////////////////////////////////////////////////////// +bool RNDISAggregationTestFixture::AddRulesNoAgg() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + uint32_t nTableHdl; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST3_CONS, + 0, &nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.retain_hdr = true; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool RNDISAggregationTestFixture::AddRulesDeAggEther() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + uint32_t nTableHdl; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST3_CONS, + 0, &nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST2_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.retain_hdr = true; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool RNDISAggregationTestFixture::AddRulesAggTimeLimit() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint32_t nTableHdl; + struct RndisEtherHeader rndisEtherHeader; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + memset(&rndisEtherHeader, 0, sizeof(struct RndisEtherHeader)); + rndisEtherHeader.rndisHeader.MessageType = 0x01; + rndisEtherHeader.rndisHeader.DataOffset = 0x24; + memcpy(&rndisEtherHeader.etherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RndisEthernet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&rndisEtherHeader, + sizeof(struct RndisEtherHeader)); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = sizeof(struct RndisEtherHeader); + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST_CONS, + sGetHeader.hdl, &nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST3_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool RNDISAggregationTestFixture::AddRulesAggByteLimit() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint32_t nTableHdl; + struct RndisEtherHeader rndisEtherHeader; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + memset(&rndisEtherHeader, 0, sizeof(struct RndisEtherHeader)); + + rndisEtherHeader.rndisHeader.MessageType = 0x01; + rndisEtherHeader.rndisHeader.DataOffset = 0x24; + memcpy(&rndisEtherHeader.etherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RndisEthernet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&rndisEtherHeader, + sizeof(struct RndisEtherHeader)); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = sizeof(struct RndisEtherHeader); + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST2_CONS, + sGetHeader.hdl, &nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST3_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool RNDISAggregationTestFixture::AddRulesAggByteLimit(bool bAggForceClose) { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + bool bRetVal = true; + IPAFilteringTable_v2 cFilterTable0; + struct ipa_flt_rule_add_v2 sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint32_t nTableHdl; + struct RndisEtherHeader rndisEtherHeader; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + memset(&rndisEtherHeader, 0, sizeof(struct RndisEtherHeader)); + + rndisEtherHeader.rndisHeader.MessageType = 0x01; + rndisEtherHeader.rndisHeader.DataOffset = 0x24; + memcpy(&rndisEtherHeader.etherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RndisEthernet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&rndisEtherHeader, + sizeof(struct RndisEtherHeader)); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = sizeof(struct RndisEtherHeader); + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST2_CONS, + sGetHeader.hdl, &nTableHdl, 0)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST3_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl; //put here the handle corresponding to Routing Rule 1 + printf("%s(), Nadav: sFilterRuleEntry.rule.rt_tbl_hdl = %d \n", __FUNCTION__, nTableHdl); + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = bAggForceClose; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + +bool RNDISAggregationTestFixture::AddRulesAggPacketLimit() { + m_eIP = IPA_IP_v4; + const char aBypass[20] = "Bypass1"; + bool bRetVal = true; + IPAFilteringTable cFilterTable0; + struct ipa_flt_rule_add sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint32_t nTableHdl; + struct RndisEtherHeader rndisEtherHeader; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + memset(&rndisEtherHeader, 0, sizeof(struct RndisEtherHeader)); + + rndisEtherHeader.rndisHeader.MessageType = 0x01; + rndisEtherHeader.rndisHeader.DataOffset = 0x24; + memcpy(&rndisEtherHeader.etherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RndisEthernet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&rndisEtherHeader, + sizeof(struct RndisEtherHeader)); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = sizeof(struct RndisEtherHeader); + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + + if (!CreateBypassRoutingTable(&m_Routing, m_eIP, aBypass, IPA_CLIENT_TEST4_CONS, + sGetHeader.hdl, &nTableHdl)) { + LOG_MSG_ERROR("CreateBypassRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + + LOG_MSG_INFO("Creation of bypass routing table completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST3_PROD, false, 1); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRules() + + + +bool RNDISAggregationTestFixture::AddRulesAggDualFC() { + m_eIP = IPA_IP_v4; + const char aBypass[2][20] = {"BypassTest2", "BypassTest4"}; + bool bRetVal = true; + IPAFilteringTable_v2 cFilterTable0; + struct ipa_flt_rule_add_v2 sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint32_t nTableHdl[2]; + struct RndisEtherHeader rndisEtherHeader; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + memset(&rndisEtherHeader, 0, sizeof(struct RndisEtherHeader)); + + rndisEtherHeader.rndisHeader.MessageType = 0x01; + rndisEtherHeader.rndisHeader.DataOffset = 0x24; + memcpy(&rndisEtherHeader.etherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RndisEthernet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&rndisEtherHeader, + sizeof(struct RndisEtherHeader)); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = sizeof(struct RndisEtherHeader); + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[0], + IPA_CLIENT_TEST2_CONS, + sGetHeader.hdl, &nTableHdl[0], 0)) { + LOG_MSG_ERROR("CreateSplitRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[1], + IPA_CLIENT_TEST4_CONS, + sGetHeader.hdl, &nTableHdl[1], 0)) { + LOG_MSG_ERROR("CreateSplitRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + LOG_MSG_INFO("Creation of bypass routing tables completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST3_PROD, false, 2); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[0]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 1; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[1]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 0; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (1) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl1=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(1)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRulesAggDualFC() + +bool RNDISAggregationTestFixture::AddRulesAggDualFcRoutingBased() { + m_eIP = IPA_IP_v4; + const char aBypass[2][20] = {"BypassTest2", "BypassTest4"}; + bool bRetVal = true; + IPAFilteringTable_v2 cFilterTable0; + struct ipa_flt_rule_add_v2 sFilterRuleEntry; + struct ipa_ioc_get_hdr sGetHeader; + uint32_t nTableHdl[2]; + struct RndisEtherHeader rndisEtherHeader; + + + LOG_MSG_STACK("Entering Function"); + memset(&sFilterRuleEntry, 0, sizeof(sFilterRuleEntry)); + memset(&sGetHeader, 0, sizeof(sGetHeader)); + memset(&rndisEtherHeader, 0, sizeof(struct RndisEtherHeader)); + + rndisEtherHeader.rndisHeader.MessageType = 0x01; + rndisEtherHeader.rndisHeader.DataOffset = 0x24; + memcpy(&rndisEtherHeader.etherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + // Create Header: + // Allocate Memory, populate it, and add in to the Header Insertion. + struct ipa_ioc_add_hdr * pHeaderDescriptor = NULL; + pHeaderDescriptor = (struct ipa_ioc_add_hdr *) calloc(1, + sizeof(struct ipa_ioc_add_hdr) + + 1 * sizeof(struct ipa_hdr_add)); + if (!pHeaderDescriptor) { + LOG_MSG_ERROR("calloc failed to allocate pHeaderDescriptor"); + bRetVal = false; + goto bail; + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + // Adding Header No1. + strlcpy(pHeaderDescriptor->hdr[0].name, "RndisEthernet", sizeof(pHeaderDescriptor->hdr[0].name)); // Header's Name + memcpy(pHeaderDescriptor->hdr[0].hdr, (void*)&rndisEtherHeader, + sizeof(struct RndisEtherHeader)); //Header's Data + pHeaderDescriptor->hdr[0].hdr_len = sizeof(struct RndisEtherHeader); + pHeaderDescriptor->hdr[0].hdr_hdl = -1; //Return Value + pHeaderDescriptor->hdr[0].is_partial = false; + pHeaderDescriptor->hdr[0].status = -1; // Return Parameter + + strlcpy(sGetHeader.name, pHeaderDescriptor->hdr[0].name, sizeof(sGetHeader.name)); + + + if (!m_HeaderInsertion.AddHeader(pHeaderDescriptor)) + { + LOG_MSG_ERROR("m_HeaderInsertion.AddHeader(pHeaderDescriptor) Failed."); + bRetVal = false; + goto bail; + } + + if (!m_HeaderInsertion.GetHeaderHandle(&sGetHeader)) + { + LOG_MSG_ERROR(" Failed"); + bRetVal = false; + goto bail; + } + LOG_MSG_DEBUG("Received Header Handle = 0x%x", sGetHeader.hdl); + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[0], + IPA_CLIENT_TEST2_CONS, + sGetHeader.hdl, &nTableHdl[0], 1)) { + LOG_MSG_ERROR("CreateSplitRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + if (!CreateBypassRoutingTable_v2(&m_Routing, m_eIP, aBypass[1], + IPA_CLIENT_TEST4_CONS, + sGetHeader.hdl, &nTableHdl[1], 0)) { + LOG_MSG_ERROR("CreateSplitRoutingTable Failed\n"); + bRetVal = false; + goto bail; + } + + LOG_MSG_INFO("Creation of bypass routing tables completed successfully"); + + // Creating Filtering Rules + cFilterTable0.Init(m_eIP,IPA_CLIENT_TEST3_PROD, false, 2); + LOG_MSG_INFO("Creation of filtering table completed successfully"); + + // Configuring Filtering Rule No.1 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[0]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000001; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 0; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (0) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl0=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(0)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(0)->status); + } + + // Configuring Filtering Rule No.2 + cFilterTable0.GeneratePresetRule(1,sFilterRuleEntry); + sFilterRuleEntry.at_rear = true; + sFilterRuleEntry.flt_rule_hdl=-1; // return Value + sFilterRuleEntry.status = -1; // return value + sFilterRuleEntry.rule.action=IPA_PASS_TO_ROUTING; + sFilterRuleEntry.rule.rt_tbl_hdl = nTableHdl[1]; //put here the handle corresponding to Routing Rule 1 + sFilterRuleEntry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; // Destination IP Based Filtering + sFilterRuleEntry.rule.attrib.u.v4.dst_addr_mask = 0xFF0000FF; // Mask + sFilterRuleEntry.rule.attrib.u.v4.dst_addr = 0x7F000002; // Filter DST_IP == 127.0.0.1. + sFilterRuleEntry.rule.close_aggr_irq_mod = 0; + if ( + ((uint8_t)-1 == cFilterTable0.AddRuleToTable(sFilterRuleEntry)) || + !m_Filtering.AddFilteringRule(cFilterTable0.GetFilteringTable()) + ) + { + LOG_MSG_ERROR ("Adding Rule (1) to Filtering block Failed."); + bRetVal = false; + goto bail; + } else + { + LOG_MSG_DEBUG("flt rule hdl1=0x%x, status=0x%x\n", cFilterTable0.ReadRuleFromTable(1)->flt_rule_hdl,cFilterTable0.ReadRuleFromTable(1)->status); + } + +bail: + Free(pHeaderDescriptor); + LOG_MSG_STACK( + "Leaving Function (Returning %s)", bRetVal?"True":"False"); + return bRetVal; +} // AddRulesAggDualFcRoutingBased() + diff --git a/kernel-tests/RNDISAggregationTestFixture.h b/kernel-tests/RNDISAggregationTestFixture.h new file mode 100644 index 0000000000..a5e012f121 --- /dev/null +++ b/kernel-tests/RNDISAggregationTestFixture.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017,2020 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 + +#include "Constants.h" +#include "Logger.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "TestBase.h" +#include "Pipe.h" +#include "RoutingDriverWrapper.h" +#include "HeaderInsertion.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" +#define MAX_PACKET_SIZE 1024 + +/*This class will be the base class of RNDIS Aggregation tests. + *Any method other than the test case itself can be + *declared in this Fixture thus allowing the derived classes to + *implement only the test case. + *All the test of the Aggregation uses one input and one output in DMA mode. + */ +class RNDISAggregationTestFixture:public TestBase +{ +public: + /*This Constructor will register each instance that it creates.*/ + RNDISAggregationTestFixture(); + + /*This method will create and initialize two Pipe object for the USB + *(Ethernet) Pipes, one as input and the other as output. + */ + virtual bool Setup(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + virtual bool Run(); + + virtual bool AddRules() = 0; + + virtual bool TestLogic() = 0; + + bool AddRulesNoAgg(); + + bool AddRulesDeAggEther(); + + bool AddRulesAggTimeLimit(); + + bool AddRulesAggByteLimit(); + + bool AddRulesAggByteLimit(bool bAggForceClose); + + bool AddRulesAggPacketLimit(); + + bool AddRulesAggDualFC(); + + bool AddRulesAggDualFcRoutingBased(); + + /*The client type are set from the peripheral perspective*/ + static Pipe m_IpaToUsbPipeAgg; + /*IPA_CLIENT_TEST2_CONS (pipe_num = 7)*/ + static Pipe m_UsbToIpaPipe; + /* IPA_CLIENT_TEST_PROD (pipe_num = 11)*/ + static Pipe m_IpaToUsbPipe; + /* IPA_CLIENT_TEST3_CONS (pipe_num = 9)*/ + static Pipe m_UsbToIpaPipeDeagg; + /* IPA_CLIENT_TEST2_PROD (pipe_num = 6)*/ + static Pipe m_IpaToUsbPipeAggTime; + /* IPA_CLIENT_TEST_CONS (pipe_num = 10)*/ + static Pipe m_IpaToUsbPipeAggPktLimit; + /* IPA_CLIENT_TEST4_CONS (pipe_num = 4)*/ + static Pipe m_HsicToIpaPipe; + /* IPA_CLIENT_TEST3_PROD (pipe_num = 13)*/ + + static RoutingDriverWrapper m_Routing; + static Filtering m_Filtering; + static HeaderInsertion m_HeaderInsertion; + +protected: + enum ipa_ip_type m_eIP; +}; diff --git a/kernel-tests/RNDISAggregationTests.cpp b/kernel-tests/RNDISAggregationTests.cpp new file mode 100644 index 0000000000..7664a8df83 --- /dev/null +++ b/kernel-tests/RNDISAggregationTests.cpp @@ -0,0 +1,1265 @@ +/* + * Copyright (c) 2017,2020 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 "hton.h" /* for htonl*/ +#include "RNDISAggregationTestFixture.h" +#include "Constants.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" + +#define IPV4_DST_ADDR_OFFSET (16) +#define IPV4_DST_ADDR_OFFSET_IN_ETH \ + (16 /* IP */ + 14 /* ethernet */) +#define IPV4_DST_ADDR_OFFSET_IN_RNDIS \ + (IPV4_DST_ADDR_OFFSET_IN_ETH + \ + sizeof(struct RndisHeader)) + +#define NUM_PACKETS (4) + +class RNDISAggregationSanityTest: public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationSanityTest() + { + m_name = "RNDISAggregationSanityTest"; + m_description = "RNDISAggregationSanityTest - Send one packet " + "and expect same packet."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesNoAgg(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + //The packets that will be sent + Byte pPacket[MAX_PACKET_SIZE]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + //int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSize; + + //initialize the packets + // Load input data (Ethernet packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!RNDISAggregationHelper::LoadEtherPacket(m_eIP, pPacket, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed default Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPacket[IPV4_DST_ADDR_OFFSET_IN_ETH],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + + + //send the packet + LOG_MSG_DEBUG("Sending packet into the A2 EMB pipe(%d bytes)\n", + pIpPacketsSize); + size_t nBytesSent = m_UsbToIpaPipe.Send(pPacket, pIpPacketsSize); + if (pIpPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the A2 EMB pipe(%d bytes) " + "failed!\n", pIpPacketsSize); + return false; + } + + //receive the packet + LOG_MSG_DEBUG("Reading packet from the A2 EMB pipe(%d bytes should be there)" + "\n", pIpPacketsSize); + size_t nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (pIpPacketsSize != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + return RNDISAggregationHelper::ComparePackets(pReceivedPacket, nBytesReceived, + pPacket, pIpPacketsSize); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +class RNDISAggregationDeaggregation1PacketTest: public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationDeaggregation1PacketTest() + { + m_name = "RNDISAggregationDeaggregation1PacketTest"; + m_description = "RNDISAggregationDeaggregation1PacketTest - Send 1 RNDIS packet " + "and expect Ethernet packet."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesDeAggEther(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + //The packets that will be sent + Byte pPacket[MAX_PACKET_SIZE]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + //int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSize; + + //initialize the packets + // Load input data (IP packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!RNDISAggregationHelper::LoadRNDISPacket(m_eIP, pPacket, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed to load RNDIS Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPacket[IPV4_DST_ADDR_OFFSET_IN_RNDIS],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + + //send the packet + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pIpPacketsSize); + size_t nBytesSent = m_UsbToIpaPipeDeagg.Send(pPacket, pIpPacketsSize); + if (pIpPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the A2 EMB pipe(%d bytes) " + "failed!\n", pIpPacketsSize); + return false; + } + + //receive the packet + LOG_MSG_DEBUG("Reading packet from the A2 TETH pipe(%d bytes should be there)" + "\n", pIpPacketsSize); + size_t nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (pIpPacketsSize - sizeof(struct RndisHeader) != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + return RNDISAggregationHelper::CompareEthervsRNDISPacket(pReceivedPacket, nBytesReceived, + pPacket, pIpPacketsSize); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +class RNDISAggregation1PacketTest: public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregation1PacketTest() + { + m_name = "RNDISAggregation1PacketTest"; + m_description = "RNDISAggregation1PacketTest - Send 1 IP packet " + "and expect RNDIS packet."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesAggTimeLimit(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + //The packets that will be sent + Byte pPacket[MAX_PACKET_SIZE]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + //int nTotalPacketsSize = MAX_PACKET_SIZE - (4 * NUM_PACKETS) - 24; + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSize; + + //initialize the packets + // Load input data (IP packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPacket, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPacket[IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + + //send the packet + LOG_MSG_DEBUG("Sending packet into the USB pipe(%d bytes)\n", + pIpPacketsSize); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPacket, pIpPacketsSize); + if (pIpPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSize); + return false; + } + + //receive the packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)" + "\n", pIpPacketsSize); + size_t nBytesReceived = m_IpaToUsbPipeAggTime.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (pIpPacketsSize != nBytesReceived - sizeof(struct RndisEtherHeader)) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + return RNDISAggregationHelper::CompareIPvsRNDISPacket(pPacket, pIpPacketsSize, + pReceivedPacket, nBytesReceived); + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +class RNDISAggregationSuspendWaTest: public RNDISAggregationTestFixture { +public: + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationSuspendWaTest() + { + m_name = "RNDISAggregationSuspendWaTest"; + m_description = "RNDISAggregationSuspendWaTest - Send 3 IP packet instead 4, suspend the pipe" + " and expect aggregation to be closed."; + m_minIPAHwType = IPA_HW_v3_0; + + // WA not needed in IPA_3_5 + m_maxIPAHwType = IPA_HW_v3_1; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesAggByteLimit(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool Setup() + { + bool bRetVal = true; + + bRetVal = RNDISAggregationTestFixture::Setup(); + if (bRetVal == false) { + return bRetVal; + } + + /* register test framework suspend handler to from_ipa_devs */ + bRetVal = RegSuspendHandler(false, true, 0); + + return bRetVal; + } + + bool TestLogic() + { + /*The packets that will be sent*/ + + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + /*Buffer for the packet that will be received*/ + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + /* + *Total size of all sent packets + * (this is the max size of the aggregated + *packet minus the size of the header and the NDP) + */ + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + size_t ExpectedPacketSize = (NUM_PACKETS - 1) * sizeof(struct RndisEtherHeader); + + struct ipa_test_ep_ctrl ep_ctrl; + + /* send one packet less than aggregation size in order to see the force close */ + for(int i = 0; i < (NUM_PACKETS - 1); i++) { + /* + *initialize the packets + *Load input data (IP packet) from file + */ + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + for(int j = pIpPacketsSizes[i]; j < MAX_PACKET_SIZE / NUM_PACKETS + 1; j++) { + pPackets[i][j] = j & 0xFF; + } + pIpPacketsSizes[i] = MAX_PACKET_SIZE / NUM_PACKETS + 1; + + /* send the packet */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pIpPacketsSizes[i]); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPackets[i], pIpPacketsSizes[i]); + if (pIpPacketsSizes[i] != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSizes[i]); + return false; + } + ExpectedPacketSize += pIpPacketsSizes[i]; + } + + /* suspend the pipe */ + ep_ctrl.from_dev_num = 0; + ep_ctrl.ipa_ep_delay = false; + ep_ctrl.ipa_ep_suspend = true; + configure_ep_ctrl(&ep_ctrl); + + /* receive the packet */ + LOG_MSG_DEBUG( + "Reading packet from the USB pipe(%d bytes should be there)" + "\n", ExpectedPacketSize); + size_t nBytesReceived = m_IpaToUsbPipeAgg + .Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (ExpectedPacketSize != nBytesReceived) + { + LOG_MSG_ERROR( + "Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + for(int i = 0; i < (NUM_PACKETS - 1); i++) { + if (!RNDISAggregationHelper:: + CompareIPvsRNDISPacket(pPackets[i], pIpPacketsSizes[i], + pReceivedPacket + (i * ExpectedPacketSize / (NUM_PACKETS - 1)), + ExpectedPacketSize / (NUM_PACKETS - 1))) + return false; + } + + return true; + } + + bool Teardown() + { + bool bRetVal = true; + + bRetVal = RNDISAggregationTestFixture::Teardown(); + if (bRetVal == false) { + return bRetVal; + } + + /* unregister the test framework suspend handler */ + bRetVal = RegSuspendHandler(false, false, 0); + + return bRetVal; + } +}; + +class RNDISAggregationByteLimitTest: public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationByteLimitTest() + { + m_name = "RNDISAggregationByteLimitTest"; + m_description = "RNDISAggregationByteLimitTest - Send 2 IP packet " + "and expect aggregated RNDIS packet."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesAggByteLimit(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + /*The packets that will be sent*/ + + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + /*Buffer for the packet that will be received*/ + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + /*Total size of all sent packets + * (this is the max size of the aggregated + *packet minus the size of the header and the NDP) + */ + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + size_t ExpectedPacketSize = NUM_PACKETS * sizeof(struct RndisEtherHeader); + + for(int i = 0; i < NUM_PACKETS; i++) { + /* + *initialize the packets + *Load input data (IP packet) from file + */ + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + for(int j = pIpPacketsSizes[i]; j < MAX_PACKET_SIZE / NUM_PACKETS + 1; j++) { + pPackets[i][j] = j & 0xFF; + } + pIpPacketsSizes[i] = MAX_PACKET_SIZE / NUM_PACKETS + 1; + + /* send the packet */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pIpPacketsSizes[i]); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPackets[i], pIpPacketsSizes[i]); + if (pIpPacketsSizes[i] != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSizes[i]); + return false; + } + ExpectedPacketSize += pIpPacketsSizes[i]; + } + + /* receive the packet */ + LOG_MSG_DEBUG( + "Reading packet from the USB pipe(%d bytes should be there)" + "\n", ExpectedPacketSize); + size_t nBytesReceived = m_IpaToUsbPipeAgg + .Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (ExpectedPacketSize != nBytesReceived) + { + LOG_MSG_ERROR( + "Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + for(int i = 0; i < NUM_PACKETS; i++) { + if (!RNDISAggregationHelper:: + CompareIPvsRNDISPacket(pPackets[i], pIpPacketsSizes[i], + pReceivedPacket + (i * ExpectedPacketSize / NUM_PACKETS), + ExpectedPacketSize / NUM_PACKETS)) + return false; + } + + return true; + } +}; + +class RNDISAggregationByteLimitTestFC : public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationByteLimitTestFC() { + m_name = "RNDISAggregationByteLimitTestFC"; + m_description = "RNDISAggregationByteLimitTestFC - Send 4 IP packet with FC" + "and expect 4 aggregated RNDIS packets."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() { + return AddRulesAggByteLimit(true); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() { + /*The packets that will be sent*/ + + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + /*Buffer for the packets that will be received*/ + Byte pReceivedPacket[NUM_PACKETS][MAX_PACKET_SIZE]; + /*Total size of all sent packets + * (this is the max size of the aggregated + *packet minus the size of the header and the NDP) + */ + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[NUM_PACKETS]; + size_t ExpectedPacketSize = + sizeof(struct RndisEtherHeader) + MAX_PACKET_SIZE / NUM_PACKETS + 1; + + for (int i = 0; i < NUM_PACKETS; i++) { + /* + *initialize the packets + *Load input data (IP packet) from file + */ + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy(&pPackets[i][IPV4_DST_ADDR_OFFSET], &nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + for (int j = pIpPacketsSizes[i]; j < MAX_PACKET_SIZE / NUM_PACKETS + 1; j++) { + pPackets[i][j] = j & 0xFF; + } + pIpPacketsSizes[i] = MAX_PACKET_SIZE / NUM_PACKETS + 1; + + /* send the packet */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pIpPacketsSizes[i]); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPackets[i], pIpPacketsSizes[i]); + if (pIpPacketsSizes[i] != nBytesSent) { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSizes[i]); + return false; + } + } + + /* receive the packet */ + LOG_MSG_DEBUG( + "Reading packets from the USB pipe(%d bytes for each)" + "\n", ExpectedPacketSize); + for (int i = 0; i < NUM_PACKETS; i++) { + size_t nBytesReceived = m_IpaToUsbPipeAgg + .Receive(pReceivedPacket[i], MAX_PACKET_SIZE); + if (ExpectedPacketSize != nBytesReceived) { + LOG_MSG_ERROR( + "Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket[i], nBytesReceived); + return false; + } + print_buff(pReceivedPacket, nBytesReceived); + } + + + for (int i = 0; i < NUM_PACKETS; i++) { + if (!RNDISAggregationHelper::CompareIPvsRNDISPacket( + pPackets[i], + pIpPacketsSizes[i], + pReceivedPacket[i], + ExpectedPacketSize)) return false; + } + + return true; + } +}; + +class RNDISAggregationDualDpTestFC : public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationDualDpTestFC() { + m_name = "RNDISAggregationDualDpTestFC"; + m_description = "RNDISAggregationDualDpTestFC - Send IP packets " + "on two datapathes: one with FC and one without. " + "Expect 2 aggregated RNDIS packets on pipe with FC. " + "Expect one aggregated RNDIS packet on pipe without FC. "; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() { + return AddRulesAggDualFC(); + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() { + int i; + /* The packets that will be sent */ + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + /* Buffer for the packets that will be received */ + Byte pReceivedPacket[(NUM_PACKETS / 2) * MAX_PACKET_SIZE]; + Byte pReceivedPacketFC[NUM_PACKETS / 2][MAX_PACKET_SIZE]; + /* + * Total size of all sent packets + * (this is the max size of the aggregated + * packet minus the size of the header and the NDP) + */ + uint32_t nIPv4DSTAddr; + size_t nBytesReceived; + size_t pIpPacketsSizes[NUM_PACKETS]; + size_t ExpectedPacketSize = + sizeof(struct RndisEtherHeader) + MAX_PACKET_SIZE / NUM_PACKETS + 1; + + for (i = 0; i < NUM_PACKETS; i++) { + /* + * Initialize the packets + * Load input data (IP packet) from file + */ + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + /* + * Half of the packets will go to 127.0.0.1 + * and the other half to 127.0.0.2 + */ + nIPv4DSTAddr = ntohl(0x7F000001 + (i & 0x1)); + memcpy(&pPackets[i][IPV4_DST_ADDR_OFFSET], &nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + for (int j = pIpPacketsSizes[i]; j < MAX_PACKET_SIZE / NUM_PACKETS + 1; j++) { + pPackets[i][j] = j & 0xFF; + } + pIpPacketsSizes[i] = MAX_PACKET_SIZE / NUM_PACKETS + 1; + + /* send the packet */ + LOG_MSG_DEBUG("Sending packet into the m_HsicToIpaPipe pipe (%d bytes)\n", + pIpPacketsSizes[i]); + print_buff(pPackets[i], pIpPacketsSizes[i]); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPackets[i], pIpPacketsSizes[i]); + if (pIpPacketsSizes[i] != nBytesSent) { + LOG_MSG_ERROR("Sending packet into the m_HsicToIpaPipe pipe (%d bytes) " + "failed!\n", pIpPacketsSizes[i]); + return false; + } + } + + /* receive the packets from FC pipe */ + LOG_MSG_DEBUG( + "Reading packets from the m_IpaToUsbPipeAgg pipe (%d bytes for each)" + "\n", ExpectedPacketSize); + for (i = 0; i < NUM_PACKETS / 2; i++) { + nBytesReceived = m_IpaToUsbPipeAgg + .Receive(pReceivedPacketFC[i], MAX_PACKET_SIZE); + if (ExpectedPacketSize != nBytesReceived) { + LOG_MSG_ERROR( + "Receiving aggregated packet from the m_IpaToUsbPipeAgg pipe (%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacketFC[i], nBytesReceived); + return false; + } + } + + for (i = 0; i < NUM_PACKETS / 2; i++) { + if (!RNDISAggregationHelper::CompareIPvsRNDISPacket( + pPackets[i * 2], + pIpPacketsSizes[i * 2], + pReceivedPacketFC[i], + ExpectedPacketSize)) return false; + } + + /* receive the packet from non-FC pipe */ + LOG_MSG_DEBUG( + "Reading packet from the m_IpaToUsbPipeAggPktLimit pipe (%d bytes)" + "\n", ExpectedPacketSize * 2); + nBytesReceived = m_IpaToUsbPipeAggPktLimit + .Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (ExpectedPacketSize * 2 != nBytesReceived) { + LOG_MSG_ERROR( + "Receiving aggregated packets from the m_IpaToUsbPipeAggPktLimit pipe (%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + for (int i = 0; i < NUM_PACKETS; i += 2) { + if (!RNDISAggregationHelper::CompareIPvsRNDISPacket( + pPackets[i + 1], // Odd packets are in the second pipe + pIpPacketsSizes[i + 1], + pReceivedPacket + (i * ExpectedPacketSize / 2), + ExpectedPacketSize)) + return false; + } + + return true; + } +}; + +class RNDISAggregationDualDpTestFcRoutingBased : public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationDualDpTestFcRoutingBased() { + m_name = "RNDISAggregationDualDpTestFcRoutingBased"; + m_description = "RNDISAggregationDualDpTestFcRoutingBased - Send IP packets " + "on two datapathes: one with RT based FC and one without. " + "Expect 2 aggregated RNDIS packets on pipe with RT based FC. " + "Expect one aggregated RNDIS packet on pipe without RT based FC. "; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() { + return AddRulesAggDualFcRoutingBased(); + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() { + int i; + /* The packets that will be sent */ + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + /* Buffer for the packets that will be received */ + Byte pReceivedPacket[(NUM_PACKETS / 2) * MAX_PACKET_SIZE]; + Byte pReceivedPacketFC[NUM_PACKETS / 2][MAX_PACKET_SIZE]; + /* + * Total size of all sent packets + * (this is the max size of the aggregated + * packet minus the size of the header and the NDP) + */ + uint32_t nIPv4DSTAddr; + size_t nBytesReceived; + size_t pIpPacketsSizes[NUM_PACKETS]; + size_t ExpectedPacketSize = + sizeof(struct RndisEtherHeader) + MAX_PACKET_SIZE / NUM_PACKETS + 1; + + for (i = 0; i < NUM_PACKETS; i++) { + /* + * Initialize the packets + * Load input data (IP packet) from file + */ + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + /* + * Half of the packets will go to 127.0.0.1 + * and the other half to 127.0.0.2 + */ + nIPv4DSTAddr = ntohl(0x7F000001 + (i & 0x1)); + memcpy(&pPackets[i][IPV4_DST_ADDR_OFFSET], &nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + for (int j = pIpPacketsSizes[i]; j < MAX_PACKET_SIZE / NUM_PACKETS + 1; j++) { + pPackets[i][j] = j & 0xFF; + } + pIpPacketsSizes[i] = MAX_PACKET_SIZE / NUM_PACKETS + 1; + + /* send the packet */ + LOG_MSG_DEBUG("Sending packet into the m_HsicToIpaPipe pipe (%d bytes)\n", + pIpPacketsSizes[i]); + print_buff(pPackets[i], pIpPacketsSizes[i]); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPackets[i], pIpPacketsSizes[i]); + if (pIpPacketsSizes[i] != nBytesSent) { + LOG_MSG_ERROR("Sending packet into the m_HsicToIpaPipe pipe (%d bytes) " + "failed!\n", pIpPacketsSizes[i]); + return false; + } + } + + /* receive the packets from FC pipe */ + LOG_MSG_DEBUG( + "Reading packets from the m_IpaToUsbPipeAgg pipe (%d bytes for each)" + "\n", ExpectedPacketSize); + for (i = 0; i < NUM_PACKETS / 2; i++) { + nBytesReceived = m_IpaToUsbPipeAgg + .Receive(pReceivedPacketFC[i], MAX_PACKET_SIZE); + if (ExpectedPacketSize != nBytesReceived) { + LOG_MSG_ERROR( + "Receiving aggregated packet from the m_IpaToUsbPipeAgg pipe (%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacketFC[i], nBytesReceived); + return false; + } + } + + for (i = 0; i < NUM_PACKETS / 2; i++) { + if (!RNDISAggregationHelper::CompareIPvsRNDISPacket( + pPackets[i * 2], + pIpPacketsSizes[i * 2], + pReceivedPacketFC[i], + ExpectedPacketSize)) return false; + } + + /* receive the packet from non-FC pipe */ + LOG_MSG_DEBUG( + "Reading packet from the m_IpaToUsbPipeAggPktLimit pipe (%d bytes)" + "\n", ExpectedPacketSize * 2); + nBytesReceived = m_IpaToUsbPipeAggPktLimit + .Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (ExpectedPacketSize * 2 != nBytesReceived) { + LOG_MSG_ERROR( + "Receiving aggregated packets from the m_IpaToUsbPipeAggPktLimit pipe (%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + for (int i = 0; i < NUM_PACKETS; i += 2) { + if (!RNDISAggregationHelper::CompareIPvsRNDISPacket( + pPackets[i + 1], // Odd packets are in the second pipe + pIpPacketsSizes[i + 1], + pReceivedPacket + (i * ExpectedPacketSize / 2), + ExpectedPacketSize)) + return false; + } + + return true; + } +}; + +class RNDISAggregationDeaggregationNumPacketsTest: + public RNDISAggregationTestFixture { +public: + + RNDISAggregationDeaggregationNumPacketsTest() + { + m_name = "RNDISAggregationDeaggregationNumPacketsTest"; + m_description = "RNDISAggregationByteLimitTest - Send on IP packet " + "and expect aggregated RNDIS packet."; + } + + virtual bool AddRules() + { + return AddRulesDeAggEther(); + } /* AddRules()*/ + + bool TestLogic() + { + /*the packets that will be sent*/ + Byte pPacket[MAX_PACKET_SIZE]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSize; + size_t pAggrPacketsSize = 0; + + for(int i = 0; i < NUM_PACKETS; i++) { + //initialize the packets + // Load input data (RNDIS packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!RNDISAggregationHelper::LoadRNDISPacket(m_eIP, pPacket + pAggrPacketsSize, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + pAggrPacketsSize += pIpPacketsSize; + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&((pPacket + i * pIpPacketsSize)[IPV4_DST_ADDR_OFFSET_IN_RNDIS]),&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + } + print_buff(pPacket, pAggrPacketsSize); + + /*send the packet*/ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pIpPacketsSize * NUM_PACKETS); + size_t nBytesSent = m_UsbToIpaPipeDeagg.Send(pPacket, pAggrPacketsSize); + if (pAggrPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSize * NUM_PACKETS); + return false; + } + for(int i = 0; i < NUM_PACKETS; i++) { + //receive the packet, one by one + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)" + "\n", pIpPacketsSize - sizeof(struct RndisHeader)); + size_t nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (pIpPacketsSize - sizeof(struct RndisHeader) != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + if (!RNDISAggregationHelper::CompareEthervsRNDISPacket(pReceivedPacket, + nBytesReceived, + pPacket + i * pIpPacketsSize, + pIpPacketsSize)) + return false; + } + + return true; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +class RNDISAggregationDeaggregationExceptionPacketsTest: + public RNDISAggregationTestFixture { +public: + + RNDISAggregationDeaggregationExceptionPacketsTest() + { + m_name = "RNDISAggregationDeaggregationExceptionPacketsTest"; + m_description = "RNDISAggregationDeaggregationExceptionPacketsTest - Send 5 frames " + "of size 43 bytes, 1025 bytes, 43 bytes, 981 bytes, and 1024 bytes " + "and expect aggregated RNDIS packet."; + } + + virtual bool AddRules() + { + return AddRulesDeAggEther(); + } /* AddRules()*/ + + bool TestLogic() + { + /*the packets that will be sent*/ + Byte pPacket[MAX_PACKET_SIZE]; + Byte pPacket1[MAX_PACKET_SIZE +1]; + Byte pPacket2[MAX_PACKET_SIZE]; + Byte pPacket3[MAX_PACKET_SIZE]; + + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSize; + size_t pAggrPacketsSize = 0; + size_t nBytesSent; + size_t nBytesReceived; + + /* Create the frame of size 43 bytes which is one less byte than RNDIS header */ + pAggrPacketsSize = sizeof(struct RndisHeader) - 1; + struct RndisHeader *pRndisHeader = (struct RndisHeader*)pPacket; + memset(pRndisHeader, 0, (sizeof(struct RndisHeader) - 1)); + pRndisHeader->MessageType = 0x01; + pRndisHeader->MessageLength = pAggrPacketsSize; + pRndisHeader->DataOffset = 0x24; + pRndisHeader->DataLength = 0; + + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&((pPacket)[IPV4_DST_ADDR_OFFSET_IN_RNDIS]),&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + print_buff(pPacket, pAggrPacketsSize); + + /* Send the first frame */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pAggrPacketsSize); + nBytesSent = m_UsbToIpaPipeDeagg.Send(pPacket, pAggrPacketsSize); + if (pAggrPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pAggrPacketsSize); + return false; + } + /* This is deaggregation exception packet, this packet should not arrive at this pipe */ + LOG_MSG_DEBUG("Reading packet from the USB pipe(0 bytes should be there)\n"); + nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (0 != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + /* Create a frame of size 1025 bytes */ + pAggrPacketsSize = 0; + for(int i = 0; i < 8; i++) { + //initialize the packets + // Load input data (RNDIS packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!RNDISAggregationHelper::LoadRNDISPacket(m_eIP, pPacket1 + pAggrPacketsSize, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + pAggrPacketsSize += pIpPacketsSize; + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&((pPacket1 + i * pIpPacketsSize)[IPV4_DST_ADDR_OFFSET_IN_RNDIS]),&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + } + + pPacket1[pAggrPacketsSize] = 0xdd; + pAggrPacketsSize = pAggrPacketsSize + 1; + + print_buff(pPacket1, pAggrPacketsSize); + + /* Send the 2nd frame */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pAggrPacketsSize); + nBytesSent = m_UsbToIpaPipeDeagg.Send(pPacket1, pAggrPacketsSize); + if (pAggrPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pAggrPacketsSize); + return false; + } + + for(int i = 0; i < 8; i++) { + //Receive the packet, one by one + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)" + "\n", pIpPacketsSize - sizeof(struct RndisHeader)); + size_t nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (pIpPacketsSize - sizeof(struct RndisHeader) != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + if (!RNDISAggregationHelper::CompareEthervsRNDISPacket(pReceivedPacket, + nBytesReceived, + pPacket1 + i * pIpPacketsSize, + pIpPacketsSize)) + return false; + } + + /* Create a frame of size 1024 bytes and send as 2 frames */ + pAggrPacketsSize = 0; + for(int i = 0; i < 8; i++) { + //initialize the packets + // Load input data (RNDIS packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!RNDISAggregationHelper::LoadRNDISPacket(m_eIP, pPacket2 + pAggrPacketsSize, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + pAggrPacketsSize += pIpPacketsSize; + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&((pPacket2 + i * pIpPacketsSize)[IPV4_DST_ADDR_OFFSET_IN_RNDIS]),&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + } + print_buff(pPacket2, pAggrPacketsSize); + + /* Send the 3rd frame */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", 43); + nBytesSent = m_UsbToIpaPipeDeagg.Send(pPacket2, 43); + if (43 != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", 43); + + return false; + } + /* This is deaggregation exception packet, this packet should not arrive at this pipe */ + LOG_MSG_DEBUG("Reading packet from the USB pipe(0 bytes should be there)\n"); + nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (0 != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + /* Send the 4rd frame */ + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pAggrPacketsSize - 43 ); + nBytesSent = m_UsbToIpaPipeDeagg.Send((pPacket2 + 43), pAggrPacketsSize - 43); + if ((pAggrPacketsSize - 43) != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pAggrPacketsSize - 43); + return false; + } + /* This is deaggregation exception packet, this packet should not arrive at this pipe */ + LOG_MSG_DEBUG("Reading packet from the USB pipe(0 bytes should be there)\n"); + nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (0 != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + /* Create a frame of size 1024 bytes */ + pAggrPacketsSize = 0; + for(int i = 0; i < 8; i++) { + //initialize the packets + //Load input data (RNDIS packet) from file + pIpPacketsSize = MAX_PACKET_SIZE; + if (!RNDISAggregationHelper::LoadRNDISPacket(m_eIP, pPacket3 + pAggrPacketsSize, pIpPacketsSize)) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + pAggrPacketsSize += pIpPacketsSize; + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&((pPacket3 + i * pIpPacketsSize)[IPV4_DST_ADDR_OFFSET_IN_RNDIS]),&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + } + print_buff(pPacket3, pAggrPacketsSize); + + /* Send the 5th frame */ + LOG_MSG_ERROR("blend-3 Sending packet into the A2 TETH pipe(%d bytes)\n", + pAggrPacketsSize); + nBytesSent = m_UsbToIpaPipeDeagg.Send(pPacket3, pAggrPacketsSize); + if (pAggrPacketsSize != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pAggrPacketsSize); + return false; + } + + for(int i = 0; i < 8; i++) { + //Receive the packet, one by one + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)" + "\n", pIpPacketsSize - sizeof(struct RndisHeader)); + size_t nBytesReceived = m_IpaToUsbPipe.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (pIpPacketsSize - sizeof(struct RndisHeader) != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + if (!RNDISAggregationHelper::CompareEthervsRNDISPacket(pReceivedPacket, + nBytesReceived, + pPacket3 + i * pIpPacketsSize, + pIpPacketsSize)) + return false; + } + + return true; + } + +}; + +class RNDISAggregationPacketLimitTest: public RNDISAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + RNDISAggregationPacketLimitTest() + { + m_name = "RNDISAggregationPacketLimitTest"; + m_description = "RNDISAggregationPacketLimitTest - Send 2 IP packet " + "and expect aggregated RNDIS packet."; + } + + ///////////////////////////////////////////////////////////////////////////////// + + virtual bool AddRules() + { + return AddRulesAggPacketLimit(); + } // AddRules() + + ///////////////////////////////////////////////////////////////////////////////// + + bool TestLogic() + { + //The packets that will be sent + + Byte pPackets[2][MAX_PACKET_SIZE]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated + //packet minus the size of the header and the NDP) + uint32_t nIPv4DSTAddr; + size_t pIpPacketsSizes[2]; + size_t ExpectedPacketSize = 2 * sizeof(struct RndisEtherHeader); + + for(int i = 0; i < 2; i++) { + //initialize the packets + // Load input data (IP packet) from file + pIpPacketsSizes[i] = MAX_PACKET_SIZE; + if (!LoadDefaultPacket(m_eIP, pPackets[i], pIpPacketsSizes[i])) + { + LOG_MSG_ERROR("Failed to load Ethernet Packet"); + return false; + } + nIPv4DSTAddr = ntohl(0x7F000001); + memcpy (&pPackets[i][IPV4_DST_ADDR_OFFSET],&nIPv4DSTAddr, + sizeof(nIPv4DSTAddr)); + + //send the packet + LOG_MSG_DEBUG("Sending packet into the A2 TETH pipe(%d bytes)\n", + pIpPacketsSizes[i]); + size_t nBytesSent = m_HsicToIpaPipe.Send(pPackets[i], pIpPacketsSizes[i]); + if (pIpPacketsSizes[i] != nBytesSent) + { + LOG_MSG_ERROR("Sending packet into the USB pipe(%d bytes) " + "failed!\n", pIpPacketsSizes[i]); + return false; + } + ExpectedPacketSize += pIpPacketsSizes[i]; + } + + //receive the packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be there)" + "\n", ExpectedPacketSize); + size_t nBytesReceived = m_IpaToUsbPipeAggPktLimit.Receive(pReceivedPacket, MAX_PACKET_SIZE); + if (ExpectedPacketSize != nBytesReceived) + { + LOG_MSG_ERROR("Receiving aggregated packet from the USB pipe(%d bytes) " + "failed!\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + for(int i = 0; i < 2; i++) { + if (!RNDISAggregationHelper::CompareIPvsRNDISPacket(pPackets[i], pIpPacketsSizes[i], + pReceivedPacket + (i * ExpectedPacketSize / 2), ExpectedPacketSize / 2)) + return false; + } + + return true; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + + + +static RNDISAggregationSanityTest aRNDISAggregationSanityTest; +static RNDISAggregationDeaggregation1PacketTest aRNDISAggregationDeaggregation1PacketTest; +static RNDISAggregation1PacketTest aRNDISAggregation1PacketTest; +static RNDISAggregationSuspendWaTest aRNDISAggregationSuspendWaTest; +static RNDISAggregationByteLimitTest aRNDISAggregationByteLimitTest; +static RNDISAggregationByteLimitTestFC aRNDISAggregationByteLimitTestFC; +static RNDISAggregationDualDpTestFC aRNDISAggregationDualDpTestFC; +static RNDISAggregationDualDpTestFcRoutingBased aRNDISAggregationDualDpTestFcRoutingBased; +static RNDISAggregationDeaggregationNumPacketsTest aRNDISAggregationDeaggregationNumPacketsTest; +static RNDISAggregationDeaggregationExceptionPacketsTest aRNDISAggregationDeaggregationExceptionPacketsTest; +static RNDISAggregationPacketLimitTest aRNDISAggregationPacketLimitTest; + +///////////////////////////////////////////////////////////////////////////////// +// EOF //// +///////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/RoutingDriverWrapper.cpp b/kernel-tests/RoutingDriverWrapper.cpp new file mode 100644 index 0000000000..25f5e1e1bd --- /dev/null +++ b/kernel-tests/RoutingDriverWrapper.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017,2020 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 "RoutingDriverWrapper.h" +#include "TestsUtils.h" + +const char* RoutingDriverWrapper::DEVICE_NAME = "/dev/ipa"; + +RoutingDriverWrapper::RoutingDriverWrapper() +{ + m_fd = open(DEVICE_NAME, O_RDWR); + if (0 == m_fd) { + printf("Failed opening %s.\n", DEVICE_NAME); + } +} + +RoutingDriverWrapper::~RoutingDriverWrapper() +{ + close(m_fd); +} + +bool RoutingDriverWrapper::DeviceNodeIsOpened() +{ + int res = fcntl(m_fd, F_GETFL); + + if (m_fd > 0 && res >=0) + return true; + else + return false; + +} + +bool RoutingDriverWrapper::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE, ruleTable); + if (retval) { + printf("%s(), failed adding routing rule table %p\n", __FUNCTION__, ruleTable); + return false; + } + + printf("%s(), Added routing rule table %p\n", __FUNCTION__, ruleTable); + return true; +} + +bool RoutingDriverWrapper::AddRoutingRule(struct ipa_ioc_add_rt_rule_v2 *ruleTable_v2) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE_V2, ruleTable_v2); + if (retval) { + printf("%s(), failed adding routing rule table %p\n", __FUNCTION__, ruleTable_v2); + return false; + } + + printf("%s(), Added routing rule table %p\n", __FUNCTION__, ruleTable_v2); + return true; +} + +bool RoutingDriverWrapper::DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_DEL_RT_RULE, ruleTable); + if (retval) { + printf("%s(), failed deleting routing rule table %p\n", __FUNCTION__, ruleTable); + return false; + } + + printf("%s(), Deleted routing rule table %p\n", __FUNCTION__, ruleTable); + return true; +} + +bool RoutingDriverWrapper::Commit(enum ipa_ip_type ip) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); + if (retval) { + printf("%s(), failed commiting routing rules.\n", __FUNCTION__); + return false; + } + + printf("%s(), Commited routing rules to IPA HW.\n", __FUNCTION__); + return true; +} + +bool RoutingDriverWrapper::Reset(enum ipa_ip_type ip) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_RESET_RT, ip); + retval |= ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); + if (retval) { + printf("%s(), failed reseting routing block.\n", __FUNCTION__); + return false; + } + + printf("%s(), Reset command issued to IPA routing block.\n", __FUNCTION__); + return true; +} + +bool RoutingDriverWrapper::GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_GET_RT_TBL, routingTable); + if (retval) { + printf("%s(), IPA_IOCTL_GET_RT_TBL ioctl failed, routingTable =0x%p, retval=0x%x.\n", __FUNCTION__, routingTable, retval); + return false; + } + + printf("%s(), IPA_IOCTL_GET_RT_TBL ioctl issued to IPA routing block.\n", __FUNCTION__); + return true; +} + +bool RoutingDriverWrapper::PutRoutingTable(uint32_t routingTableHandle) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) + return false; + + retval = ioctl(m_fd, IPA_IOC_PUT_RT_TBL, routingTableHandle); + if (retval) { + printf("%s(), IPA_IOCTL_PUT_RT_TBL ioctl failed.\n", __FUNCTION__); + return false; + } + + printf("%s(), IPA_IOCTL_PUT_RT_TBL ioctl issued to IPA routing block.\n", __FUNCTION__); + return true; +} + diff --git a/kernel-tests/RoutingDriverWrapper.h b/kernel-tests/RoutingDriverWrapper.h new file mode 100644 index 0000000000..e02aad76f7 --- /dev/null +++ b/kernel-tests/RoutingDriverWrapper.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017,2020 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 ROUTING_H_ +#define ROUTING_H_ + +#include +#include "linux/msm_ipa.h" + +using namespace std; + +class RoutingDriverWrapper +{ +public: + RoutingDriverWrapper(); + ~RoutingDriverWrapper(); + + bool AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable); + bool AddRoutingRule(ipa_ioc_add_rt_rule_v2 *ruleTable_v2); + bool DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable); + + bool Commit(enum ipa_ip_type ip); + bool Reset(enum ipa_ip_type ip); + + bool GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable); + bool PutRoutingTable(uint32_t routingTableHandle); + + bool DeviceNodeIsOpened(); + +private: + static const char *DEVICE_NAME; + /* File descriptor of the IPA device node /dev/ipa*/ + int m_fd; +}; + +#endif + diff --git a/kernel-tests/RoutingTests.cpp b/kernel-tests/RoutingTests.cpp new file mode 100644 index 0000000000..e7ea2f0e50 --- /dev/null +++ b/kernel-tests/RoutingTests.cpp @@ -0,0 +1,5133 @@ +/* + * Copyright (c) 2017-2018,2020 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 "hton.h" // for htonl + + +#include "InterfaceAbstraction.h" +#include "Constants.h" +#include "Logger.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" +#include "RoutingDriverWrapper.h" +#include "Filtering.h" +#include "IPAFilteringTable.h" + +#define TOS_FIELD_OFFSET (1) +#define DST_ADDR_LSB_OFFSET_IPV4 (19) +#define SRC_ADDR_LSB_OFFSET_IPV4 (15) +#define DST_ADDR_MSB_OFFSET_IPV6 (24) +#define DST_ADDR_LSB_OFFSET_IPV6 (39) +#define TRAFFIC_CLASS_MSB_OFFSET_IPV6 (0) +#define TRAFFIC_CLASS_LSB_OFFSET_IPV6 (1) +#define FLOW_CLASS_MSB_OFFSET_IPV6 (1) +#define FLOW_CLASS_MB_OFFSET_IPV6 (2) +#define FLOW_CLASS_LSB_OFFSET_IPV6 (3) +#define IPV4_DST_PORT_OFFSET (20+2) +#define IPV6_SRC_PORT_OFFSET (40) +#define IPV6_DST_PORT_OFFSET (40+2) +#define IPv4_TCP_FLAGS_OFFSET (20+13) +#define IPv6_TCP_FLAGS_OFFSET (40+13) + +#define TCP_ACK_FLAG_MASK (0x10) + +extern Logger g_Logger; + +class IpaRoutingBlockTestFixture:public TestBase +{ +public: + IpaRoutingBlockTestFixture(): + m_sendSize (BUFF_MAX_SIZE), + m_sendSize2 (BUFF_MAX_SIZE), + m_sendSize3 (BUFF_MAX_SIZE), + m_IpaIPType(IPA_IP_v4) + { + memset(m_sendBuffer, 0, sizeof(m_sendBuffer)); + memset(m_sendBuffer2, 0, sizeof(m_sendBuffer2)); + memset(m_sendBuffer3, 0, sizeof(m_sendBuffer3)); + m_testSuiteName.push_back("Routing"); + } + + static int SetupKernelModule(bool en_status = false) + { + int retval; + struct ipa_channel_config from_ipa_channels[3]; + struct test_ipa_ep_cfg from_ipa_cfg[3]; + 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[3]; + + /* From ipa configurations - 3 pipes */ + memset(&from_ipa_cfg[0], 0, sizeof(from_ipa_cfg[0])); + prepare_channel_struct(&from_ipa_channels[0], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST2_CONS, + (void *)&from_ipa_cfg[0], + sizeof(from_ipa_cfg[0]), en_status); + from_ipa_array[0] = &from_ipa_channels[0]; + + memset(&from_ipa_cfg[1], 0, sizeof(from_ipa_cfg[1])); + prepare_channel_struct(&from_ipa_channels[1], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST3_CONS, + (void *)&from_ipa_cfg[1], + sizeof(from_ipa_cfg[1]), en_status); + from_ipa_array[1] = &from_ipa_channels[1]; + + memset(&from_ipa_cfg[2], 0, sizeof(from_ipa_cfg[2])); + prepare_channel_struct(&from_ipa_channels[2], + header.from_ipa_channels_num++, + IPA_CLIENT_TEST4_CONS, + (void *)&from_ipa_cfg[2], + sizeof(from_ipa_cfg[2]), en_status); + from_ipa_array[2] = &from_ipa_channels[2]; + + /* To ipa configurations - 1 pipes */ + memset(&to_ipa_cfg[0], 0, sizeof(to_ipa_cfg[0])); + 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); + + retval = GenericConfigureScenario(&header); + + return retval; + } + + bool Setup(bool en_status) + { + bool bRetVal = true; + + bRetVal = SetupKernelModule(en_status); + if (bRetVal != true) { + return bRetVal; + } + 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); + m_consumer2.Open(INTERFACE2_TO_IPA_DATA_PATH, INTERFACE2_FROM_IPA_DATA_PATH); + m_defaultConsumer.Open(INTERFACE3_TO_IPA_DATA_PATH, INTERFACE3_FROM_IPA_DATA_PATH); + + if (!m_routing.DeviceNodeIsOpened()) { + printf("Routing block is not ready for immediate commands!\n"); + return false; + } + + if (!m_filtering.DeviceNodeIsOpened()) { + printf("Filtering block is not ready for immediate commands!\n"); + return false; + } + m_routing.Reset(IPA_IP_v4); + m_routing.Reset(IPA_IP_v6); + + return true; + } /* Setup()*/ + + bool Setup() + { + return Setup(false); + } + + bool Teardown() + { + if (!m_routing.DeviceNodeIsOpened()) { + printf("Routing block is not ready for immediate commands!\n"); + return false; + } + if (!m_filtering.DeviceNodeIsOpened()) { + printf("Filtering block is not ready for immediate commands!\n"); + return false; + } + + m_producer.Close(); + m_consumer.Close(); + m_consumer2.Close(); + m_defaultConsumer.Close(); + + return true; + } /* Teardown() */ + + bool LoadFiles(enum ipa_ip_type ip) + { + string fileName; + + if (IPA_IP_v4 == ip) { + fileName = "Input/IPv4_1"; + } else { + fileName = "Input/IPv6"; + } + + if (!LoadDefaultPacket(ip, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + if (!LoadDefaultPacket(ip, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + if (!LoadDefaultPacket(ip, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + return true; + } + + bool ReceivePacketAndCompareFrom(InterfaceAbstraction& cons, Byte* send, + size_t send_sz, bool shouldBeHit) + { + size_t receivedSize = 0; + bool isSuccess = true; + + /* Receive results*/ + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = cons.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, cons.m_fromChannelName.c_str()); + + // Compare results + isSuccess &= CompareResultVsGolden_w_Status(send, send_sz, rxBuff1, receivedSize); + + if (shouldBeHit) { + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(send_sz, receivedSize, rxBuff1) : IsCacheHit(send_sz, receivedSize, rxBuff1); + } + else + { + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(send_sz, receivedSize, rxBuff1) : IsCacheMiss(send_sz, receivedSize, rxBuff1); + } + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; +// char * p = recievedBuffer; + size_t j; + for(j = 0; j < m_sendSize; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", send[j]); + for(j = 0; j < receivedSize; j++) +// recievedBuffer += sprintf(recievedBuffer, "%02X", rxBuff1[i]); + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff1[j]); + printf("Expected Value (%zu)\n%s\n, Received Value1(%zu)\n%s\n",send_sz,sentBuffer,receivedSize,recievedBuffer); + + delete[] rxBuff1; + delete[] recievedBuffer; + delete[] sentBuffer; + + return isSuccess; + } + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool pkt1_cmp_succ, pkt2_cmp_succ, pkt3_cmp_succ; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + memset(rxBuff1, 0, 0x400); + memset(rxBuff2, 0, 0x400); + memset(rxBuff3, 0, 0x400); + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + pkt1_cmp_succ = CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + pkt2_cmp_succ = CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + pkt3_cmp_succ = CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + size_t recievedBufferSize = + MAX3(receivedSize, receivedSize2, receivedSize3) * 3; + size_t sentBufferSize = + MAX3(m_sendSize, m_sendSize2, m_sendSize3) * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + if (NULL == recievedBuffer || NULL == sentBuffer) { + printf("Memory allocation error\n"); + return false; + } + + size_t j; + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + for(j = 0; j < m_sendSize; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", m_sendBuffer[j]); + for(j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff1[j]); + printf("Expected Value1(%zu)\n%s\n, Received Value1(%zu)\n%s\n-->Value1 %s\n", + m_sendSize,sentBuffer,receivedSize,recievedBuffer, + pkt1_cmp_succ?"Match":"no Match"); + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + for(j = 0; j < m_sendSize2; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", m_sendBuffer2[j]); + for(j = 0; j < receivedSize2; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff2[j]); + printf("Expected Value2 (%zu)\n%s\n, Received Value2(%zu)\n%s\n-->Value2 %s\n", + m_sendSize2,sentBuffer,receivedSize2,recievedBuffer, + pkt2_cmp_succ?"Match":"no Match"); + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + for(j = 0; j < m_sendSize3; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - (3 * j + 1), " %02X", m_sendBuffer3[j]); + for(j = 0; j < receivedSize3; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - (3 * j + 1), " %02X", rxBuff3[j]); + printf("Expected Value3 (%zu)\n%s\n, Received Value3(%zu)\n%s\n-->Value3 %s\n", + m_sendSize3,sentBuffer,receivedSize3,recievedBuffer, + pkt3_cmp_succ?"Match":"no Match"); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return pkt1_cmp_succ && pkt2_cmp_succ && pkt3_cmp_succ; + } + + void print_packets(size_t receivedSize, size_t m_sendSize, size_t recievedBufferSize, size_t sentBufferSize, Byte *rxBuff, Byte *m_sendBuffer, char *recievedBuffer, char *sentBuffer) + { + size_t j; + + for(j = 0; j < m_sendSize; j++) { + snprintf(&sentBuffer[3 * j], sentBufferSize - 3 * j, + " %02X", m_sendBuffer[j]); + } + for(j = 0; j < receivedSize; j++) { + snprintf(&recievedBuffer[3 * j], recievedBufferSize- 3 * j, + " %02X", rxBuff[j]); + } + printf("Expected Value (%zu)\n%s\n, Received Value(%zu)\n%s\n",m_sendSize,sentBuffer,receivedSize,recievedBuffer); + } + + ~IpaRoutingBlockTestFixture() + { + m_sendSize = 0; + m_sendSize2 = 0; + m_sendSize3 = 0; + } + + void InitFilteringBlock() + { + IPAFilteringTable fltTable; + struct ipa_ioc_get_rt_tbl st_rt_tbl; + struct ipa_flt_rule_add flt_rule_entry; + + memset(&st_rt_tbl, 0, sizeof(st_rt_tbl)); + memset(&flt_rule_entry, 0, sizeof(flt_rule_entry)); + strlcpy(st_rt_tbl.name, "LAN", sizeof(st_rt_tbl.name)); + st_rt_tbl.ip = m_IpaIPType; + fltTable.Init(m_IpaIPType, IPA_CLIENT_TEST_PROD, false, 1); + m_routing.GetRoutingTable(&st_rt_tbl); + flt_rule_entry.rule.rt_tbl_hdl = st_rt_tbl.hdl; + fltTable.AddRuleToTable(flt_rule_entry); + m_filtering.AddFilteringRule(fltTable.GetFilteringTable()); + } + + inline bool VerifyStatusReceived(size_t SendSize, size_t RecvSize) + { + size_t stts_size = sizeof(struct ipa3_hw_pkt_status); + + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) { + stts_size = sizeof(struct ipa3_hw_pkt_status_hw_v5_0); + } + + if ((RecvSize <= SendSize) || + ((RecvSize - SendSize) != stts_size)){ + printf("received buffer size does not match! sent:receive [%zu]:[%zu]\n",SendSize,RecvSize); + return false; + } + + return true; + } + + inline bool IsCacheHit(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status *pStatus = (struct ipa3_hw_pkt_status *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if((bool)pStatus->route_hash){ + printf ("%s::cache hit!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache miss!! \n",__FUNCTION__); + return false; + + } + + inline bool IsCacheHit_v5_0(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status_hw_v5_0 *pStatus = (struct ipa3_hw_pkt_status_hw_v5_0 *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if((bool)pStatus->route_hash){ + printf ("%s::cache hit!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache miss!! \n",__FUNCTION__); + return false; + + } + + inline bool IsCacheMiss(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status *pStatus = (struct ipa3_hw_pkt_status *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if(!((bool)pStatus->route_hash)){ + printf ("%s::cache miss!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache hit!! \n",__FUNCTION__); + return false; + } + + inline bool IsCacheMiss_v5_0(size_t SendSize, size_t RecvSize, void *Buff) + { + struct ipa3_hw_pkt_status_hw_v5_0 *pStatus = (struct ipa3_hw_pkt_status_hw_v5_0 *)Buff; + + if (VerifyStatusReceived(SendSize,RecvSize) == false){ + return false; + } + + if(!((bool)pStatus->route_hash)){ + printf ("%s::cache miss!! \n",__FUNCTION__); + return true; + } + + printf ("%s::cache hit!! \n",__FUNCTION__); + return false; + } + + static RoutingDriverWrapper m_routing; + static Filtering m_filtering; + + static const size_t BUFF_MAX_SIZE = 1024; + + InterfaceAbstraction m_producer; + InterfaceAbstraction m_consumer; + InterfaceAbstraction m_consumer2; + InterfaceAbstraction m_defaultConsumer; + Byte m_sendBuffer[BUFF_MAX_SIZE]; // First input file / IP packet + Byte m_sendBuffer2[BUFF_MAX_SIZE]; // Second input file / IP packet + Byte m_sendBuffer3[BUFF_MAX_SIZE]; // Third input file (default) / IP packet + size_t m_sendSize; + size_t m_sendSize2; + size_t m_sendSize3; + enum ipa_ip_type m_IpaIPType; + + +private: +}; + +RoutingDriverWrapper IpaRoutingBlockTestFixture::m_routing; +Filtering IpaRoutingBlockTestFixture::m_filtering; + +/*---------------------------------------------------------------------------*/ +/* Test1: Tests routing by destination address */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest1 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest1() + { + m_name = "IpaRoutingBlockTest1"; + m_description =" \ + Routing block test 001 - Destination address exact match\1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.169.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.255 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802FF; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test2: Tests routing by destination address with a subnet (mask) */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest2 : IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest2() + { + m_name = "IpaRoutingBlockTest2"; + m_description =" \ + Routing block test 002 - Destination address subnet match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.169.170.0 & 255.255.255.0)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.255.0 & 255.255.255.0)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("ENTRY: IpaRoutingBlockTest2::Run()\n"); + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[18] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[18] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + printf("ENTRY: IpaRoutingBlockTest2::AddRules()\n"); + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A8FF00; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFF00; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A8AA00; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFF00; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + printf("Before calling m_routing.AddRoutingRule()\n"); + printf("m_routing = %p\n", &m_routing); + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + + +/*---------------------------------------------------------------------------*/ +/* Test3: Tests routing by TOS (Type Of Service) */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest3 : IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest3() + { + m_name = "IpaRoutingBlockTest3"; + m_description = " \ + Routing block test 003 - TOS exact match\ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All TOS == 0xBF traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All TOS == 0x3A traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[TOS_FIELD_OFFSET] = 0xBF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[TOS_FIELD_OFFSET] = 0x3A; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; + // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TOS; + rt_rule_entry->rule.attrib.u.v4.tos = 0xBF; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TOS; + rt_rule_entry->rule.attrib.u.v4.tos = 0x3A; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test4: Destination address exact match and TOS exact match */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest4 : IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest4() + { + m_name = "IpaRoutingBlockTest4"; + m_description =" \ + Routing block test 004 - Source and Destination address and TOS exact match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.169.2.255 & 255.255.255.255) and TOS == 0xFF traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.170 & 255.255.255.255) and TOS == 0xAA traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All DST_IP == (192.168.2.85 & 255.255.255.255) and SRC_IP == (192.168.2.241 & 255.255.255.255) TOS == 0x24 traffic goes to pipe IPA_CLIENT_TEST3_CONS"; + m_IpaIPType = IPA_IP_v4; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[TOS_FIELD_OFFSET] = 0xFF; + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[TOS_FIELD_OFFSET] = 0xAA; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + m_sendBuffer3[TOS_FIELD_OFFSET] = 0x24; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV4] = 0x55; + m_sendBuffer3[SRC_ADDR_LSB_OFFSET_IPV4] = 0xF1; + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TOS | IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.tos = 0xFF; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802FF; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TOS | IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.tos = 0xAA; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TOS | IPA_FLT_DST_ADDR | IPA_FLT_SRC_ADDR; + rt_rule_entry->rule.attrib.u.v4.tos = 0x24; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A80255; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v4.src_addr = 0xC0A802F1; + rt_rule_entry->rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test5: IPv6 - Tests routing by destination address */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest5 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest5() + { + m_name = "IpaRoutingBlockTest5"; + m_description =" \ + Routing block test 005 - IPv6 Destination address exact match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF \ + traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000AA; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test6: IPv6 - Tests routing by destination address */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest006 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest006() + { + m_name = "IpaRoutingBlockTest006"; + m_description =" \ + Routing block test 006 - IPv6 Destination address Subnet match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match 0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x0000000). \ + All DST_IP == 0X11020000 \ + 0x00000000 \ + 0x00000000 \ + 0X0000000C \ + traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == 0X22020000 \ + 0x00000000 \ + 0x00000000 \ + 0X0000000C \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_MSB_OFFSET_IPV6] = 0x11; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_MSB_OFFSET_IPV6] = 0x22; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO: Header Insertion gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0X11020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X0000000C; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO: Header Insertion gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0X22020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X0000000C; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test7: IPv6 - Tests routing by destination address */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest007 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest007() + { + m_name = "IpaRoutingBlockTest007"; + m_description = " \ + Routing block test 007 - IPv6 Exact Traffic Class Match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All Traffic Class == 0xAA traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All Traffic Class == 0xBB traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[TRAFFIC_CLASS_MSB_OFFSET_IPV6] &= 0xF0; + m_sendBuffer[TRAFFIC_CLASS_MSB_OFFSET_IPV6] |= 0x0A; + m_sendBuffer[TRAFFIC_CLASS_LSB_OFFSET_IPV6] &= 0x0F; + m_sendBuffer[TRAFFIC_CLASS_LSB_OFFSET_IPV6] |= 0xA0; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[TRAFFIC_CLASS_MSB_OFFSET_IPV6] &= 0xF0; + m_sendBuffer2[TRAFFIC_CLASS_MSB_OFFSET_IPV6] |= 0x0B; + m_sendBuffer2[TRAFFIC_CLASS_LSB_OFFSET_IPV6] &= 0x0F; + m_sendBuffer2[TRAFFIC_CLASS_LSB_OFFSET_IPV6] |= 0xB0; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + // rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO: Header Insertion gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TC; + rt_rule_entry->rule.attrib.u.v6.tc = 0xAA; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // TODO: Header Insertion gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_TC; + rt_rule_entry->rule.attrib.u.v6.tc = 0xBB; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test8: IPv6 - Tests routing by destination address */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest008 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest008() + { + m_name = "IpaRoutingBlockTest008"; + m_description = " \ + Routing block test 008 - IPv6 Destination address exact match and Traffic Class Match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All Traffic Class == 0xAA & IPv6 DST Addr 0xFF020000...00AA traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All Traffic Class == 0xBB & IPv6 DST Addr 0xFF020000...00BB traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[TRAFFIC_CLASS_MSB_OFFSET_IPV6] &= 0xF0; + m_sendBuffer[TRAFFIC_CLASS_MSB_OFFSET_IPV6] |= 0x0A; + m_sendBuffer[TRAFFIC_CLASS_LSB_OFFSET_IPV6] &= 0x0F; + m_sendBuffer[TRAFFIC_CLASS_LSB_OFFSET_IPV6] |= 0xA0; + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[TRAFFIC_CLASS_MSB_OFFSET_IPV6] &= 0xF0; + m_sendBuffer2[TRAFFIC_CLASS_MSB_OFFSET_IPV6] |= 0x0B; + m_sendBuffer2[TRAFFIC_CLASS_LSB_OFFSET_IPV6] &= 0x0F; + m_sendBuffer2[TRAFFIC_CLASS_LSB_OFFSET_IPV6] |= 0xB0; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR | IPA_FLT_TC; + rt_rule_entry->rule.attrib.u.v6.tc = 0xAA; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR | IPA_FLT_TC; + rt_rule_entry->rule.attrib.u.v6.tc = 0xBB; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000AA; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test9: IPv6 - Tests routing by destination address */ +/*---------------------------------------------------------------------------*/ +class IpaRoutingBlockTest009 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest009() + { + m_name = "IpaRoutingBlockTest009"; + m_description = " \ + Routing block test 009 - IPv6 Exact Flow Label Match \ + 1. Generate and commit a single routing tables. \ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All Flow Label == 0xABCDE traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All Flow Label == 0x12345 traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + Register(*this); + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[FLOW_CLASS_MSB_OFFSET_IPV6] &= 0xF0; + m_sendBuffer[FLOW_CLASS_MSB_OFFSET_IPV6] |= 0x0A; + m_sendBuffer[FLOW_CLASS_MB_OFFSET_IPV6] = 0xBC; + m_sendBuffer[FLOW_CLASS_LSB_OFFSET_IPV6] = 0xDE; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[FLOW_CLASS_MSB_OFFSET_IPV6] &= 0xF0; + m_sendBuffer2[FLOW_CLASS_MSB_OFFSET_IPV6] |= 0x01; + m_sendBuffer2[FLOW_CLASS_MB_OFFSET_IPV6] = 0x23; + m_sendBuffer2[FLOW_CLASS_LSB_OFFSET_IPV6] = 0x45; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_FLOW_LABEL; + rt_rule_entry->rule.attrib.u.v6.flow_label = 0xABCDE; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; +// rt_rule_entry->rule.hdr_hdl = hdr_entry->hdr_hdl; // gidons, there is no support for header insertion / removal yet. + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_FLOW_LABEL; + rt_rule_entry->rule.attrib.u.v6.flow_label = 0x12345; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*--------------------------------------------------------------------------*/ +/* Test10: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest010 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest010() + { + m_name = "IpaRoutingBlockTest10"; + m_description =" \ + Routing block test 010 - Destination address exact match non hashable priority higher than hashable \ + both match the packet but only non hashable should hit\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + +/*--------------------------------------------------------------------------*/ +/* Test11: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest011 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest011() + { + m_name = "IpaRoutingBlockTest011"; + m_description =" \ + Routing block test 011 - Destination address exact match hashable priority higher than non hashable \ + both match the packet but only hashable should hit, second packet should get cache hit\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + return IpaRoutingBlockTestFixture:: Setup(true); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheHit(m_sendSize2,receivedSize2,rxBuff2); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + +/*--------------------------------------------------------------------------*/ +/* Test12: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest012 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest012() + { + m_name = "IpaRoutingBlockTest012"; + m_description =" \ + Routing block test 012 - Destination address exact match hashable priority lower than non hashable \ + no match on non hashable rule (with higher priority), match on hashable rule. two packets with\ + different tuple are sent (but match the rule) cache miss expected\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.171 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + return IpaRoutingBlockTestFixture:: Setup(true); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AB; //192.168.02.171 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + unsigned short port; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + port = ntohs(547);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer2.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer2.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheMiss(m_sendSize2,receivedSize2,rxBuff2); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*--------------------------------------------------------------------------*/ +/* Test13: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest013 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest013() + { + m_name = "IpaRoutingBlockTest013"; + m_description =" \ + Routing block test 013 - Destination address exact match \ + no match on non hashable rule (with lower priority), match on hashable rule. two packets with\ + different tuple are sent (but match the rule) cache miss expected\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.171 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + return IpaRoutingBlockTestFixture:: Setup(true); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AB; //192.168.02.171 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + unsigned short port; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + port = ntohs(547);//DHCP Client Port + memcpy (&m_sendBuffer[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer2[IPV4_DST_PORT_OFFSET], &port, sizeof(port)); + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheMiss(m_sendSize2,receivedSize2,rxBuff2); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*--------------------------------------------------------------------------*/ +/* Test14: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest014 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest014() + { + m_name = "IpaRoutingBlockTest014"; + m_description =" \ + Routing block test 014 - Destination address exact match \ + no match on non hashable rule(with higher priority) , match on hashable rule. two identical\ + packets are sent cache hit expected on the second one\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.171 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + return IpaRoutingBlockTestFixture:: Setup(true); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AB; //192.168.02.171 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer2.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer2.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer2.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheHit(m_sendSize2,receivedSize2,rxBuff2); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } +}; + + +/*--------------------------------------------------------------------------*/ +/* Test15: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest015 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest015() + { + m_name = "IpaRoutingBlockTest015"; + m_description =" \ + Routing block test 015 - Destination address exact match \ + no match on non hashable rule(with lower priority) , match on hashable rule. two identical\ + packets are sent cache hit expected on the second one\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.171 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool Setup() + { + return IpaRoutingBlockTestFixture:: Setup(true); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AB; //192.168.02.171 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + for (int i = 0; i < rt_rule->num_rules; i++) { + uRtRuleHdl[i] = rt_rule->rules[i].rt_rule_hdl; + } + uNumRtRules = rt_rule->num_rules; + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool RemoveLastRule(enum ipa_ip_type ipType) + { + struct ipa_ioc_del_rt_rule *ruleTable; + + ruleTable = (struct ipa_ioc_del_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_del_rt_rule) + + sizeof(struct ipa_rt_rule_del)); + + ruleTable->commit = 1; + ruleTable->ip = ipType; + ruleTable->num_hdls = 1; + ruleTable->hdl[0].hdl = uRtRuleHdl[uNumRtRules - 1]; + ruleTable->hdl[0].status = 0; + + if (false == m_routing.DeleteRoutingRule(ruleTable)) + { + printf("Routing rule deletion failed!\n"); + return false; + } + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheHit_v5_0(m_sendSize2, receivedSize2, rxBuff2) : IsCacheHit(m_sendSize2,receivedSize2,rxBuff2); + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize3, receivedSize3, rxBuff3) : IsCacheMiss(m_sendSize3,receivedSize3,rxBuff3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + + bool ReceivePacketsAndCompareSpecial() + { + size_t receivedSize = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + + if (NULL == rxBuff1) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden_w_Status(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + + isSuccess &= (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) ? + IsCacheMiss_v5_0(m_sendSize, receivedSize, rxBuff1) : IsCacheMiss(m_sendSize,receivedSize,rxBuff1); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + size_t j; + for(j = 0; j < m_sendSize; j++) + snprintf(&sentBuffer[3 * j], sentBufferSize - 3 * j, + " %02X", m_sendBuffer[j]); + for(j = 0; j < receivedSize; j++) + snprintf(&recievedBuffer[3 * j], recievedBufferSize - 3 * j, + " %02X", rxBuff1[j]); + printf("Expected Value1 (%zu)\n%s\n, Received Value1(%zu)\n%s\n",m_sendSize,sentBuffer,receivedSize,recievedBuffer); + + delete[] rxBuff1; + + return isSuccess; + } + +protected: + uint32_t uRtRuleHdl[3]; + uint8_t uNumRtRules; +}; + +/*--------------------------------------------------------------------------*/ +/* Test16: IPv4 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest016 : public IpaRoutingBlockTestFixture +{ +public: + + IpaRoutingBlockTest016() + { + m_name = "IpaRoutingBlockTest016"; + m_description =" \ + Routing block test 016 - Destination address exact match max priority for non hashable \ + match on both rule, non hashable rule should win because max priority\ + packets are sent. No cache hit is expected\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.170 & 255.255.255.255)traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v3_0; + Register(*this); + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802AA; //192.168.02.170 + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + rt_rule_entry->rule.max_prio = 1; // max priority + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool ReceivePacketsAndCompare() + { + size_t receivedSize = 0; + size_t receivedSize2 = 0; + size_t receivedSize3 = 0; + bool isSuccess = true; + + // Receive results + Byte *rxBuff1 = new Byte[0x400]; + Byte *rxBuff2 = new Byte[0x400]; + Byte *rxBuff3 = new Byte[0x400]; + + if (NULL == rxBuff1 || NULL == rxBuff2 || NULL == rxBuff3) + { + printf("Memory allocation error.\n"); + return false; + } + + receivedSize = m_consumer2.ReceiveData(rxBuff1, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize, m_consumer.m_fromChannelName.c_str()); + + receivedSize2 = m_consumer2.ReceiveData(rxBuff2, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize2, m_consumer.m_fromChannelName.c_str()); + + receivedSize3 = m_defaultConsumer.ReceiveData(rxBuff3, 0x400); + printf("Received %zu bytes on %s.\n", receivedSize3, m_defaultConsumer.m_fromChannelName.c_str()); + + /* Compare results */ + isSuccess &= CompareResultVsGolden(m_sendBuffer, m_sendSize, rxBuff1, receivedSize); + isSuccess &= CompareResultVsGolden(m_sendBuffer2, m_sendSize2, rxBuff2, receivedSize2); + isSuccess &= CompareResultVsGolden(m_sendBuffer3, m_sendSize3, rxBuff3, receivedSize3); + + size_t recievedBufferSize = receivedSize * 3; + size_t sentBufferSize = m_sendSize * 3; + char *recievedBuffer = new char[recievedBufferSize]; + char *sentBuffer = new char[sentBufferSize]; + + memset(recievedBuffer, 0, recievedBufferSize); + memset(sentBuffer, 0, sentBufferSize); + + print_packets(receivedSize, m_sendSize, recievedBufferSize, sentBufferSize, rxBuff1, m_sendBuffer, recievedBuffer, sentBuffer); + print_packets(receivedSize2, m_sendSize2, recievedBufferSize, sentBufferSize, rxBuff2, m_sendBuffer2, recievedBuffer, sentBuffer); + print_packets(receivedSize3, m_sendSize3, recievedBufferSize, sentBufferSize, rxBuff3, m_sendBuffer3, recievedBuffer, sentBuffer); + + delete[] recievedBuffer; + delete[] sentBuffer; + + delete[] rxBuff1; + delete[] rxBuff2; + delete[] rxBuff3; + + return isSuccess; + } + +}; + +/*--------------------------------------------------------------------------*/ +/* Test17: IPv4 - Tests routing hashable, non hashable, */ +/* cache/hash invalidation test on rule addition */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest017 : public IpaRoutingBlockTest015 +{ +public: + + IpaRoutingBlockTest017() + { + m_name = "IpaRoutingBlockTest017"; + m_description =" \ + Routing block test 017 - this test perform test 015 and then commits another rule\ + another identical packet is sent: DST_IP == 192.168.02.170 and expected to get cache miss"; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompare failure.\n"); + return false; + } + + // until here test 15 was run, now we test hash invalidation + + // commit the rules again to clear the cache + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // send the packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // validate we got cache miss + isSuccess = ReceivePacketsAndCompareSpecial(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompareSpecial failure.\n"); + } + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test18: IPv4 - Tests routing hashable, non hashable, */ +/* cache/hash invalidation test on rule delition */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest018 : public IpaRoutingBlockTest015 +{ +public: + + IpaRoutingBlockTest018() + { + m_name = "IpaRoutingBlockTest018"; + m_description =" \ + Routing block test 018 - this test perform test 015 and then removes last rule\ + another identical packet is sent: DST_IP == 192.168.02.170 and expected to get cache miss"; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xAA; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompare failure.\n"); + return false; + } + + // until here test 15 was run, now we test hash invalidation + + // delete the last rule, this should clear the cache + res = RemoveLastRule(IPA_IP_v4); + if (false == res) { + printf("Failed removing filtering rules.\n"); + return false; + } + + // send the packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // validate we got cache miss + isSuccess = ReceivePacketsAndCompareSpecial(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompareSpecial failure.\n"); + } + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test20: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest020 : public IpaRoutingBlockTest010 +{ +public: + + IpaRoutingBlockTest020() + { + m_name = "IpaRoutingBlockTest20"; + m_description =" \ + Routing block test 020 - Destination address exact match non hashable priority higher than hashable \ + both match the packet but only non hashable should hit\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF \ + traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() +}; + + +/*--------------------------------------------------------------------------*/ +/* Test21: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest021 : public IpaRoutingBlockTest011 +{ +public: + + IpaRoutingBlockTest021() + { + m_name = "IpaRoutingBlockTest021"; + m_description =" \ + Routing block test 021 - Destination address exact match hashable priority higher than non hashable \ + both match the packet but only hashable should hit, second packet should get cache hit\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - hashable\ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - non hahsable \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test22: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest022 : public IpaRoutingBlockTest012 +{ +public: + + IpaRoutingBlockTest022() + { + m_name = "IpaRoutingBlockTest022"; + m_description =" \ + Routing block test 022 - Destination address exact match hashable priority higher than non hashable \ + no match on non hashable rule (with higher priority), match on hashable rule. two packets with\ + different tuple are sent (but match the rule) cache miss expected\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000AA - non hashable\ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - hahsable \ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000AA; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + unsigned short port; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + port = ntohs(547);//DHCP Client Port + memcpy (&m_sendBuffer2[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test23: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest023 : public IpaRoutingBlockTest013 +{ +public: + + IpaRoutingBlockTest023() + { + m_name = "IpaRoutingBlockTest023"; + m_description =" \ + Routing block test 023 - Destination address exact match \ + no match on non hashable rule (with lower priority), match on hashable rule. two packets with\ + different tuple are sent (but match the rule) cache miss expected\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - hashable\ + traffic goes to pipe IPA_CLIENT_TEST2_CONS\ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000AA - non hahsable \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000AA; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + unsigned short port; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + port = ntohs(546);//DHCP Client Port + memcpy (&m_sendBuffer[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + port = ntohs(547);//DHCP Client Port + memcpy (&m_sendBuffer2[IPV6_DST_PORT_OFFSET], &port, sizeof(port)); + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + +}; + +/*--------------------------------------------------------------------------*/ +/* Test24: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest024 : public IpaRoutingBlockTest014 +{ +public: + + IpaRoutingBlockTest024() + { + m_name = "IpaRoutingBlockTest024"; + m_description =" \ + Routing block test 024 - Destination address exact match \ + no match on non hashable rule(with higher priority) , match on hashable rule. two identical\ + packets are sent cache hit expected on the second one\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000AA - non hashable\ + traffic goes to pipe IPA_CLIENT_TEST2_CONS\ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - hahsable \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000AA; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + +}; + +/*--------------------------------------------------------------------------*/ +/* Test25: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest025 : public IpaRoutingBlockTest015 +{ +public: + IpaRoutingBlockTest025() + { + m_name = "IpaRoutingBlockTest025"; + m_description =" \ + Routing block test 025 - Destination address exact match \ + no match on non hashable rule(with lower priority) , match on hashable rule. two identical\ + packets are sent cache hit expected on the second one\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - hashable\ + traffic goes to pipe IPA_CLIENT_TEST2_CONS\ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000AA - non hahsable \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000AA; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + for (int i = 0; i < rt_rule->num_rules; i++) { + uRtRuleHdl[i] = rt_rule->rules[i].rt_rule_hdl; + } + uNumRtRules = rt_rule->num_rules; + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() +}; + + +/*--------------------------------------------------------------------------*/ +/* Test26: IPv6 - Tests routing hashable vs non hashable priorities */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest026 : public IpaRoutingBlockTest016 +{ +public: + + IpaRoutingBlockTest026() + { + m_name = "IpaRoutingBlockTest026"; + m_description =" \ + Routing block test 026 - Destination address exact match max priority for non hashable \ + match on both rule, non hashable rule should win because max priority\ + packets are sent cache hit expected on the second one\ + 2. Generate and commit Three routing rules: (DST & Mask Match). \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - hashable\ + traffic goes to pipe IPA_CLIENT_TEST2_CONS\ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000FF - non hahsable max prio \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v3_0; + } + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; // hashable + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000FF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 0; // non hashable + rt_rule_entry->rule.max_prio = 1; // max prio + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + rt_rule_entry->rule.hashable = 0; // non hashable + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + free(rt_rule); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test27: IPv6 - Tests routing hashable, non hashable, */ +/* cache/hash invalidation test on rule addition */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest027 : public IpaRoutingBlockTest025 +{ +public: + + IpaRoutingBlockTest027() + { + m_name = "IpaRoutingBlockTest027"; + m_description =" \ + Routing block test 027 - this test perform test 025 and then commits another rule\ + another identical packet is sent: DST_IP == 192.168.02.170 and expected to get cache miss"; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompare failure.\n"); + return false; + } + + // until here test 25 was run, now we test hash invalidation + + // commit the rules again to clear the cache + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // send the packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // validate we got cache miss + isSuccess = ReceivePacketsAndCompareSpecial(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompareSpecial failure.\n"); + } + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test28: IPv6 - Tests routing hashable, non hashable, */ +/* cache/hash invalidation test on rule delition */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest028 : public IpaRoutingBlockTest025 +{ +public: + + IpaRoutingBlockTest028() + { + m_name = "IpaRoutingBlockTest028"; + m_description =" \ + Routing block test 028 - this test perform test 025 and then deletes last rule\ + another identical packet is sent: DST_IP == 192.168.02.170 and expected to get cache miss"; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v6); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xFF; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompare failure.\n"); + return false; + } + + // until here test 25 was run, now we test hash invalidation + + // delete the last rule, this should clear the cache + res = RemoveLastRule(IPA_IP_v6); + if (false == res) { + printf("Failed removing filtering rules.\n"); + return false; + } + + // send the packet again + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // validate we got cache miss + isSuccess = ReceivePacketsAndCompareSpecial(); + if (false == isSuccess) + { + printf("ReceivePacketsAndCompareSpecial failure.\n"); + } + return isSuccess; + } // Run() +}; + +/*--------------------------------------------------------------------------*/ +/* Test30: Pure ack packet matching */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest030 : IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest030() + { + m_name = "IpaRoutingBlockTest030"; + m_description =" \ + Routing block test 030 - Pure Ack packet matching \ + 1. Generate and commit a single routing table. \ + 2. Generate and commit Three routing rules: \ + All TCP pure ack traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == (192.168.2.200 & 255.255.255.255) traffic goes to pipe IPA_CLIENT_TEST3_CONS\ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v4_5; + Register(*this); + } + + bool LoadPackets() + { + if (!LoadNoPayloadPacket(m_IpaIPType, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed loading No Payload Packet"); + return false; + } + + if (!LoadDefaultPacket(m_IpaIPType, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + if (!LoadDefaultPacket(m_IpaIPType, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load IP packets + res = LoadPackets(); + if (false == res) { + printf("Failed loading packets\n"); + return false; + } + + // Send first packet + m_sendBuffer[IPv4_TCP_FLAGS_OFFSET] |= TCP_ACK_FLAG_MASK; + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0xC8; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[IPv4_TCP_FLAGS_OFFSET] |= TCP_ACK_FLAG_MASK; + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV4] = 0xC8; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize2); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + m_sendBuffer3[IPv4_TCP_FLAGS_OFFSET] |= TCP_ACK_FLAG_MASK; + m_sendBuffer3[DST_ADDR_LSB_OFFSET_IPV4] = 0x64; + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_IS_PURE_ACK; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A802C8; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*--------------------------------------------------------------------------*/ +/* Test31: IPv6 Pure ack packet matching */ +/*--------------------------------------------------------------------------*/ +class IpaRoutingBlockTest031 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest031() + { + m_name = "IpaRoutingBlockTest031"; + m_description =" \ + Routing block test 031 - IPv6 Pure Ack packet matching \ + 1. Generate and commit a single routing table. \ + 2. Generate and commit Three routing rules: \ + All TCP pure ack traffic goes to pipe IPA_CLIENT_TEST2_CONS \ + All DST_IP == 0XFF020000 \ + 0x00000000 \ + 0x00000000 \ + 0X000000F5 \ + traffic goes to pipe IPA_CLIENT_TEST3_CONS \ + All other traffic goes to pipe IPA_CLIENT_TEST4_CONS"; + m_IpaIPType = IPA_IP_v6; + m_minIPAHwType = IPA_HW_v4_5; + Register(*this); + } + + bool LoadPackets() + { + if (!LoadNoPayloadPacket(m_IpaIPType, m_sendBuffer, m_sendSize)) { + LOG_MSG_ERROR("Failed loading No Payload Packet"); + return false; + } + + if (!LoadNoPayloadPacket(m_IpaIPType, m_sendBuffer2, m_sendSize2)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + if (!LoadNoPayloadPacket(m_IpaIPType, m_sendBuffer3, m_sendSize3)) { + LOG_MSG_ERROR("Failed loading default Packet"); + return false; + } + + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + // Add the relevant routing rules + res = AddRules(); + if (false == res) { + printf("Failed adding routing rules.\n"); + return false; + } + + // Load input data (IP packet) + res = LoadPackets(); + if (false == res) { + printf("Failed loading packets\n"); + return false; + } + + // Send first packet + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV6] = 0xF5; + m_sendBuffer[IPv6_TCP_FLAGS_OFFSET] |= TCP_ACK_FLAG_MASK; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send second packet + m_sendBuffer2[DST_ADDR_LSB_OFFSET_IPV6] = 0xF5; + isSuccess = m_producer.SendData(m_sendBuffer2, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Send third packet + isSuccess = m_producer.SendData(m_sendBuffer3, m_sendSize3); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + // Receive packets from the channels and compare results + isSuccess = ReceivePacketsAndCompare(); + + return isSuccess; + } // Run() + + bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 3; + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES*sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("fail\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_IS_PURE_ACK; + + rt_rule_entry = &rt_rule->rules[1]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST3_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0XFF020000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0x00000000; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0X000000F5; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry = &rt_rule->rules[2]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST4_CONS; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + free(rt_rule); + + InitFilteringBlock(); + + return true; + } +}; + +/*---------------------------------------------------------------------------*/ +/* Test100: Cache LRU behavior test */ +/*---------------------------------------------------------------------------*/ +#define CHACHE_ENTRIES 64 +#define CHACHE_PLUS_ONE (CHACHE_ENTRIES +1) +class IpaRoutingBlockTest040 : public IpaRoutingBlockTestFixture +{ +public: + IpaRoutingBlockTest040() + { + m_name = "IpaRoutingBlockTest040"; + m_description = " \ + Routing block test 40 - Cache LRU behavior test \ + 1. Preload the cache by sending 64 packets for different connections \ + 2. Send another packet for 65th connection \ + 3. Send packets for first 64 connections \ + 4. Verify that 1st connection’s entry was reclaimed"; + m_IpaIPType = IPA_IP_v4; + m_minIPAHwType = IPA_HW_v4_0; + Register(*this); + } + + bool Setup() + { + return IpaRoutingBlockTestFixture:: Setup(true); + } + + virtual bool AddRules() + { + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + CHACHE_PLUS_ONE * sizeof(struct ipa_rt_rule_add)); + + if(!rt_rule) { + printf("Failed memory allocation for rt_rule\n"); + return false; + } + + rt_rule->commit = 1; + rt_rule->num_rules = CHACHE_PLUS_ONE; + rt_rule->ip = IPA_IP_v4; + strlcpy(rt_rule->rt_tbl_name, "LAN", sizeof(rt_rule->rt_tbl_name)); + + for (int i = 0; i < CHACHE_PLUS_ONE; i++) { + rt_rule_entry = &rt_rule->rules[i]; + rt_rule_entry->at_rear = 1; + rt_rule_entry->rule.dst = IPA_CLIENT_TEST2_CONS; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0xC0A80101 + i; // DST_IP == 192.168.1.(1+i) + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + rt_rule_entry->rule.hashable = 1; + } + + // The last rule has to be catch all, otherwize no rule will work + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0x0; + + if (false == m_routing.AddRoutingRule(rt_rule)) + { + printf("Routing rule addition failed!\n"); + return false; + } + + printf("rt rule hdl1=%x\n", rt_rule_entry->rt_rule_hdl); + + free(rt_rule); + + InitFilteringBlock(); + + printf("Leaving %s, %s()\n",__FUNCTION__, __FILE__); + return true; + } + + bool Run() + { + bool res = false; + bool isSuccess = false; + + printf("Entering %s, %s()\n", __FUNCTION__, __FILE__); + + // Add the relevant filtering rules + res = AddRules(); + if (false == res) { + printf("Failed adding filtering rules.\n"); + return false; + } + + // Load input data (IP packet) from file + res = LoadFiles(IPA_IP_v4); + if (false == res) { + printf("Failed loading files.\n"); + return false; + } + + // Send the first CHACHE_ENTRIES packets + // Receive packets from the channels and compare results + // All rules should be cache miss + for (int i = 0; i < CHACHE_ENTRIES; i++) { + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0x1 + i; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, false); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + } + + // Send again the first CHACHE_ENTRIES packets + // Receive packets from the channels and compare results + // All rules should be cache hit + for (int i = 0; i < CHACHE_ENTRIES; i++) { + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0x1 + i; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) + { + printf("SendData failure.\n"); + return false; + } + + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, true); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + } + + // Send a packet to a new filter entry, this should trigger the LRU clear + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0x1 + CHACHE_ENTRIES; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, false); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + + // send the first packet again + m_sendBuffer[DST_ADDR_LSB_OFFSET_IPV4] = 0x1; + isSuccess = m_producer.SendData(m_sendBuffer, m_sendSize); + if (false == isSuccess) { + printf("SendData failure.\n"); + return false; + } + + // receive and verify that cache was missed + isSuccess = ReceivePacketAndCompareFrom(m_consumer, m_sendBuffer, m_sendSize, false); + if (false == isSuccess) { + printf("%s:%d: ReceivePacketAndCompareFrom failure.\n", __FUNCTION__, __LINE__); + return false; + } + + printf("Leaving %s, %s(), Returning %d\n",__FUNCTION__, __FILE__, isSuccess); + + return isSuccess; + } // Run() +}; + +static class IpaRoutingBlockTest1 ipaRoutingBlockTest1; +static class IpaRoutingBlockTest2 ipaRoutingBlockTest2; +static class IpaRoutingBlockTest3 ipaRoutingBlockTest3; +static class IpaRoutingBlockTest4 ipaRoutingBlockTest4; +static class IpaRoutingBlockTest5 ipaRoutingBlockTest5; +static class IpaRoutingBlockTest006 ipaRoutingBlockTest006; +static class IpaRoutingBlockTest007 ipaRoutingBlockTest007; +static class IpaRoutingBlockTest008 ipaRoutingBlockTest008; +static class IpaRoutingBlockTest009 ipaRoutingBlockTest009; + +static class IpaRoutingBlockTest010 ipaRoutingBlockTest010; +static class IpaRoutingBlockTest011 ipaRoutingBlockTest011; +static class IpaRoutingBlockTest012 ipaRoutingBlockTest012; +static class IpaRoutingBlockTest013 ipaRoutingBlockTest013; +static class IpaRoutingBlockTest014 ipaRoutingBlockTest014; +static class IpaRoutingBlockTest015 ipaRoutingBlockTest015; +static class IpaRoutingBlockTest016 ipaRoutingBlockTest016; +static class IpaRoutingBlockTest017 ipaRoutingBlockTest017; +static class IpaRoutingBlockTest018 ipaRoutingBlockTest018; + +static class IpaRoutingBlockTest020 ipaRoutingBlockTest020; +static class IpaRoutingBlockTest021 ipaRoutingBlockTest021; +static class IpaRoutingBlockTest022 ipaRoutingBlockTest022; +static class IpaRoutingBlockTest023 ipaRoutingBlockTest023; +static class IpaRoutingBlockTest024 ipaRoutingBlockTest024; +static class IpaRoutingBlockTest025 ipaRoutingBlockTest025; +static class IpaRoutingBlockTest026 ipaRoutingBlockTest026; +static class IpaRoutingBlockTest027 ipaRoutingBlockTest027; +static class IpaRoutingBlockTest028 ipaRoutingBlockTest028; + +static class IpaRoutingBlockTest030 ipaRoutingBlockTest030; +static class IpaRoutingBlockTest031 ipaRoutingBlockTest031; + +static class IpaRoutingBlockTest040 ipaRoutingBlockTest040; + + diff --git a/kernel-tests/TLPAggregationTestFixture.cpp b/kernel-tests/TLPAggregationTestFixture.cpp new file mode 100644 index 0000000000..b3b94634ad --- /dev/null +++ b/kernel-tests/TLPAggregationTestFixture.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017 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 "TLPAggregationTestFixture.h" + +///////////////////////////////////////////////////////////////////////////////// + +//define the static Pipes which will be used by all derived tests. +Pipe TLPAggregationTestFixture::m_IpaToUsbPipeNoAgg(IPA_CLIENT_TEST3_CONS, + IPA_TEST_CONFIGURATION_8); +Pipe TLPAggregationTestFixture::m_IpaToUsbPipeAggr(IPA_CLIENT_TEST_CONS, + IPA_TEST_CONFIGURATION_8); +Pipe TLPAggregationTestFixture::m_UsbNoAggToIpaPipeAgg(IPA_CLIENT_TEST3_PROD, + IPA_TEST_CONFIGURATION_8); +Pipe TLPAggregationTestFixture::m_UsbDeaggToIpaPipeNoAgg(IPA_CLIENT_TEST_PROD, + IPA_TEST_CONFIGURATION_8); +Pipe TLPAggregationTestFixture::m_UsbDeaggToIpaPipeAgg(IPA_CLIENT_TEST2_PROD, + IPA_TEST_CONFIGURATION_8); +Pipe TLPAggregationTestFixture::m_IpaToUsbPipeAggTime(IPA_CLIENT_TEST2_CONS, + IPA_TEST_CONFIGURATION_8); +Pipe TLPAggregationTestFixture::m_UsbNoAggToIpaPipeAggTime(IPA_CLIENT_TEST4_PROD, + IPA_TEST_CONFIGURATION_8); + +///////////////////////////////////////////////////////////////////////////////// + +TLPAggregationTestFixture::TLPAggregationTestFixture() +{ + m_testSuiteName.push_back("TLPAgg"); + m_maxIPAHwType = IPA_HW_v2_6L; + Register(*this); +} + +///////////////////////////////////////////////////////////////////////////////// + +bool TLPAggregationTestFixture::Setup() +{ + bool bRetVal = true; + + //Set the configuration to support USB->IPA and IPA->USB pipes. + ConfigureScenario(8); + + //Initialize the pipe for all the tests - this will open the inode which represents the pipe. + bRetVal &= m_IpaToUsbPipeNoAgg.Init(); + bRetVal &= m_IpaToUsbPipeAggr.Init(); + bRetVal &= m_UsbNoAggToIpaPipeAgg.Init(); + bRetVal &= m_UsbDeaggToIpaPipeNoAgg.Init(); + bRetVal &= m_UsbDeaggToIpaPipeAgg.Init(); + bRetVal &= m_IpaToUsbPipeAggTime.Init(); + bRetVal &= m_UsbNoAggToIpaPipeAggTime.Init(); + return bRetVal; +} + +///////////////////////////////////////////////////////////////////////////////// + +bool TLPAggregationTestFixture::Teardown() +{ + //The Destroy method will close the inode. + m_IpaToUsbPipeNoAgg.Destroy(); + m_IpaToUsbPipeAggr.Destroy(); + m_UsbNoAggToIpaPipeAgg.Destroy(); + m_UsbDeaggToIpaPipeNoAgg.Destroy(); + m_UsbDeaggToIpaPipeAgg.Destroy(); + m_IpaToUsbPipeAggTime.Destroy(); + m_UsbNoAggToIpaPipeAggTime.Destroy(); + return true; +} + +///////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/TLPAggregationTestFixture.h b/kernel-tests/TLPAggregationTestFixture.h new file mode 100644 index 0000000000..7e88e7e740 --- /dev/null +++ b/kernel-tests/TLPAggregationTestFixture.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017 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 "Constants.h" +#include "Logger.h" +#include "linux/msm_ipa.h" +#include "TestsUtils.h" +#include "TestBase.h" +#include "Pipe.h" + +/*This class will be the base class of all TLP Aggregation tests. + *Any method other than the test case itself can be declared in + *this Fixture thus allowing the derived classes to + *implement only the test case. + *All the test of the Aggregation uses one + *input and one output in DMA mode. + */ +class TLPAggregationTestFixture:public TestBase +{ +public: + /*This Constructor will register each instance that it creates.*/ + TLPAggregationTestFixture(); + + /*This method will create and initialize two Pipe object for the + *USB (Ethernet) Pipes, one as input and the other as output. + */ + virtual bool Setup(); + + /*This method will destroy the pipes.*/ + virtual bool Teardown(); + + /*The client type are set from the peripheral perspective*/ + static Pipe m_IpaToUsbPipeNoAgg; + static Pipe m_IpaToUsbPipeAggr; + static Pipe m_UsbNoAggToIpaPipeAgg; + static Pipe m_UsbDeaggToIpaPipeNoAgg; + static Pipe m_UsbDeaggToIpaPipeAgg; + static Pipe m_IpaToUsbPipeAggTime; + static Pipe m_UsbNoAggToIpaPipeAggTime; +}; diff --git a/kernel-tests/TLPAggregationTests.cpp b/kernel-tests/TLPAggregationTests.cpp new file mode 100644 index 0000000000..c9bb2a5637 --- /dev/null +++ b/kernel-tests/TLPAggregationTests.cpp @@ -0,0 +1,946 @@ +/* + * Copyright (c) 2017 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 "TLPAggregationTestFixture.h" +#include "Constants.h" +#include "TestsUtils.h" +#include "linux/msm_ipa.h" + +#define NUM_PACKETS 5 +#define TIME_LIMIT_NUM_PACKETS 1 +#define MAX_PACKET_SIZE 1024 +#define AGGREGATION_LOOP 4 + +int test_num = 0; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPAggregationTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPAggregationTest() + { + m_name = "TLPAggregationTest"; + m_description = "TLP Aggregation test - sends 5 packets and receives 1 " + "aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + bool bTestResult = true; + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated packet + //minus 2 bytes for each packet in the aggregated packet) + int nTotalPacketsSize = MAX_PACKET_SIZE - (2 * NUM_PACKETS); + //The expected aggregated packet + Byte pExpectedAggregatedPacket[MAX_PACKET_SIZE] = {0}; + + //initialize the packets + //example: for NUM_PACKETS = 5 and MAX_PACKET_SIZE = 1024: + //nTotalPacketsSize will be 1024 - 5*2 = 1014 + //packets[0] size will be 1014/5 = 202 bytes of 0 + //packets[1] size will be (1014 - 202) / 5 = 162 bytes of 1 + //packets[2] size will be (1014 - 201 - 162) / 5 = 130 bytes of 2 + //packets[3] size will be (1014 - 201 - 162 - 130) / 5 = 104 bytes of 3 + //packets[4] size will be 1014 - 201 - 162 - 130 - 104 = 416 bytes of 4 + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + nTotalPacketsSize -= pPacketsSizes[i]; + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i + 16*test_num; + } + test_num++; + + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = m_UsbNoAggToIpaPipeAgg.Send(pPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE); + int nBytesReceived = m_IpaToUsbPipeAggr.Receive(pReceivedPacket, + MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", MAX_PACKET_SIZE); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pExpectedAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pExpectedAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pExpectedAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + + bTestResult &= !memcmp(pExpectedAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket)); + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPDeaggregationTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPDeaggregationTest() + { + m_name = "TLPDeaggregationTest"; + m_description = "TLP Deaggregation test - sends an aggregated packet made from" + "5 packets and receives 5 packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + bool bTestResult = true; + //The packets that the aggregated packet will be made of + Byte pExpectedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[NUM_PACKETS]; + //Buffers for the packets that will be received + Byte pReceivedPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //Total size of all the packets that the aggregated packet will be made of + //(this is the max size of the aggregated packet + //minus 2 bytes for each packet in the aggregated packet) + int nTotalPacketsSize = MAX_PACKET_SIZE - (2 * NUM_PACKETS); + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + + //initialize the packets + //example: for NUM_PACKETS = 5 and MAX_PACKET_SIZE = 1024: + //nTotalPacketsSize will be 1024 - 5*2 = 1014 + //packets[0] size will be 1014/5 = 202 bytes of 0 + //packets[1] size will be (1014 - 202) / 5 = 162 bytes of 1 + //packets[2] size will be (1014 - 201 - 162) / 5 = 130 bytes of 2 + //packets[3] size will be (1014 - 201 - 162 - 130) / 5 = 104 bytes of 3 + //packets[4] size will be 1014 - 201 - 162 - 130 - 104 = 416 bytes of 4 + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + nTotalPacketsSize -= pPacketsSizes[i]; + for (int j = 0; j < pPacketsSizes[i]; j++) + pExpectedPackets[i][j] = i+ 16*test_num; + } + test_num++; + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pAggregatedPacket[k] = pExpectedPackets[i][j]; + k++; + } + } + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)\n", + sizeof(pAggregatedPacket)); + int nBytesSent = m_UsbDeaggToIpaPipeNoAgg.Send(pAggregatedPacket, + sizeof(pAggregatedPacket)); + if (sizeof(pAggregatedPacket) != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes) " + "failed!\n", sizeof(pAggregatedPacket)); + return false; + } + + + //receive the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Reading packet %d from the USB pipe(%d bytes should be " + "there)\n", i, pPacketsSizes[i]); + int nBytesReceived = m_IpaToUsbPipeNoAgg.Receive(pReceivedPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving packet %d from the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + print_buff(pReceivedPackets[i], nBytesReceived); + return false; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + for (int i = 0; i < NUM_PACKETS; i++) + bTestResult &= !memcmp(pExpectedPackets[i], pReceivedPackets[i], pPacketsSizes[i]); + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + +class TLPDeaggregationAndAggregationTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPDeaggregationAndAggregationTest() + { + m_name = "TLPDeaggregationAndAggregationTest"; + m_description = "TLP Deaggregation and Aggregation test - sends an aggregated " + "packet made from 5 packets and receives the same aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + bool bTestResult = true; + //The packets that the aggregated packet will be made of + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that the aggregated packet will be made of + int pPacketsSizes[NUM_PACKETS]; + //Buffers for the packets that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all the packets that the aggregated packet will be made of + //(this is the max size of the aggregated packet + //minus 2 bytes for each packet in the aggregated packet) + int nTotalPacketsSize = MAX_PACKET_SIZE - (2 * NUM_PACKETS); + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + + //initialize the packets + //example: for NUM_PACKETS = 5 and MAX_PACKET_SIZE = 1024: + //nTotalPacketsSize will be 1024 - 5*2 = 1014 + //packets[0] size will be 1014/5 = 202 bytes of 0 + //packets[1] size will be (1014 - 202) / 5 = 162 bytes of 1 + //packets[2] size will be (1014 - 201 - 162) / 5 = 130 bytes of 2 + //packets[3] size will be (1014 - 201 - 162 - 130) / 5 = 104 bytes of 3 + //packets[4] size will be 1014 - 201 - 162 - 130 - 104 = 416 bytes of 4 + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + nTotalPacketsSize -= pPacketsSizes[i]; + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i+ 16*test_num; + } + test_num++; + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)\n", + sizeof(pAggregatedPacket)); + int nBytesSent = m_UsbDeaggToIpaPipeAgg.Send(pAggregatedPacket, + sizeof(pAggregatedPacket)); + if (sizeof(pAggregatedPacket) != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d bytes)" + " failed!\n", sizeof(pAggregatedPacket)); + return false; + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading aggregated packet from the USB pipe(%d bytes " + "should be there)\n", sizeof(pAggregatedPacket)); + int nBytesReceived = m_IpaToUsbPipeAggr.Receive(pReceivedPacket, + sizeof(pAggregatedPacket)); + if (sizeof(pAggregatedPacket) != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", sizeof(pAggregatedPacket)); + LOG_MSG_DEBUG("Received %d bytes\n", nBytesReceived); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } +print_buff(pReceivedPacket, nBytesReceived); + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + bTestResult &= !memcmp(pAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket)); + + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPAggregationLoopTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPAggregationLoopTest() + { + m_name = "TLPAggregationLoopTest"; + m_description = "TLP Aggregation Loop test - sends 5 packets and expects to" + "receives 1 aggregated packet a few times"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated packet + //minus 2 bytes for each packet in the aggregated packet) + int nTotalPacketsSize = MAX_PACKET_SIZE - (2 * NUM_PACKETS); + //The expected aggregated packet + Byte pExpectedAggregatedPacket[MAX_PACKET_SIZE] = {0}; + + //initialize the packets + //example: for NUM_PACKETS = 5 and MAX_PACKET_SIZE = 1024: + //nTotalPacketsSize will be 1024 - 5*2 = 1014 + //packets[0] size will be 1014/5 = 202 bytes of 0 + //packets[1] size will be (1014 - 202) / 5 = 162 bytes of 1 + //packets[2] size will be (1014 - 201 - 162) / 5 = 130 bytes of 2 + //packets[3] size will be (1014 - 201 - 162 - 130) / 5 = 104 bytes of 3 + //packets[4] size will be 1014 - 201 - 162 - 130 - 104 = 416 bytes of 4 + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + nTotalPacketsSize -= pPacketsSizes[i]; + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i+ 16*test_num; + } + test_num++; + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pExpectedAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pExpectedAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pExpectedAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + for (int j = 0; j < AGGREGATION_LOOP; j++) + { + //send the packets + for (int i = 0; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", + i, pPacketsSizes[i]); + int nBytesSent = m_UsbNoAggToIpaPipeAgg.Send(pPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + memset(pReceivedPacket, 0, sizeof(pReceivedPacket)); + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE); + int nBytesReceived = m_IpaToUsbPipeAggr.Receive(pReceivedPacket, + MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", MAX_PACKET_SIZE); + return false; + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + + if (0 != memcmp(pExpectedAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket))) + { + LOG_MSG_DEBUG("Comparison of packet %d failed!\n", j); + return false; + } + } + + return true; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPAggregationTimeLimitTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPAggregationTimeLimitTest() + { + m_name = "TLPAggregationTimeLimitTest"; + m_description = "TLP Aggregation time limit test - sends 1 packet " + "smaller than the byte limit and receives 1 aggregated packet"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + bool bTestResult = true; + //The packets that will be sent + Byte pPackets[TIME_LIMIT_NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[TIME_LIMIT_NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE] = {0}; + //The expected aggregated packet + Byte pExpectedAggregatedPacket[MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 0; + + //initialize the packets + for (int i = 0; i < TIME_LIMIT_NUM_PACKETS; i++) + { + pPacketsSizes[i] = i + 1; + nTotalPacketsSize += pPacketsSizes[i] + 2; //size of the packet + 2 bytes for length + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i+ 16*test_num; + } + test_num++; + + //send the packets + for (int i = 0; i < TIME_LIMIT_NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = m_UsbNoAggToIpaPipeAggTime.Send(pPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", nTotalPacketsSize); + int nBytesReceived = m_IpaToUsbPipeAggTime.Receive(pReceivedPacket, + nTotalPacketsSize); + if (nTotalPacketsSize != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", nTotalPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < TIME_LIMIT_NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pExpectedAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pExpectedAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pExpectedAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + + bTestResult &= !memcmp(pExpectedAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket)); + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPAggregationByteLimitTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPAggregationByteLimitTest() + { + m_name = "TLPAggregationByteLimitTest"; + m_description = "TLP Aggregation byte limit test - sends 2 packets that together " + "are larger than the byte limit "; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + bool bTestResult = true; + //The packets that will be sent + Byte pPackets[2][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[2]; + //Buffer for the packet that will be received + Byte pReceivedPacket[2*MAX_PACKET_SIZE] = {0}; + //The expected aggregated packet + Byte pExpectedAggregatedPacket[2*MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 0; + + //initialize the packets + for (int i = 0; i < 2; i++) + { + pPacketsSizes[i] = (MAX_PACKET_SIZE / 2) + 10; + nTotalPacketsSize += pPacketsSizes[i] + 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i+ 16*test_num; + } + test_num++; + + //send the packets + for (int i = 0; i < 2; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = m_UsbNoAggToIpaPipeAgg.Send(pPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", nTotalPacketsSize); + int nBytesReceived = m_IpaToUsbPipeAggr.Receive(pReceivedPacket, + nTotalPacketsSize); + if (nTotalPacketsSize != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d" + " bytes) failed!\n", nTotalPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < 2; i++) + { + //the first 2 bytes are the packet length in little endian + pExpectedAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pExpectedAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pExpectedAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + + bTestResult &= !memcmp(pExpectedAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket)); + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPAggregation2PipesTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPAggregation2PipesTest() + { + m_name = "TLPAggregation2PipesTest"; + m_description = "TLP Aggregation 2 pipes test - sends 3 packets from one pipe" + "and an aggregated packet made of 2 packets from another pipe and " + "receives 1 aggregated packet made of all 5 packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + bool bTestResult = true; + //The packets that will be sent + Byte pPackets[NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE]; + //Total size of all sent packets (this is the max size of the aggregated packet + //minus 2 bytes for each packet in the aggregated packet) + int nTotalPacketsSize = MAX_PACKET_SIZE - (2 * NUM_PACKETS); + //The expected aggregated packet + Byte pExpectedAggregatedPacket[MAX_PACKET_SIZE] = {0}; + //The aggregated packet that will be sent + Byte pAggregatedPacket[MAX_PACKET_SIZE] = {0}; + //The size of the sent aggregated packet + int nAggregatedPacketSize = 0; + + //initialize the packets + //example: for NUM_PACKETS = 5 and MAX_PACKET_SIZE = 1024: + //nTotalPacketsSize will be 1024 - 5*2 = 1014 + //packets[0] size will be 1014/5 = 202 bytes of 0 + //packets[1] size will be (1014 - 202) / 5 = 162 bytes of 1 + //packets[2] size will be (1014 - 201 - 162) / 5 = 130 bytes of 2 + //packets[3] size will be (1014 - 201 - 162 - 130) / 5 = 104 bytes of 3 + //packets[4] size will be 1014 - 201 - 162 - 130 - 104 = 416 bytes of 4 + for (int i = 0; i < NUM_PACKETS; i++) + { + if (NUM_PACKETS - 1 == i) + pPacketsSizes[i] = nTotalPacketsSize; + else + pPacketsSizes[i] = nTotalPacketsSize / NUM_PACKETS; + nTotalPacketsSize -= pPacketsSizes[i]; + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i+ 16*test_num; + } + test_num++; + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < 2; i++) + { + nAggregatedPacketSize += pPacketsSizes[i] + 2; + //the first 2 bytes are the packet length in little endian + pAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //send the aggregated packet + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d " + "bytes)\n", nAggregatedPacketSize); + int nBytesSent = m_UsbDeaggToIpaPipeAgg.Send(pAggregatedPacket, + nAggregatedPacketSize); + if (nAggregatedPacketSize != nBytesSent) + { + LOG_MSG_DEBUG("Sending aggregated packet into the USB pipe(%d " + "bytes) failed!\n", nAggregatedPacketSize); + return false; + } + + //send the packets + for (int i = 2; i < NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", i, + pPacketsSizes[i]); + int nBytesSent = m_UsbNoAggToIpaPipeAgg.Send(pPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes) " + "failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", MAX_PACKET_SIZE); + int nBytesReceived = m_IpaToUsbPipeAggr.Receive(pReceivedPacket, + MAX_PACKET_SIZE); + if (MAX_PACKET_SIZE != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", MAX_PACKET_SIZE); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + + //initializing the aggregated packet + k = 0; + for (int i = 0; i < NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pExpectedAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pExpectedAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pExpectedAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + + bTestResult &= !memcmp(pExpectedAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket)); + + return bTestResult; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +class TLPAggregationTimeLimitLoopTest: public TLPAggregationTestFixture { +public: + + ///////////////////////////////////////////////////////////////////////////////// + + TLPAggregationTimeLimitLoopTest() + { + m_name = "TLPAggregationTimeLimitLoopTest"; + m_description = "TLP Aggregation time limit loop test - sends 1 packet " + "smaller than the byte limit and receives 1 aggregated packets"; + } + + ///////////////////////////////////////////////////////////////////////////////// + + bool Run() + { + //The packets that will be sent + Byte pPackets[TIME_LIMIT_NUM_PACKETS][MAX_PACKET_SIZE]; + //The real sizes of the packets that will be sent + int pPacketsSizes[TIME_LIMIT_NUM_PACKETS]; + //Buffer for the packet that will be received + Byte pReceivedPacket[MAX_PACKET_SIZE] = {0}; + //The expected aggregated packet + Byte pExpectedAggregatedPacket[MAX_PACKET_SIZE] = {0}; + //Size of aggregated packet + int nTotalPacketsSize = 0; + + //initialize the packets + for (int i = 0; i < TIME_LIMIT_NUM_PACKETS; i++) + { + pPacketsSizes[i] = i + 1; + nTotalPacketsSize += pPacketsSizes[i] + 2; //size of the packet + 2 bytes for length + for (int j = 0; j < pPacketsSizes[i]; j++) + pPackets[i][j] = i+ 16*test_num; + } + test_num++; + + for (int n = 0; n < NUM_PACKETS; n++) + { + //send the packets + for (int i = 0; i < TIME_LIMIT_NUM_PACKETS; i++) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d bytes)\n", + i, pPacketsSizes[i]); + int nBytesSent = m_UsbNoAggToIpaPipeAggTime.Send(pPackets[i], + pPacketsSizes[i]); + if (pPacketsSizes[i] != nBytesSent) + { + LOG_MSG_DEBUG("Sending packet %d into the USB pipe(%d " + "bytes) failed!\n", i, pPacketsSizes[i]); + return false; + } + } + + //receive the aggregated packet + LOG_MSG_DEBUG("Reading packet from the USB pipe(%d bytes should be " + "there)\n", nTotalPacketsSize); + int nBytesReceived = m_IpaToUsbPipeAggTime.Receive(pReceivedPacket, + nTotalPacketsSize); + if (nTotalPacketsSize != nBytesReceived) + { + LOG_MSG_DEBUG("Receiving aggregated packet from the USB pipe(%d " + "bytes) failed!\n", nTotalPacketsSize); + print_buff(pReceivedPacket, nBytesReceived); + return false; + } + + //initializing the aggregated packet + int k = 0; + for (int i = 0; i < TIME_LIMIT_NUM_PACKETS; i++) + { + //the first 2 bytes are the packet length in little endian + pExpectedAggregatedPacket[k] = pPacketsSizes[i] & 0x00FF; + pExpectedAggregatedPacket[k+1] = pPacketsSizes[i] >> 8; + k += 2; + for (int j = 0; j < pPacketsSizes[i]; j++) + { + pExpectedAggregatedPacket[k] = pPackets[i][j]; + k++; + } + } + + //comparing the received packet to the aggregated packet + LOG_MSG_DEBUG("Checking sent.vs.received packet\n"); + if (0 != memcmp(pExpectedAggregatedPacket, pReceivedPacket, + sizeof(pReceivedPacket))) + { + LOG_MSG_DEBUG("Comparison of packet %d failed!\n", n); + return false; + } + } + + return true; + } + + ///////////////////////////////////////////////////////////////////////////////// +}; + + +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + +//Those tests should be run with configuration number 8. +//Please look at the Fixture for more configurations update. +static TLPAggregationTest tlpAggregationTest; +static TLPDeaggregationTest tlpDeaggregationTest; +static TLPAggregationLoopTest tlpAggregationLoopTest; +static TLPAggregationTimeLimitTest tlpAggregationTimeLimitTest; +static TLPAggregationByteLimitTest tlpAggregationByteLimitTest; +static TLPAggregation2PipesTest tlpAggregation2PipesTest; +static TLPAggregationTimeLimitLoopTest tlpAggregationTimeLimitLoopTest; +static TLPDeaggregationAndAggregationTest tlpDeaggregationAndAggregationTest; + +///////////////////////////////////////////////////////////////////////////////// +// EOF //// +///////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/TestBase.cpp b/kernel-tests/TestBase.cpp new file mode 100644 index 0000000000..f7886ee1ec --- /dev/null +++ b/kernel-tests/TestBase.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017,2020 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 "TestBase.h" +#include "TestManager.h" +#include "linux/msm_ipa.h" + +////////////////////////////////////////////////////////////////////// + +TestBase::TestBase() : + m_runInRegression(true), + m_minIPAHwType(IPA_HW_v1_1), + m_maxIPAHwType(IPA_HW_MAX) +{ + m_mem_type = DFLT_NAT_MEM_TYPE; +} + +////////////////////////////////////////////////////////////////////// + +void TestBase::Register(TestBase &test) +{ + TestManager::GetInstance()->Register(test); +} + +////////////////////////////////////////////////////////////////////// + +//Empty default implementation, a test does not have to implement Setup() +bool TestBase::Setup() +{ + return true; +} + +////////////////////////////////////////////////////////////////////// + +//Empty default implementation, a test does not have to implement Teardown() +bool TestBase::Teardown() +{ + return true; +} + +////////////////////////////////////////////////////////////////////// + +TestBase::~TestBase() +{ + +} + +////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/TestBase.h b/kernel-tests/TestBase.h new file mode 100644 index 0000000000..47d0347d0d --- /dev/null +++ b/kernel-tests/TestBase.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017,2020 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 _TEST_BASE_H_ +#define _TEST_BASE_H_ + +#include +#include + +#define DFLT_NAT_MEM_TYPE "HYBRID" + +using namespace std; + +class TestBase +{ +public: + virtual bool Setup(); + /* Empty default implementation, + * a test does not have to implement Setup() + */ + virtual bool Run() = 0; + /* A test must implement Run() */ + virtual bool Teardown(); + /* Empty default implementation, + * a test does not have to implement Teardown() + */ + void Register(TestBase & test); + virtual ~TestBase(); + TestBase(); + void SetMemType( + const char* mem_type = DFLT_NAT_MEM_TYPE) + { + m_mem_type = mem_type; + } + + const char* m_mem_type; + string m_name; + string m_description; + vector < string > m_testSuiteName; + /* Every test can belong to multiple test suites */ + bool m_runInRegression; + /* Should this test be run in a regression test ? (Default is yes) */ + int m_minIPAHwType; + /* The minimal IPA HW version which this test can run on */ + int m_maxIPAHwType; + /* The maximal IPA HW version which this test can run on */ +}; +#endif diff --git a/kernel-tests/TestManager.cpp b/kernel-tests/TestManager.cpp new file mode 100644 index 0000000000..268f7391e8 --- /dev/null +++ b/kernel-tests/TestManager.cpp @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2017-2018,2020 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 // std::find +#include // std::vector +#include +#include +#include +#include +#include "TestManager.h" +#include "TestsUtils.h" +#include +#include +#include "ipa_test_module.h" +#include + +using namespace std; + +/* Global static pointer used to ensure a single instance of the class. */ +TestManager* TestManager::m_instance = NULL; + + +#ifdef HAVE_LIBXML + +TestsXMLResult::TestsXMLResult() +{ + xmlNodePtr node; + + // initialize xml report document and add a root to node it + m_XML_doc_ptr = xmlNewDoc(BAD_CAST "1.0"); + if (m_XML_doc_ptr == NULL){ + printf("error on allocation xml doc\n"); + exit(-1); + } + + node = xmlNewNode(NULL, BAD_CAST "testsuites"); + if (!node) { + printf("failed to allocate XML node\n"); + exit (-1); + } + xmlDocSetRootElement(m_XML_doc_ptr, node); +} + +TestsXMLResult::~TestsXMLResult() +{ + if (m_XML_doc_ptr) + xmlFreeDoc(m_XML_doc_ptr); + xmlCleanupParser(); +} + +/* + * Returns xmlPtr to testsuite element node, if doesn't exist + * creates one by that name + */ +xmlNodePtr TestsXMLResult::GetSuiteElement(const string& suite_name) +{ + xmlNodePtr root_node, suite_node, new_child_node; + + if (!m_XML_doc_ptr) { + printf("no xml document\n"); + return NULL; + } + + root_node = xmlDocGetRootElement(m_XML_doc_ptr); + suite_node = xmlFirstElementChild(root_node); + while (suite_node) + { + /* get suite name */ + xmlChar *val = xmlGetProp(suite_node, BAD_CAST "name"); + + /* change xmlCHar* to string */ + string node_suite_name(reinterpret_cast(val)); + xmlFree(val); //free val allocated memory + + if (node_suite_name == suite_name) + return suite_node; + else suite_node = suite_node->next; + } + + /* If we got here no suitable suite name was found, + * so we create a new suite element and return it + */ + new_child_node = xmlNewChild(root_node, NULL, BAD_CAST "testsuite", BAD_CAST ""); + if (!new_child_node) { + printf("failed creating new XML node\n"); + return NULL; + } + xmlSetProp(new_child_node, BAD_CAST "name", BAD_CAST suite_name.c_str()); + + return xmlGetLastChild(root_node); +} + +/* + * Creates new testcase element + */ +void TestsXMLResult::AddTestcase(const string &suite_nm, const string &test_nm, + double runtime, bool pass) +{ + xmlNodePtr suite_node, new_testcase, fail_node; + ostringstream runtime_str; + + if (!suite_nm.size() || !test_nm.size()) { + printf("Input error: suite_nm size %d , test_nm size %d", + suite_nm.size(), test_nm.size()); + exit(-1); + } + + suite_node = GetSuiteElement(suite_nm); + if (!suite_node) { + printf("failed getting suite element\n"); + exit(-1); + } + + /* Create new testcase element as son to suite element */ + new_testcase = xmlNewChild(suite_node, NULL, BAD_CAST "testcase", NULL); + if (!new_testcase) { + printf("failed creating XML new child for testcase\n"); + exit(-1); + } + xmlSetProp(new_testcase, BAD_CAST "name", BAD_CAST test_nm.c_str()); + + runtime_str << runtime; + xmlSetProp(new_testcase, BAD_CAST "time", BAD_CAST runtime_str.str().c_str()); + + if (!pass) { + fail_node = xmlNewChild(new_testcase, NULL, BAD_CAST "failure", NULL); + if (!fail_node) { + printf("failed creating fail node\n"); + exit(-1); + } + } +} + +/* + * Prints the XML tree to file + */ +void TestsXMLResult::GenerateXMLReport(void) +{ + if (!m_XML_doc_ptr) { + printf("no xml document\n"); + return; + } + + xmlSaveFormatFileEnc(XUNIT_REPORT_PATH_AND_NAME, m_XML_doc_ptr, "UTF-8", 1); +} + +#else /* HAVE_LIBXML */ + +TestsXMLResult::TestsXMLResult() {} +TestsXMLResult::~TestsXMLResult() {} +void TestsXMLResult::AddTestcase(const string &suite_nm, const string &test_nm, + double runtime, bool pass) {} +void TestsXMLResult::GenerateXMLReport(void) +{ + printf("No XML support\n"); +} + +#endif /* HAVE_LIBXML */ + +TestManager::TestManager( + const char* nat_mem_type_ptr) +{ + m_testList.clear(); + m_failedTestsNames.clear(); + m_numTestsFailed = 0; + m_numTestsRun = 0; + FetchIPAHwType(); + m_nat_mem_type_ptr = nat_mem_type_ptr; +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +TestManager::~TestManager() +{ + m_testList.clear(); +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +TestManager* TestManager::GetInstance( + const char* nat_mem_type_ptr) +{ + if (!m_instance) // Only allow one instance of class to be generated. + m_instance = new TestManager(nat_mem_type_ptr); + + return m_instance; +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +void TestManager::Register(TestBase &test) +{ + m_testList.push_back(&test); +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +bool TestManager::Run(vector testSuiteList, vector testNameList) +{ + TestBase *test = NULL; + bool pass = true; + vector::iterator testIter; + vector::iterator testSuiteIter; + bool runTest = false; + clock_t begin_test_clk, end_test_clk; + double test_runtime_sec = 0, total_time_sec = 0; + TestsXMLResult xml_res; + + if (m_testList.size() == 0) + return false; + + /* PrintRegisteredTests(); */ + + for (unsigned int i = 0 ; i < m_testList.size() ; i++ , runTest = false) { + pass = true; + test = m_testList[i]; + + // Run only tests from the list of test suites which is stated in the command + // line. In case the list is empty, run all tests. + if (testSuiteList.size() > 0) { + for (unsigned int j = 0; j < test->m_testSuiteName.size(); j++) { + testSuiteIter = find(testSuiteList.begin(), testSuiteList.end(), test->m_testSuiteName[j]); + if (testSuiteIter != testSuiteList.end()) { + runTest = true; + } + } + } + + // We also support test by name + if (testNameList.size() > 0) { + testIter = find(testNameList.begin(), testNameList.end(), test->m_name); + if (testIter != testNameList.end()) + runTest = true; + } + + // Run the test only if it's applicable to the current IPA HW type / version + if (runTest) { + if (!(m_IPAHwType >= test->m_minIPAHwType && m_IPAHwType <= test->m_maxIPAHwType)) + runTest = false; + } + + if (!runTest) + continue; + + printf("\n\nExecuting test %s\n", test->m_name.c_str()); + printf("Description: %s\n", test->m_description.c_str()); + + printf("Setup()\n"); + begin_test_clk = clock(); + test->SetMemType(GetMemType()); + pass &= test->Setup(); + + //In case the test's setup did not go well it will be a bad idea to try and run it. + if (true == pass) + { + printf("Run()\n"); + pass &= test->Run(); + } + + printf("Teardown()\n"); + pass &= test->Teardown(); + + end_test_clk = clock(); + test_runtime_sec = double(end_test_clk - begin_test_clk) / CLOCKS_PER_SEC; + total_time_sec += test_runtime_sec; + + if (pass) + { + m_numTestsRun++; + PrintSeparator(test->m_name.size()); + printf("Test %s PASSED ! time:%g\n", test->m_name.c_str(), test_runtime_sec); + PrintSeparator(test->m_name.size()); + } + else + { + m_numTestsRun++; + m_numTestsFailed++; + m_failedTestsNames.push_back(test->m_name); + PrintSeparator(test->m_name.size()); + printf("Test %s FAILED ! time:%g\n", test->m_name.c_str(), test_runtime_sec); + PrintSeparator(test->m_name.size()); + } + + xml_res.AddTestcase(test->m_testSuiteName[0], test->m_name, test_runtime_sec, pass); + } // for + + // Print summary + printf("\n\n"); + printf("==================== RESULTS SUMMARY ========================\n"); + printf("%zu tests were run, %zu failed, total time:%g.\n", m_numTestsRun, m_numTestsFailed, total_time_sec); + if (0 != m_numTestsFailed) { + printf("Failed tests list:\n"); + for (size_t i = 0; i < m_numTestsFailed; i++) { + printf(" %s\n", m_failedTestsNames[i].c_str()); + m_failedTestsNames.pop_back(); + } + } + printf("=============================================================\n"); + xml_res.GenerateXMLReport(); + + return pass; +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +void TestManager::PrintSeparator(size_t len) +{ + string separator; + + for (size_t i = 0; i < len + 15; i++) { + separator += "-"; + } + + printf("%s\n", separator.c_str()); +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +TestManager::TestManager(TestManager const&) +{ + +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +TestManager& TestManager::operator=(TestManager const&) +{ + return *m_instance; +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +void TestManager::PrintRegisteredTests() +{ + printf("Test list: (%zu registered)\n", m_testList.size()); + for (unsigned int i = 0; i < m_testList.size(); i++) { + printf("%d) name = %s, suite name = %s, regression = %d\n", i, m_testList[i]->m_name.c_str(), + m_testList[i]->m_testSuiteName[0].c_str(), m_testList[i]->m_runInRegression); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// + +void TestManager::FetchIPAHwType() +{ + int fd; + + // Open ipa_test device node + fd = open("/dev/ipa_test" , O_RDONLY); + if (fd < 0) { + printf("Failed opening %s. errno %d: %s\n", "/dev/ipa_test", errno, strerror(errno)); + m_IPAHwType = IPA_HW_None; + return; + } + + printf("%s(), fd is %d\n", __FUNCTION__, fd); + + m_IPAHwType = (enum ipa_hw_type)ioctl(fd, IPA_TEST_IOC_GET_HW_TYPE); + if (-1 == m_IPAHwType) { + printf("%s(), IPA_TEST_IOC_GET_HW_TYPE ioctl failed\n", __FUNCTION__); + m_IPAHwType = IPA_HW_None; + } + + printf("%s(), IPA HW type (version) = %d\n", __FUNCTION__, m_IPAHwType); + close(fd); +} + + +//////////////////////////////////////////////////////////////////////////////////////////// diff --git a/kernel-tests/TestManager.h b/kernel-tests/TestManager.h new file mode 100644 index 0000000000..c106ad3ebb --- /dev/null +++ b/kernel-tests/TestManager.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017-2018,2020 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 _TEST_MANAGER_H_ +#define _TEST_MANAGER_H_ + +#include "TestBase.h" +#include +#include +#include "linux/msm_ipa.h" + +#ifdef HAVE_LIBXML +#include +#include +#endif + +using namespace std; + + +class TestsXMLResult +{ +public: + TestsXMLResult(); + ~TestsXMLResult(); + void AddTestcase(const string &suite_nm, const string &test_nm, + double runtime, bool pass); + void GenerateXMLReport(void); +private: +#ifdef HAVE_LIBXML + xmlNodePtr GetSuiteElement(const string& suite_name); + xmlDocPtr m_XML_doc_ptr; +#endif +}; + +class TestManager /* Singleton */ +{ +public: + static TestManager *GetInstance( + const char* nat_mem_type_ptr = DFLT_NAT_MEM_TYPE); + ~TestManager(); + void Register(TestBase & test); + bool Setup(); + /* This is the place to put initialization + * for the whole test framework + */ + bool Run(vector testSuiteList, + vector testNameList); + /* This function will run all the tests in the system */ + bool Teardown(); + /* This is the place to put tear-down for the whole test framework */ + vector < TestBase * > m_testList; + /* Holds pointers to all of the tests in the system */ + + enum ipa_hw_type GetIPAHwType() {return m_IPAHwType;} + const char* GetMemType() { return m_nat_mem_type_ptr; } + +private: + TestManager( + const char* nat_mem_type_ptr = DFLT_NAT_MEM_TYPE); + TestManager(TestManager const &); + TestManager & operator = (TestManager const &); + void PrintSeparator(size_t len); + void PrintRegisteredTests(); + void BuildRegressionTestSuite(); + void FetchIPAHwType(); + + static TestManager *m_instance; + + size_t m_numTestsRun; + size_t m_numTestsFailed; + enum ipa_hw_type m_IPAHwType; + const char* m_nat_mem_type_ptr; + + vector < string > m_failedTestsNames; +}; + +#endif diff --git a/kernel-tests/TestsUtils.cpp b/kernel-tests/TestsUtils.cpp new file mode 100644 index 0000000000..4a6e36fc4c --- /dev/null +++ b/kernel-tests/TestsUtils.cpp @@ -0,0 +1,1814 @@ +/* + * Copyright (c) 2017-2020 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 +#include +#include +#include +#include "TestsUtils.h" +#include "InterfaceAbstraction.h" +#include "Constants.h" +#include "Pipe.h" + +using namespace std; +/////////////////////////////////////////////////////////////////////////////// + +extern Logger g_Logger; + +static uint8_t IPv4Packet[IP4_PACKET_SIZE] = { + 0x45, 0x00, 0x00, 0x2e, + 0x00, 0x00, 0x40, 0x00, + 0xff, 0x06, 0xf5, 0xfd,// Protocol = 06 (TCP) + 0xc0, 0xa8, 0x02, 0x13,// IPv4 SRC Addr 192.168.2.19 + 0xc0, 0xa8, 0x02, 0x68,// IPv4 DST Addr 192.168.2.104 + 0x04, 0x57, 0x08, 0xae, + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, + 0x00, 0xaa, 0xaa, 0xaa, + 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb +}; + +static uint8_t IPv6Packet[] = { + 0x60, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x06, 0x01, // Protocol = 6 (TCP) + 0xfe, 0x80, 0x00, 0x00, // source address (16B) + 0x00, 0x00, 0x00, 0x00, + 0xd9, 0xf9, 0xce, 0x5e, + 0x02, 0xec, 0x32, 0x99, + 0xff, 0x02, 0x00, 0x00, // dst address (16B) + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, + 0x12, 0x34, 0x12, 0x34, // port src = 0x1234 dest = 0x1234 + 0x00, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // options + 0xda, 0x7a, 0xda, 0x7a // payload +}; + +static uint8_t IPv6PacketFragExtHdr[] = { + 0x60, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x2C, 0x01, // Next header = FRAGMENT HEADER(44) + 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xd9, 0xf9, 0xce, 0x5e, + 0x02, 0xec, 0x32, 0x99, + 0xff, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, + 0x06, 0x00, 0x00, 0x00, // fragment header, Protocol = 6 (TCP) + 0x00, 0x00, 0x00, 0x00, + 0x12, 0x34, 0x12, 0x34, // port src = 0x1234 dest = 0x1234 + 0x00, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xda, 0x7a, 0xda, 0x7a // payload +}; + +static const uint8_t Eth2IPv4Packet[] = +{ + // ETH2 - 14 bytes + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11, // ETH2 DST + 0x22, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, // ETH2 SRC + 0x08, 0x00, // ETH2 TYPE IPv4 - ETH_P_IP 0x0800 + + // IPv4 + 0x45, 0x00, 0x00, 0x2e, + 0x00, 0x00, 0x40, 0x00, + 0xff, 0x06, 0xf5, 0xfd, // Protocol = 06 (TCP) + 0xc0, 0xa8, 0x02, 0x13, // IPv4 SRC Addr 192.168.2.19 + 0xc0, 0xa8, 0x02, 0x68, // IPv4 DST Addr 192.168.2.104 + 0x04, 0x57, 0x08, 0xae, + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, + 0x00 +}; + +static const uint8_t Eth2IPv6Packet[] = +{ + // ETH2 - 14 bytes + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11, // ETH2 DST + 0x22, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, // ETH2 SRC + 0x86, 0xdd, // ETH2 TYPE IPv6 - ETH_P_IPV6 x86DD + + // IPv6 + 0x60, 0x00, 0x00, 0x00, + 0x02, 0x12, 0x11, 0x01, + 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xd9, 0xf9, 0xce, 0x5e, + 0x02, 0xec, 0x32, 0x99, + 0xff, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c +}; + +static const uint8_t WLANEth2IPv4Packet[] = +{ + // WLAN + 0xa1, 0xb2, 0xc3, 0xd4, // WLAN hdr + + // ETH2 - 14 bytes + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11, // ETH2 DST + 0x22, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, // ETH2 SRC + 0x08, 0x00, // ETH2 TYPE IPv4 - ETH_P_IP 0x0800 + + // IPv4 + 0x45, 0x00, 0x00, 0x2e, + 0x00, 0x00, 0x40, 0x00, + 0xff, 0x06, 0xf5, 0xfd, // Protocol = 06 (TCP) + 0xc0, 0xa8, 0x02, 0x13, // IPv4 SRC Addr 192.168.2.19 + 0xc0, 0xa8, 0x02, 0x68, // IPv4 DST Addr 192.168.2.104 + 0x04, 0x57, 0x08, 0xae, + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, + 0x00 +}; + +static const uint8_t WLAN802_3IPv4Packet[] = +{ + // WLAN + 0xa1, 0xb2, 0xc3, 0xd4, // WLAN hdr + + // 802_3 - 26 bytes + 0xa5, 0xb6, 0xc7, 0xd8, // ROME proprietary header + 0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0x33, // 802_3 DST + 0x44, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, // 802_3 SRC + 0x00, IP4_PACKET_SIZE, // 802_3 length + 0x04, 0x15, 0x26, 0x37, 0x48, 0x59, // LLC/SNAP + 0x08, 0x00, // Ethrtype - 0x0800 + + // IPv4 + 0x45, 0x00, 0x00, 0x2e, + 0x00, 0x00, 0x40, 0x00, + 0xff, 0x06, 0xf5, 0xfd, // Protocol = 06 (TCP) + 0xc0, 0xa8, 0x02, 0x13, // IPv4 SRC Addr 192.168.2.19 + 0xc0, 0xa8, 0x02, 0x68, // IPv4 DST Addr 192.168.2.104 + 0x04, 0x57, 0x08, 0xae, + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, + 0x00 +}; + +static uint8_t IPv4_TCP_No_Payload_Packet[] = { + 0x45, 0x00, 0x00, 0x28, // Total length is 40 + 0x00, 0x00, 0x40, 0x00, + 0xff, 0x06, 0xf5, 0xfd, // Protocol = 06 (TCP) + 0xc0, 0xa8, 0x02, 0x13, // IPv4 SRC Addr 192.168.2.19 + 0xc0, 0xa8, 0x02, 0xc8, // IPv4 DST Addr 192.168.2.200 + 0x04, 0x57, 0x08, 0xae, + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, +}; + +static uint8_t IPv6_TCP_No_Payload_Packet[] = { + 0x60, 0x00, 0x00, 0x00, + 0x00, 0x14, 0x06, 0x01, // Payload is 20 Bytes (TCP header only) + 0xfe, 0x80, 0x00, 0x00, // SRC Addr + 0x00, 0x00, 0x00, 0x00, + 0xd9, 0xf9, 0xce, 0x5e, + 0x02, 0xec, 0x32, 0x99, + 0xff, 0x02, 0x00, 0x00, // DST Addr + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4b, + 0x04, 0x57, 0x08, 0xae, // TCP header + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, +}; + +static const uint8_t Eth2IPv4Packet802_1Q_tag[] = +{ + // ETH2 + 8021Q - 14 + 4 bytes + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11, // ETH2 DST + 0x22, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, // ETH2 SRC + 0x81, 0x00, 0x20, 0x03, // 802.1Q header with VLAN ID = 3 + 0x08, 0x00, // ETH2 TYPE IPv4 - ETH_P_IP 0x0800 + // IPv4 + 0x45, 0x00, 0x00, 0x2e, + 0x00, 0x00, 0x40, 0x00, + 0xff, 0x06, 0xf5, 0xfd, // Protocol = 06 (TCP) + 0xc0, 0xa8, 0x02, 0x13, // IPv4 SRC Addr 192.168.2.19 + 0xc0, 0xa8, 0x02, 0x68, // IPv4 DST Addr 192.168.2.104 + 0x04, 0x57, 0x08, 0xae, + 0x00, 0x00, 0x30, 0x34, + 0x00, 0x00, 0x00, 0x50, + 0x50, 0xc1, 0x40, 0x00, + 0xab, 0xc9, 0x00, 0x00, + 0x00 +}; + +static struct ipa_test_config_header *current_configuration = NULL; + +/////////////////////////////////////////////////////////////////////////////// +/** +*@brief Function loads a default IPv4 / IPv6 Packet +* +*@param [in] eIP - Type of Packet to load (IPA_IP_v4 / IPA_IP_v6) +*@param [in] pBuffer - pointer to the destination buffer +*@param [in,out] nMaxSize - The size of the buffer.*Upon function return, +* the total number of bytes copied will be stored in this parameter. +*@return boolean indicating whether the operation completed successfully or not. +*@details Function loads a default IPv4 / IPv6 packet into pBuffer. +*/ +bool LoadDefaultPacket( + enum ipa_ip_type eIP, + enum ipv6_ext_hdr_type extHdrType, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (IPA_IP_v4 == eIP) { + if (nMaxSize < sizeof(IPv4Packet)) + { + LOG_MSG_ERROR("Buffer is smaller than %d, no Data was copied.",sizeof(IPv4Packet)); + return false; + } + memcpy(pBuffer,IPv4Packet, sizeof(IPv4Packet)); + nMaxSize = sizeof(IPv4Packet); + return true; + } else { + if (extHdrType == FRAGMENT) + { + if (nMaxSize < sizeof(IPv6PacketFragExtHdr)) + { + LOG_MSG_ERROR("Buffer is smaller than %d, no Data was copied.",sizeof(IPv6PacketFragExtHdr)); + return false; + } + memcpy(pBuffer,IPv6PacketFragExtHdr, sizeof(IPv6PacketFragExtHdr)); + nMaxSize = sizeof(IPv6PacketFragExtHdr); + + } + else + { + if (nMaxSize < sizeof(IPv6Packet)) + { + LOG_MSG_ERROR("Buffer is smaller than %d, no Data was copied.",sizeof(IPv6Packet)); + return false; + } + memcpy(pBuffer,IPv6Packet, sizeof(IPv6Packet)); + nMaxSize = sizeof(IPv6Packet); + } + return true; + } +} + +bool LoadDefaultPacket(enum ipa_ip_type eIP, uint8_t *pBuffer, size_t &nMaxSize) +{ + return LoadDefaultPacket(eIP, NONE, pBuffer, nMaxSize); +} + +bool LoadNoPayloadPacket(enum ipa_ip_type eIP, uint8_t *pBuffer, size_t &nMaxSize) +{ + if (IPA_IP_v4 == eIP) { + if (nMaxSize < sizeof(IPv4_TCP_No_Payload_Packet)) + { + LOG_MSG_ERROR("Buffer is smaller than %zu, no Data was copied.", + sizeof(IPv4_TCP_No_Payload_Packet)); + return false; + } + memcpy(pBuffer, IPv4_TCP_No_Payload_Packet, sizeof(IPv4_TCP_No_Payload_Packet)); + nMaxSize = sizeof(IPv4_TCP_No_Payload_Packet); + } else { + if (nMaxSize < sizeof(IPv6_TCP_No_Payload_Packet)) + { + LOG_MSG_ERROR("Buffer is smaller than %zu, no Data was copied.", + sizeof(IPv6_TCP_No_Payload_Packet)); + return false; + } + memcpy(pBuffer, IPv6_TCP_No_Payload_Packet, sizeof(IPv6_TCP_No_Payload_Packet)); + nMaxSize = sizeof(IPv6_TCP_No_Payload_Packet); + } + + return true; +} + +bool LoadDefaultEth2Packet( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (IPA_IP_v4 == eIP) { + if (nMaxSize < sizeof(Eth2IPv4Packet)) + { + LOG_MSG_ERROR( + "Buffer is smaller than %d, " + "no data was copied.", + sizeof(Eth2IPv4Packet)); + return false; + } + memcpy(pBuffer,Eth2IPv4Packet, + sizeof(Eth2IPv4Packet)); + nMaxSize = sizeof(Eth2IPv4Packet); + } + else + { + if (nMaxSize < sizeof(Eth2IPv6Packet)) + { + LOG_MSG_ERROR( + "Buffer is smaller than %d, " + "no data was copied.", + sizeof(Eth2IPv6Packet)); + return false; + } + memcpy(pBuffer,Eth2IPv6Packet, + sizeof(Eth2IPv6Packet)); + nMaxSize = sizeof(Eth2IPv6Packet); + } + + return true; +} + +bool LoadDefaultWLANEth2Packet( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (IPA_IP_v4 == eIP) { + if (nMaxSize < sizeof(WLANEth2IPv4Packet)) + { + LOG_MSG_ERROR( + "Buffer is smaller than %d, " + "no data was copied.", + sizeof(WLANEth2IPv4Packet)); + return false; + } + memcpy(pBuffer,WLANEth2IPv4Packet, + sizeof(WLANEth2IPv4Packet)); + nMaxSize = sizeof(WLANEth2IPv4Packet); + } + else + { + LOG_MSG_ERROR("%s isn't implemented " + "for IPv6 - do it yourself :-)", + __FUNCTION__); + return false; + } + + return true; +} + +bool LoadDefaultWLAN802_32Packet( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (IPA_IP_v4 == eIP) { + if (nMaxSize < sizeof(WLAN802_3IPv4Packet)) + { + LOG_MSG_ERROR( + "Buffer is smaller than %d, " + "no data was copied.", + sizeof(WLAN802_3IPv4Packet)); + return false; + } + memcpy(pBuffer,WLAN802_3IPv4Packet, + sizeof(WLAN802_3IPv4Packet)); + nMaxSize = sizeof(WLAN802_3IPv4Packet); + } + else + { + LOG_MSG_ERROR("%s isn't implemented" + " for IPv6 - do it yourself :-)", + __FUNCTION__); + return false; + } + + return true; +} + +bool LoadDefault802_1Q( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (IPA_IP_v4 == eIP) { + if (nMaxSize < sizeof(Eth2IPv4Packet802_1Q_tag)) { + LOG_MSG_ERROR( + "Buffer is smaller than %d, " + "no data was copied.", + sizeof(Eth2IPv4Packet802_1Q_tag)); + return false; + } + memcpy(pBuffer, Eth2IPv4Packet802_1Q_tag, + sizeof(Eth2IPv4Packet802_1Q_tag)); + nMaxSize = sizeof(Eth2IPv4Packet802_1Q_tag); + } else { + LOG_MSG_ERROR("%s isn't implemented" + " for IPv6 - do it yourself :-)", + __FUNCTION__); + return false; + } + + return true; +} + +bool SendReceiveAndCompare(InterfaceAbstraction *pSink, uint8_t* pSendBuffer, size_t nSendBuffSize, + InterfaceAbstraction *pSource, uint8_t* pExpectedBuffer, size_t nExpectedBuffSize) +{ + LOG_MSG_STACK("Entering Function"); + bool bRetVal = true; + uint8_t * pRxBuff = new uint8_t[2*(nExpectedBuffSize+1)]; + size_t nReceivedBuffSize = 0; + size_t j; + + // Send buffer to pSink + bRetVal = pSink->SendData((Byte *) pSendBuffer, nSendBuffSize); + if (!bRetVal) + { + LOG_MSG_ERROR("SendData (pOutputBuffer=0x%p) failed",pSendBuffer); + goto bail; + } + + // Receive buffer from pSource + if (NULL == pRxBuff) + { + LOG_MSG_ERROR("Failed to allocated pRxBuff[%d]",2*(nExpectedBuffSize+1)); + goto bail; + } + nReceivedBuffSize = pSource->ReceiveData(pRxBuff, 2*(nExpectedBuffSize+1)); // We cannot overflow here. + LOG_MSG_INFO("Received %d bytes on %s.", nReceivedBuffSize, pSource->m_fromChannelName.c_str()); + if (0 > nReceivedBuffSize) + { + bRetVal = false; + goto bail; + } + + {// Logging Expected and Received buffers + char aExpectedBufferStr[3*nExpectedBuffSize+1]; + char aRecievedBufferStr[3*nReceivedBuffSize+1]; + memset(aExpectedBufferStr,0,3*nExpectedBuffSize+1); + memset(aRecievedBufferStr,0,3*nReceivedBuffSize+1); + + for(j = 0; j < nExpectedBuffSize; j++) + snprintf(&aExpectedBufferStr[3*j], 3*nExpectedBuffSize+1 - (3*j + 1), " %02X", pExpectedBuffer[j]); + for(j = 0; j < nReceivedBuffSize; j++) + snprintf(&aRecievedBufferStr[3*j], 3*nReceivedBuffSize+1 - (3*j + 1), " %02X", pRxBuff[j]); + LOG_MSG_INFO("\nExpected Value (%d)\n%s\n, Received Value(%d)\n%s\n",nExpectedBuffSize,aExpectedBufferStr,nReceivedBuffSize,aRecievedBufferStr); + } + + //Comparing Expected and received sizes + if (nExpectedBuffSize != nReceivedBuffSize) + { + LOG_MSG_INFO("Buffers' Size differ: expected(%d), Received(%d)",nExpectedBuffSize,nReceivedBuffSize); + bRetVal = false; + goto bail; + } + + bRetVal = !memcmp((void*)pRxBuff, (void*)pExpectedBuffer, nExpectedBuffSize); + LOG_MSG_INFO("Buffers %s ",bRetVal?"MATCH":"MISMATCH"); + + + LOG_MSG_INFO("Verify that pipe is Empty"); + nReceivedBuffSize = pSource->ReceiveData(pRxBuff, 2*(nExpectedBuffSize+1)); // We cannot overflow here. + while (nReceivedBuffSize){ + char aRecievedBufferStr[3*nReceivedBuffSize+1]; + bRetVal = false; + LOG_MSG_ERROR("More Data in Pipe!\nReceived %d bytes on %s.", nReceivedBuffSize, pSource->m_fromChannelName.c_str()); + memset(aRecievedBufferStr,0,3*nReceivedBuffSize+1); + for(j = 0; j < nReceivedBuffSize; j++) { + snprintf(&aRecievedBufferStr[3*j], 3*nReceivedBuffSize+1 - (3*j + 1), " %02X", pRxBuff[j]); + } + LOG_MSG_ERROR("\nReceived Value(%d)\n%s\n",nReceivedBuffSize,aRecievedBufferStr); + nReceivedBuffSize = pSource->ReceiveData(pRxBuff, 2*(nExpectedBuffSize+1)); // We cannot overflow here. + } + +bail: + delete (pRxBuff); + LOG_MSG_STACK("Leaving Function (Returning %s)",bRetVal?"True":"False"); + return bRetVal; +} + +bool CreateBypassRoutingTable (RoutingDriverWrapper * pRouting,enum ipa_ip_type eIP, + const char * pTableName, enum ipa_client_type eRuleDestination, + uint32_t uHeaderHandle, uint32_t * pTableHdl) +{ + bool bRetVal = true; + struct ipa_ioc_add_rt_rule *pRoutingRule = NULL; + struct ipa_rt_rule_add *pRoutingRuleEntry = NULL; + struct ipa_ioc_get_rt_tbl sRoutingTable; + + LOG_MSG_STACK("Entering Function"); + memset(&sRoutingTable,0,sizeof(sRoutingTable)); + pRoutingRule = (struct ipa_ioc_add_rt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_rt_rule) + + 1*sizeof(struct ipa_rt_rule_add) + ); + if(!pRoutingRule) { + LOG_MSG_ERROR("calloc failed to allocate pRoutingRule"); + bRetVal = false; + goto bail; + } + + pRoutingRule->num_rules = 1; + pRoutingRule->ip = ((IPA_IP_v4 == eIP)? IPA_IP_v4 : IPA_IP_v6); + pRoutingRule->commit = true; + strlcpy(pRoutingRule->rt_tbl_name, pTableName, sizeof(pRoutingRule->rt_tbl_name)); + + pRoutingRuleEntry = &(pRoutingRule->rules[0]); + pRoutingRuleEntry->at_rear = 1; + pRoutingRuleEntry->rule.dst = eRuleDestination;// Setting Rule's Destination Pipe + pRoutingRuleEntry->rule.hdr_hdl = uHeaderHandle; // Header handle + pRoutingRuleEntry->rule.attrib.attrib_mask = 0;// All Packets will get a "Hit" + if (false == pRouting->AddRoutingRule(pRoutingRule)) + { + LOG_MSG_ERROR("Routing rule addition(pRoutingRule) failed!"); + bRetVal = false; + goto bail; + } + if (!pRoutingRuleEntry->rt_rule_hdl) + { + LOG_MSG_ERROR("pRoutingRuleEntry->rt_rule_hdl == 0, Routing rule addition(pRoutingRule) failed!"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("pRoutingRuleEntry->rt_rule_hdl == 0x%x added to Table %s",pRoutingRuleEntry->rt_rule_hdl,pTableName); + sRoutingTable.ip = eIP; + strlcpy(sRoutingTable.name, pTableName, sizeof(sRoutingTable.name)); + if (!pRouting->GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&sRoutingTable=0x%p) Failed.", &sRoutingTable); + bRetVal = false; + goto bail; + } + if(NULL != pTableHdl){ + (* pTableHdl ) = sRoutingTable.hdl; + LOG_MSG_DEBUG("Table Handle =0x%x will be returned.",(*pTableHdl)); + } + +bail: + Free (pRoutingRule); + LOG_MSG_STACK("Leaving Function (Returning %s)",bRetVal?"True":"False"); + return bRetVal; +} + +bool CreateBypassRoutingTable_v2 (RoutingDriverWrapper * pRouting,enum ipa_ip_type eIP, + const char * pTableName, enum ipa_client_type eRuleDestination, + uint32_t uHeaderHandle, uint32_t * pTableHdl, uint8_t uClsAggrIrqMod) +{ + bool bRetVal = true; + struct ipa_ioc_add_rt_rule_v2 *pRoutingRule = NULL; + struct ipa_rt_rule_add_v2 *pRoutingRuleEntry = NULL; + struct ipa_ioc_get_rt_tbl sRoutingTable; + + LOG_MSG_STACK("Entering Function"); + memset(&sRoutingTable,0,sizeof(sRoutingTable)); + pRoutingRule = (struct ipa_ioc_add_rt_rule_v2 *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule_v2)); + if(!pRoutingRule) { + LOG_MSG_ERROR("calloc failed to allocate pRoutingRule"); + bRetVal = false; + goto bail; + } + pRoutingRule->rules = (uint64_t)calloc(1, sizeof(struct ipa_rt_rule_add_v2)); + if (!pRoutingRule->rules) { + LOG_MSG_ERROR("calloc failed to allocate pRoutingRule->rules"); + bRetVal = false; + goto bail; + } + + pRoutingRule->num_rules = 1; + pRoutingRule->rule_add_size = sizeof(struct ipa_rt_rule_add_v2); + printf("%s(), Nadav: Adding rule_add_size\n", __FUNCTION__); + pRoutingRule->ip = ((IPA_IP_v4 == eIP)? IPA_IP_v4 : IPA_IP_v6); + pRoutingRule->commit = true; + strlcpy(pRoutingRule->rt_tbl_name, pTableName, sizeof(pRoutingRule->rt_tbl_name)); + + pRoutingRuleEntry = &(((struct ipa_rt_rule_add_v2 *)pRoutingRule->rules)[0]); + pRoutingRuleEntry->at_rear = 1; + pRoutingRuleEntry->rule.dst = eRuleDestination;// Setting Rule's Destination Pipe + printf("%s(), Nadav: Destination = %d\n", __FUNCTION__, pRoutingRuleEntry->rule.dst); + pRoutingRuleEntry->rule.hdr_hdl = uHeaderHandle; // Header handle + pRoutingRuleEntry->rule.attrib.attrib_mask = 0;// All Packets will get a "Hit" + pRoutingRuleEntry->rule.close_aggr_irq_mod = uClsAggrIrqMod; + if (false == pRouting->AddRoutingRule(pRoutingRule)) + { + LOG_MSG_ERROR("Routing rule addition(pRoutingRule) failed!"); + bRetVal = false; + goto bail; + } + if (!pRoutingRuleEntry->rt_rule_hdl) + { + LOG_MSG_ERROR("pRoutingRuleEntry->rt_rule_hdl == 0, Routing rule addition(pRoutingRule) failed!"); + bRetVal = false; + goto bail; + } + LOG_MSG_INFO("pRoutingRuleEntry->rt_rule_hdl == 0x%x added to Table %s",pRoutingRuleEntry->rt_rule_hdl,pTableName); + sRoutingTable.ip = eIP; + strlcpy(sRoutingTable.name, pTableName, sizeof(sRoutingTable.name)); + if (!pRouting->GetRoutingTable(&sRoutingTable)) { + LOG_MSG_ERROR( + "m_routing.GetRoutingTable(&sRoutingTable=0x%p) Failed.", &sRoutingTable); + bRetVal = false; + goto bail; + } + if(NULL != pTableHdl){ + (* pTableHdl ) = sRoutingTable.hdl; + LOG_MSG_DEBUG("Table Handle =0x%x will be returned.",(*pTableHdl)); + } + +bail: + Free (pRoutingRule); + LOG_MSG_STACK("Leaving Function (Returning %s)",bRetVal?"True":"False"); + return bRetVal; +} + +//Don't use these methods directly. use MACROs instead +void __log_msg(enum msgType logType, const char* filename, int line, const char* function, const char* format, ... ) +{ + va_list args; + switch (logType) { + case ERROR: + fprintf( stderr, "ERROR!"); + break; + case DEBUG: + fprintf( stderr, "DEBUG:"); + break; + case INFO: + fprintf( stderr, "INFO :"); + break; + case STACK: + fprintf( stderr, "STACK:"); + break; + default: + fprintf( stderr, "BUG!!!"); + break; + } + fprintf( stderr, " [%s:%d, %s()] ",filename,line,function); + va_start( args, format ); + vfprintf( stderr, format, args ); + va_end( args ); + fprintf( stderr, "\n" ); +} + +bool file_exists(const char* filename) +{ + return (access(filename, F_OK) == 0); +} + +int ConfigureSystem(int testConfiguration, int fd) +{ + return ConfigureSystem(testConfiguration, fd, NULL); +} + +int ConfigureSystem(int testConfiguration, int fd, const char* params) +{ + char testConfigurationStr[10]; + int ret; + char *pSendBuffer; + char str[10]; + int iter_cnt = 2000; + + if(params != NULL) + pSendBuffer = new char[strlen(params) + 10]; + else + pSendBuffer = new char[10]; + + if (NULL == pSendBuffer) + { + LOG_MSG_ERROR("Failed to allocated pSendBuffer"); + return -1; + } + + if(params != NULL) + snprintf(pSendBuffer, strlen(params) + 10, "%d %s", testConfiguration, params); + else + snprintf(pSendBuffer, 10, "%d", testConfiguration); + + ret = write(fd, pSendBuffer, sizeof(pSendBuffer) ); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s Write operation failed.\n", __FUNCTION__); + goto bail; + } + + // Wait until the system is fully configured + + // Convert testConfiguration to string + snprintf(testConfigurationStr, sizeof(testConfigurationStr), "%d", testConfiguration); + + // Read the configuration index from the device node + ret = read(fd, str, sizeof(str)); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s Read operation failed.\n", __FUNCTION__); + goto bail; + } + + while ( strcmp(str, testConfigurationStr) ) { + // Sleep for 5 msec + struct timespec time; + time.tv_sec = 0; + time.tv_nsec = 50e6; + nanosleep(&time, NULL); + ret = read(fd, str, sizeof(str)); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s Read operation failed.\n", __FUNCTION__); + goto bail; + } + if (!--iter_cnt) { + g_Logger.AddMessage(LOG_ERROR, "%s timeout waiting for test driver.\n", __FUNCTION__); + ret = -1; + goto bail; + } + } +bail: + delete[] pSendBuffer; + return ret; +} + +void ConfigureScenario(int testConfiguration) +{ + ConfigureScenario(testConfiguration, NULL); +} + +void ConfigureScenario(int testConfiguration, const char* params) +{ + int fd, ret; + char str[10]; + int currentConf; + + // Open /dev/ipa_test device node. This will allow to configure the system + // and read its current configuration. + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s Could not open configuration device node.\n", __FUNCTION__); + exit(0); + } + + // Read the current configuration. + ret = read(fd, str, sizeof(str)); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s Read operation failed.\n", __FUNCTION__); + return; + } + currentConf = atoi(str); + + // Do not reconfigure to the same configuration + if (currentConf == testConfiguration) { + g_Logger.AddMessage(LOG_DEVELOPMENT,"%s System was already configured as required(%d)\n", + __FUNCTION__, currentConf); + return; + } + + /* in case the system is not "clean"*/ + if (-1 != currentConf) { + g_Logger.AddMessage(LOG_DEVELOPMENT,"%s System has other configuration (%d) - cleanup\n", __FUNCTION__, currentConf); + ret = ConfigureSystem(-1, fd); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s Configure operation failed.\n", + __FUNCTION__); + return; + } + } + + // Start system configuration. + g_Logger.AddMessage(LOG_DEVELOPMENT,"%s Setting system to the required configuration (%d)\n", __FUNCTION__, testConfiguration); + + ret = ConfigureSystem(testConfiguration, fd, params); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s configure operation failed.\n", + __FUNCTION__); + return; + } + + ret = system("mdev -s"); + if (ret < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s system(\"mdev -s\") returned %d\n", + __FUNCTION__, ret); + } + + close(fd); +}//func + +void clean_old_stashed_config() +{ + if (current_configuration == NULL) + return; + + for (int i = 0 ; i < current_configuration->from_ipa_channels_num ; i++) { + delete((struct test_ipa_ep_cfg*) + current_configuration->from_ipa_channel_config[i]->cfg); + delete((struct test_ipa_ep_cfg*) + current_configuration->from_ipa_channel_config[i]); + } + + for (int i = 0 ; i < current_configuration->to_ipa_channels_num ; i++) { + delete((struct test_ipa_ep_cfg*) + current_configuration->to_ipa_channel_config[i]->cfg); + delete((struct test_ipa_ep_cfg*) + current_configuration->to_ipa_channel_config[i]); + } + delete(current_configuration); + current_configuration = NULL; +} + +void stash_new_configuration(struct ipa_test_config_header *header) +{ + clean_old_stashed_config(); + + /* + * We will start by shallow copying each level, and afterwards, + * override the pointers + */ + current_configuration = new ipa_test_config_header(); + *current_configuration = *header; + + current_configuration->from_ipa_channel_config = + new ipa_channel_config*[header->from_ipa_channels_num](); + + current_configuration->to_ipa_channel_config = + new ipa_channel_config*[header->to_ipa_channels_num](); + + for (int i = 0 ; i < current_configuration->from_ipa_channels_num ; i++) { + current_configuration->from_ipa_channel_config[i] = + new ipa_channel_config; + *current_configuration->from_ipa_channel_config[i] = + *header->from_ipa_channel_config[i]; + current_configuration->from_ipa_channel_config[i]->cfg = + new test_ipa_ep_cfg(); + memcpy(current_configuration->from_ipa_channel_config[i]->cfg, + header->from_ipa_channel_config[i]->cfg, + header->from_ipa_channel_config[i]->config_size); + } + + for (int i = 0 ; i < current_configuration->to_ipa_channels_num ; i++) { + current_configuration->to_ipa_channel_config[i] = + new ipa_channel_config; + *current_configuration->to_ipa_channel_config[i] = + *header->to_ipa_channel_config[i]; + current_configuration->to_ipa_channel_config[i]->cfg = new test_ipa_ep_cfg(); + memcpy(current_configuration->to_ipa_channel_config[i]->cfg, + header->to_ipa_channel_config[i]->cfg, + header->to_ipa_channel_config[i]->config_size); + } +} + +bool is_prev_configuration_generic() +{ + int fd; + char str[10] = {0}; + int retval; + int current_conf_num; + + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd < 0) { + g_Logger.AddMessage(LOG_ERROR ,"%s Could not open configuration device node.\n", __FUNCTION__); + exit(0); + } + + retval = read(fd, str, sizeof(str)); + close(fd); + if (retval < 0) { + g_Logger.AddMessage(LOG_ERROR ,"%s Read operation failed.\n", __FUNCTION__); + return true; + } + current_conf_num = atoi(str); + + if (current_conf_num == GENERIC_TEST_CONFIGURATION_IDX) + return true; + + return false; +} + + +static bool is_reconfigure_required(struct ipa_test_config_header *header) +{ + // Is reconfiguration not required flag (current conf is cool) + bool flag = true; + + if (is_prev_configuration_generic() == false) { + g_Logger.AddMessage(LOG_DEVELOPMENT , + "prev configuration didn't use generic configuration\n"); + return true; + } + + if (current_configuration == NULL) { + g_Logger.AddMessage(LOG_DEVELOPMENT , + "no prev generic configuration found in the test app data-base\n"); + return true; + } + + flag &= (header->from_ipa_channels_num == + current_configuration->from_ipa_channels_num); + flag &= (header->to_ipa_channels_num == + current_configuration->to_ipa_channels_num); + + if (flag == false) { + g_Logger.AddMessage(LOG_DEVELOPMENT , + "not same number of pipes\n"); + return true; + } + + for (int i = 0 ; i < header->from_ipa_channels_num ; i++) { + flag &= (header->from_ipa_channel_config[i]->client == + current_configuration->from_ipa_channel_config[i]->client); + flag &= (header->from_ipa_channel_config[i]->index == + current_configuration->from_ipa_channel_config[i]->index); + flag &= !memcmp(header->from_ipa_channel_config[i]->cfg, + current_configuration->from_ipa_channel_config[i]->cfg, + header->from_ipa_channel_config[i]->config_size); + flag &= (header->from_ipa_channel_config[i]->en_status == + current_configuration->from_ipa_channel_config[i]->en_status); + } + + if (flag == false) { + g_Logger.AddMessage(LOG_DEVELOPMENT , + "\"from\" endpoint configuration is different from prev\n"); + return true; + } + + for (int i = 0 ; i < header->to_ipa_channels_num ; i++) { + flag &= (header->to_ipa_channel_config[i]->client == + current_configuration->to_ipa_channel_config[i]->client); + flag &= (header->to_ipa_channel_config[i]->index == + current_configuration->to_ipa_channel_config[i]->index); + flag &= !memcmp(header->to_ipa_channel_config[i]->cfg, + current_configuration->to_ipa_channel_config[i]->cfg, + header->to_ipa_channel_config[i]->config_size); + flag &= (header->to_ipa_channel_config[i]->en_status == + current_configuration->to_ipa_channel_config[i]->en_status); + } + + if (flag == false) { + g_Logger.AddMessage(LOG_DEVELOPMENT , + "\"to\" endpoint configuration is different from prev\n"); + return true; + } + + return false; +} + +int GenericConfigureScenario(struct ipa_test_config_header *header) +{ + int fd; + int retval; + + if (is_reconfigure_required(header) == false) { + 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, "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->from_ipa_channels_num=%d\n", header->from_ipa_channels_num); + g_Logger.AddMessage(LOG_DEVELOPMENT, "header->to_ipa_channels_num=%d\n", header->to_ipa_channels_num); + g_Logger.AddMessage(LOG_DEVELOPMENT, "header->tail_marker=0x%x\n", header->tail_marker); + + for (int i = 0 ; i < header->from_ipa_channels_num ; i++) { + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->from_ipa_channel_config[%d]->head_marker=0x%x\n", i, + header->from_ipa_channel_config[i]->head_marker); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->from_ipa_channel_config[%d]->index=%d\n", i, + header->from_ipa_channel_config[i]->index); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->from_ipa_channel_config[%d]->client=%d\n", i, + header->from_ipa_channel_config[i]->client); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->from_ipa_channel_config[%d]->config_size=%d\n", i, + header->from_ipa_channel_config[i]->config_size); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->from_ipa_channel_config[%d]->en_status=%d\n", i, + header->from_ipa_channel_config[i]->en_status); + } + + for (int i = 0 ; i < header->to_ipa_channels_num ; i++) { + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->to_ipa_channel_config[%d]->head_marker=0x%x\n", i, + header->to_ipa_channel_config[i]->head_marker); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->to_ipa_channel_config[%d]->index=%d\n", i, + header->to_ipa_channel_config[i]->index); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->to_ipa_channel_config[%d]->client=%d\n", i, + header->to_ipa_channel_config[i]->client); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->to_ipa_channel_config[%d]->config_size=%d\n", i, + header->to_ipa_channel_config[i]->config_size); + g_Logger.AddMessage(LOG_DEVELOPMENT, + "header->to_ipa_channel_config[%d]->en_status=%d\n", i, + header->to_ipa_channel_config[i]->en_status); + } + + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd == -1) { + g_Logger.AddMessage(LOG_ERROR, + "%s - open %s failed (fd=%d,errno=%s)\n", + __FUNCTION__, CONFIGURATION_NODE_PATH, fd, strerror(errno)); + return false; + } + + 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); + return false; + } else { + g_Logger.AddMessage(LOG_DEVELOPMENT, "system was successfully configured\n"); + } + + retval = close(fd); + if (retval) { + g_Logger.AddMessage(LOG_ERROR, + "%s - fail to close the fd (path=%s,retval=%d,fd=%d,errno=%s)\n", + __FUNCTION__, CONFIGURATION_NODE_PATH, retval, fd, strerror(errno)); + return false; + } + + g_Logger.AddMessage(LOG_DEVELOPMENT ,"stashing new configuration\n"); + stash_new_configuration(header); + + g_Logger.AddMessage(LOG_DEVELOPMENT, + "Running mdev in order to create the device nodes.\n"); + + retval = system("mdev -s"); + if (retval < 0) { + g_Logger.AddMessage(LOG_ERROR, "%s system(\"mdev -s\") returned %d\n", + __FUNCTION__, retval); + } + + return true; +} + +int GenericConfigureScenarioDestory(void) +{ + int fd; + int retval; + + g_Logger.AddMessage(LOG_DEVELOPMENT, "cleanup started\n"); + + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd == -1) { + g_Logger.AddMessage(LOG_ERROR, + "%s - open %s failed (retval=%d,fd=%d,errno=%s)\n", + __FUNCTION__, CONFIGURATION_NODE_PATH, fd, strerror(errno)); + return false; + } + + retval = ioctl(fd, IPA_TEST_IOC_CLEAN); + if (retval) + g_Logger.AddMessage(LOG_ERROR, "fail to clean the system (%d)\n", retval); + else + g_Logger.AddMessage(LOG_DEVELOPMENT, "system was successfully cleaned\n"); + + retval = close(fd); + if (retval) { + g_Logger.AddMessage(LOG_ERROR, "fail to close the fd - %d\n", retval); + return false; + } + + return true; +} + +bool configure_ep_ctrl(struct ipa_test_ep_ctrl *ep_ctrl) +{ + int fd; + int retval = 0; + + g_Logger.AddMessage(LOG_DEVELOPMENT, "ep ctrl started \n"); + + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd == -1) { + g_Logger.AddMessage(LOG_ERROR, + "%s - open %s failed (retval=%d,fd=%d,errno=%s)\n", + __FUNCTION__, CONFIGURATION_NODE_PATH, fd, strerror(errno)); + return false; + } + + retval = ioctl(fd, IPA_TEST_IOC_EP_CTRL, ep_ctrl); + if (retval) + g_Logger.AddMessage(LOG_ERROR, "fail to perform ep ctrl (%d)\n", retval); + else + g_Logger.AddMessage(LOG_DEVELOPMENT, "ep ctrl was successfully executed\n"); + + retval = close(fd); + if (retval) { + g_Logger.AddMessage(LOG_ERROR, "fail to close the fd - %d\n", retval); + } + + return true; +} + +bool configure_holb(struct ipa_test_holb_config *test_holb_config) +{ + int fd; + int retval = 0; + + g_Logger.AddMessage(LOG_DEVELOPMENT, "holb config started \n"); + + if (!test_holb_config) { + g_Logger.AddMessage(LOG_ERROR, "Null pointer argument!"); + return false; + } + + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd == -1) { + g_Logger.AddMessage(LOG_ERROR, + "%s - open %s failed (retval=%d,fd=%d,errno=%s)\n", + __FUNCTION__, CONFIGURATION_NODE_PATH, fd, strerror(errno)); + return false; + } + + retval = ioctl(fd, IPA_TEST_IOC_HOLB_CONFIG, test_holb_config); + if (retval) + g_Logger.AddMessage(LOG_ERROR, + "fail to perform holb config (%d)\n", + retval); + else + g_Logger.AddMessage(LOG_DEVELOPMENT, + "holb config was successfully executed\n"); + + retval = close(fd); + if (retval) { + g_Logger.AddMessage(LOG_ERROR, "fail to close the fd - %d\n", retval); + } + + return true; +} + +void prepare_channel_struct(struct ipa_channel_config *channel, + int index, + enum ipa_client_type client, + void *cfg, + size_t config_size, + bool en_status) +{ + channel->head_marker = IPA_TEST_CHANNEL_CONFIG_MARKER; + channel->index = index; + channel->client = client; + channel->cfg = (char*)cfg; + channel->config_size = config_size; + channel->tail_marker = IPA_TEST_CHANNEL_CONFIG_MARKER; + channel->en_status = en_status; +} + +void prepare_header_struct(struct ipa_test_config_header *header, + struct ipa_channel_config **from, + struct ipa_channel_config **to) +{ + header->head_marker = IPA_TEST_CONFIG_MARKER; + header->from_ipa_channel_config = from; + header->to_ipa_channel_config = to; + header->tail_marker = IPA_TEST_CONFIG_MARKER; +} + +bool CompareResultVsGolden(Byte *goldenBuffer, unsigned int goldenSize, + Byte *receivedBuffer, unsigned int receivedSize) +{ + if (receivedSize != goldenSize) { + g_Logger.AddMessage(LOG_VERBOSE, "%s File sizes are different.\n", __FUNCTION__); + return false; + } + return !memcmp((void*)receivedBuffer, (void*)goldenBuffer, goldenSize); +} + +bool CompareResultVsGolden_w_Status(Byte *goldenBuffer, unsigned int goldenSize, + Byte *receivedBuffer, unsigned int receivedSize) +{ + size_t stts_size = sizeof(struct ipa3_hw_pkt_status); + + if (TestManager::GetInstance()->GetIPAHwType() >= IPA_HW_v5_0) { + stts_size = sizeof(struct ipa3_hw_pkt_status_hw_v5_0); + } + + if ((receivedSize - stts_size) != goldenSize) { + g_Logger.AddMessage(LOG_VERBOSE, "%s Buffer sizes are different.\n", __FUNCTION__); + return false; + } + + printf("comparison is made considering %zu status bytes!\n", stts_size); + + return !memcmp((void*)((unsigned char *)receivedBuffer + + stts_size), (void*)goldenBuffer, goldenSize); +} + + +Byte *LoadFileToMemory(const string &name, unsigned int *sizeLoaded) +{ + FILE *file; + Byte *buffer; + size_t fileLen; + + // Open file + file = fopen(name.c_str(), "rb"); + if (!file) { + g_Logger.AddMessage(LOG_ERROR, "Unable to open file %s\n", name.c_str()); + return NULL; + } + + // Get file length + fseek(file, 0, SEEK_END); + fileLen = ftell(file); + fseek(file, 0, SEEK_SET); + + // Allocate memory + buffer=(Byte*)malloc(fileLen+1); + if (!buffer) { + fprintf(stderr, "Memory error!\n"); + fclose(file); + return NULL; + } + + // Read file contents into buffer + *sizeLoaded = fread(buffer, 1, fileLen, file); + fclose(file); + + return buffer; +} + +void print_buff(void *data, size_t size) +{ + uint8_t bytes_in_line = 16; + uint i, j, num_lines; + char str[1024], tmp[4]; + + num_lines = size / bytes_in_line; + if (size % bytes_in_line > 0) + num_lines++; + + printf("Printing buffer at address 0x%p, size = %zu: \n", data, size); + for (i = 0 ; i < num_lines; i++) { + str[0] = '\0'; + for (j = 0; (j < bytes_in_line) && ((i * bytes_in_line + j) < size); j++) { + snprintf(tmp, sizeof(tmp), "%02x ", + ((unsigned char*)data)[i * bytes_in_line + j]); + strlcpy(str + strlen(str), tmp, sizeof(str) - strlen(str)); + } + printf("%s\n", str); + } +} + +void add_buff(uint8_t *data, size_t size, uint8_t val) +{ + for (int i = 0; i < static_cast(size); i++) + data[i]+=val; +} + +bool RegSuspendHandler(bool deferred_flag, bool reg, int DevNum) +{ + int fd = 0; + int retval = 0; + struct ipa_test_reg_suspend_handler RegData; + + fd = open(CONFIGURATION_NODE_PATH, O_RDWR); + if (fd == -1) { + g_Logger.AddMessage(LOG_ERROR, + "%s - open %s failed (fd=%d,errno=%s)\n", + __FUNCTION__, CONFIGURATION_NODE_PATH, fd, strerror(errno)); + return false; + } + + RegData.DevNum = DevNum; + RegData.reg = reg; + RegData.deferred_flag = deferred_flag; + + retval = ioctl(fd, IPA_TEST_IOC_REG_SUSPEND_HNDL, &RegData); + if (retval) { + g_Logger.AddMessage(LOG_ERROR, "fail to reg suspend handler (%d)\n", retval); + close(fd); + return false; + } else { + g_Logger.AddMessage(LOG_DEVELOPMENT, "suspend handler was successfully configured\n"); + } + + close(fd); + + return true; +} + +const Byte Eth2Helper::m_ETH2_IP4_HDR[ETH_HLEN] = +{ + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, // ETH2 DST + 0xA7, 0xA8, 0xA9, 0xB0, 0xB1, 0xB2, // ETH2 SRC + 0x08, 0x00, // ETH2 TYPE IPv4 - ETH_P_IP 0x0800 +}; + +bool Eth2Helper::LoadEth2IP4Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + if (bufferSize < ETH_HLEN) + { + LOG_MSG_ERROR("Buffer too small\n"); + return false; + } + + memcpy(pBuffer, m_ETH2_IP4_HDR, ETH_HLEN); + + *pLen = ETH_HLEN; + + return true; +} + +bool Eth2Helper::LoadEth2IP6Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + if (bufferSize < ETH_HLEN) + { + LOG_MSG_ERROR("Buffer too small\n"); + return false; + } + + // copy eth2 ip4 header + memcpy(pBuffer, m_ETH2_IP4_HDR, ETH_HLEN); + + // change ethtype to ip6 + pBuffer[ETH2_ETH_TYPE_OFFSET] = 0x86; + pBuffer[ETH2_ETH_TYPE_OFFSET+1] = 0xdd; + + *pLen = ETH_HLEN; + + return true; +} + +bool Eth2Helper::LoadEth2IP4Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + size_t cnt = 0; + size_t len = 0; + + if (!LoadEth2IP4Header(pBuffer, bufferSize, &cnt)) + return false; + + len = bufferSize - cnt; + + if (!LoadDefaultPacket(IPA_IP_v4, pBuffer + cnt, len)) + return false; + + *pLen = len + cnt; + + return true; +} + +bool Eth2Helper::LoadEth2IP6Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + size_t cnt = 0; + size_t len = 0; + + if (!LoadEth2IP6Header(pBuffer, bufferSize, &cnt)) + return false; + + len = bufferSize - cnt; + + if (!LoadDefaultPacket(IPA_IP_v6, pBuffer + cnt, len)) + return false; + + *pLen = len + cnt; + + return true; +} + +const Byte WlanHelper::m_WLAN_HDR[WLAN_HDR_SIZE] = +{ + // WLAN hdr - 4 bytes + 0x01, 0x02, 0x03, 0x04 +}; + +bool WlanHelper::LoadWlanHeader( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + if (bufferSize < WLAN_HDR_SIZE) + { + LOG_MSG_ERROR("Buffer too small\n"); + return false; + } + + memcpy(pBuffer, m_WLAN_HDR, WLAN_HDR_SIZE); + + *pLen = WLAN_HDR_SIZE; + + return true; +} + +bool WlanHelper::LoadWlanEth2IP4Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + size_t cnt = 0; + size_t len = 0; + + if (!LoadWlanHeader(pBuffer, bufferSize, &cnt)) + return false; + + if (!Eth2Helper::LoadEth2IP4Header( + pBuffer + cnt, + bufferSize - cnt, + &len)) + return false; + + *pLen = len + cnt; + + return true; +} + +bool WlanHelper::LoadWlanEth2IP6Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + size_t cnt = 0; + size_t len = 0; + + if (!LoadWlanHeader(pBuffer, bufferSize, &cnt)) + return false; + + if (!Eth2Helper::LoadEth2IP6Header( + pBuffer + cnt, + bufferSize - cnt, + &len)) + return false; + + *pLen = len + cnt; + + return true; +} + +bool WlanHelper::LoadWlanEth2IP4Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen) +{ + size_t cnt = 0; + size_t len = 0; + + if (!LoadWlanHeader(pBuffer, bufferSize, &cnt)) + return false; + + if (!Eth2Helper::LoadEth2IP4Packet( + pBuffer + cnt, + bufferSize - cnt, + &len)) + return false; + + *pLen = len + cnt; + + return true; +} + +bool PadByLength( + uint8_t *pBuffer, + size_t bufferSize, + size_t len, + uint8_t padValue) +{ + if (bufferSize < len) + { + LOG_MSG_ERROR("bufferSize < len.\n"); + return false; + } + + memset(pBuffer, padValue, len); + + return true; +} + +bool WlanHelper::LoadWlanEth2IP4PacketByLength( + uint8_t *pBuffer, + size_t bufferSize, + size_t len, + uint8_t padValue) +{ + size_t cnt = 0; + + if (!LoadWlanEth2IP4Packet(pBuffer, bufferSize, &cnt)) + return false; + + if (!PadByLength(pBuffer + cnt, bufferSize - cnt, len - cnt, padValue)) + return false; + + return true; +} + +bool RNDISAggregationHelper::LoadRNDISHeader( + uint8_t *pBuffer, + size_t bufferSize, + uint32_t messageLength, + size_t *pLen) +{ + if (bufferSize < RNDIS_HDR_SIZE) + { + LOG_MSG_ERROR("Buffer too small\n"); + return false; + } + + struct RndisHeader *pRndisHeader = + reinterpret_cast(pBuffer); + + memset(pRndisHeader, 0, sizeof(struct RndisHeader)); + pRndisHeader->MessageType = 0x01; + pRndisHeader->DataOffset = 0x24; + + if (messageLength > RNDIS_HDR_SIZE) + { + pRndisHeader->MessageLength = messageLength; + pRndisHeader->DataLength = messageLength - RNDIS_HDR_SIZE; + } + else + { + // This handles a case where we use the header + // in IPA headers table + // IPA needs to set these values + pRndisHeader->MessageLength = 0; + pRndisHeader->DataLength = 0; + } + + *pLen = RNDIS_HDR_SIZE; + + return true; +} + +bool RNDISAggregationHelper::LoadRNDISEth2IP4Header( + uint8_t *pBuffer, + size_t bufferSize, + uint32_t messageLength, + size_t *pLen) +{ + size_t cnt = 0; + size_t len = 0; + + if (!LoadRNDISHeader(pBuffer, bufferSize, messageLength, &cnt)) + return 0; + + if (!Eth2Helper::LoadEth2IP4Header(pBuffer + cnt, bufferSize - cnt, &len)) + return false; + + *pLen = cnt + len; + + return true; +} + +bool RNDISAggregationHelper::LoadRNDISPacket( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (nMaxSize < sizeof(struct RndisHeader)) + { + LOG_MSG_ERROR("Buffer too small\n"); + return false; + } + + size_t nMaxSizeForDefaultPacket = nMaxSize - sizeof(struct RndisHeader); + + if (!LoadEtherPacket(eIP, pBuffer + sizeof(struct RndisHeader), + nMaxSizeForDefaultPacket)) + { + LOG_MSG_ERROR("LoadEtherPacket() failed\n"); + return false; + } + + nMaxSize = nMaxSizeForDefaultPacket + sizeof(struct RndisHeader); + struct RndisHeader *pRndisHeader = (struct RndisHeader*)pBuffer; + + memset(pRndisHeader, 0, sizeof(struct RndisHeader)); + pRndisHeader->MessageType = 0x01; + pRndisHeader->MessageLength = nMaxSize; + pRndisHeader->DataOffset = 0x24; + pRndisHeader->DataLength = nMaxSizeForDefaultPacket; + return true; +} + +bool RNDISAggregationHelper::LoadEtherPacket( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize) +{ + if (nMaxSize < sizeof(struct ethhdr)) + { + LOG_MSG_ERROR("Buffer too small\n"); + return false; + } + + size_t nMaxSizeForDefaultPacket = nMaxSize - sizeof(struct ethhdr); + + if (!LoadDefaultPacket(eIP, pBuffer + sizeof(struct ethhdr), + nMaxSizeForDefaultPacket)) + { + LOG_MSG_ERROR("LoadDefaultPacket() failed\n"); + return false; + } + + nMaxSize = nMaxSizeForDefaultPacket + sizeof(struct ethhdr); + struct ethhdr *pEtherHeader = (struct ethhdr*)pBuffer; + + memcpy(pEtherHeader, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + + print_buff(pBuffer, nMaxSize); + return true; + + +} + +bool RNDISAggregationHelper::CompareIPvsRNDISPacket( + Byte *pIPPacket, + int ipPacketSize, + Byte *pRNDISPacket, + size_t rndisPacketSize) +{ + struct RndisHeader *pRndisHeader = (struct RndisHeader*)pRNDISPacket; + + if (pRndisHeader->MessageType != 0x01) + { + LOG_MSG_ERROR("Wrong MessageType 0x%8x\n", + pRndisHeader->MessageType); + return false; + } + + if (pRndisHeader->MessageLength != rndisPacketSize) + { + LOG_MSG_ERROR( + "Packet sizes do not match 0x%8x expected 0x%8x\n", + pRndisHeader->MessageLength, rndisPacketSize); + return false; + } + + // Create Ethernet packet from the IP packet and compare it to RNDIS payload + size_t EtherPacketSize = ipPacketSize + sizeof(struct ethhdr); + Byte* pEtherPacket = (Byte *) malloc(EtherPacketSize); + if (pEtherPacket == NULL) { + LOG_MSG_ERROR("Memory allocation failure.\n"); + return false; + } + + memcpy(pEtherPacket, Eth2Helper::m_ETH2_IP4_HDR, sizeof(struct ethhdr)); + memcpy(pEtherPacket + sizeof(struct ethhdr), pIPPacket, ipPacketSize); + + if (pRndisHeader->DataLength != EtherPacketSize) + { + LOG_MSG_ERROR( + "Packet sizes do not match 0x%8x expected 0x%8x\n", + pRndisHeader->DataLength, EtherPacketSize); + Free(pEtherPacket); + return false; + } + + if(!ComparePackets( + (Byte*)&pRndisHeader->DataOffset + pRndisHeader->DataOffset, + EtherPacketSize, pEtherPacket, EtherPacketSize)) + { + LOG_MSG_ERROR("Packets do not match\n"); + Free(pEtherPacket); + return false; + } + + Free(pEtherPacket); + return true; +} + +bool RNDISAggregationHelper::CompareEthervsRNDISPacket( + Byte *pIPPacket, + size_t ipPacketSize, + Byte *pRNDISPacket, + size_t rndisPacketSize) +{ + struct RndisHeader *pRndisHeader = (struct RndisHeader*)pRNDISPacket; + + if (pRndisHeader->MessageType != 0x01) + { + LOG_MSG_ERROR("Wrong MessageType 0x%8x\n", + pRndisHeader->MessageType); + return false; + } + + if (pRndisHeader->MessageLength != rndisPacketSize) + { + LOG_MSG_ERROR( + "Packet sizes do not match 0x%8x expected 0x%8x\n", + pRndisHeader->MessageLength, rndisPacketSize); + return false; + } + + if (pRndisHeader->DataLength != ipPacketSize) + { + LOG_MSG_ERROR( + "Packet sizes do not match 0x%8x expected 0x%8x\n", + pRndisHeader->DataLength, ipPacketSize); + return false; + } + + return ComparePackets( + (Byte*)&pRndisHeader->DataOffset + pRndisHeader->DataOffset, + ipPacketSize, pIPPacket, ipPacketSize); +} + +bool RNDISAggregationHelper::ComparePackets( + Byte *pPacket, + int packetSize, + Byte *pExpectedPacket, + int expectedPacketSize) +{ + bool res = true; + + if (packetSize != expectedPacketSize) + { + LOG_MSG_ERROR("Packet sizes do not match\n"); + res = false; + } + + for (int i = 0; i < packetSize; i++) + { + if (pPacket[i] != pExpectedPacket[i]) + { + LOG_MSG_ERROR( + "Byte %d not match 0x%2x != 0x%2x\n", + i, pPacket[i], pExpectedPacket[i]); + res = false; + } + } + + if (!res) + { + LOG_MSG_ERROR("Packet:\n"); + print_buff(pPacket, packetSize); + LOG_MSG_ERROR("Expected Packet:\n"); + print_buff(pExpectedPacket, expectedPacketSize); + } + + return res; +} + + +#if !defined(MSM_IPA_TESTS) && !defined(USE_GLIB) && !defined(FEATURE_IPA_ANDROID) +size_t strlcpy(char* dst, const char* src, size_t size) +{ + size_t i; + + if (size == 0) + return strlen(src); + + for (i = 0; i < (size - 1) && src[i] != '\0'; ++i) + dst[i] = src[i]; + + dst[i] = '\0'; + + return i + strlen(src + i); +} +#endif diff --git a/kernel-tests/TestsUtils.h b/kernel-tests/TestsUtils.h new file mode 100644 index 0000000000..6be92d1997 --- /dev/null +++ b/kernel-tests/TestsUtils.h @@ -0,0 +1,798 @@ +/* + * Copyright (c) 2017-2020 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 __TESTS_UTILS__H__ +#define __TESTS_UTILS__H__ + +#include +#include +#include +#include +#include +#include "TestBase.h" +#include "Constants.h" +#include "RoutingDriverWrapper.h" +#include "InterfaceAbstraction.h" +#include "ipa_test_module.h" +#include "TestManager.h" +#include "Logger.h" +#include "Constants.h" +extern "C" { +#include "ipa_nat_utils.h" +} + +using namespace std; +#define TEST_APP_VERSION "2.00" + +#define Free(x) do { if (x) {free(x); x = NULL; } } while (0) + +#define MAX3(_X, _Y, _Z) max(max((_X), (_Y)), (_Z)) + +#define ETH2_DST_ADDR_OFFSET (0) +#define ETH2_SRC_ADDR_OFFSET (ETH_ALEN) +#define ETH2_ETH_TYPE_OFFSET (ETH2_SRC_ADDR_OFFSET + ETH_ALEN) +#define ETH2_ETH_TYPE_LEN (2) +#define ETH2_PAYLOAD_OFFSET (ETH2_ETH_TYPE_OFFSET + ETH2_ETH_TYPE_LEN) + +#define ETH8021Q_HEADER_LEN (18) +#define ETH8021Q_METADATA_OFFSET (12) +#define ETH8021Q_8021Q_TAG_LEN (4) +#define ETH8021Q_ETH_TYPE_OFFSET (ETH8021Q_METADATA_OFFSET + ETH8021Q_8021Q_TAG_LEN) + +#define WLAN_HDR_SIZE (4) +#define RNDIS_HDR_SIZE (44) + +// 26 ROME WLAN Frame = +// 4 ROME WLAN header + +// 14 IEEE 802.3 + +// 8 802.2 LLC/SNAP +#define _802_3_HDR_SIZE (26) + +// [WLAN][ETH2] header +#define WLAN_ETH2_HDR_SIZE (WLAN_HDR_SIZE + ETH_HLEN) + +// [RNDIS][ETH2] header +#define RNDIS_ETH2_HDR_SIZE (RNDIS_HDR_SIZE + ETH_HLEN) +#define IP4_PACKET_SIZE (70) // Arbitrary number + +// OFFSET = sizeof(struct rndis_pkt_hdr) - RNDIS_HDR_OFST(data_ofst) +#define RNDIS_DATA_OFFSET (36) + +// [WLAN][802.3] header +#define WLAN_802_3_HDR_SIZE (WLAN_HDR_SIZE + _802_3_HDR_SIZE) + +#define IPA_CLIENT_IS_PROD(x) \ + (x < IPA_CLIENT_MAX && (x & 0x1) == 0) +#define IPA_CLIENT_IS_CONS(x) \ + (x < IPA_CLIENT_MAX && (x & 0x1) == 1) + +enum msgType { + ERROR = 0, + DEBUG, + INFO, + STACK +}; + +/** + @brief + Do not Use this function. Use MACROs instead. + + @details + Do not Use this function. + Instead use the MACROs: LOG_MSG_ERROR, LOG_MSG_INFO & LOG_MSG_DEBUG + */ +void __log_msg(enum msgType, + const char *filename, + int line, const char *function, + const char *format, ...); + +#define LOG_MSG_ERROR(...) \ +__log_msg(ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define LOG_MSG_DEBUG(...) \ +__log_msg(DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define LOG_MSG_INFO(...) \ +__log_msg(INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define LOG_MSG_STACK(...) \ +__log_msg(STACK, __FILE__, __LINE__, __func__, __VA_ARGS__) + +/*#define LOG_MSG_ERROR(x...) +__log_msg(ERROR, __FILE__, __LINE__, __func__, x) +#define LOG_MSG_DEBUG(x...) +__log_msg(DEBUG, __FILE__, __LINE__, __func__, x) +#define LOG_MSG_INFO(x...) +__log_msg(INFO, __FILE__, __LINE__, __func__, x) +#define LOG_MSG_STACK(x...) +__log_msg(STACK, __FILE__, __LINE__, __func__, x)*/ + +/** + @brief + Function loads a default IPv4 / IPv6 Packet + + @param [in] eIP - Type of Packet to load (IPA_IP_v4 / IPA_IP_v6) + @param [in] pBuffer - pointer to the destination buffer + @param [in,out] nMaxSize - The size of the buffer. + Upon function return, + the total number of bytes copied will be stored in this parameter. + @return boolean indicating whether the + operation completed successfully or not. + + @details + Function loads a default IPv4 / IPv6 packet into pBuffer. + */ +bool LoadDefaultPacket( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + +bool LoadDefaultEth2Packet( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + +bool LoadDefaultWLANEth2Packet( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + +bool LoadDefaultWLAN802_32Packet( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + +bool LoadNoPayloadPacket( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + +bool LoadDefault802_1Q( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + +/** + @brief + Function loads a default IPv4 / IPv6 Packet + + @param [in] eIP - Type of Packet to load (IPA_IP_v4 / IPA_IP_v6) + @param [in] extHdrType - Type of IPV6 extension header(FRAGMENT / NONE) + @param [in] pBuffer - pointer to the destination buffer + @param [in,out] nMaxSize - The size of the buffer. + Upon function return, + the total number of bytes copied will be stored in this parameter. + @return boolean indicating whether the + operation completed successfully or not. + + @details + Function loads a default IPv4 / IPv6 packet into pBuffer. + */ +bool LoadDefaultPacket( + enum ipa_ip_type eIP, + enum ipv6_ext_hdr_type extHdrType, + uint8_t *pBuffer, + size_t &nMaxSize); +/** + @brief + Function Sends a Packet, Receive a packet + and compares the received result with an expected buffer + + @param [in] pSink - Destination to which a packet will be sent. + @param [in] pSendBuffer - + Pointer to a buffer containing the packet that will be sent. + @param [in] nSendBuffSize - The size of the data in the packet. + @param [in] pSource - Source from which a packet will be received. + @param [in] pExpectedBuffer - Pointer a + buffer containing the expected packet (from the receiver) + @param [in] nExpectedBuffSize - The size of + valid data within pExpectedBuffer. + @return Boolean indicating whether the operation + completed successfully and the buffers matching or not. + + @details + Function sends a packet to pSink, and receives a packet from pSource. + The packet received from pSource + is compared to the expected data from pExpectedBuffer. + If ExpectData is identical to the + received data, the function returns TRUE. + */ +bool SendReceiveAndCompare( + InterfaceAbstraction * pSink, + uint8_t *pSendBuffer, + size_t nSendBuffSize, + InterfaceAbstraction * pSource, + uint8_t *pExpectedBuffer, + size_t nExpectedBuffSize); + +/** + @brief + This function creates a bypass rule within a table in the Routing block + + @param [in] pRouting - pointer to the Routing Class + @param [in] eIP - Type of Packet to load (IPA_IP_v4 / IPA_IP_v6) + @param [in] pTableName - pointer to the Table's Name. + @param [in] eRuleDestination - destination of the bypass rule. + @param [in] uHeaderHandle - + handle to the Header that should be Added (0 should be used as default). + @param [out] pTableHdl - + pointer to the table Handle (Can be Null) + @return boolean indicating whether + the operation completed successfully or not. + + @details + This function creates bypass rule within a table in the Routing block. + */ +bool CreateBypassRoutingTable( + RoutingDriverWrapper * pRouting, + enum ipa_ip_type eIP, + const char *pTableName, + enum ipa_client_type eRuleDestination, + uint32_t uHeaderHandle, + uint32_t *pTableHdl); + +/** + @brief + This function creates a bypass rule within a table in the Routing block + + @param [in] pRouting - pointer to the Routing Class + @param [in] eIP - Type of Packet to load (IPA_IP_v4 / IPA_IP_v6) + @param [in] pTableName - pointer to the Table's Name. + @param [in] eRuleDestination - destination of the bypass rule. + @param [in] uHeaderHandle - + handle to the Header that should be Added (0 should be used as default). + @param [out] pTableHdl - + pointer to the table Handle (Can be Null) + @return boolean indicating whether + the operation completed successfully or not. + + @details + This function creates bypass rule within a table in the Routing block. + */ +bool CreateBypassRoutingTable_v2( + RoutingDriverWrapper * pRouting, + enum ipa_ip_type eIP, + const char *pTableName, + enum ipa_client_type eRuleDestination, + uint32_t uHeaderHandle, + uint32_t *pTableHdl, + uint8_t uClsAggrIrqMod); + +/** + @brief + Configures the sytem to one of the pre-determined + configurations. + + @param [in] testConfiguration - Configuration number + @param [in] params - additional parameters + @return void + + @details + Writes the configuration index to /dev/ipa_test. In case + the system has already been configured, returns. +*/ +void ConfigureScenario(int testConfiguration); +void ConfigureScenario(int testConfiguration, const char *params); +int GenericConfigureScenario(struct ipa_test_config_header *header); +int GenericConfigureScenarioDestory(void); +int ConfigureSystem(int testConfiguration, int fd); +int ConfigureSystem(int testConfiguration, int fd, const char *params); + +void prepare_channel_struct(struct ipa_channel_config *channel, + int index, + enum ipa_client_type client, + void *cfg, + size_t config_size, + bool en_status = 0); + +void prepare_header_struct(struct ipa_test_config_header *header, + struct ipa_channel_config **from, + struct ipa_channel_config **to); + +/** + @brief + Compares two data buffers. + + @param [in] goldenBuffer - Pointer to the first data + buffer + @param [in] goldenSize - First data buffer size + @param [in] receivedBuffer - Pointer to the second data + buffer + @param [in] receivedSize - Second data buffer size + @return True - the buffers are identical. False + otherwise. + + @details + In case the sizes are differnt, false is returned. +*/ +bool CompareResultVsGolden( + unsigned char *goldenBuffer, + unsigned int goldenSize, + unsigned char *receivedBuffer, + unsigned int receivedSize); + +/** + @brief + Compares two data buffers considering the returned status. + + @param [in] goldenBuffer - Pointer to the first data + buffer + @param [in] goldenSize - First data buffer size + @param [in] receivedBuffer - Pointer to the second data + buffer + @param [in] receivedSize - Second data buffer size + @return True - the buffers are identical. False + otherwise. + + @details + In case the sizes are differnt, false is returned. +*/ +bool CompareResultVsGolden_w_Status( + Byte *goldenBuffer, + unsigned int goldenSize, + Byte *receivedBuffer, + unsigned int receivedSize); + + +/** + @brief + Loads a file to memory + + @param [in] fileFullPath + @param [inout] sizeLoaded - returns the number of bytes + which were read from the file + @return Address of the loaded data buffer + + @details + Allocates memory by itself, user should free the memory + +*/ +unsigned char *LoadFileToMemory( + const string & fileFullPath, + unsigned int *sizeLoaded); + +/** + @brief + Checks whether a file exists on disk + + @param [in] filename + @return True if the file exists, false otherwise. + + @details +*/ +bool file_exists(const char *filename); + +/** + @brief + Prints a data buffer. + @param [in] data - Pointer to the data + @param [in] size - How many bytes to print + @return void + + @details +*/ +void print_buff(void *data, size_t size); + +void add_buff(uint8_t *data, size_t size, uint8_t val); + +/** + @brief + Performes ep control of a specific endpoint. + @param [in] ep_ctrl - Pointer to ipa_test_ep_ctrl struct with + the data of the requested operation + @return bool + + @details + Suspend\Unsuspends\Delays\resumes an endpoint. +*/ +bool configure_ep_ctrl(struct ipa_test_ep_ctrl *ep_ctrl); + +/** + @brief + Performes holb config of a specific pipe. + * @param [in] test_holb_config - Pointer to + * ipa_test_holb_config struct with the data of + * the requested operation + @return bool + + @details + Configures HOLB parameters on a pipe. +*/ +bool configure_holb(struct ipa_test_holb_config *test_holb_config); + +/** + @brief + Register an alternative suspend handler + @param [in] deferred_flag - should the handler execute in defer mode + @param [in] reg - register or unregister the suspend handler + @param [in] DevNum - the index of the ep that the handler is registered to + @return bool + + @details + Register the test framework suspend handler for a given endpoint +*/ +bool RegSuspendHandler(bool deferred_flag, bool reg, int DevNum); + +class Eth2Helper { +public: + static const Byte m_ETH2_IP4_HDR[ETH_HLEN]; + + static bool LoadEth2IP4Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadEth2IP6Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadEth2IP4Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadEth2IP6Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); +}; + +class WlanHelper { +public: + static const Byte m_WLAN_HDR[WLAN_HDR_SIZE]; + + static bool LoadWlanHeader( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadWlanEth2IP4Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadWlanEth2IP6Header( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadWlanEth2IP4Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); + + static bool LoadWlanEth2IP4PacketByLength( + uint8_t *pBuffer, + size_t bufferSize, + size_t len, + uint8_t padValue); + + static bool LoadWlanEth2IP6Packet( + uint8_t *pBuffer, + size_t bufferSize, + size_t *pLen); +}; + +#pragma pack(push) /* push current alignment to stack */ +#pragma pack(1) /* set alignment to 1 byte boundary */ +struct RndisHeader { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t DataOffset; + uint32_t DataLength; + uint32_t OOBDataOffset; + uint32_t OOBDataLength; + uint32_t OOBNumber; + uint32_t PacketInfoOffset; + uint32_t PacketInfoLength; + uint64_t Reserved; +}; + +struct RndisEtherHeader { + struct RndisHeader rndisHeader; + struct ethhdr etherHeader; +}; +#pragma pack(pop) /* restore original alignment from stack */ + +class RNDISAggregationHelper { +public: + static const size_t RNDIS_AGGREGATION_BYTE_LIMIT = 1024; + + static bool LoadRNDISHeader( + uint8_t *pBuffer, + size_t bufferSize, + uint32_t messageLength, + size_t *pLen); + + static bool LoadRNDISEth2IP4Header( + uint8_t *pBuffer, + size_t bufferSize, + uint32_t messageLength, + size_t *pLen); + + static bool LoadRNDISPacket( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + + static bool LoadEtherPacket( + enum ipa_ip_type eIP, + uint8_t *pBuffer, + size_t &nMaxSize); + + static bool ComparePackets( + Byte *pPacket1, + int pPacket1Size, + Byte *pPacket2, + int pPacket2Size); + + static bool CompareEthervsRNDISPacket( + Byte *pIPPacket, + size_t ipPacketSize, + Byte *pRNDISPacket, + size_t rndisPacketSize); + + static bool CompareIPvsRNDISPacket( + Byte *pIPPacket, + int ipPacketSize, + Byte *pRNDISPacket, + size_t rndisPacketSize); +}; + +enum ipa_nat_en_type { + IPA_BYPASS_NAT, + IPA_SRC_NAT, + IPA_DST_NAT, +}; + +enum ipa_ipv6ct_en_type { + IPA_BYPASS_IPV6CT, + IPA_ENABLE_IPV6CT, +}; + +enum ipa_mode_type { + IPA_BASIC, + IPA_ENABLE_FRAMING_HDLC, + IPA_ENABLE_DEFRAMING_HDLC, + IPA_DMA, +}; + +enum ipa_aggr_en_type { + IPA_BYPASS_AGGR, + IPA_ENABLE_AGGR, + IPA_ENABLE_DEAGGR, +}; + +enum ipa_aggr_type { + IPA_MBIM_16 = 0, + IPA_HDLC = 1, + IPA_TLP = 2, + IPA_RNDIS = 3, + IPA_GENERIC = 4, + IPA_QCMAP = 6, +}; + +enum ipa_aggr_mode { + IPA_MBIM_AGGR, + IPA_QCNCM_AGGR, +}; + +enum hdr_total_len_or_pad_type { + IPA_HDR_PAD = 0, + IPA_HDR_TOTAL_LEN = 1, +}; + +struct ipa_ep_cfg_nat { + enum ipa_nat_en_type nat_en; +}; + +struct ipa_ep_cfg_conn_track { + enum ipa_ipv6ct_en_type conn_track_en; +}; + +struct ipa_ep_cfg_hdr { + uint32_t hdr_len; + uint32_t hdr_ofst_metadata_valid; + uint32_t hdr_ofst_metadata; + uint32_t hdr_additional_const_len; + uint32_t hdr_ofst_pkt_size_valid; + uint32_t hdr_ofst_pkt_size; + uint32_t hdr_a5_mux; + uint32_t hdr_remove_additional; + uint32_t hdr_metadata_reg_valid; +}; + +struct ipa_ep_cfg_hdr_ext { + uint32_t hdr_pad_to_alignment; + uint32_t hdr_total_len_or_pad_offset; + bool hdr_payload_len_inc_padding; + enum hdr_total_len_or_pad_type hdr_total_len_or_pad; + bool hdr_total_len_or_pad_valid; + bool hdr_little_endian; + struct ipa_ep_cfg_hdr *hdr; + bool hdr_bytes_to_remove_valid; + uint32_t hdr_bytes_to_remove; +}; + +struct ipa_ep_cfg_mode { + enum ipa_mode_type mode; + enum ipa_client_type dst; +}; + +struct ipa_ep_cfg_aggr { + enum ipa_aggr_en_type aggr_en; + enum ipa_aggr_type aggr; + uint32_t aggr_byte_limit; + uint32_t aggr_time_limit; + uint32_t aggr_pkt_limit; + uint32_t aggr_hard_byte_limit_en; + bool aggr_sw_eof_active; + uint8_t pulse_generator; + uint8_t scaled_time; +}; + +struct ipa_ep_cfg_route { + uint32_t rt_tbl_hdl; +}; + +struct ipa_ep_cfg_deaggr { + uint32_t deaggr_hdr_len; + bool syspipe_err_detection; + bool packet_offset_valid; + uint32_t packet_offset_location; + bool ignore_min_pkt_err; + uint32_t max_packet_len; +}; + +enum ipa_cs_offload { + IPA_DISABLE_CS_OFFLOAD, + IPA_ENABLE_CS_OFFLOAD_UL, + IPA_ENABLE_CS_OFFLOAD_DL, + IPA_CS_RSVD +}; + +struct ipa_ep_cfg_cfg { + bool frag_offload_en; + enum ipa_cs_offload cs_offload_en; + uint8_t cs_metadata_hdr_offset; + uint8_t gen_qmb_master_sel; + uint8_t tx_instance; +}; + +struct ipa_ep_cfg_metadata_mask { + uint32_t metadata_mask; +}; + +struct ipa_ep_cfg_metadata { + uint32_t qmap_id; +}; + +struct ipa_ep_cfg_seq { + bool set_dynamic; + int seq_type; +}; + +struct ipa_ep_cfg_holb { + uint32_t tmr_val; + uint32_t base_val; + uint32_t scale; + uint16_t en; + uint8_t pulse_generator; + uint8_t scaled_time; +}; + +/* + * This struct is a mirroring of the ipa struct + * the test module expect to get from user-space the + * exact same struct as IPA driver defined. + * In case of any change to IPA driver struct + * this struct should be updated as well! + */ +struct test_ipa_ep_cfg { + struct ipa_ep_cfg_nat nat; + struct ipa_ep_cfg_conn_track conn_track; + struct ipa_ep_cfg_hdr hdr; + struct ipa_ep_cfg_hdr_ext hdr_ext; + struct ipa_ep_cfg_mode mode; + struct ipa_ep_cfg_aggr aggr; + struct ipa_ep_cfg_deaggr deaggr; + struct ipa_ep_cfg_route route; + struct ipa_ep_cfg_cfg cfg; + struct ipa_ep_cfg_metadata_mask metadata_mask; + struct ipa_ep_cfg_metadata meta; + struct ipa_ep_cfg_seq seq; +}; + +/*! @brief Struct for the IPAv3.0 UL packet status header */ +struct ipa3_hw_pkt_status { + uint64_t status_opcode:8; + uint64_t exception:8; + uint64_t status_mask:16; + uint64_t pkt_len:16; + uint64_t endp_src_idx:5; + uint64_t reserved_1:3; + uint64_t endp_dest_idx:5; + uint64_t reserved_2:3; + uint64_t metadata:32; + uint64_t filt_local:1; + uint64_t filt_hash:1; + uint64_t filt_global:1; + uint64_t ret_hdr:1; + uint64_t filt_rule_id:10; + uint64_t route_local:1; + uint64_t route_hash:1; + uint64_t ucp:1; + uint64_t route_tbl_idx:5; + uint64_t route_rule_id:10; + uint64_t nat_hit:1; + uint64_t nat_tbl_idx:13; + uint64_t nat_type:2; + uint64_t tag:48; + uint64_t seq_num:8; + uint64_t time_day_ctr:24; + uint64_t hdr_local:1; + uint64_t hdr_offset:10; + uint64_t frag_hit:1; + uint64_t frag_rule:4; + uint64_t reserved_4:16; +}; + +struct ipa3_hw_pkt_status_hw_v5_0 { + uint64_t status_opcode : 8; + uint64_t exception : 8; + uint64_t status_mask : 16; + uint64_t pkt_len : 16; + uint64_t endp_src_idx : 8; + uint64_t reserved_1 : 3; + uint64_t route_local : 1; + uint64_t route_hash : 1; + uint64_t reserved_2 : 3; + uint64_t metadata : 32; + uint64_t filt_local : 1; + uint64_t filt_hash : 1; + uint64_t filt_global : 1; + uint64_t ret_hdr : 1; + uint64_t filt_rule_id : 10; + uint64_t route_tbl_idx : 8; + uint64_t route_rule_id : 10; + uint64_t nat_hit : 1; + uint64_t nat_tbl_idx : 13; + uint64_t nat_type : 2; + uint64_t tag : 48; + uint64_t seq_num : 8; + uint64_t time_day_ctr : 24; + uint64_t hdr_local : 1; + uint64_t hdr_offset : 10; + uint64_t frag_hit : 1; + uint64_t frag_rule : 4; + uint64_t endp_dest_idx : 8; + uint64_t reserved_4 : 7; + uint64_t ucp : 1; +}; + + +#endif diff --git a/kernel-tests/autogen.sh b/kernel-tests/autogen.sh new file mode 100755 index 0000000000..53263574ae --- /dev/null +++ b/kernel-tests/autogen.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# autogen.sh -- Autotools bootstrapping +# + +AUTO_TOOLS_VER=$(automake --version | grep ^automake | sed 's/^.* //g' | cut -d'.' -f1-2) + +aclocal-${AUTO_TOOLS_VER} &&\ +autoheader &&\ +autoconf &&\ +automake-${AUTO_TOOLS_VER} --add-missing --copy + diff --git a/kernel-tests/build_kernel_tests.py b/kernel-tests/build_kernel_tests.py new file mode 100644 index 0000000000..f3014744dc --- /dev/null +++ b/kernel-tests/build_kernel_tests.py @@ -0,0 +1,129 @@ +#! /usr/bin/env python + +# 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. + +import os +import os.path +import subprocess +import sys +import shutil + +install_dir = '/ipa-kernel-tests' # unlikely to ever change, so 'file constant' + + +def get_args(): + class Args: + pass + + args = Args() + + try: + args.cc_path = os.path.dirname(os.environ['CROSS_COMPILE']) + except: + args.cc_path = None + + try: + args.arch = os.environ['ARCH'] + except: + raise Exception("ARCH must be set") + + try: + args.kdir = os.environ['KDIR'] + except: + raise Exception("KDIR must be set") + + try: + args.dest = os.environ['DESTDIR'] + except: + raise Exception("DESTDIR must be set") + + return args + + +def do(cmd, wdir=None): + cwd = None + if wdir: + cwd = os.getcwd() + os.chdir(wdir) + subprocess.check_call(cmd) + if cwd: + os.chdir(cwd) + + +def build(args): + + if args.cc_path: + os.environ['PATH'] = args.cc_path + ':' + os.environ['PATH'] + + args.uapi = args.kdir + '/usr/include' + args.src = args.kdir + '/techpack/dataipa/kernel-tests' + args.inc = args.kdir + '/techpack/dataipa/drivers/platform/msm/ipa/ipa_test_module' + + full_uapi = os.path.abspath(args.uapi) + os.environ['CPPFLAGS'] = ('-I' + full_uapi) + full_inc = os.path.abspath(args.inc) + os.environ['CPPFLAGS'] += (' -I' + full_inc) + + configure(args, args.src) + + do(['make'], args.src) + do(['make', 'DESTDIR=' + args.dest, 'install'], args.src) + + +def configure(args, wdir): + + if os.path.isfile(os.path.join(wdir, 'config.h')): + return + + do(['libtoolize'], wdir) + do(['./autogen.sh'], wdir) + + full_idir = os.path.abspath(os.path.join(wdir, install_dir)) + host_str = 'arm-linux-gnueabihf' + config_extra = '' + if args.arch == 'arm64': + host_str = 'aarch64-linux-gnu' + config_extra = '--disable-swp' + do(['./configure', + '--host=' + host_str, + '--prefix=' + full_idir, + config_extra], wdir) + + +def main(): + rc = 0 + try: + args = get_args() + build(args) + except Exception as e: + rc = 1 + print(e) + sys.exit(rc) + +if __name__ == '__main__': + main() diff --git a/kernel-tests/configure.ac b/kernel-tests/configure.ac new file mode 100644 index 0000000000..97569885bb --- /dev/null +++ b/kernel-tests/configure.ac @@ -0,0 +1,56 @@ +AC_PREREQ(2.64) + +AC_INIT([ipa-kernel-tests],[1.0.0]) +AM_INIT_AUTOMAKE([-Wall -Werror gnu foreign]) + +AM_MAINTAINER_MODE + +AC_CONFIG_HEADER([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +AC_PROG_LIBTOOL +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_PROG_CXX + + +AS_CASE([$host], + [aarch64*], [ARM64=yes], + [ARM64=no] +) + +AM_CONDITIONAL(ARM64, [test "x$ARM64" = "xyes"]) + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +AC_ARG_WITH(ipanat-headers, + AS_HELP_STRING([--with-ipanat-headers=DIR], + [Specify the location of the ipanat headers]), + [CPPFLAGS="$CPPFLAGS -idirafter $withval"]) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +AC_CONFIG_FILES([ + Makefile + ]) +AC_OUTPUT diff --git a/kernel-tests/create_symlinks.sh b/kernel-tests/create_symlinks.sh new file mode 100755 index 0000000000..efe3772708 --- /dev/null +++ b/kernel-tests/create_symlinks.sh @@ -0,0 +1,80 @@ +# 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. + +# This script creates symlinks for tests that are compiled as Soong modules, so +# that they may be accessed from their old location in /data/kernel-tests + +#!/bin/sh + +NTEST_PATH="/data/nativetest" +KTEST_PATH="/data/kernel-tests" + +# Any test that is compiled as a cc_test module (which applies to any Soong +# module in kernel-tests-internal) is given a directory, in to which the +# compiled test and its supporting files are placed. This function iterates +# over the test directories in $1 and creates symlinks to all the files +# contained within a given test directory. $2 and later arguemnts can be used to +# specify directores to skip. +create_links() +{ + BASE_PATH="$1" + shift + SKIP_FILES=$@ # These can also be directories + + for TEST_DIR in `ls "$BASE_PATH"`; do + # Filter out any file / directory in SKIP_FILES. + SHOULD_SKIP="" + for i in $SKIP_FILES; do + if [ "$TEST_DIR" = "$i" ]; then + SHOULD_SKIP="TRUE" + break + fi + done + if [ ! "$SHOULD_SKIP" = "" ]; then + continue + fi + + + # Filter out any files that aren't directories (since every test we + # compile is given a directory) + if [ ! -d "$BASE_PATH/$TEST_DIR" ]; then + continue + fi + + # Now, create the symlinks for each test file inside of TEST_DIR + for TEST_FILE in `ls "$BASE_PATH/$TEST_DIR"`; do + ln -fs "$BASE_PATH/$TEST_DIR/$TEST_FILE" "$KTEST_PATH/$TEST_FILE" + done + done +} + +# Create /data/kernel-tests, if it doesn't exist already +mkdir -p "$KTEST_PATH" + +# Create the symlinks +create_links "$NTEST_PATH" "vendor" +create_links "$NTEST_PATH/vendor" diff --git a/kernel-tests/hton.h b/kernel-tests/hton.h new file mode 100644 index 0000000000..7da15ee282 --- /dev/null +++ b/kernel-tests/hton.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 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 HTON_H_ +#define HTON_H_ + +#include +#include "linux/msm_ipa.h" + +#include + +#endif + diff --git a/kernel-tests/main.cpp b/kernel-tests/main.cpp new file mode 100644 index 0000000000..ff57c097c1 --- /dev/null +++ b/kernel-tests/main.cpp @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2017-2018,2020 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 "Logger.h" +#include "TestManager.h" +#include "TestsUtils.h" +#include +#include +#include +/////////////////////////////////////////////////////////// + +Logger g_Logger(LOG_ERROR); +#define CHOOSER_MODE "--chooser" +#define SHOW_TEST_FLAG "--show_tests" +#define SHOW_SUIT_FLAG "--show_suites" +#define RUN_TEST_FLAG "--test" +#define RUN_SUIT_FLAG "--suite" +string sFormat = "ip_accelerator , ..., \n" + "contorl_flag = " RUN_TEST_FLAG " or " RUN_SUIT_FLAG "\n" + "ip_accelerator " SHOW_TEST_FLAG "\n" + "ip_accelerator " SHOW_SUIT_FLAG "\n" + "or ip_accelerator --chooser " + "for menu chooser interface\n"; +#define MAX_SUITES 15 + +#undef strcasesame +#define strcasesame(x, y) \ + (! strcasecmp((x), (y))) + +#undef legal_nat_mem_type +#define legal_nat_mem_type(mt) \ + ( strcasesame(mt, "DDR") || \ + strcasesame(mt, "SRAM") || \ + strcasesame(mt, "HYBRID") ) + +TestManager *testmanager = NULL; + +enum ipa_test_type{ + TEST = 1, + SUITE, + EXIT, + MAX_TYPE +}; + +const char *ipa_hw_type_name[] = { + "None", + "1.0", + "1.1", + "2.0", + "2.1", + "2.5/2.6", + "2.6L", + "Unused", + "Unused", + "Unused", + "3.0", + "3.1", + "3.5", + "3.5.1", + "4.0", + "4.1", + "4.2", + "4.5", + "4.9", + "5.0", + "MAX" +}; + +void BuildRegressionTestSuite() +{ + TestBase *test; + + for (unsigned int i = 0; i < testmanager->m_testList.size(); i++) { + test = testmanager->m_testList[i]; + if (test->m_runInRegression) { + test->m_testSuiteName.push_back("Regression"); + } + } +} + + +/////////////////////////////////////////////////////////// +void showTests() +{ + TestBase *test = testmanager->m_testList[0]; + + for (unsigned i = 0; i < testmanager->m_testList.size(); i++) { + test = testmanager->m_testList[i]; + string name = test->m_name, index = test->m_testSuiteName[0]; + + printf("%d) %s (part of %s suite" ,i+1, name.c_str(), index.c_str()); + for (unsigned j = 0; j < test->m_testSuiteName.size(); ++j) { + if ( test->m_testSuiteName[j] == index) + continue; + printf(", %s suite", + test->m_testSuiteName[j].c_str()); + index = test->m_testSuiteName[j]; + } + printf("), (%s <= HW Version <= %s)\n", + ipa_hw_type_name[test->m_minIPAHwType], + ipa_hw_type_name[test->m_maxIPAHwType]); + } + + // Example: + // 15) DmaModeMBIMggregationLoopTest (part of DmaMbim16Agg suite), (1.0 <= HW Version <= 2.1) +} + +void showSuits() +{ + TestBase *test; + std::set suiteSet; + int suiteIndex = 1; + + test = testmanager->m_testList[0]; + + for (unsigned i = 0; i < testmanager->m_testList.size(); i++) { + test = testmanager->m_testList[i]; + for (unsigned j = 0; j < test->m_testSuiteName.size() ; j++) + suiteSet.insert(test->m_testSuiteName[j]); + } + + for (std::set::iterator i = suiteSet.begin(); + i != suiteSet.end(); suiteIndex++) { + printf("%d) %s\n", suiteIndex, (*i).c_str()); + ++i; + } +} + +void preparTests(int argc, char* argv[], + vector& list) +{ + for (int i = 2; i < argc; i++) + list.push_back(argv[i]); +} + +const char* getSuite(int suite_num) { + int count = 0, suiteIndex = 1; + string result = "error"; + TestBase *test = testmanager->m_testList[0]; + set suiteSet; + + if (testmanager->m_testList.size() < 1) + return NULL; + + if (count == suite_num) + return testmanager->m_testList[0]->m_testSuiteName[0].c_str(); + + for (unsigned i = 0; i < testmanager->m_testList.size(); i++) { + test = testmanager->m_testList[i]; + for (unsigned j = 0; j < test->m_testSuiteName.size() ; j++) + suiteSet.insert(test->m_testSuiteName[j]); + } + + for (std::set::iterator i = suiteSet.begin(); + i != suiteSet.end(); suiteIndex++) { + printf("%d) %s\n", suiteIndex, (*i).c_str()); + if (suiteIndex == suite_num) + return (*i).c_str(); + ++i; + } + return NULL; +} + +int chooserMode() { + vector testSuiteList; + vector testNameList; + unsigned int test_num; + int suite_num; + int type; + TestBase *test; + const char* res; + int result = 0; + char input_str[4]; + + printf("Welcome to the ip_accelerator\nChoose an option:\n"); + printf("1) Run tests\n2) Run suites\n3) Exit\nChoose an option: "); + res = fgets(input_str, sizeof(input_str), stdin); + type = atoi(input_str); + switch((enum ipa_test_type)type) { + case TEST: + BuildRegressionTestSuite(); + showTests(); + printf("Choose which test you wish to run: \n"); + fflush(stdin); + res = fgets(input_str, sizeof(input_str), stdin); + test_num = atoi(input_str); + if ( test_num > testmanager->m_testList.size()) { + printf("Invalid test number. Try again\n"); + result = -1; + break; + } + test = testmanager->m_testList[test_num-1]; + printf("Running Test %s\n", + test->m_name. + c_str()); + testNameList.push_back(test->m_name.c_str()); + BuildRegressionTestSuite(); + testmanager->Run(testSuiteList, testNameList); + testNameList.clear(); + break; + case SUITE: + BuildRegressionTestSuite(); + showSuits(); + printf("Choose which suite you wish to run: \n"); + fflush(stdin); + res = fgets(input_str, sizeof(input_str), stdin); + suite_num = atoi(input_str); + if (suite_num < 0 || suite_num > MAX_SUITES) { + printf("Invalid test number. Try again\n"); + result = -1; + break; + } + res = getSuite(suite_num); + if (!res) { + printf("Error in getSuite. Exiting\n"); + result = -1; + break; + } + testSuiteList.push_back(res); + testmanager->Run(testSuiteList, testNameList); + testSuiteList.clear(); + break; + default: + printf("Exiting\n"); + break; + } + return result; +} + +int scriptMode(int argc, char* argv[]) { + vector testSuiteList; + vector testNameList; + string sControlFlag; + + if (argc < 2) { + printf("please use correct format:\n%s", sFormat.c_str()); + return -1; + } + + sControlFlag = argv[1]; + + if (sControlFlag.find("--") == string::npos) { + printf("please use correct format:\n%s", sFormat.c_str()); + return -1; + } + + BuildRegressionTestSuite(); + + if (sControlFlag.compare(SHOW_TEST_FLAG) == 0) { + showTests(); + return 0; + } else if (sControlFlag.compare(SHOW_SUIT_FLAG) == 0) { + showSuits(); + return 0; + } + + if (sControlFlag.compare(RUN_TEST_FLAG) == 0) { + preparTests(argc, argv, testNameList); + } else if (sControlFlag.compare(RUN_SUIT_FLAG) == 0) { + preparTests(argc, argv, testSuiteList); + } else { + printf("please use correct format:\n%s", sFormat.c_str()); + return -1; + } + + testmanager->Run(testSuiteList, testNameList); + return 0; +} + +int main(int argc, char* argv[]) +{ + string nat_mem_type = DFLT_NAT_MEM_TYPE; + + int c, result = 0, what = 0; + + int opt_idx = 0; + + struct option opts[] = { + /* These options set a flag. */ + {"chooser", no_argument, &what, 1}, + {"show_tests", no_argument, &what, 2}, + {"show_suites", no_argument, &what, 3}, + {"test", no_argument, &what, 4}, + {"suite", no_argument, &what, 5}, + {"mem", required_argument, 0, 'm'}, + {0, 0, 0, 0} + }; + + if (argc <= 1) { + printf("please use correct format:\n%s", sFormat.c_str()); + return -1; + } + + while ( (c = getopt_long(argc, argv, "", opts, &opt_idx)) != -1 ) + { + switch ( c ) + { + case 0: + break; + case 'm': + if ( legal_nat_mem_type(optarg) ) + { + nat_mem_type = optarg; + } + else + { + fprintf(stderr, "Illegal: --mem %s\n", optarg); + exit(1); + } + break; + default: + fprintf(stderr, "Illegal command line argument passed\n"); + printf("please use correct format:\n%s", sFormat.c_str()); + exit(1); + } + } + + if ( what == 0 ) { + printf("please use correct format:\n%s", sFormat.c_str()); + return -1; + } + + argc = 2; + + switch ( what ) + { + case 1: + argv[1] = (char*) CHOOSER_MODE; + break; + case 2: + argv[1] = (char*) SHOW_TEST_FLAG; + break; + case 3: + argv[1] = (char*) SHOW_SUIT_FLAG; + break; + case 4: + argv[1] = (char*) RUN_TEST_FLAG; + break; + case 5: + argv[1] = (char*) RUN_SUIT_FLAG; + break; + default: + printf("please use correct format:\n%s", sFormat.c_str()); + exit(1); + } + + testmanager = TestManager::GetInstance(nat_mem_type.c_str()); + + string sControlFlag = argv[1]; + + if (sControlFlag.compare(CHOOSER_MODE) == 0) { + result = chooserMode(); + } else { + result = scriptMode(argc, argv); + } + return result; +}//main + +//////////////////////////////////////////////////////////////////// + diff --git a/kernel-tests/run.sh b/kernel-tests/run.sh new file mode 100644 index 0000000000..36250e74e8 --- /dev/null +++ b/kernel-tests/run.sh @@ -0,0 +1,64 @@ +#! /bin/sh + +# Copyright (c) 2014,2017,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. + +set -e +./test_env_setup.sh + +echo "Starting test" + +if [ $# -eq 0 ]; then + echo "No args\n" + exec ./ipa_kernel_tests --suite_name Regression +fi + +#Parse the args for valid switches +while [ $# -gt 0 ]; do + case $1 in + -n | --nominal) + echo "Nominal\n" + exec ./ipa_kernel_tests --suite_name Regression + exit 0 + ;; + -a | --adversarial) + echo "adversarial\n" + echo "Currently no adversarial tests" + exit 0 + ;; + -r | --repeatability) + echo "Currently no repeatability tests" + -s | --stress) + echo "Currently no stress tests" + exit 0 + ;; + -h | --help | *) + echo "Usage: ./run.sh -[n][a][r][s]" + exit 1 + ;; + esac +done