#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MOCK_NR_DEV_MAX 512 #define MOCK_SIZE_CFGFILE_CONTENT (128 + (MOCK_NR_DEV_MAX * 128)) char * mock_cfgfile_content = NULL; char mock_devs_name[MOCK_NR_DEV_MAX][32]; struct mr_dev_desc * mock_devs_desc[MOCK_NR_DEV_MAX]; static struct rte_mempool * mock_pktmbuf_pool = NULL; extern const char * create_config_file(const char * content); /* * generate the configuration string */ char * generate_config_string(uint32_t num_adapters, int mode, int is_random) { memset(mock_cfgfile_content, 0, MOCK_SIZE_CFGFILE_CONTENT); strcpy(mock_cfgfile_content, "[limits]\n" "nr_max_link_dbs=64\n" "nr_max_ef_adapters=32\n\n" "[ef_adapters]\n" "sid_start=100\n" "sid_end=200\n\n"); /* generate the dynamic parts */ if (is_random) { srand(time(NULL)); } /* Allocate memory for used_ids */ int * used_ids = (int *)calloc(num_adapters, sizeof(int)); if (used_ids == NULL) { perror("Failed to allocate memory for used_ids"); return NULL; } /* generate the adapter entries */ char adapter_entry[1024]; for (int i = 0; i < num_adapters; i++) { int ef_adapter_id; if (is_random) { do { ef_adapter_id = rand() % num_adapters; } while (used_ids[ef_adapter_id]); } else { ef_adapter_id = i; } used_ids[ef_adapter_id] = 1; snprintf(adapter_entry, sizeof(adapter_entry), "[ef_adapter:%d]\nef_adapter_id=%d\nmode=%d\nlisten_device=ens4f0np%d\n\n", i, ef_adapter_id, mode, i); strcat(mock_cfgfile_content, adapter_entry); } free(used_ids); return mock_cfgfile_content; } /* --------------------------------------------------- mock func --------------------------------------------------- */ struct mr_dev_desc * __wrap_mr_dev_desc_lookup(struct devmgr_main * devmgr_main, const char * devsym) { // printf("Mocking mr_dev_desc_lookup\n"); check_expected(devsym); return mock_type(struct mr_dev_desc *); } int __wrap_port_adapter_mapping_insert(port_id_t port_id, enum adapter_type adapter_type) { return RT_SUCCESS; } /* ------------------------------------------- Test group setup/teardown ------------------------------------------- */ static int testgroup_common_setup(void ** state) { struct sc_main * mock_sc = rte_zmalloc(NULL, sizeof(struct sc_main), 0); assert_non_null(mock_sc); mock_sc->nr_io_thread = 1; *state = mock_sc; return 0; } static int testgroup_common_teardown(void ** state) { struct sc_main * mock_sc = *state; rte_free(mock_sc); return 0; } /* ------------------------------------------- Test case 'config handle' ------------------------------------------- */ extern struct ef_config_handle * ef_config_handle_create(uint32_t ef_adapters_max); extern int ef_config_handle_delete(struct ef_config_handle * cfg_handle); extern int ef_config_parse(struct sc_main * sc, struct ef_config_handle * cfg_handle); extern struct ef_adapter * ef_config_handle_adapters_data_get(struct ef_config_handle * cfg_handle); uint16_t ef_config_handle_nr_adapters_get(struct ef_config_handle * cfg_handle); uint32_t ef_config_handle_sid_start_get(struct ef_config_handle * cfg_handle); uint32_t ef_config_handle_sid_end_get(struct ef_config_handle * cfg_handle); uint32_t ef_config_handle_ef_adapters_max_get(struct ef_config_handle * cfg_handle); uint32_t ef_config_handle_link_dbs_max_get(struct ef_config_handle * cfg_handle); /* * Test Case: ef config handle success */ static void testcase_ef_config_handle_success(void ** state) { /* * Case 1: the etherfabric id is continuous from 100 to 200 */ /* generate the configuration string */ uint32_t nr_ef_adapters = 200 - 100 + 1; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); struct sc_main * mock_sc = *state; strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ uint32_t ef_adapters_max = nr_ef_adapters; struct ef_config_handle * cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ int ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ struct ef_adapter * ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); /* check the number of ef adapters */ assert_int_equal(ef_config_handle_nr_adapters_get(cfg_handle), nr_ef_adapters); /* check the sid range */ assert_int_equal(ef_config_handle_sid_start_get(cfg_handle), 100); assert_int_equal(ef_config_handle_sid_end_get(cfg_handle), 200); /* check the ef adapters max */ assert_int_equal(ef_config_handle_ef_adapters_max_get(cfg_handle), ef_adapters_max); /* check the link dbs max */ assert_int_equal(ef_config_handle_link_dbs_max_get(cfg_handle), 64); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 2: the etherfabric id is radom from 100 to 200 */ /* generate the configuration string */ test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 1); assert_non_null(test_cfgfile_content); /* create the configuration file */ filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ ef_adapters_max = nr_ef_adapters; cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); /* check the number of ef adapters */ assert_int_equal(ef_config_handle_nr_adapters_get(cfg_handle), nr_ef_adapters); /* check the sid range */ assert_int_equal(ef_config_handle_sid_start_get(cfg_handle), 100); assert_int_equal(ef_config_handle_sid_end_get(cfg_handle), 200); /* check the ef adapters max */ assert_int_equal(ef_config_handle_ef_adapters_max_get(cfg_handle), ef_adapters_max); /* check the link dbs max */ assert_int_equal(ef_config_handle_link_dbs_max_get(cfg_handle), 64); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 3: the nr_ef_adapters less then sid range( 100 - 200) */ /* generate the configuration string */ nr_ef_adapters = 32; test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 1); assert_non_null(test_cfgfile_content); /* create the configuration file */ filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ ef_adapters_max = nr_ef_adapters; cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); /* check the number of ef adapters */ assert_int_equal(ef_config_handle_nr_adapters_get(cfg_handle), nr_ef_adapters); /* check the sid range */ assert_int_equal(ef_config_handle_sid_start_get(cfg_handle), 100); assert_int_equal(ef_config_handle_sid_end_get(cfg_handle), 200); /* check the ef adapters max */ assert_int_equal(ef_config_handle_ef_adapters_max_get(cfg_handle), ef_adapters_max); /* check the link dbs max */ assert_int_equal(ef_config_handle_link_dbs_max_get(cfg_handle), 64); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); } /* * Test Case: ef config handle failure */ static void testcase_ef_config_handle_failure(void ** state) { /* * Case 1: the nr etherfabric adapter is out of sid range( 100 -200) */ /* generate the configuration string */ uint32_t nr_ef_adapters = 256; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); assert_non_null(test_cfgfile_content); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); struct sc_main * mock_sc = *state; strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ uint32_t ef_adapters_max = nr_ef_adapters; struct ef_config_handle * cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ int ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_ERR); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 2: the nr etherfabric adapter is out of ethernet adapter capacity */ /* generate the configuration string */ nr_ef_adapters = 128; test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); assert_non_null(test_cfgfile_content); /* create the configuration file */ filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ ef_adapters_max = 64; assert(ef_adapters_max <= 512); for (uint32_t i = 0; i < ef_adapters_max; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ struct ef_adapter * ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); /* check the number of ef adapters */ assert_int_equal(ef_config_handle_nr_adapters_get(cfg_handle), ef_adapters_max); /* check the sid range */ assert_int_equal(ef_config_handle_sid_start_get(cfg_handle), 100); assert_int_equal(ef_config_handle_sid_end_get(cfg_handle), 200); /* check the ef adapters max */ assert_int_equal(ef_config_handle_ef_adapters_max_get(cfg_handle), ef_adapters_max); /* check the link dbs max */ assert_int_equal(ef_config_handle_link_dbs_max_get(cfg_handle), 64); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); } /* ----------------------------------------- Test case 'ef adapter handle' ----------------------------------------- */ struct ef_adapter; struct ef_adapter_handle; enum ef_adapter_mode; extern struct ef_adapter_handle * ef_adapter_handle_create(struct ef_adapter * adapters_data, uint16_t capacity, uint16_t nr_adapters); extern int ef_adapter_handle_delete(struct ef_adapter_handle * handle); extern uint16_t ef_adapter_handle_capacity_get(struct ef_adapter_handle * handle); extern uint16_t ef_adapter_handle_nr_adapters_get(struct ef_adapter_handle * handle); extern struct ef_adapter * ef_adapter_handle_adapter_get_by_id(struct ef_adapter_handle * handle, uint16_t adapter_id); extern int ef_adapter_handle_adapter_lookup(struct ef_adapter_handle * handle, uint32_t dst_addr, uint16_t * out_ef_adapter_id); extern uint16_t ef_adapter_id_get(struct ef_adapter * ef_adapter); /* * Test Case: ef adapter handle success */ static void testcase_ef_adapter_handle_success(void ** state) { /* * Case 1: the etherfabric id is continuous from 100 to 200 */ /* generate the configuration string */ uint16_t nr_ef_adapters = 200 - 100 + 1; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); assert_non_null(test_cfgfile_content); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); struct sc_main * mock_sc = *state; strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ uint32_t ef_adapters_max = nr_ef_adapters; struct ef_config_handle * cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ int ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ struct ef_adapter * ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); uint16_t capacity = ef_config_handle_ef_adapters_max_get(cfg_handle); assert_int_equal(capacity, ef_adapters_max); uint16_t nr_adapters = ef_config_handle_nr_adapters_get(cfg_handle); assert_int_equal(nr_adapters, nr_ef_adapters); /* create the ef adapter handle */ struct ef_adapter_handle * ef_adapter_handle = ef_adapter_handle_create(ef_adapters_data, capacity, nr_ef_adapters); assert_non_null(ef_adapter_handle); /* check the capacity */ assert_int_equal(ef_adapter_handle_capacity_get(ef_adapter_handle), capacity); /* check the number of adapters */ assert_int_equal(ef_adapter_handle_nr_adapters_get(ef_adapter_handle), nr_adapters); /* check the ef adapter by id */ for (uint16_t i = 0; i < nr_adapters; i++) { struct ef_adapter * adapter = ef_adapter_handle_adapter_get_by_id(ef_adapter_handle, i); assert_non_null(adapter); } /* check the ef adapter lookup */ for (uint32_t i = 0; i < nr_adapters; i++) { uint16_t ef_adapter_id; uint32_t dst_addr = htonl(0x0A0A0A0A + i); ret = ef_adapter_handle_adapter_lookup(ef_adapter_handle, dst_addr, &ef_adapter_id); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(ef_adapter_id, i); } /* delete the ef adapter handle */ ret = ef_adapter_handle_delete(ef_adapter_handle); assert_int_equal(ret, RT_SUCCESS); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 2: the etherfabric id is radom from 100 to 200 */ /* generate the configuration string */ nr_ef_adapters = 200 - 100 + 1; test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 1); assert_non_null(test_cfgfile_content); /* create the configuration file */ filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ ef_adapters_max = nr_ef_adapters; cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); capacity = ef_config_handle_ef_adapters_max_get(cfg_handle); assert_int_equal(capacity, ef_adapters_max); nr_adapters = ef_config_handle_nr_adapters_get(cfg_handle); assert_int_equal(nr_adapters, nr_ef_adapters); /* create the ef adapter handle */ ef_adapter_handle = ef_adapter_handle_create(ef_adapters_data, capacity, nr_adapters); assert_non_null(ef_adapter_handle); /* check the capacity */ assert_int_equal(ef_adapter_handle_capacity_get(ef_adapter_handle), capacity); /* check the number of adapters */ assert_int_equal(ef_adapter_handle_nr_adapters_get(ef_adapter_handle), nr_adapters); /* check the ef adapter by id */ for (uint16_t i = 0; i < nr_adapters; i++) { struct ef_adapter * adapter = ef_adapter_handle_adapter_get_by_id(ef_adapter_handle, i); assert_non_null(adapter); } /* check the ef adapter lookup */ for (uint32_t i = 0; i < nr_adapters; i++) { uint16_t ef_adapter_id; uint32_t dst_addr = htonl(0x0A0A0A0A + i); ret = ef_adapter_handle_adapter_lookup(ef_adapter_handle, dst_addr, &ef_adapter_id); assert_int_equal(ret, RT_SUCCESS); struct ef_adapter * adapter = ef_adapter_handle_adapter_get_by_id(ef_adapter_handle, ef_adapter_id); assert_non_null(adapter); assert_int_equal(ef_adapter_id, ef_adapter_id_get(adapter)); } /* delete the ef adapter handle */ ret = ef_adapter_handle_delete(ef_adapter_handle); assert_int_equal(ret, RT_SUCCESS); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); } /* * Test Case: ef adapter handle failure */ static void testcase_ef_adapter_handle_failure(void ** state) { /* * Case 1: adapter lookup failure */ /* generate the configuration string */ uint16_t nr_ef_adapters = 200 - 100 + 1; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); assert_non_null(test_cfgfile_content); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); struct sc_main * mock_sc = *state; strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ uint32_t ef_adapters_max = nr_ef_adapters; struct ef_config_handle * cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ int ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ struct ef_adapter * ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); uint16_t capacity = ef_config_handle_ef_adapters_max_get(cfg_handle); assert_int_equal(capacity, ef_adapters_max); uint16_t nr_adapters = ef_config_handle_nr_adapters_get(cfg_handle); assert_int_equal(nr_adapters, nr_ef_adapters); /* create the ef adapter handle */ struct ef_adapter_handle * ef_adapter_handle = ef_adapter_handle_create(ef_adapters_data, capacity, nr_adapters); assert_non_null(ef_adapter_handle); /* check the capacity */ assert_int_equal(ef_adapter_handle_capacity_get(ef_adapter_handle), capacity); /* check the number of adapters */ assert_int_equal(ef_adapter_handle_nr_adapters_get(ef_adapter_handle), nr_adapters); /* check the ef adapter lookup */ uint16_t ef_adapter_id; uint32_t dst_addr = 0x0A0A0A0A + 256; ret = ef_adapter_handle_adapter_lookup(ef_adapter_handle, dst_addr, &ef_adapter_id); assert_int_equal(ret, RT_ERR); /* delete the ef adapter handle */ ret = ef_adapter_handle_delete(ef_adapter_handle); assert_int_equal(ret, RT_SUCCESS); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 2: the number of adapter is out of capacity */ /* generate the configuration string */ nr_ef_adapters = 200 - 100 + 1; test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); assert_non_null(test_cfgfile_content); /* create the configuration file */ filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ ef_adapters_max = nr_ef_adapters; cfg_handle = ef_config_handle_create(ef_adapters_max); /* parse the configuration */ ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); capacity = ef_config_handle_ef_adapters_max_get(cfg_handle); assert_int_equal(capacity, ef_adapters_max); nr_adapters = ef_config_handle_nr_adapters_get(cfg_handle); assert_int_equal(nr_adapters, nr_ef_adapters); /* create the ef adapter handle */ capacity = 64; ef_adapter_handle = ef_adapter_handle_create(ef_adapters_data, capacity, nr_adapters); assert_null(ef_adapter_handle); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 3: delete the ef adapter handle */ ret = ef_adapter_handle_delete(NULL); assert_int_equal(ret, RT_ERR); } /* ------------------------------------------- Test case 'ef peer handle' ------------------------------------------ */ /* Should match the #define LCORE_CACHE_SIZE value in rte_cuckoo_hash.h */ #define LCORE_CACHE_SIZE 64 #define SC_EF_PEER_ENTRIES 256 // #define SC_EF_PEER_MEMBER (SC_EF_PEER_ENTRIES + (RTE_MAX_LCORE - 1) * (LCORE_CACHE_SIZE - 1) + 1) #define SC_EF_PEER_CAPACITY_CALC(entries, cache_size) ((entries) + (RTE_MAX_LCORE - 1) * ((cache_size)-1) + 1) struct ef_peer_handle; union ef_peer_key { struct { uint32_t ip_src; struct rte_ether_addr mac_src; }; xmm_t xmm; }; extern int ef_peer_handle_delete(struct ef_peer_handle * ef_peer_handle); extern struct ef_peer_handle * ef_peer_handle_create(uint32_t entries); extern uint16_t ef_peer_handle_capacity_get(struct ef_peer_handle * handle); extern uint32_t ef_peer_handle_entries_get(struct ef_peer_handle * handle); extern uint32_t ef_peer_handle_remaining_entries_get(struct ef_peer_handle * handle); extern struct ef_peer * ef_peer_handle_peer_get(struct ef_peer_handle * handle, uint16_t ef_peer_index); extern int ef_peer_handle_peer_lookup(struct ef_peer_handle * handle, const union ef_peer_key * key); extern int ef_peer_handle_peer_add(struct ef_peer_handle * handle, const union ef_peer_key * key); extern uint32_t ef_peer_ip_addr_get(struct ef_peer * ef_peer); extern struct rte_ether_addr * ef_peer_mac_addr_get(struct ef_peer * ef_peer); /* * Test Case: ef peer handle success */ static void testcase_ef_peer_handle_success(void ** state) { /* * Case 1: basic test for ef peer handle */ /* create the ef peer handle */ struct ef_peer_handle * ef_peer_handle = ef_peer_handle_create(SC_EF_PEER_ENTRIES); assert_non_null(ef_peer_handle); /* check the ef peer handle */ assert_int_equal(ef_peer_handle_capacity_get(ef_peer_handle), SC_EF_PEER_CAPACITY_CALC(SC_EF_PEER_ENTRIES, LCORE_CACHE_SIZE)); /* check the ef peer handle entries */ assert_int_equal(ef_peer_handle_entries_get(ef_peer_handle), SC_EF_PEER_ENTRIES); /* check the ef peer handle peer get */ for (uint16_t i = 0; i < SC_EF_PEER_ENTRIES; i++) { struct ef_peer * peer = ef_peer_handle_peer_get(ef_peer_handle, i); assert_non_null(peer); } /* check the ef peer handle peer lookup */ union ef_peer_key key; key.ip_src = 0x0A0A0A0A; struct rte_ether_addr mac_src = {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}; key.mac_src = mac_src; int ret = ef_peer_handle_peer_lookup(ef_peer_handle, &key); assert_int_equal(ret < 0, 1); /* check the ef peer handle peer add */ int out_add_peer_id = ef_peer_handle_peer_add(ef_peer_handle, &key); assert_int_not_equal(out_add_peer_id, RT_ERR); /* check the ef peer handle peer lookup */ int peer_id = ef_peer_handle_peer_lookup(ef_peer_handle, &key); assert_int_not_equal(peer_id, RT_ERR); assert_int_equal(out_add_peer_id, peer_id); /* check the ef peer handle peer get */ struct ef_peer * ef_peer = ef_peer_handle_peer_get(ef_peer_handle, peer_id); assert_non_null(ef_peer); /* check the ef peer ip addr */ assert_int_equal(ef_peer_ip_addr_get(ef_peer), key.ip_src); /* check the ef peer mac addr */ assert_memory_equal(ef_peer_mac_addr_get(ef_peer), &key.mac_src, sizeof(struct rte_ether_addr)); /* delete the ef peer handle */ ret = ef_peer_handle_delete(ef_peer_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 2: add peer to full ef peer handle */ /* create the ef peer handle */ ef_peer_handle = ef_peer_handle_create(SC_EF_PEER_ENTRIES); assert_non_null(ef_peer_handle); /* check the ef peer handle */ assert_int_equal(ef_peer_handle_capacity_get(ef_peer_handle), SC_EF_PEER_CAPACITY_CALC(SC_EF_PEER_ENTRIES, LCORE_CACHE_SIZE)); /* check the ef peer handle entries */ uint32_t nr_entries = ef_peer_handle_entries_get(ef_peer_handle); assert_int_equal(nr_entries, SC_EF_PEER_ENTRIES); /* Add peer to full ef peer handle */ int out_add_peer_ids[nr_entries]; for (uint16_t i = 0; i < nr_entries; i++) { key.ip_src = 0x0A0A0A0A + i; key.mac_src.addr_bytes[5] = i; out_add_peer_ids[i] = ef_peer_handle_peer_add(ef_peer_handle, &key); assert_int_not_equal(out_add_peer_ids[i], RT_ERR); } /* lookup peer from full ef peer handle */ int out_peer_ids[nr_entries]; for (uint16_t i = 0; i < nr_entries; i++) { key.ip_src = 0x0A0A0A0A + i; key.mac_src.addr_bytes[5] = i; out_peer_ids[i] = ef_peer_handle_peer_lookup(ef_peer_handle, &key); assert_int_not_equal(out_peer_ids[i], RT_ERR); } /* check the ef peer handle peer get */ for (uint16_t i = 0; i < nr_entries; i++) { struct ef_peer * ef_peer = ef_peer_handle_peer_get(ef_peer_handle, out_peer_ids[i]); assert_non_null(ef_peer); key.ip_src = 0x0A0A0A0A + i; key.mac_src.addr_bytes[5] = i; assert_int_equal(out_add_peer_ids[i], out_peer_ids[i]); assert_int_equal(ef_peer_ip_addr_get(ef_peer), key.ip_src); assert_memory_equal(ef_peer_mac_addr_get(ef_peer), &key.mac_src, sizeof(struct rte_ether_addr)); } /* delete the ef peer handle */ ret = ef_peer_handle_delete(ef_peer_handle); assert_int_equal(ret, RT_SUCCESS); } /* * Test Case: ef peer handle failure */ static void testcase_ef_peer_handle_failure(void ** state) { /* * Case 1: delete the ef peer handle (NULL) */ int ret = ef_peer_handle_delete(NULL); assert_int_equal(ret, RT_ERR); /* * Case 2: create the ef peer handle with invalid entries */ struct ef_peer_handle * ef_peer_handle = ef_peer_handle_create(0); assert_null(ef_peer_handle); /* * Case 3:create the ef peer handle with entries too large */ ef_peer_handle = ef_peer_handle_create(UINT32_MAX); assert_null(ef_peer_handle); /* * Case 4: lookup the ef peer with invalid key */ ef_peer_handle = ef_peer_handle_create(SC_EF_PEER_ENTRIES); assert_non_null(ef_peer_handle); union ef_peer_key key; key.ip_src = 0x0A0A0A0A; struct rte_ether_addr mac_src = {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}; key.mac_src = mac_src; int peer_id = ef_peer_handle_peer_lookup(ef_peer_handle, &key); assert_int_equal(peer_id < 0, 1); /* delete the ef peer handle */ ret = ef_peer_handle_delete(ef_peer_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 5: Adding ef peers exceeds the maximum number of entries */ /* create the ef peer handle */ ef_peer_handle = ef_peer_handle_create(SC_EF_PEER_ENTRIES); assert_non_null(ef_peer_handle); /* check the ef peer handle */ assert_int_equal(ef_peer_handle_capacity_get(ef_peer_handle), SC_EF_PEER_CAPACITY_CALC(SC_EF_PEER_ENTRIES, LCORE_CACHE_SIZE)); /* check the ef peer handle entries */ uint32_t nr_entries = ef_peer_handle_entries_get(ef_peer_handle); assert_int_equal(nr_entries, SC_EF_PEER_ENTRIES); /* Add peer to full ef peer handle */ for (uint32_t i = 0; i < nr_entries; i++) { key.ip_src = 0x0A0A0A0A + i; key.mac_src.addr_bytes[5] = i; ef_peer_handle_peer_add(ef_peer_handle, &key); if (ef_peer_handle_remaining_entries_get(ef_peer_handle) == 0) { break; } } /* Add peer to full ef peer handle */ uint32_t nr_remaining_entries = ef_peer_handle_remaining_entries_get(ef_peer_handle); assert_int_equal(nr_remaining_entries, 0); /* delete the ef peer handle */ ret = ef_peer_handle_delete(ef_peer_handle); assert_int_equal(ret, RT_SUCCESS); } /* ---------------------------- Test case 'traffic link to etherfabric peer map handle' ---------------------------- */ struct tl_to_ef_peer_map_handle; extern struct tl_to_ef_peer_map_handle * tl_to_ef_peer_map_handle_create(uint16_t capacity); extern int tl_to_ef_peer_map_handle_delete(struct tl_to_ef_peer_map_handle * handle); extern uint16_t tl_to_ef_peer_map_handle_capacity_get(struct tl_to_ef_peer_map_handle * handle); extern int tl_to_ef_peer_map_handle_associate(struct tl_to_ef_peer_map_handle * handle, uint16_t traffic_link_id, int ef_peer_index); extern int tl_to_ef_peer_map_handle_get_ef_peer_index_by_tl_id(struct tl_to_ef_peer_map_handle * handle, uint16_t traffic_link_id, uint16_t * out_ef_peer_index); /* * Test Case: tl to ef peer map handle success */ static void testcase_tl_to_ef_peer_map_handle_success(void ** state) { /* * Case 1: basic test for tl to ef peer map handle */ /* create the tl to ef peer map handle */ uint16_t capacity = 1; struct tl_to_ef_peer_map_handle * tl_to_ef_peer_map_handle = tl_to_ef_peer_map_handle_create(capacity); assert_non_null(tl_to_ef_peer_map_handle); /* check the tl to ef peer map handle */ assert_int_equal(tl_to_ef_peer_map_handle_capacity_get(tl_to_ef_peer_map_handle), capacity); /* associate the tl to ef peer map handle */ int ret = tl_to_ef_peer_map_handle_associate(tl_to_ef_peer_map_handle, 0, 0); assert_int_equal(ret, RT_SUCCESS); /* check the tl to ef peer map handle get ef peer index by tl id */ uint16_t ef_peer_index; ret = tl_to_ef_peer_map_handle_get_ef_peer_index_by_tl_id(tl_to_ef_peer_map_handle, 0, &ef_peer_index); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(ef_peer_index, 0); /* delete the tl to ef peer map handle */ ret = tl_to_ef_peer_map_handle_delete(tl_to_ef_peer_map_handle); assert_int_equal(ret, RT_SUCCESS); /* * Case 2: associate the traffic link ID with the EtherFabric peer map at full capacity */ /* create the tl to ef peer map handle */ capacity = UINT16_MAX; tl_to_ef_peer_map_handle = tl_to_ef_peer_map_handle_create(capacity); assert_non_null(tl_to_ef_peer_map_handle); /* check the tl to ef peer map handle */ assert_int_equal(tl_to_ef_peer_map_handle_capacity_get(tl_to_ef_peer_map_handle), capacity); /* associate the tl to ef peer map handle */ for (uint16_t i = 0; i < capacity; i++) { int ret = tl_to_ef_peer_map_handle_associate(tl_to_ef_peer_map_handle, i, i); assert_int_equal(ret, RT_SUCCESS); } /* check the tl to ef peer map handle get ef peer index by tl id */ for (uint16_t i = 0; i < capacity; i++) { uint16_t ef_peer_index; int ret = tl_to_ef_peer_map_handle_get_ef_peer_index_by_tl_id(tl_to_ef_peer_map_handle, i, &ef_peer_index); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(ef_peer_index, i); } /* delete the tl to ef peer map handle */ ret = tl_to_ef_peer_map_handle_delete(tl_to_ef_peer_map_handle); assert_int_equal(ret, RT_SUCCESS); } /* * Test Case: tl to ef peer map handle failure */ static void testcase_tl_to_ef_peer_map_handle_failure(void ** state) { /* * Case 1: delete the tl to ef peer map handle (NULL) */ int ret = tl_to_ef_peer_map_handle_delete(NULL); assert_int_equal(ret, RT_ERR); /* * Case 2: create the tl to ef peer map handle with invalid capacity */ struct tl_to_ef_peer_map_handle * tl_to_ef_peer_map_handle = tl_to_ef_peer_map_handle_create(0); assert_null(tl_to_ef_peer_map_handle); /* * Case 3: associate the traffic link ID with the EtherFabric peer map out of capacity */ /* create the tl to ef peer map handle */ uint32_t capacity = UINT16_MAX; tl_to_ef_peer_map_handle = tl_to_ef_peer_map_handle_create(capacity); assert_non_null(tl_to_ef_peer_map_handle); /* check the tl to ef peer map handle */ assert_int_equal(tl_to_ef_peer_map_handle_capacity_get(tl_to_ef_peer_map_handle), capacity); /* associate the tl to ef peer map handle */ for (uint32_t i = 0; i < capacity; i++) { int ret = tl_to_ef_peer_map_handle_associate(tl_to_ef_peer_map_handle, i, i); assert_int_equal(ret, RT_SUCCESS); } /* associate the tl to ef peer map handle at full capacity */ ret = tl_to_ef_peer_map_handle_associate(tl_to_ef_peer_map_handle, capacity, capacity); assert_int_equal(ret, RT_ERR); /* delete the tl to ef peer map handle */ ret = tl_to_ef_peer_map_handle_delete(tl_to_ef_peer_map_handle); assert_int_equal(ret, RT_SUCCESS); } /* ------------------------------------------- Test case 'ef node main' -------------------------------------------- */ struct ef_node_main; extern int node_ef_main_delete(struct ef_node_main * ef_main); extern struct ef_node_main * node_ef_main_create(struct sc_main * sc, struct ef_config_handle * ef_node_cfg); extern void ef_info_dump(struct ef_node_main * ef_main); extern uint16_t node_ef_main_nr_graphs_get(struct ef_node_main * ef_main); extern struct sid_handle * node_ef_main_sid_handle_get(struct ef_node_main * ef_main); extern struct ef_adapter_handle * node_ef_main_ef_adapter_handle_get(struct ef_node_main * ef_main); extern struct link_db_ctx * node_ef_main_link_db_ctx_get(struct ef_node_main * ef_main); extern struct ef_peer_handle * node_ef_main_ef_peer_handle_get(struct ef_node_main * ef_main); extern struct tl_to_ef_peer_map_handle * node_ef_main_tl_to_ef_peer_map_handle_get(struct ef_node_main * ef_main); extern struct sc_metrics_handle * node_ef_main_ingress_metrics_handle_get(struct ef_node_main * ef_main, uint16_t graph_id); extern struct sc_metrics_handle * node_ef_main_egress_metrics_handle_get(struct ef_node_main * ef_main, uint16_t graph_id); /* * Test Case: ef node main success */ static void testcase_ef_node_main_success(void ** state) { /* * Case 1: basic test for ef node main */ /* generate the configuration string */ uint32_t nr_ef_adapters = 200 - 100 + 1; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); struct sc_main * mock_sc = *state; strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* create the ef config handle */ uint32_t ef_adapters_max = nr_ef_adapters; struct ef_config_handle * cfg_handle = ef_config_handle_create(ef_adapters_max); assert_non_null(cfg_handle); /* parse the configuration */ int ret = ef_config_parse(mock_sc, cfg_handle); assert_int_equal(ret, RT_SUCCESS); /* check the ef adapters data */ struct ef_adapter * ef_adapters_data = ef_config_handle_adapters_data_get(cfg_handle); assert_non_null(ef_adapters_data); /* check the number of ef adapters */ assert_int_equal(ef_config_handle_nr_adapters_get(cfg_handle), nr_ef_adapters); /* check the sid range */ assert_int_equal(ef_config_handle_sid_start_get(cfg_handle), 100); assert_int_equal(ef_config_handle_sid_end_get(cfg_handle), 200); /* check the ef adapters max */ assert_int_equal(ef_config_handle_ef_adapters_max_get(cfg_handle), ef_adapters_max); /* check the link dbs max */ assert_int_equal(ef_config_handle_link_dbs_max_get(cfg_handle), 64); /* create the ef node main */ struct ef_node_main * ef_main = node_ef_main_create(mock_sc, cfg_handle); assert_non_null(ef_main); /* check the ef node main */ ef_info_dump(ef_main); /* check the number of graphs */ assert_int_equal(node_ef_main_nr_graphs_get(ef_main), 1); /* check the sid handle */ struct sid_handle * sid_handle = node_ef_main_sid_handle_get(ef_main); assert_non_null(sid_handle); /* check the ef adapter handle */ struct ef_adapter_handle * ef_adapter_handle = node_ef_main_ef_adapter_handle_get(ef_main); assert_non_null(ef_adapter_handle); /* check the link db ctx */ struct link_db_ctx * link_db_ctx = node_ef_main_link_db_ctx_get(ef_main); assert_non_null(link_db_ctx); /* check the ef peer handle */ struct ef_peer_handle * ef_peer_handle = node_ef_main_ef_peer_handle_get(ef_main); assert_non_null(ef_peer_handle); /* check the tl to ef peer map handle */ struct tl_to_ef_peer_map_handle * tl_to_ef_peer_map_handle = node_ef_main_tl_to_ef_peer_map_handle_get(ef_main); assert_non_null(tl_to_ef_peer_map_handle); /* check the ingress metrics handle */ struct sc_metrics_handle * ingress_metrics_handle = node_ef_main_ingress_metrics_handle_get(ef_main, 0); assert_non_null(ingress_metrics_handle); /* check the egress metrics handle */ struct sc_metrics_handle * egress_metrics_handle = node_ef_main_egress_metrics_handle_get(ef_main, 0); assert_non_null(egress_metrics_handle); /* delete the ef node main */ ret = node_ef_main_delete(ef_main); assert_int_equal(ret, RT_SUCCESS); /* delete the ef config handle */ ret = ef_config_handle_delete(cfg_handle); assert_int_equal(ret, RT_SUCCESS); } /* * Test Case: ef node main failure */ static void testcase_ef_node_main_failure(void ** state) { /* * Case 1: delete the ef node main (NULL) */ int ret = node_ef_main_delete(NULL); assert_int_equal(ret, RT_ERR); /* * Case 2: create the ef node main with a NULL argument */ struct ef_node_main * ef_main = node_ef_main_create(NULL, NULL); assert_null(ef_main); } /* ---------------------------------------------- Test case 'ef init' ---------------------------------------------- */ extern int ef_init(struct sc_main * sc); extern int ef_deinit(); /* * Test Case: ef init success */ static void testcase_ef_init_success(void ** state) { /* * Case 1: basic test for ef init */ /* generate the configuration string */ uint32_t nr_ef_adapters = 32; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); struct sc_main * mock_sc = *state; strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* Initialize the ef */ int ret = ef_init(mock_sc); assert_int_equal(ret, RT_SUCCESS); /* Deinitialize the ef */ ret = ef_deinit(); assert_int_equal(ret, RT_SUCCESS); } /* ---------------------------------------------- Test case 'ef node' ---------------------------------------------- */ struct ef_test_main { struct sc_main * mock_sc; rte_graph_t graph; }; /* Set the pkt offset */ const static int ef_encap_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr) + sizeof(struct g_vxlan_hdr); extern struct ef_node_main * g_ef_node_main_get(void); extern void eth_header_construct(struct rte_ether_hdr * eth_hdr, struct rte_ether_addr * src_mac, struct rte_ether_addr * dst_mac, uint16_t eth_type); extern int ipv4_header_construct(struct rte_ipv4_hdr * ipv4_hdr, const char * src_ip, const char * dst_ip, uint8_t proto, uint16_t payload_length); extern int ipv6_header_construct(struct rte_ipv6_hdr * ipv6_hdr, const char * src_ip, const char * dst_ip, uint8_t proto, uint16_t payload_length); extern void udp_header_construct(struct rte_udp_hdr * udp_hdr, uint16_t src_port, uint16_t dst_port, uint16_t length); extern void tcp_header_construct(struct rte_tcp_hdr * tcp_hdr, uint16_t src_port, uint16_t dst_port, uint32_t seq_num, uint32_t ack_num, uint8_t data_offset, uint8_t flags, uint16_t window); extern int vxlan_encap_constructed_pkt(struct rte_mbuf * mbuf, uint8_t dir, uint16_t ef_link_id, const char * src_ip, const char * dst_ip, struct rte_ether_addr * src_mac, struct rte_ether_addr * dst_mac, uint16_t eth_type); extern int sc_metrics_value_get(struct sc_metrics_handle * metrics_handle, uint64_t * value, uint16_t key); /* * Etherfabric ingress setup */ static int testgroup_ef_ingress_setup(void ** state) { /* mock pkt source to generate mock packets */ const char * node_patterns[] = { "mock_pkt_input", "mock_pkt_output", "ef_ingress", }; /* create a fake graph */ struct rte_graph_param graph_param = { .node_patterns = node_patterns, .nb_node_patterns = RTE_DIM(node_patterns), .socket_id = 0, }; /* Update the pkt input's next id */ rte_node_t node_id_pkt_input = rte_node_from_name("mock_pkt_input"); assert_int_not_equal(node_id_pkt_input, RTE_NODE_ID_INVALID); const char * updated_next_node[] = {"ef_ingress"}; int rc = rte_node_edge_update(node_id_pkt_input, 0, updated_next_node, RTE_DIM(updated_next_node)); assert_int_equal(rc, 1); /* Update the node edge */ rte_node_t node_id_ef_ingress = rte_node_from_name("ef_ingress"); assert_int_not_equal(node_id_ef_ingress, RTE_NODE_ID_INVALID); const char * ef_ingress_updated_next_node[] = { "mock_pkt_output", "mock_pkt_drop", }; rc = rte_node_edge_update(node_id_ef_ingress, 0, ef_ingress_updated_next_node, RTE_DIM(ef_ingress_updated_next_node)); assert_int_equal(rc, 2); rte_graph_t graph = rte_graph_create("test_ef_ingress", &graph_param); assert_int_not_equal(graph, RTE_GRAPH_ID_INVALID); /* create a graph worker */ struct sc_main * mock_sc = rte_zmalloc(NULL, sizeof(struct sc_main), 0); assert_non_null(mock_sc); mock_sc->nr_io_thread = 1; /* generate the configuration string */ uint32_t nr_ef_adapters = 32; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* ef init */ int ret = ef_init(mock_sc); assert_int_equal(ret, RT_SUCCESS); /* create the ef test main */ struct ef_test_main * ef_test_main = rte_zmalloc(NULL, sizeof(struct ef_test_main), 0); assert_non_null(ef_test_main); ef_test_main->mock_sc = mock_sc; ef_test_main->graph = graph; *state = ef_test_main; return 0; } /* * Etherfabric ingress teardown */ static int testgroup_ef_ingress_teardown(void ** state) { struct ef_test_main * ef_test_main = *state; /* ef deinit */ int ret = ef_deinit(); assert_int_equal(ret, RT_SUCCESS); /* free the mock_sc */ rte_free(ef_test_main->mock_sc); /* destroy the graph */ rte_graph_destroy(ef_test_main->graph); /* free the ef test main */ rte_free(ef_test_main); return 0; } /* * Etherfabric egress vwire mode setup */ static int testgroup_ef_egress_vwire_mode_setup(void ** state) { /* mock pkt source to generate mock packets */ const char * node_patterns[] = { "mock_pkt_input", "mock_pkt_output", "ef_egress", }; /* create a fake graph */ struct rte_graph_param graph_param = { .node_patterns = node_patterns, .nb_node_patterns = RTE_DIM(node_patterns), .socket_id = 0, }; /* Update the pkt input's next id */ rte_node_t node_id_pkt_input = rte_node_from_name("mock_pkt_input"); assert_int_not_equal(node_id_pkt_input, RTE_NODE_ID_INVALID); const char * updated_next_node[] = {"ef_egress"}; int rc = rte_node_edge_update(node_id_pkt_input, 0, updated_next_node, RTE_DIM(updated_next_node)); assert_int_equal(rc, 1); /* Update the node edge */ rte_node_t node_id_ef_ingress = rte_node_from_name("ef_egress"); assert_int_not_equal(node_id_ef_ingress, RTE_NODE_ID_INVALID); const char * ef_ingress_updated_next_node[] = { "mock_pkt_output", "mock_pkt_drop", }; rc = rte_node_edge_update(node_id_ef_ingress, 0, ef_ingress_updated_next_node, RTE_DIM(ef_ingress_updated_next_node)); assert_int_equal(rc, 2); rte_graph_t graph = rte_graph_create("test_ef_egress", &graph_param); assert_int_not_equal(graph, RTE_GRAPH_ID_INVALID); /* create a graph worker */ struct sc_main * mock_sc = rte_zmalloc(NULL, sizeof(struct sc_main), 0); assert_non_null(mock_sc); mock_sc->nr_io_thread = 1; /* generate the configuration string */ uint32_t nr_ef_adapters = 32; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 1, 0); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* ef init */ int ret = ef_init(mock_sc); assert_int_equal(ret, RT_SUCCESS); /* create the ef test main */ struct ef_test_main * ef_test_main = rte_zmalloc(NULL, sizeof(struct ef_test_main), 0); assert_non_null(ef_test_main); ef_test_main->mock_sc = mock_sc; ef_test_main->graph = graph; *state = ef_test_main; return 0; } /* * Etherfabric egress tap mode setup */ static int testgroup_ef_egress_tap_mode_setup(void ** state) { /* mock pkt source to generate mock packets */ const char * node_patterns[] = { "mock_pkt_input", "mock_pkt_output", "ef_egress", }; /* create a fake graph */ struct rte_graph_param graph_param = { .node_patterns = node_patterns, .nb_node_patterns = RTE_DIM(node_patterns), .socket_id = 0, }; /* Update the pkt input's next id */ rte_node_t node_id_pkt_input = rte_node_from_name("mock_pkt_input"); assert_int_not_equal(node_id_pkt_input, RTE_NODE_ID_INVALID); const char * updated_next_node[] = {"ef_egress"}; int rc = rte_node_edge_update(node_id_pkt_input, 0, updated_next_node, RTE_DIM(updated_next_node)); assert_int_equal(rc, 1); /* Update the node edge */ rte_node_t node_id_ef_ingress = rte_node_from_name("ef_egress"); assert_int_not_equal(node_id_ef_ingress, RTE_NODE_ID_INVALID); const char * ef_ingress_updated_next_node[] = { "mock_pkt_output", "mock_pkt_drop", }; rc = rte_node_edge_update(node_id_ef_ingress, 0, ef_ingress_updated_next_node, RTE_DIM(ef_ingress_updated_next_node)); assert_int_equal(rc, 2); rte_graph_t graph = rte_graph_create("test_ef_egress", &graph_param); assert_int_not_equal(graph, RTE_GRAPH_ID_INVALID); /* create a graph worker */ struct sc_main * mock_sc = rte_zmalloc(NULL, sizeof(struct sc_main), 0); assert_non_null(mock_sc); mock_sc->nr_io_thread = 1; /* generate the configuration string */ uint32_t nr_ef_adapters = 32; char * test_cfgfile_content = generate_config_string(nr_ef_adapters, 2, 0); /* create the configuration file */ const char * filename = create_config_file(test_cfgfile_content); assert_non_null(filename); strcpy(mock_sc->local_cfgfile, filename); /* mock the mr_dev_desc_lookup function */ assert(nr_ef_adapters <= MOCK_NR_DEV_MAX); for (uint32_t i = 0; i < nr_ef_adapters; i++) { expect_string(__wrap_mr_dev_desc_lookup, devsym, mock_devs_name[i]); will_return(__wrap_mr_dev_desc_lookup, mock_devs_desc[i]); } /* ef init */ int ret = ef_init(mock_sc); assert_int_equal(ret, RT_SUCCESS); /* create the ef test main */ struct ef_test_main * ef_test_main = rte_zmalloc(NULL, sizeof(struct ef_test_main), 0); assert_non_null(ef_test_main); ef_test_main->mock_sc = mock_sc; ef_test_main->graph = graph; *state = ef_test_main; return 0; } /* * Etherfabric egress common teardown */ static int testgroup_ef_egress_common_teardown(void ** state) { struct ef_test_main * ef_test_main = *state; /* ef deinit */ int ret = ef_deinit(); assert_int_equal(ret, RT_SUCCESS); /* free the mock_sc */ rte_free(ef_test_main->mock_sc); /* destroy the graph */ rte_graph_destroy(ef_test_main->graph); /* free the ef test main */ rte_free(ef_test_main); return 0; } /* * Test Case: ef ingress forward pkts */ static void testcase_ef_ingress_forward_pkts(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_ingress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[2]; for (uint8_t i = 0; i < 2; i++) { mbuf_input[i] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[i]); } /* set the return value for the mock function */ will_return(mock_pkt_input_process, 2); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_output[2] = {}; unsigned int nr_mbuf_output = 0; will_return(mock_pkt_output_process, mbuf_output); will_return(mock_pkt_output_process, &nr_mbuf_output); struct rte_mbuf * mbuf_drop[2] = {}; unsigned int nr_mbuf_drop = 0; will_return(mock_pkt_drop_process, mbuf_drop); will_return(mock_pkt_drop_process, &nr_mbuf_drop); /* * construct the test packet for IPv4 */ /* set mbuf pkt_len for IPv4 */ uint32_t input_internal_pkt_len_0 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_internal_pkt_len_0; mbuf_input[0]->pkt_len = input_internal_pkt_len_0; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr_0 = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(input_internal_eth_hdr_0 + 1); struct rte_tcp_hdr * input_internal_tcp_hdr = (struct rte_tcp_hdr *)(input_internal_ipv4_hdr + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_internal_eth_hdr_0, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_internal_ipv4_hdr, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_internal_tcp_hdr, 80, 80, 0, 0, 5, 0, 1000); /* encap vxlan */ uint8_t input_dir_0 = 0; uint16_t input_ef_link_id_0 = 31; const char * input_src_ip_0 = "10.11.11.11"; const char * input_dst_ip_0 = "10.10.10.10"; struct rte_ether_addr src_mac_0 = {.addr_bytes = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; struct rte_ether_addr dst_mac_0 = {.addr_bytes = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}}; int ret = vxlan_encap_constructed_pkt(mbuf_input[0], input_dir_0, input_ef_link_id_0, input_src_ip_0, input_dst_ip_0, &src_mac_0, &dst_mac_0, RTE_ETHER_TYPE_IPV4); assert_int_equal(ret, RT_SUCCESS); /* get external ether header */ struct rte_ether_hdr * external_ether_hdr_0 = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); assert_non_null(external_ether_hdr_0); /* set metadata */ struct mrb_metadata * input_mrb_meta_0 = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_0); sid_list_init(&input_mrb_meta_0->sid_list); /* prepare to parse the ingress pkt */ struct pkt_parser input_pkt_parser_0; pkt_parser_init(&input_pkt_parser_0, &input_mrb_meta_0->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX); pkt_parser_exec(&input_pkt_parser_0, mbuf_input[0]); /* save the pkt parser result */ struct pkt_parser_result input_pkt_parser_result_0; rte_memcpy(&input_pkt_parser_result_0, &input_mrb_meta_0->pkt_parser_result, sizeof(struct pkt_parser_result)); /* * construct the test packet for ipv6 */ /* set mbuf pkt_len for ipv6 */ uint32_t input_internal_pkt_len_1 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_udp_hdr); mbuf_input[1]->data_len = input_internal_pkt_len_1; mbuf_input[1]->pkt_len = input_internal_pkt_len_1; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr_1 = rte_pktmbuf_mtod(mbuf_input[1], struct rte_ether_hdr *); struct rte_ipv6_hdr * ipv6_hdr = (struct rte_ipv6_hdr *)(input_internal_eth_hdr_1 + 1); struct rte_udp_hdr * udp_hdr = (struct rte_udp_hdr *)(ipv6_hdr + 1); /* set the ether header */ eth_header_construct(input_internal_eth_hdr_1, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV6); /* set the ipv6 header */ ipv6_header_construct(ipv6_hdr, NULL, NULL, IPPROTO_UDP, sizeof(struct rte_udp_hdr)); /* set the udp header */ udp_header_construct(udp_hdr, 80, 80, sizeof(struct rte_udp_hdr)); /* encap vxlan */ uint8_t input_dir_1 = 1; uint16_t input_ef_link_id_1 = 30; const char * input_src_ip_1 = "10.11.11.12"; const char * input_dst_ip_1 = "10.10.10.11"; struct rte_ether_addr src_mac_1 = {.addr_bytes = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01}}; struct rte_ether_addr dst_mac_1 = {.addr_bytes = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA}}; ret = vxlan_encap_constructed_pkt(mbuf_input[1], input_dir_1, input_ef_link_id_1, input_src_ip_1, input_dst_ip_1, &src_mac_1, &dst_mac_1, RTE_ETHER_TYPE_IPV6); assert_int_equal(ret, RT_SUCCESS); /* get external ether header */ struct rte_ether_hdr * external_ether_hdr_1 = rte_pktmbuf_mtod(mbuf_input[1], struct rte_ether_hdr *); assert_non_null(external_ether_hdr_1); /* set metadata */ struct mrb_metadata * input_mrb_meta_1 = mrbuf_cz_data(mbuf_input[1], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_1); sid_list_init(&input_mrb_meta_1->sid_list); /* prepare to parse the ingress pkt */ struct pkt_parser input_pkt_parser_1; pkt_parser_init(&input_pkt_parser_1, &input_mrb_meta_1->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX); pkt_parser_exec(&input_pkt_parser_1, mbuf_input[0]); /* save the pkt parser result */ struct pkt_parser_result input_pkt_parser_result_1; rte_memcpy(&input_pkt_parser_result_1, &input_mrb_meta_1->pkt_parser_result, sizeof(struct pkt_parser_result)); /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_output, 2); /* check the output mbuf */ for (uint8_t i = 0; i < nr_mbuf_output; i++) { assert_non_null(mbuf_output[i]); assert_ptr_equal(mbuf_output[i], mbuf_input[i]); } /* * check the output mbuf 0 (IPv4) */ /* check the metadata */ struct mrb_metadata * output_mrb_meta_0 = mrbuf_cz_data(mbuf_output[0], MR_NODE_CTRLZONE_ID); assert_int_equal(output_mrb_meta_0->adapter_type, ADAPTER_TYPE_EF); assert_int_equal(output_mrb_meta_0->adapter_id, 0); assert_int_equal(output_mrb_meta_0->ef_link_id, input_ef_link_id_0); assert_int_equal(output_mrb_meta_0->traffic_link_id, UINT16_MAX); assert_int_equal(output_mrb_meta_0->dir, input_dir_0); /* check the peer index */ struct ef_node_main * ef_main = g_ef_node_main_get(); assert_non_null(ef_main); struct ef_peer_handle * ef_peer_handle = node_ef_main_ef_peer_handle_get(ef_main); assert_non_null(ef_peer_handle); struct ef_peer * ef_peer = ef_peer_handle_peer_get(ef_peer_handle, output_mrb_meta_0->ef_peer_index); assert_non_null(ef_peer); assert_memory_equal(ef_peer_mac_addr_get(ef_peer), &src_mac_0, sizeof(struct rte_ether_addr)); assert_int_equal(ef_peer_ip_addr_get(ef_peer), inet_addr(input_src_ip_0)); /* check the sid */ unsigned int nr_mbuf_0_sids = 0; uint16_t mbuf_0_sids[MR_NODE_COMMON_MAX_SID_NUM] = {}; nr_mbuf_0_sids = sid_list_get(&output_mrb_meta_0->sid_list, mbuf_0_sids, RTE_DIM(mbuf_0_sids)); assert_int_equal(nr_mbuf_0_sids, 1); assert_int_equal(mbuf_0_sids[0], 100); /* check the pkt parser result */ assert_int_equal(output_mrb_meta_0->pkt_parser_result.start_layers, input_pkt_parser_result_0.start_layers + 4); /* check the pkt */ uint32_t output_pkt_len_0 = rte_pktmbuf_pkt_len(mbuf_output[0]); assert_int_equal(output_pkt_len_0, input_internal_pkt_len_0); /* check the outer ether header */ assert_memory_equal(external_ether_hdr_0->src_addr.addr_bytes, dst_mac_0.addr_bytes, RTE_ETHER_ADDR_LEN); assert_memory_equal(external_ether_hdr_0->dst_addr.addr_bytes, src_mac_0.addr_bytes, RTE_ETHER_ADDR_LEN); /* check the interne pkt */ struct rte_ether_hdr * out_ether_hdr_0 = rte_pktmbuf_mtod(mbuf_output[0], struct rte_ether_hdr *); assert_non_null(out_ether_hdr_0); struct rte_ipv4_hdr * out_ipv4_hdr_0 = (struct rte_ipv4_hdr *)(out_ether_hdr_0 + 1); assert_non_null(out_ipv4_hdr_0); struct rte_tcp_hdr * out_tcp_hdr_0 = (struct rte_tcp_hdr *)(out_ipv4_hdr_0 + 1); assert_non_null(out_tcp_hdr_0); assert_memory_equal(out_ether_hdr_0, input_internal_eth_hdr_0, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_ipv4_hdr_0, input_internal_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); assert_memory_equal(out_tcp_hdr_0, input_internal_tcp_hdr, sizeof(struct rte_tcp_hdr)); /* * check the output mbuf 1 (IPv6) */ /* check the metadata */ struct mrb_metadata * output_mrb_meta_1 = mrbuf_cz_data(mbuf_output[1], MR_NODE_CTRLZONE_ID); assert_int_equal(output_mrb_meta_1->adapter_type, ADAPTER_TYPE_EF); assert_int_equal(output_mrb_meta_1->adapter_id, 1); assert_int_equal(output_mrb_meta_1->ef_link_id, input_ef_link_id_1); assert_int_equal(output_mrb_meta_1->traffic_link_id, UINT16_MAX); assert_int_equal(output_mrb_meta_1->dir, input_dir_1); /* check the peer index */ struct ef_peer * ef_peer_1 = ef_peer_handle_peer_get(ef_peer_handle, output_mrb_meta_1->ef_peer_index); assert_non_null(ef_peer_1); assert_memory_equal(ef_peer_mac_addr_get(ef_peer_1), &src_mac_1, sizeof(struct rte_ether_addr)); assert_int_equal(ef_peer_ip_addr_get(ef_peer_1), inet_addr(input_src_ip_1)); /* check the sid */ unsigned int nr_mbuf_1_sids = 0; uint16_t mbuf_1_sids[MR_NODE_COMMON_MAX_SID_NUM] = {}; nr_mbuf_1_sids = sid_list_get(&output_mrb_meta_1->sid_list, mbuf_1_sids, RTE_DIM(mbuf_1_sids)); assert_int_equal(nr_mbuf_1_sids, 1); assert_int_equal(mbuf_1_sids[0], 101); /* check the pkt parser result */ assert_int_equal(output_mrb_meta_1->pkt_parser_result.start_layers, input_pkt_parser_result_1.start_layers + 4); /* check the pkt */ uint32_t output_pkt_len_1 = rte_pktmbuf_pkt_len(mbuf_output[1]); assert_int_equal(output_pkt_len_1, input_internal_pkt_len_1); /* check the outer ether header */ assert_memory_equal(external_ether_hdr_1->src_addr.addr_bytes, dst_mac_1.addr_bytes, RTE_ETHER_ADDR_LEN); assert_memory_equal(external_ether_hdr_1->dst_addr.addr_bytes, src_mac_1.addr_bytes, RTE_ETHER_ADDR_LEN); /* check the interne pkt */ struct rte_ether_hdr * out_ether_hdr_1 = rte_pktmbuf_mtod(mbuf_output[1], struct rte_ether_hdr *); assert_non_null(out_ether_hdr_1); struct rte_ipv6_hdr * out_ipv6_hdr_1 = (struct rte_ipv6_hdr *)(out_ether_hdr_1 + 1); assert_non_null(out_ipv6_hdr_1); struct rte_udp_hdr * out_udp_hdr_1 = (struct rte_udp_hdr *)(out_ipv6_hdr_1 + 1); assert_non_null(out_udp_hdr_1); assert_memory_equal(out_ether_hdr_1, input_internal_eth_hdr_1, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_ipv6_hdr_1, ipv6_hdr, sizeof(struct rte_ipv6_hdr)); assert_memory_equal(out_udp_hdr_1, udp_hdr, sizeof(struct rte_udp_hdr)); /* check metrics */ struct sc_metrics_handle * ingress_metrics_handle = node_ef_main_ingress_metrics_handle_get(ef_main, 0); assert_non_null(ingress_metrics_handle); uint64_t total_pkts; ret = sc_metrics_value_get(ingress_metrics_handle, &total_pkts, 0); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(total_pkts, 2); uint64_t to_classifier_pkts; ret = sc_metrics_value_get(ingress_metrics_handle, &to_classifier_pkts, 2); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(to_classifier_pkts, 2); /* release the mbufs */ for (uint8_t i = 0; i < 2; i++) { rte_pktmbuf_free(mbuf_input[i]); } assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* * Test Case: ef ingress drop for adapter no exist */ static void testcase_ef_ingress_drop_adapter_no_exist(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_ingress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[1]; mbuf_input[0] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[0]); /* set the return value for the mock function */ will_return(mock_pkt_input_process, 1); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_drop[1] = {}; unsigned int nr_mbuf_drop = 0; will_return(mock_pkt_drop_process, mbuf_drop); will_return(mock_pkt_drop_process, &nr_mbuf_drop); /* * construct the test packet */ /* set mbuf pkt_len */ uint32_t input_internal_pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_internal_pkt_len; mbuf_input[0]->pkt_len = input_internal_pkt_len; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(input_internal_eth_hdr + 1); struct rte_tcp_hdr * input_internal_tcp_hdr = (struct rte_tcp_hdr *)(input_internal_ipv4_hdr + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_internal_eth_hdr, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_internal_ipv4_hdr, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_internal_tcp_hdr, 80, 80, 0, 0, 5, 0, 1000); /* encap vxlan */ uint8_t input_dir_0 = 0; uint16_t input_ef_link_id_0 = 31; const char * input_src_ip_0 = "10.11.11.11"; const char * input_dst_ip_0 = "192.168.1.1"; struct rte_ether_addr src_mac_0 = {.addr_bytes = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; struct rte_ether_addr dst_mac_0 = {.addr_bytes = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}}; int ret = vxlan_encap_constructed_pkt(mbuf_input[0], input_dir_0, input_ef_link_id_0, input_src_ip_0, input_dst_ip_0, &src_mac_0, &dst_mac_0, RTE_ETHER_TYPE_IPV4); assert_int_equal(ret, RT_SUCCESS); /* get external header */ struct rte_ether_hdr * input_external_ether_hdr = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); assert_non_null(input_external_ether_hdr); struct rte_ipv4_hdr * input_external_ipv4_hdr = (struct rte_ipv4_hdr *)(input_external_ether_hdr + 1); assert_non_null(input_external_ipv4_hdr); struct rte_udp_hdr * input_external_udp_hdr = (struct rte_udp_hdr *)(input_external_ipv4_hdr + 1); assert_non_null(input_external_udp_hdr); struct g_vxlan_hdr * input_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(input_external_udp_hdr + 1); assert_non_null(input_external_p_vxlan_hdr); /* set metadata */ struct mrb_metadata * input_mrb_meta = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta); sid_list_init(&input_mrb_meta->sid_list); /* prepare to parse the ingress pkt */ struct pkt_parser input_pkt_parser; pkt_parser_init(&input_pkt_parser, &input_mrb_meta->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX); pkt_parser_exec(&input_pkt_parser, mbuf_input[0]); /* save the pkt parser result */ struct pkt_parser_result input_pkt_parser_result; rte_memcpy(&input_pkt_parser_result, &input_mrb_meta->pkt_parser_result, sizeof(struct pkt_parser_result)); /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_drop, 1); /* check the drop mbuf */ assert_non_null(mbuf_drop[0]); assert_ptr_equal(mbuf_drop[0], mbuf_input[0]); /* check the metadata */ struct mrb_metadata * drop_mrb_meta = mrbuf_cz_data(mbuf_drop[0], MR_NODE_CTRLZONE_ID); assert_memory_equal(drop_mrb_meta, input_mrb_meta, sizeof(struct mrb_metadata)); /* check the pkt */ uint32_t drop_pkt_len = rte_pktmbuf_pkt_len(mbuf_drop[0]); assert_int_equal(drop_pkt_len, input_internal_pkt_len + ef_encap_len); /* check the drop external ether header */ struct rte_ether_hdr * drop_external_ether_hdr = rte_pktmbuf_mtod(mbuf_drop[0], struct rte_ether_hdr *); assert_non_null(drop_external_ether_hdr); assert_memory_equal(drop_external_ether_hdr, input_external_ether_hdr, sizeof(struct rte_ether_hdr)); /* check the drop external ipv4 header */ struct rte_ipv4_hdr * drop_external_ipv4_hdr = (struct rte_ipv4_hdr *)(drop_external_ether_hdr + 1); assert_non_null(drop_external_ipv4_hdr); assert_memory_equal(drop_external_ipv4_hdr, input_external_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); /* check the drop external udp header */ struct rte_udp_hdr * drop_external_udp_hdr = (struct rte_udp_hdr *)(drop_external_ipv4_hdr + 1); assert_non_null(drop_external_udp_hdr); assert_memory_equal(drop_external_udp_hdr, input_external_udp_hdr, sizeof(struct rte_udp_hdr)); /* check the drop external vxlan header */ struct g_vxlan_hdr * drop_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(drop_external_udp_hdr + 1); assert_non_null(drop_external_p_vxlan_hdr); assert_memory_equal(drop_external_p_vxlan_hdr, input_external_p_vxlan_hdr, sizeof(struct g_vxlan_hdr)); /* check the drop internal ether header */ struct rte_ether_hdr * drop_internal_eth_hdr = (struct rte_ether_hdr *)(drop_external_p_vxlan_hdr + 1); assert_non_null(drop_internal_eth_hdr); assert_memory_equal(drop_internal_eth_hdr, input_internal_eth_hdr, sizeof(struct rte_ether_hdr)); /* check the drop internal ipv4 header */ struct rte_ipv4_hdr * drop_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(drop_internal_eth_hdr + 1); assert_non_null(drop_internal_ipv4_hdr); assert_memory_equal(drop_internal_ipv4_hdr, input_internal_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); /* check the drop internal tcp header */ struct rte_tcp_hdr * drop_internal_tcp_hdr = (struct rte_tcp_hdr *)(drop_internal_ipv4_hdr + 1); assert_non_null(drop_internal_tcp_hdr); assert_memory_equal(drop_internal_tcp_hdr, input_internal_tcp_hdr, sizeof(struct rte_tcp_hdr)); /* check metrics */ struct ef_node_main * ef_main = g_ef_node_main_get(); assert_non_null(ef_main); struct sc_metrics_handle * ingress_metrics_handle = node_ef_main_ingress_metrics_handle_get(ef_main, 0); assert_non_null(ingress_metrics_handle); uint64_t dorp_adapter_no_exist_pkts; ret = sc_metrics_value_get(ingress_metrics_handle, &dorp_adapter_no_exist_pkts, 3); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(dorp_adapter_no_exist_pkts, 1); /* release the mbufs */ rte_pktmbuf_free(mbuf_input[0]); assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* * Test Case: ef ingress drop for prepend sid error */ static void testcase_ef_ingress_drop_prepend_sid_error(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_ingress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[1]; mbuf_input[0] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[0]); /* set the return value for the mock function */ will_return(mock_pkt_input_process, 1); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_drop[1] = {}; unsigned int nr_mbuf_drop = 0; will_return(mock_pkt_drop_process, mbuf_drop); will_return(mock_pkt_drop_process, &nr_mbuf_drop); /* * construct the test packet */ /* set mbuf pkt_len */ uint32_t input_internal_pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_internal_pkt_len; mbuf_input[0]->pkt_len = input_internal_pkt_len; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(input_internal_eth_hdr + 1); struct rte_tcp_hdr * input_internal_tcp_hdr = (struct rte_tcp_hdr *)(input_internal_ipv4_hdr + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_internal_eth_hdr, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_internal_ipv4_hdr, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_internal_tcp_hdr, 80, 80, 0, 0, 5, 0, 1000); /* encap vxlan */ uint8_t input_dir_0 = 0; uint16_t input_ef_link_id_0 = 31; const char * input_src_ip_0 = "10.11.11.13"; const char * input_dst_ip_0 = "10.10.10.10"; struct rte_ether_addr src_mac_0 = {.addr_bytes = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}}; struct rte_ether_addr dst_mac_0 = {.addr_bytes = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}}; int ret = vxlan_encap_constructed_pkt(mbuf_input[0], input_dir_0, input_ef_link_id_0, input_src_ip_0, input_dst_ip_0, &src_mac_0, &dst_mac_0, RTE_ETHER_TYPE_IPV4); assert_int_equal(ret, RT_SUCCESS); /* get external header */ struct rte_ether_hdr * input_external_ether_hdr = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); assert_non_null(input_external_ether_hdr); struct rte_ipv4_hdr * input_external_ipv4_hdr = (struct rte_ipv4_hdr *)(input_external_ether_hdr + 1); assert_non_null(input_external_ipv4_hdr); struct rte_udp_hdr * input_external_udp_hdr = (struct rte_udp_hdr *)(input_external_ipv4_hdr + 1); assert_non_null(input_external_udp_hdr); struct g_vxlan_hdr * input_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(input_external_udp_hdr + 1); assert_non_null(input_external_p_vxlan_hdr); /* set metadata */ struct mrb_metadata * input_mrb_meta = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta); sid_list_init(&input_mrb_meta->sid_list); ret = RT_SUCCESS; do { /* set the sid */ uint16_t sid = 111; ret = sid_list_prepend(&input_mrb_meta->sid_list, &sid, 1); } while (ret == RT_SUCCESS); /* prepare to parse the ingress pkt */ struct pkt_parser input_pkt_parser; pkt_parser_init(&input_pkt_parser, &input_mrb_meta->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX); pkt_parser_exec(&input_pkt_parser, mbuf_input[0]); /* save the pkt parser result */ struct pkt_parser_result input_pkt_parser_result; rte_memcpy(&input_pkt_parser_result, &input_mrb_meta->pkt_parser_result, sizeof(struct pkt_parser_result)); /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_drop, 1); /* check the drop mbuf */ assert_non_null(mbuf_drop[0]); assert_ptr_equal(mbuf_drop[0], mbuf_input[0]); /* check the metadata */ struct mrb_metadata * drop_mrb_meta = mrbuf_cz_data(mbuf_drop[0], MR_NODE_CTRLZONE_ID); drop_mrb_meta->dir = input_dir_0; drop_mrb_meta->adapter_type = ADAPTER_TYPE_EF; drop_mrb_meta->adapter_id = 0; drop_mrb_meta->ef_link_id = input_ef_link_id_0; drop_mrb_meta->traffic_link_id = UINT16_MAX; /* check the peer index */ struct ef_node_main * ef_main = g_ef_node_main_get(); assert_non_null(ef_main); struct ef_peer_handle * ef_peer_handle = node_ef_main_ef_peer_handle_get(ef_main); assert_non_null(ef_peer_handle); struct ef_peer * ef_peer_1 = ef_peer_handle_peer_get(ef_peer_handle, drop_mrb_meta->ef_peer_index); assert_non_null(ef_peer_1); assert_memory_equal(ef_peer_mac_addr_get(ef_peer_1), &src_mac_0, sizeof(struct rte_ether_addr)); assert_int_equal(ef_peer_ip_addr_get(ef_peer_1), inet_addr(input_src_ip_0)); /* check the pkt */ uint32_t drop_pkt_len = rte_pktmbuf_pkt_len(mbuf_drop[0]); assert_int_equal(drop_pkt_len, input_internal_pkt_len + ef_encap_len); /* check the drop external ether header */ struct rte_ether_hdr * drop_external_ether_hdr = rte_pktmbuf_mtod(mbuf_drop[0], struct rte_ether_hdr *); assert_non_null(drop_external_ether_hdr); assert_memory_equal(drop_external_ether_hdr, input_external_ether_hdr, sizeof(struct rte_ether_hdr)); /* check the drop external ipv4 header */ struct rte_ipv4_hdr * drop_external_ipv4_hdr = (struct rte_ipv4_hdr *)(drop_external_ether_hdr + 1); assert_non_null(drop_external_ipv4_hdr); assert_memory_equal(drop_external_ipv4_hdr, input_external_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); /* check the drop external udp header */ struct rte_udp_hdr * drop_external_udp_hdr = (struct rte_udp_hdr *)(drop_external_ipv4_hdr + 1); assert_non_null(drop_external_udp_hdr); assert_memory_equal(drop_external_udp_hdr, input_external_udp_hdr, sizeof(struct rte_udp_hdr)); /* check the drop external vxlan header */ struct g_vxlan_hdr * drop_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(drop_external_udp_hdr + 1); assert_non_null(drop_external_p_vxlan_hdr); assert_memory_equal(drop_external_p_vxlan_hdr, input_external_p_vxlan_hdr, sizeof(struct g_vxlan_hdr)); /* check the drop internal ether header */ struct rte_ether_hdr * drop_internal_eth_hdr = (struct rte_ether_hdr *)(drop_external_p_vxlan_hdr + 1); assert_non_null(drop_internal_eth_hdr); assert_memory_equal(drop_internal_eth_hdr, input_internal_eth_hdr, sizeof(struct rte_ether_hdr)); /* check the drop internal ipv4 header */ struct rte_ipv4_hdr * drop_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(drop_internal_eth_hdr + 1); assert_non_null(drop_internal_ipv4_hdr); assert_memory_equal(drop_internal_ipv4_hdr, input_internal_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); /* check the drop internal tcp header */ struct rte_tcp_hdr * drop_internal_tcp_hdr = (struct rte_tcp_hdr *)(drop_internal_ipv4_hdr + 1); assert_non_null(drop_internal_tcp_hdr); assert_memory_equal(drop_internal_tcp_hdr, input_internal_tcp_hdr, sizeof(struct rte_tcp_hdr)); /* check metrics */ struct sc_metrics_handle * ingress_metrics_handle = node_ef_main_ingress_metrics_handle_get(ef_main, 0); assert_non_null(ingress_metrics_handle); uint64_t dorp_sid_prepend_err_pkts; ret = sc_metrics_value_get(ingress_metrics_handle, &dorp_sid_prepend_err_pkts, 4); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(dorp_sid_prepend_err_pkts, 1); /* release the mbufs */ rte_pktmbuf_free(mbuf_input[0]); assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* * Test Case: ef ingress drop for peer add error */ static void testcase_ef_ingress_drop_peer_add_error(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_ingress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[1]; mbuf_input[0] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[0]); /* set the return value for the mock function */ will_return(mock_pkt_input_process, 1); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_drop[1] = {}; unsigned int nr_mbuf_drop = 0; will_return(mock_pkt_drop_process, mbuf_drop); will_return(mock_pkt_drop_process, &nr_mbuf_drop); /* * construct the test packet */ /* set mbuf pkt_len */ uint32_t input_internal_pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_internal_pkt_len; mbuf_input[0]->pkt_len = input_internal_pkt_len; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(input_internal_eth_hdr + 1); struct rte_tcp_hdr * input_internal_tcp_hdr = (struct rte_tcp_hdr *)(input_internal_ipv4_hdr + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_internal_eth_hdr, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_internal_ipv4_hdr, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_internal_tcp_hdr, 80, 80, 0, 0, 5, 0, 1000); /* encap vxlan */ uint8_t input_dir_0 = 0; uint16_t input_ef_link_id_0 = 31; const char * input_src_ip_0 = "192.168.1.1"; const char * input_dst_ip_0 = "10.10.10.10"; struct rte_ether_addr src_mac_0 = {.addr_bytes = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}}; struct rte_ether_addr dst_mac_0 = {.addr_bytes = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}}; int ret = vxlan_encap_constructed_pkt(mbuf_input[0], input_dir_0, input_ef_link_id_0, input_src_ip_0, input_dst_ip_0, &src_mac_0, &dst_mac_0, RTE_ETHER_TYPE_IPV4); assert_int_equal(ret, RT_SUCCESS); /* get external header */ struct rte_ether_hdr * input_external_ether_hdr = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); assert_non_null(input_external_ether_hdr); struct rte_ipv4_hdr * input_external_ipv4_hdr = (struct rte_ipv4_hdr *)(input_external_ether_hdr + 1); assert_non_null(input_external_ipv4_hdr); struct rte_udp_hdr * input_external_udp_hdr = (struct rte_udp_hdr *)(input_external_ipv4_hdr + 1); assert_non_null(input_external_udp_hdr); struct g_vxlan_hdr * input_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(input_external_udp_hdr + 1); assert_non_null(input_external_p_vxlan_hdr); /* set metadata */ struct mrb_metadata * input_mrb_meta = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta); sid_list_init(&input_mrb_meta->sid_list); /* prepare to parse the ingress pkt */ struct pkt_parser input_pkt_parser; pkt_parser_init(&input_pkt_parser, &input_mrb_meta->pkt_parser_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX); pkt_parser_exec(&input_pkt_parser, mbuf_input[0]); /* save the pkt parser result */ struct pkt_parser_result input_pkt_parser_result; rte_memcpy(&input_pkt_parser_result, &input_mrb_meta->pkt_parser_result, sizeof(struct pkt_parser_result)); struct ef_node_main * ef_main = g_ef_node_main_get(); assert_non_null(ef_main); struct ef_peer_handle * ef_peer_handle = node_ef_main_ef_peer_handle_get(ef_main); assert_non_null(ef_peer_handle); ret = RT_SUCCESS; uint32_t nr_add_ef_adapters = 0; do { union ef_peer_key key = {}; key.ip_src = nr_add_ef_adapters; key.mac_src.addr_bytes[5] = nr_add_ef_adapters; ret = ef_peer_handle_peer_add(ef_peer_handle, &key); nr_add_ef_adapters++; } while (ef_peer_handle_remaining_entries_get(ef_peer_handle) > 0); /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_drop, 1); /* check the drop mbuf */ assert_non_null(mbuf_drop[0]); assert_ptr_equal(mbuf_drop[0], mbuf_input[0]); /* check the metadata */ struct mrb_metadata * drop_mrb_meta = mrbuf_cz_data(mbuf_drop[0], MR_NODE_CTRLZONE_ID); assert_memory_equal(drop_mrb_meta, input_mrb_meta, sizeof(struct mrb_metadata)); /* check the pkt */ uint32_t drop_pkt_len = rte_pktmbuf_pkt_len(mbuf_drop[0]); assert_int_equal(drop_pkt_len, input_internal_pkt_len + ef_encap_len); /* check the drop external ether header */ struct rte_ether_hdr * drop_external_ether_hdr = rte_pktmbuf_mtod(mbuf_drop[0], struct rte_ether_hdr *); assert_non_null(drop_external_ether_hdr); assert_memory_equal(drop_external_ether_hdr, input_external_ether_hdr, sizeof(struct rte_ether_hdr)); /* check the drop external ipv4 header */ struct rte_ipv4_hdr * drop_external_ipv4_hdr = (struct rte_ipv4_hdr *)(drop_external_ether_hdr + 1); assert_non_null(drop_external_ipv4_hdr); assert_memory_equal(drop_external_ipv4_hdr, input_external_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); /* check the drop external udp header */ struct rte_udp_hdr * drop_external_udp_hdr = (struct rte_udp_hdr *)(drop_external_ipv4_hdr + 1); assert_non_null(drop_external_udp_hdr); assert_memory_equal(drop_external_udp_hdr, input_external_udp_hdr, sizeof(struct rte_udp_hdr)); /* check the drop external vxlan header */ struct g_vxlan_hdr * drop_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(drop_external_udp_hdr + 1); assert_non_null(drop_external_p_vxlan_hdr); assert_memory_equal(drop_external_p_vxlan_hdr, input_external_p_vxlan_hdr, sizeof(struct g_vxlan_hdr)); /* check the drop internal ether header */ struct rte_ether_hdr * drop_internal_eth_hdr = (struct rte_ether_hdr *)(drop_external_p_vxlan_hdr + 1); assert_non_null(drop_internal_eth_hdr); assert_memory_equal(drop_internal_eth_hdr, input_internal_eth_hdr, sizeof(struct rte_ether_hdr)); /* check the drop internal ipv4 header */ struct rte_ipv4_hdr * drop_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(drop_internal_eth_hdr + 1); assert_non_null(drop_internal_ipv4_hdr); assert_memory_equal(drop_internal_ipv4_hdr, input_internal_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); /* check the drop internal tcp header */ struct rte_tcp_hdr * drop_internal_tcp_hdr = (struct rte_tcp_hdr *)(drop_internal_ipv4_hdr + 1); assert_non_null(drop_internal_tcp_hdr); assert_memory_equal(drop_internal_tcp_hdr, input_internal_tcp_hdr, sizeof(struct rte_tcp_hdr)); /* check metrics */ struct sc_metrics_handle * ingress_metrics_handle = node_ef_main_ingress_metrics_handle_get(ef_main, 0); assert_non_null(ingress_metrics_handle); uint64_t dorp_peer_add_err_pkts; ret = sc_metrics_value_get(ingress_metrics_handle, &dorp_peer_add_err_pkts, 5); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(dorp_peer_add_err_pkts, 1); /* release the mbufs */ rte_pktmbuf_free(mbuf_input[0]); assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* * Test Case: ef egress forward pkts */ static void testcase_ef_egress_forward_pkts(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_egress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[2]; for (uint8_t i = 0; i < 2; i++) { mbuf_input[i] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[i]); } /* set the return value for the mock function */ will_return(mock_pkt_input_process, 2); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_output[2] = {}; unsigned int nr_mbuf_output = 0; will_return(mock_pkt_output_process, mbuf_output); will_return(mock_pkt_output_process, &nr_mbuf_output); /* * construct the test packet for IPv4 */ /* set mbuf pkt_len for IPv4 */ uint32_t input_internal_pkt_len_0 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_internal_pkt_len_0; mbuf_input[0]->pkt_len = input_internal_pkt_len_0; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr_0 = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(input_internal_eth_hdr_0 + 1); struct rte_tcp_hdr * input_internal_tcp_hdr = (struct rte_tcp_hdr *)(input_internal_ipv4_hdr + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_internal_eth_hdr_0, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_internal_ipv4_hdr, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_internal_tcp_hdr, 80, 80, 0, 0, 5, 0, 1000); /* encap vxlan */ uint8_t input_dir_0 = 0; uint16_t input_ef_link_id_0 = 31; const char * input_src_ip_0 = "10.11.11.11"; const char * input_dst_ip_0 = "10.10.10.10"; struct rte_ether_addr src_mac_0 = {.addr_bytes = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}; struct rte_ether_addr dst_mac_0 = {.addr_bytes = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}}; int ret = vxlan_encap_constructed_pkt(mbuf_input[0], input_dir_0, input_ef_link_id_0, input_src_ip_0, input_dst_ip_0, &src_mac_0, &dst_mac_0, RTE_ETHER_TYPE_IPV4); assert_int_equal(ret, RT_SUCCESS); /* get external ether header */ struct rte_ether_hdr * input_external_ether_hdr_0 = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); assert_non_null(input_external_ether_hdr_0); struct rte_ipv4_hdr * input_external_ipv4_hdr_0 = (struct rte_ipv4_hdr *)(input_external_ether_hdr_0 + 1); assert_non_null(input_external_ipv4_hdr_0); struct rte_udp_hdr * input_external_udp_hdr_0 = (struct rte_udp_hdr *)(input_external_ipv4_hdr_0 + 1); assert_non_null(input_external_udp_hdr_0); struct g_vxlan_hdr * input_external_p_vxlan_hdr_0 = (struct g_vxlan_hdr *)(input_external_udp_hdr_0 + 1); assert_non_null(input_external_p_vxlan_hdr_0); /* offset to the internal packet within the buffer */ rte_pktmbuf_adj(mbuf_input[0], ef_encap_len); /* set metadata */ struct mrb_metadata * input_mrb_meta_0 = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_0); sid_list_init(&input_mrb_meta_0->sid_list); input_mrb_meta_0->packet_create_from_nf = 0; input_mrb_meta_0->cur_sid = 100; /* * construct the test packet for ipv6 */ /* set mbuf pkt_len for ipv6 */ uint32_t input_internal_pkt_len_1 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_udp_hdr); mbuf_input[1]->data_len = input_internal_pkt_len_1; mbuf_input[1]->pkt_len = input_internal_pkt_len_1; /* prepare the test packet */ struct rte_ether_hdr * input_internal_eth_hdr_1 = rte_pktmbuf_mtod(mbuf_input[1], struct rte_ether_hdr *); struct rte_ipv6_hdr * input_internal_ipv6_hdr_1 = (struct rte_ipv6_hdr *)(input_internal_eth_hdr_1 + 1); struct rte_udp_hdr * input_internal_udp_hdr_1 = (struct rte_udp_hdr *)(input_internal_ipv6_hdr_1 + 1); /* set the ether header */ eth_header_construct(input_internal_eth_hdr_1, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV6); /* set the ipv6 header */ ipv6_header_construct(input_internal_ipv6_hdr_1, NULL, NULL, IPPROTO_UDP, sizeof(struct rte_udp_hdr)); /* set the udp header */ udp_header_construct(input_internal_udp_hdr_1, 80, 80, sizeof(struct rte_udp_hdr)); /* encap vxlan */ uint8_t input_dir_1 = 1; uint16_t input_ef_link_id_1 = 30; const char * input_src_ip_1 = "10.11.11.12"; const char * input_dst_ip_1 = "10.10.10.11"; struct rte_ether_addr src_mac_1 = {.addr_bytes = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01}}; struct rte_ether_addr dst_mac_1 = {.addr_bytes = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA}}; ret = vxlan_encap_constructed_pkt(mbuf_input[1], input_dir_1, input_ef_link_id_1, input_src_ip_1, input_dst_ip_1, &src_mac_1, &dst_mac_1, RTE_ETHER_TYPE_IPV6); assert_int_equal(ret, RT_SUCCESS); /* get external ether header */ struct rte_ether_hdr * input_external_ether_hdr_1 = rte_pktmbuf_mtod(mbuf_input[1], struct rte_ether_hdr *); assert_non_null(input_external_ether_hdr_1); struct rte_ipv4_hdr * input_external_ipv4_hdr_1 = (struct rte_ipv4_hdr *)(input_external_ether_hdr_1 + 1); assert_non_null(input_external_ipv4_hdr_1); struct rte_udp_hdr * input_external_udp_hdr_1 = (struct rte_udp_hdr *)(input_external_ipv4_hdr_1 + 1); assert_non_null(input_external_udp_hdr_1); struct g_vxlan_hdr * input_external_p_vxlan_hdr_1 = (struct g_vxlan_hdr *)(input_external_udp_hdr_1 + 1); assert_non_null(input_external_p_vxlan_hdr_1); /* offset to the internal packet within the buffer */ rte_pktmbuf_adj(mbuf_input[1], ef_encap_len); /* set metadata */ struct mrb_metadata * input_mrb_meta_1 = mrbuf_cz_data(mbuf_input[1], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_1); sid_list_init(&input_mrb_meta_1->sid_list); input_mrb_meta_1->packet_create_from_nf = 0; input_mrb_meta_1->cur_sid = 101; /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_output, 2); /* check the output mbuf */ for (uint8_t i = 0; i < nr_mbuf_output; i++) { assert_non_null(mbuf_output[i]); assert_ptr_equal(mbuf_output[i], mbuf_input[i]); } /* * check the output mbuf 0 (IPv4) */ /* check the metadata */ struct mrb_metadata * output_mrb_meta_0 = mrbuf_cz_data(mbuf_output[0], MR_NODE_CTRLZONE_ID); assert_int_equal(output_mrb_meta_0->port_egress, 0); /* check the pkt len */ uint32_t output_pkt_len_0 = rte_pktmbuf_pkt_len(mbuf_output[0]); assert_int_equal(output_pkt_len_0, input_internal_pkt_len_0 + ef_encap_len); /* check the outer external pkt */ struct rte_ether_hdr * out_external_ether_hdr_0 = rte_pktmbuf_mtod(mbuf_output[0], struct rte_ether_hdr *); assert_non_null(out_external_ether_hdr_0); struct rte_ipv4_hdr * out_external_ipv4_hdr = (struct rte_ipv4_hdr *)(out_external_ether_hdr_0 + 1); assert_non_null(out_external_ipv4_hdr); struct rte_udp_hdr * out_external_udp_hdr = (struct rte_udp_hdr *)(out_external_ipv4_hdr + 1); assert_non_null(out_external_udp_hdr); struct g_vxlan_hdr * out_external_p_vxlan_hdr = (struct g_vxlan_hdr *)(out_external_udp_hdr + 1); assert_non_null(out_external_p_vxlan_hdr); assert_memory_equal(out_external_ether_hdr_0, input_external_ether_hdr_0, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_external_ipv4_hdr, input_external_ipv4_hdr_0, sizeof(struct rte_ipv4_hdr)); assert_memory_equal(out_external_udp_hdr, input_external_udp_hdr_0, sizeof(struct rte_udp_hdr)); assert_memory_equal(out_external_p_vxlan_hdr, input_external_p_vxlan_hdr_0, sizeof(struct g_vxlan_hdr)); /* check the outer internal pkt */ struct rte_ether_hdr * out_internal_eth_hdr_0 = (struct rte_ether_hdr *)(out_external_p_vxlan_hdr + 1); assert_non_null(out_internal_eth_hdr_0); struct rte_ipv4_hdr * out_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(out_internal_eth_hdr_0 + 1); assert_non_null(out_internal_ipv4_hdr); struct rte_tcp_hdr * out_internal_tcp_hdr = (struct rte_tcp_hdr *)(out_internal_ipv4_hdr + 1); assert_non_null(out_internal_tcp_hdr); assert_memory_equal(out_internal_eth_hdr_0, input_internal_eth_hdr_0, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_internal_ipv4_hdr, input_internal_ipv4_hdr, sizeof(struct rte_ipv4_hdr)); assert_memory_equal(out_internal_tcp_hdr, input_internal_tcp_hdr, sizeof(struct rte_tcp_hdr)); /* * check the output mbuf 1 (IPv6) */ /* check the metadata */ struct mrb_metadata * output_mrb_meta_1 = mrbuf_cz_data(mbuf_output[1], MR_NODE_CTRLZONE_ID); assert_int_equal(output_mrb_meta_1->port_egress, 1); /* check the pkt len */ uint32_t output_pkt_len_1 = rte_pktmbuf_pkt_len(mbuf_output[1]); assert_int_equal(output_pkt_len_1, input_internal_pkt_len_1 + ef_encap_len); /* check the outer external pkt */ struct rte_ether_hdr * out_external_ether_hdr_1 = rte_pktmbuf_mtod(mbuf_output[1], struct rte_ether_hdr *); assert_non_null(out_external_ether_hdr_1); struct rte_ipv4_hdr * out_external_ipv4_hdr_1 = (struct rte_ipv4_hdr *)(out_external_ether_hdr_1 + 1); assert_non_null(out_external_ipv4_hdr_1); struct rte_udp_hdr * out_external_udp_hdr_1 = (struct rte_udp_hdr *)(out_external_ipv4_hdr_1 + 1); assert_non_null(out_external_udp_hdr_1); struct g_vxlan_hdr * out_external_p_vxlan_hdr_1 = (struct g_vxlan_hdr *)(out_external_udp_hdr_1 + 1); assert_non_null(out_external_p_vxlan_hdr_1); assert_memory_equal(out_external_ether_hdr_1, input_external_ether_hdr_1, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_external_ipv4_hdr_1, input_external_ipv4_hdr_1, sizeof(struct rte_ipv4_hdr)); assert_memory_equal(out_external_udp_hdr_1, input_external_udp_hdr_1, sizeof(struct rte_udp_hdr)); assert_memory_equal(out_external_p_vxlan_hdr_1, input_external_p_vxlan_hdr_1, sizeof(struct g_vxlan_hdr)); /* check the outer internal pkt */ struct rte_ether_hdr * out_internal_eth_hdr_1 = (struct rte_ether_hdr *)(out_external_p_vxlan_hdr_1 + 1); assert_non_null(out_internal_eth_hdr_1); struct rte_ipv6_hdr * out_internal_ipv6_hdr = (struct rte_ipv6_hdr *)(out_internal_eth_hdr_1 + 1); assert_non_null(out_internal_ipv6_hdr); struct rte_udp_hdr * out_internal_udp_hdr = (struct rte_udp_hdr *)(out_internal_ipv6_hdr + 1); assert_non_null(out_internal_udp_hdr); assert_memory_equal(out_internal_eth_hdr_1, input_internal_eth_hdr_1, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_internal_ipv6_hdr, input_internal_ipv6_hdr_1, sizeof(struct rte_ipv6_hdr)); assert_memory_equal(out_internal_udp_hdr, input_internal_udp_hdr_1, sizeof(struct rte_udp_hdr)); /* check metrics */ struct ef_node_main * ef_main = g_ef_node_main_get(); struct sc_metrics_handle * egress_metrics_handle = node_ef_main_egress_metrics_handle_get(ef_main, 0); assert_non_null(egress_metrics_handle); uint64_t total_pkts; ret = sc_metrics_value_get(egress_metrics_handle, &total_pkts, 0); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(total_pkts, 2); uint64_t to_eth_egress_pkts; ret = sc_metrics_value_get(egress_metrics_handle, &to_eth_egress_pkts, 3); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(to_eth_egress_pkts, 2); /* release the mbufs */ for (uint8_t i = 0; i < 2; i++) { rte_pktmbuf_free(mbuf_input[i]); } assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* * Test Group: ef egress nf create pkts */ static void testgroup_ef_egress_nf_create_pkts(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_egress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[2]; for (uint8_t i = 0; i < 2; i++) { mbuf_input[i] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[i]); } /* set the return value for the mock function */ will_return(mock_pkt_input_process, 2); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_output[2] = {}; unsigned int nr_mbuf_output = 0; will_return(mock_pkt_output_process, mbuf_output); will_return(mock_pkt_output_process, &nr_mbuf_output); /* * construct the test packet for IPv4 */ /* set mbuf pkt_len for IPv4 */ uint32_t input_pkt_len_0 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_pkt_len_0; mbuf_input[0]->pkt_len = input_pkt_len_0; /* set the hash for mbuf */ mbuf_input[0]->hash.usr = 16384; /* prepare the test packet */ struct rte_ether_hdr * input_eth_hdr_0 = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_ipv4_hdr_0 = (struct rte_ipv4_hdr *)(input_eth_hdr_0 + 1); struct rte_tcp_hdr * input_tcp_hdr_0 = (struct rte_tcp_hdr *)(input_ipv4_hdr_0 + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_eth_hdr_0, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_ipv4_hdr_0, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_tcp_hdr_0, 80, 80, 0, 0, 5, 0, 1000); /* add the peer */ struct ef_node_main * ef_main = g_ef_node_main_get(); assert_non_null(ef_main); struct ef_peer_handle * ef_peer_handle = node_ef_main_ef_peer_handle_get(ef_main); assert_non_null(ef_peer_handle); union ef_peer_key key; uint32_t peer_add_ip_0; inet_pton(AF_INET, "192.168.2.1", &peer_add_ip_0); struct rte_ether_addr peer_ether_addr_0 = {.addr_bytes = {0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x01}}; key.ip_src = peer_add_ip_0; rte_memcpy(&key.mac_src, &peer_ether_addr_0, sizeof(struct rte_ether_addr)); int peer_index_0 = ef_peer_handle_peer_add(ef_peer_handle, &key); assert_int_not_equal(peer_index_0, RT_ERR); /* set metadata */ uint8_t input_dir_0 = 0; uint16_t ef_link_id_0 = 30; struct mrb_metadata * input_mrb_meta_0 = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_0); sid_list_init(&input_mrb_meta_0->sid_list); input_mrb_meta_0->packet_create_from_nf = 1; input_mrb_meta_0->cur_sid = 100; input_mrb_meta_0->ef_peer_index = peer_index_0; input_mrb_meta_0->dir = input_dir_0; input_mrb_meta_0->ef_link_id = ef_link_id_0; /* * construct the test packet for ipv6 */ /* set mbuf pkt_len for ipv6 */ uint32_t input_pkt_len_1 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_udp_hdr); mbuf_input[1]->data_len = input_pkt_len_1; mbuf_input[1]->pkt_len = input_pkt_len_1; /* set the hash for mbuf */ mbuf_input[1]->hash.usr = 16385; /* prepare the test packet */ struct rte_ether_hdr * input_eth_hdr_1 = rte_pktmbuf_mtod(mbuf_input[1], struct rte_ether_hdr *); struct rte_ipv6_hdr * input_ipv6_hdr_1 = (struct rte_ipv6_hdr *)(input_eth_hdr_1 + 1); struct rte_udp_hdr * input_udp_hdr_1 = (struct rte_udp_hdr *)(input_ipv6_hdr_1 + 1); /* set the ether header */ eth_header_construct(input_eth_hdr_1, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV6); /* set the ipv6 header */ ipv6_header_construct(input_ipv6_hdr_1, NULL, NULL, IPPROTO_UDP, sizeof(struct rte_udp_hdr)); /* set the udp header */ udp_header_construct(input_udp_hdr_1, 80, 80, sizeof(struct rte_udp_hdr)); /* add the peer */ uint32_t peer_add_ip_1; inet_pton(AF_INET, "192.168.2.2", &peer_add_ip_1); struct rte_ether_addr peer_ether_addr_1 = {.addr_bytes = {0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x02}}; key.ip_src = peer_add_ip_1; rte_memcpy(&key.mac_src, &peer_ether_addr_1, sizeof(struct rte_ether_addr)); int peer_index_1 = ef_peer_handle_peer_add(ef_peer_handle, &key); assert_int_not_equal(peer_index_1, RT_ERR); /* set metadata */ uint8_t input_dir_1 = 1; uint16_t ef_link_id_1 = 31; struct mrb_metadata * input_mrb_meta_1 = mrbuf_cz_data(mbuf_input[1], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_1); sid_list_init(&input_mrb_meta_1->sid_list); input_mrb_meta_1->packet_create_from_nf = 1; input_mrb_meta_1->cur_sid = 101; input_mrb_meta_1->ef_peer_index = peer_index_1; input_mrb_meta_1->dir = input_dir_1; input_mrb_meta_1->ef_link_id = ef_link_id_1; /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_output, 2); /* check the output mbuf */ for (uint8_t i = 0; i < nr_mbuf_output; i++) { assert_non_null(mbuf_output[i]); assert_ptr_equal(mbuf_output[i], mbuf_input[i]); } /* * check the output mbuf 0 (IPv4) */ /* check the metadata */ struct mrb_metadata * output_mrb_meta_0 = mrbuf_cz_data(mbuf_output[0], MR_NODE_CTRLZONE_ID); assert_non_null(output_mrb_meta_0); assert_int_equal(output_mrb_meta_0->port_egress, 0); /* check the pkt len */ uint32_t output_pkt_len_0 = rte_pktmbuf_pkt_len(mbuf_output[0]); assert_int_equal(output_pkt_len_0, input_pkt_len_0 + ef_encap_len); /* check the outer external pkt */ struct rte_ether_hdr * out_external_ether_hdr_0 = rte_pktmbuf_mtod(mbuf_output[0], struct rte_ether_hdr *); assert_non_null(out_external_ether_hdr_0); struct rte_ipv4_hdr * out_external_ipv4_hdr_0 = (struct rte_ipv4_hdr *)(out_external_ether_hdr_0 + 1); assert_non_null(out_external_ipv4_hdr_0); struct rte_udp_hdr * out_external_udp_hdr_0 = (struct rte_udp_hdr *)(out_external_ipv4_hdr_0 + 1); assert_non_null(out_external_udp_hdr_0); struct g_vxlan_hdr * out_external_p_vxlan_hdr_0 = (struct g_vxlan_hdr *)(out_external_udp_hdr_0 + 1); assert_non_null(out_external_p_vxlan_hdr_0); /* check the outer eth header */ assert_memory_equal(&out_external_ether_hdr_0->dst_addr, &peer_ether_addr_0, sizeof(struct rte_ether_addr)); assert_memory_equal(&out_external_ether_hdr_0->src_addr, &mock_devs_desc[output_mrb_meta_0->port_egress]->eth_addr, sizeof(struct rte_ether_addr)); assert_int_equal(out_external_ether_hdr_0->ether_type, rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)); /* check the outer ipv4 header */ assert_int_equal(out_external_ipv4_hdr_0->version_ihl, 0x45); assert_int_equal(out_external_ipv4_hdr_0->type_of_service, 0); assert_int_equal(out_external_ipv4_hdr_0->packet_id, 0x0100); assert_int_equal(out_external_ipv4_hdr_0->fragment_offset, 0); assert_int_equal(out_external_ipv4_hdr_0->time_to_live, 0x40); assert_int_equal(out_external_ipv4_hdr_0->next_proto_id, IPPROTO_UDP); assert_int_equal(out_external_ipv4_hdr_0->src_addr, mock_devs_desc[output_mrb_meta_0->port_egress]->in_addr.s_addr); assert_int_equal(out_external_ipv4_hdr_0->dst_addr, peer_add_ip_0); assert_int_equal(out_external_ipv4_hdr_0->total_length, rte_cpu_to_be_16(input_pkt_len_0 + ef_encap_len - sizeof(struct rte_ether_hdr))); uint16_t out_external_ipv4_checksum_0 = out_external_ipv4_hdr_0->hdr_checksum; out_external_ipv4_hdr_0->hdr_checksum = 0; assert_int_equal(rte_ipv4_cksum(out_external_ipv4_hdr_0), out_external_ipv4_checksum_0); /* check the outer udp header */ assert_int_equal(out_external_udp_hdr_0->src_port, rte_cpu_to_be_16(49152)); assert_int_equal(out_external_udp_hdr_0->dst_port, rte_cpu_to_be_16(4789)); assert_int_equal( out_external_udp_hdr_0->dgram_len, rte_cpu_to_be_16(input_pkt_len_0 + ef_encap_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr))); assert_int_equal(out_external_udp_hdr_0->dgram_cksum, 0); /* check the outer vxlan header */ assert_int_equal(out_external_p_vxlan_hdr_0->flags, 0); assert_int_equal(out_external_p_vxlan_hdr_0->reserved[0], 0); assert_int_equal(out_external_p_vxlan_hdr_0->reserved[1], 0); assert_int_equal(out_external_p_vxlan_hdr_0->reserved[2], 0); assert_int_equal(out_external_p_vxlan_hdr_0->vlan_id_half_high, 0); assert_int_equal(out_external_p_vxlan_hdr_0->link_layer_type, 0); assert_int_equal(out_external_p_vxlan_hdr_0->vlan_id_half_low, 0); assert_int_equal(out_external_p_vxlan_hdr_0->dir, input_dir_0); assert_int_equal(out_external_p_vxlan_hdr_0->link_id, ef_link_id_0); assert_int_equal(out_external_p_vxlan_hdr_0->online_test, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r7, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r6, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r5, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r4, 0); assert_int_equal(out_external_p_vxlan_hdr_0->vni_flag, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r2, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r1, 0); assert_int_equal(out_external_p_vxlan_hdr_0->r0, 0); /* check the outer internal pkt */ struct rte_ether_hdr * out_internal_eth_hdr_0 = (struct rte_ether_hdr *)(out_external_p_vxlan_hdr_0 + 1); assert_non_null(out_internal_eth_hdr_0); struct rte_ipv4_hdr * out_internal_ipv4_hdr = (struct rte_ipv4_hdr *)(out_internal_eth_hdr_0 + 1); assert_non_null(out_internal_ipv4_hdr); struct rte_tcp_hdr * out_internal_tcp_hdr = (struct rte_tcp_hdr *)(out_internal_ipv4_hdr + 1); assert_non_null(out_internal_tcp_hdr); assert_memory_equal(out_internal_eth_hdr_0, input_eth_hdr_0, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_internal_ipv4_hdr, input_ipv4_hdr_0, sizeof(struct rte_ipv4_hdr)); assert_memory_equal(out_internal_tcp_hdr, input_tcp_hdr_0, sizeof(struct rte_tcp_hdr)); /* * check the output mbuf 1 (IPv6) */ /* check the metadata */ struct mrb_metadata * output_mrb_meta_1 = mrbuf_cz_data(mbuf_output[1], MR_NODE_CTRLZONE_ID); assert_non_null(output_mrb_meta_1); assert_int_equal(output_mrb_meta_1->port_egress, 1); /* check the pkt len */ uint32_t output_pkt_len_1 = rte_pktmbuf_pkt_len(mbuf_output[1]); assert_int_equal(output_pkt_len_1, input_pkt_len_1 + ef_encap_len); /* check the outer external pkt */ struct rte_ether_hdr * out_external_ether_hdr_1 = rte_pktmbuf_mtod(mbuf_output[1], struct rte_ether_hdr *); assert_non_null(out_external_ether_hdr_1); struct rte_ipv4_hdr * out_external_ipv4_hdr_1 = (struct rte_ipv4_hdr *)(out_external_ether_hdr_1 + 1); assert_non_null(out_external_ipv4_hdr_1); struct rte_udp_hdr * out_external_udp_hdr_1 = (struct rte_udp_hdr *)(out_external_ipv4_hdr_1 + 1); assert_non_null(out_external_udp_hdr_1); struct g_vxlan_hdr * out_external_p_vxlan_hdr_1 = (struct g_vxlan_hdr *)(out_external_udp_hdr_1 + 1); assert_non_null(out_external_p_vxlan_hdr_1); /* check the outer eth header */ assert_memory_equal(&out_external_ether_hdr_1->dst_addr, &peer_ether_addr_1, sizeof(struct rte_ether_addr)); assert_memory_equal(&out_external_ether_hdr_1->src_addr, &mock_devs_desc[output_mrb_meta_1->port_egress]->eth_addr, sizeof(struct rte_ether_addr)); assert_int_equal(out_external_ether_hdr_1->ether_type, rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)); /* check the outer ipv4 header */ assert_int_equal(out_external_ipv4_hdr_1->version_ihl, 0x45); assert_int_equal(out_external_ipv4_hdr_1->type_of_service, 0); assert_int_equal(out_external_ipv4_hdr_1->packet_id, 0x0100); assert_int_equal(out_external_ipv4_hdr_1->fragment_offset, 0); assert_int_equal(out_external_ipv4_hdr_1->time_to_live, 0x40); assert_int_equal(out_external_ipv4_hdr_1->next_proto_id, IPPROTO_UDP); assert_int_equal(out_external_ipv4_hdr_1->src_addr, mock_devs_desc[output_mrb_meta_1->port_egress]->in_addr.s_addr); assert_int_equal(out_external_ipv4_hdr_1->dst_addr, peer_add_ip_1); assert_int_equal(out_external_ipv4_hdr_1->total_length, rte_cpu_to_be_16(input_pkt_len_1 + ef_encap_len - sizeof(struct rte_ether_hdr))); uint16_t out_external_ipv4_checksum_1 = out_external_ipv4_hdr_1->hdr_checksum; out_external_ipv4_hdr_1->hdr_checksum = 0; assert_int_equal(rte_ipv4_cksum(out_external_ipv4_hdr_1), out_external_ipv4_checksum_1); /* check the outer udp header */ assert_int_equal(out_external_udp_hdr_1->src_port, rte_cpu_to_be_16(49153)); assert_int_equal(out_external_udp_hdr_1->dst_port, rte_cpu_to_be_16(4789)); assert_int_equal( out_external_udp_hdr_1->dgram_len, rte_cpu_to_be_16(input_pkt_len_1 + ef_encap_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr))); assert_int_equal(out_external_udp_hdr_1->dgram_cksum, 0); /* check the outer vxlan header */ assert_int_equal(out_external_p_vxlan_hdr_1->flags, 0); assert_int_equal(out_external_p_vxlan_hdr_1->reserved[0], 0); assert_int_equal(out_external_p_vxlan_hdr_1->reserved[1], 0); assert_int_equal(out_external_p_vxlan_hdr_1->reserved[2], 0); assert_int_equal(out_external_p_vxlan_hdr_1->vlan_id_half_high, 0); assert_int_equal(out_external_p_vxlan_hdr_1->link_layer_type, 0); assert_int_equal(out_external_p_vxlan_hdr_1->vlan_id_half_low, 0); assert_int_equal(out_external_p_vxlan_hdr_1->dir, input_dir_1); assert_int_equal(out_external_p_vxlan_hdr_1->link_id, ef_link_id_1); assert_int_equal(out_external_p_vxlan_hdr_1->online_test, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r7, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r6, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r5, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r4, 0); assert_int_equal(out_external_p_vxlan_hdr_1->vni_flag, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r2, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r1, 0); assert_int_equal(out_external_p_vxlan_hdr_1->r0, 0); /* check the outer internal pkt */ struct rte_ether_hdr * out_internal_eth_hdr_1 = (struct rte_ether_hdr *)(out_external_p_vxlan_hdr_1 + 1); assert_non_null(out_internal_eth_hdr_1); struct rte_ipv6_hdr * out_internal_ipv6_hdr_1 = (struct rte_ipv6_hdr *)(out_internal_eth_hdr_1 + 1); assert_non_null(out_internal_ipv6_hdr_1); struct rte_udp_hdr * out_internal_udp_hdr_1 = (struct rte_udp_hdr *)(out_internal_ipv6_hdr_1 + 1); assert_non_null(out_internal_udp_hdr_1); assert_memory_equal(out_internal_eth_hdr_1, input_eth_hdr_1, sizeof(struct rte_ether_hdr)); assert_memory_equal(out_internal_ipv6_hdr_1, input_ipv6_hdr_1, sizeof(struct rte_ipv6_hdr)); assert_memory_equal(out_internal_udp_hdr_1, input_udp_hdr_1, sizeof(struct rte_udp_hdr)); /* check metrics */ struct sc_metrics_handle * egress_metrics_handle = node_ef_main_egress_metrics_handle_get(ef_main, 0); assert_non_null(egress_metrics_handle); uint64_t nr_vxlan_encap_pkts; int ret = sc_metrics_value_get(egress_metrics_handle, &nr_vxlan_encap_pkts, 2); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(nr_vxlan_encap_pkts, 2); /* release the mbufs */ for (uint8_t i = 0; i < 2; i++) { rte_pktmbuf_free(mbuf_input[i]); } assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* * Test Group: ef egress tap mode */ static void testgroup_ef_egress_tap_mode(void ** state) { /* get the graph pointer */ struct rte_graph * graph_ptr = rte_graph_lookup("test_ef_egress"); assert_non_null(graph_ptr); /* alloc the mbuf as input */ struct rte_mbuf * mbuf_input[2]; for (uint8_t i = 0; i < 2; i++) { mbuf_input[i] = rte_pktmbuf_alloc(mock_pktmbuf_pool); assert_non_null(mbuf_input[i]); } /* set the return value for the mock function */ will_return(mock_pkt_input_process, 2); will_return(mock_pkt_input_process, mbuf_input); struct rte_mbuf * mbuf_output[2] = {}; unsigned int nr_mbuf_output = 0; will_return(mock_pkt_output_process, mbuf_output); will_return(mock_pkt_output_process, &nr_mbuf_output); struct rte_mbuf * mbuf_drop[2] = {}; unsigned int nr_mbuf_drop = 0; will_return(mock_pkt_drop_process, mbuf_drop); will_return(mock_pkt_drop_process, &nr_mbuf_drop); /* * construct the test packet for IPv4 */ /* set mbuf pkt_len for IPv4 */ uint32_t input_pkt_len_0 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr); mbuf_input[0]->data_len = input_pkt_len_0; mbuf_input[0]->pkt_len = input_pkt_len_0; /* prepare the test packet */ struct rte_ether_hdr * input_eth_hdr_0 = rte_pktmbuf_mtod(mbuf_input[0], struct rte_ether_hdr *); struct rte_ipv4_hdr * input_ipv4_hdr_0 = (struct rte_ipv4_hdr *)(input_eth_hdr_0 + 1); struct rte_tcp_hdr * input_tcp_hdr_0 = (struct rte_tcp_hdr *)(input_ipv4_hdr_0 + 1); /* set the ether header */ struct rte_ether_addr src_mac = {.addr_bytes = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; struct rte_ether_addr dst_mac = {.addr_bytes = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}; eth_header_construct(input_eth_hdr_0, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV4); /* set the IPv4 header */ ipv4_header_construct(input_ipv4_hdr_0, NULL, NULL, IPPROTO_TCP, sizeof(struct rte_tcp_hdr)); /* set the tcp header */ tcp_header_construct(input_tcp_hdr_0, 80, 80, 0, 0, 5, 0, 1000); /* set metadata */ uint8_t input_dir_0 = 0; uint16_t ef_link_id_0 = 30; struct mrb_metadata * input_mrb_meta_0 = mrbuf_cz_data(mbuf_input[0], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_0); sid_list_init(&input_mrb_meta_0->sid_list); input_mrb_meta_0->cur_sid = 100; input_mrb_meta_0->dir = input_dir_0; input_mrb_meta_0->ef_link_id = ef_link_id_0; /* * construct the test packet for ipv6 */ /* set mbuf pkt_len for ipv6 */ uint32_t input_pkt_len_1 = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_udp_hdr); mbuf_input[1]->data_len = input_pkt_len_1; mbuf_input[1]->pkt_len = input_pkt_len_1; /* prepare the test packet */ struct rte_ether_hdr * input_eth_hdr_1 = rte_pktmbuf_mtod(mbuf_input[1], struct rte_ether_hdr *); struct rte_ipv6_hdr * input_ipv6_hdr_1 = (struct rte_ipv6_hdr *)(input_eth_hdr_1 + 1); struct rte_udp_hdr * input_udp_hdr_1 = (struct rte_udp_hdr *)(input_ipv6_hdr_1 + 1); /* set the ether header */ eth_header_construct(input_eth_hdr_1, &src_mac, &dst_mac, RTE_ETHER_TYPE_IPV6); /* set the ipv6 header */ ipv6_header_construct(input_ipv6_hdr_1, NULL, NULL, IPPROTO_UDP, sizeof(struct rte_udp_hdr)); /* set the udp header */ udp_header_construct(input_udp_hdr_1, 80, 80, sizeof(struct rte_udp_hdr)); /* set metadata */ uint8_t input_dir_1 = 1; uint16_t ef_link_id_1 = 31; struct mrb_metadata * input_mrb_meta_1 = mrbuf_cz_data(mbuf_input[1], MR_NODE_CTRLZONE_ID); mrb_metadata_clear(input_mrb_meta_1); sid_list_init(&input_mrb_meta_1->sid_list); input_mrb_meta_1->cur_sid = 101; input_mrb_meta_1->dir = input_dir_1; input_mrb_meta_1->ef_link_id = ef_link_id_1; /* walk the graph */ rte_graph_walk(graph_ptr); /* check the count */ assert_int_equal(nr_mbuf_drop, 2); /* check the drop mbuf */ for (uint8_t i = 0; i < nr_mbuf_drop; i++) { assert_non_null(mbuf_drop[i]); assert_ptr_equal(mbuf_drop[i], mbuf_input[i]); } /* * check the output mbuf 0 (IPv4) */ /* check the drop pkt */ struct rte_ether_hdr * drop_eth_hdr_0 = rte_pktmbuf_mtod(mbuf_drop[0], struct rte_ether_hdr *); assert_non_null(drop_eth_hdr_0); struct rte_ipv4_hdr * drop_ipv4_hdr_0 = (struct rte_ipv4_hdr *)(drop_eth_hdr_0 + 1); assert_non_null(drop_ipv4_hdr_0); struct rte_tcp_hdr * drop_tcp_hdr_0 = (struct rte_tcp_hdr *)(drop_ipv4_hdr_0 + 1); assert_non_null(drop_tcp_hdr_0); assert_memory_equal(drop_eth_hdr_0, input_eth_hdr_0, sizeof(struct rte_ether_hdr)); assert_memory_equal(drop_ipv4_hdr_0, input_ipv4_hdr_0, sizeof(struct rte_ipv4_hdr)); assert_memory_equal(drop_tcp_hdr_0, input_tcp_hdr_0, sizeof(struct rte_tcp_hdr)); /* * check the output mbuf 1 (IPv6) */ /* check the drop pkt */ struct rte_ether_hdr * drop_eth_hdr_1 = rte_pktmbuf_mtod(mbuf_drop[1], struct rte_ether_hdr *); assert_non_null(drop_eth_hdr_1); struct rte_ipv6_hdr * drop_ipv6_hdr_1 = (struct rte_ipv6_hdr *)(drop_eth_hdr_1 + 1); assert_non_null(drop_ipv6_hdr_1); struct rte_udp_hdr * drop_udp_hdr_1 = (struct rte_udp_hdr *)(drop_ipv6_hdr_1 + 1); assert_non_null(drop_udp_hdr_1); assert_memory_equal(drop_eth_hdr_1, input_eth_hdr_1, sizeof(struct rte_ether_hdr)); assert_memory_equal(drop_ipv6_hdr_1, input_ipv6_hdr_1, sizeof(struct rte_ipv6_hdr)); assert_memory_equal(drop_udp_hdr_1, input_udp_hdr_1, sizeof(struct rte_udp_hdr)); /* check metrics */ struct ef_node_main * ef_main = g_ef_node_main_get(); struct sc_metrics_handle * egress_metrics_handle = node_ef_main_egress_metrics_handle_get(ef_main, 0); assert_non_null(egress_metrics_handle); uint64_t nr_drop_rsn_tap_mode; int ret = sc_metrics_value_get(egress_metrics_handle, &nr_drop_rsn_tap_mode, 4); assert_int_equal(ret, RT_SUCCESS); assert_int_equal(nr_drop_rsn_tap_mode, 2); /* release the mbufs */ for (uint8_t i = 0; i < 2; i++) { rte_pktmbuf_free(mbuf_input[i]); } assert_true(rte_mempool_full(mock_pktmbuf_pool) == 1); } /* ------------------------------------------------------ Main ----------------------------------------------------- */ int main(int argc, char * argv[]) { /* generate the eal args */ static char * eal_args[] = { "test_node_ef", "-c 0x1", "--no-huge", "--no-pci", }; /* run the eal with no huge pages */ int ret = rte_eal_init(RTE_DIM(eal_args), eal_args); if (ret < 0) { rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); } mock_pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool", 1024, 32, 128, RTE_MBUF_DEFAULT_BUF_SIZE, SOCKET_ID_ANY); assert_non_null(mock_pktmbuf_pool); mock_cfgfile_content = rte_zmalloc(NULL, MOCK_SIZE_CFGFILE_CONTENT, 0); uint32_t in_addr = 0x0A0A0A0A; for (int i = 0; i < MOCK_NR_DEV_MAX; i++) { mock_devs_desc[i] = (struct mr_dev_desc *)rte_zmalloc(NULL, sizeof(struct mr_dev_desc), 0); assert_non_null(mock_devs_desc[i]); mock_devs_desc[i]->port_id = i; mock_devs_desc[i]->in_addr.s_addr = htonl(in_addr + i); struct rte_ether_addr eth_addr = {.addr_bytes = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, i}}; rte_memcpy(&mock_devs_desc[i]->eth_addr, ð_addr, RTE_ETHER_ADDR_LEN); snprintf(mock_devs_name[i], 32, "ens4f0np%d", i); rte_memcpy(mock_devs_desc[i]->symbol, mock_devs_name[i], strlen(mock_devs_name[i])); } const struct CMUnitTest group_ef_config_handle[] = { cmocka_unit_test(testcase_ef_config_handle_success), cmocka_unit_test(testcase_ef_config_handle_failure), }; const struct CMUnitTest group_ef_adapter_handle[] = { cmocka_unit_test(testcase_ef_adapter_handle_success), cmocka_unit_test(testcase_ef_adapter_handle_failure), }; const struct CMUnitTest group_ef_peer_handle[] = { cmocka_unit_test(testcase_ef_peer_handle_success), cmocka_unit_test(testcase_ef_peer_handle_failure), }; const struct CMUnitTest group_tl_to_ef_peer_map_handle[] = { cmocka_unit_test(testcase_tl_to_ef_peer_map_handle_success), cmocka_unit_test(testcase_tl_to_ef_peer_map_handle_failure), }; const struct CMUnitTest group_ef_node_main[] = { cmocka_unit_test(testcase_ef_node_main_success), cmocka_unit_test(testcase_ef_node_main_failure), }; const struct CMUnitTest group_ef_init[] = { cmocka_unit_test(testcase_ef_init_success), }; const struct CMUnitTest group_ef_ingress[] = { cmocka_unit_test(testcase_ef_ingress_forward_pkts), cmocka_unit_test(testcase_ef_ingress_drop_adapter_no_exist), cmocka_unit_test(testcase_ef_ingress_drop_prepend_sid_error), cmocka_unit_test(testcase_ef_ingress_drop_peer_add_error), }; const struct CMUnitTest group_ef_egress_vwire_mode[] = { cmocka_unit_test(testcase_ef_egress_forward_pkts), cmocka_unit_test(testgroup_ef_egress_nf_create_pkts), }; const struct CMUnitTest group_ef_egress_tap_mode[] = { cmocka_unit_test(testgroup_ef_egress_tap_mode), }; ret = cmocka_run_group_tests(group_ef_config_handle, testgroup_common_setup, testgroup_common_teardown); ret += cmocka_run_group_tests(group_ef_adapter_handle, testgroup_common_setup, testgroup_common_teardown); ret += cmocka_run_group_tests(group_ef_peer_handle, NULL, NULL); ret += cmocka_run_group_tests(group_tl_to_ef_peer_map_handle, NULL, NULL); ret += cmocka_run_group_tests(group_ef_node_main, testgroup_common_setup, testgroup_common_teardown); ret += cmocka_run_group_tests(group_ef_init, testgroup_common_setup, testgroup_common_teardown); ret += cmocka_run_group_tests(group_ef_ingress, testgroup_ef_ingress_setup, testgroup_ef_ingress_teardown); ret += cmocka_run_group_tests(group_ef_egress_vwire_mode, testgroup_ef_egress_vwire_mode_setup, testgroup_ef_egress_common_teardown); ret += cmocka_run_group_tests(group_ef_egress_tap_mode, testgroup_ef_egress_tap_mode_setup, testgroup_ef_egress_common_teardown); /* free the memory */ rte_free(mock_cfgfile_content); for (int i = 0; i < MOCK_NR_DEV_MAX; i++) { rte_free(mock_devs_desc[i]); } rte_mempool_free(mock_pktmbuf_pool); rte_eal_cleanup(); return ret; }