/* * Call add, lookup and delete for a single rule with depth > 24 */ int32_t test16(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 128, next_hop_add = 100, next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; }
/* * Use rte_lpm6_add to add rules which effect only the second half of the lpm * table. Use all possible depths ranging from 1..32. Set the next hop = to the * depth. Check lookup hit for on every add and check for lookup miss on the * first half of the lpm table after each add. Finally delete all rules going * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each * delete. The lookup should return the next_hop_add value related to the * previous depth value (i.e. depth -1). */ int32_t test17(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip1[] = {127,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255}; uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* Loop with rte_lpm6_add. */ for (depth = 1; depth <= 128; depth++) { /* Let the next_hop_add value = depth. Just for change. */ next_hop_add = depth; status = rte_lpm6_add(lpm, ip2, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); /* Check IP in first half of tbl24 which should be empty. */ status = rte_lpm6_lookup(lpm, ip1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); status = rte_lpm6_lookup(lpm, ip2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } /* Loop with rte_lpm6_delete. */ for (depth = 128; depth >= 1; depth--) { next_hop_add = (uint8_t) (depth - 1); status = rte_lpm6_delete(lpm, ip2, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip2, &next_hop_return); if (depth != 1) { TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } else { TEST_LPM_ASSERT(status == -ENOENT); } status = rte_lpm6_lookup(lpm, ip1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); } rte_lpm6_free(lpm); return PASS; }
/* * Check that rte_lpm6_lookup fails gracefully for incorrect user input * arguments */ int32_t test6(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_lookup: lpm == NULL */ status = rte_lpm6_lookup(NULL, ip, &next_hop_return); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm6_lookup: ip = NULL */ status = rte_lpm6_lookup(lpm, NULL, &next_hop_return); TEST_LPM_ASSERT(status < 0); /* rte_lpm6_lookup: next_hop = NULL */ status = rte_lpm6_lookup(lpm, ip, NULL); TEST_LPM_ASSERT(status < 0); rte_lpm6_free(lpm); return PASS; }
/* * Add a rule that reaches the end of the tree. * Add a rule that is more generic than the first one. * Check every possible combination that produces a match for the second rule. * This tests tbl expansion. */ int32_t test27(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0}; uint8_t depth = 128, next_hop_add = 100, next_hop_return; int32_t status = 0; int i, j; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); depth = 128; next_hop_add = 128; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); depth = 112; next_hop_add = 112; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); for (i = 0; i < 256; i++) { ip[14] = (uint8_t)i; for (j = 0; j < 256; j++) { ip[15] = (uint8_t)j; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); if (i == 0 && j == 0) TEST_LPM_ASSERT(status == 0 && next_hop_return == 128); else TEST_LPM_ASSERT(status == 0 && next_hop_return == 112); } } rte_lpm6_free(lpm); return PASS; }
static int rate_limit_ipv6(cmdline_ipaddr_t* ip, uint32_t num, int socket_id) { static uint8_t next_hop_count[NB_SOCKETS] = {0}; uint16_t next_hop = 0; // store the rule so it can applied once // it is added if it is not already // check if this address is already stored for (next_hop = 0; next_hop < NEI_NUM_ENTRIES; next_hop++) { // if addresses match if (!memcmp(&rlimit6_lookup_table[socket_id][next_hop].addr, &ip->addr.ipv6, sizeof(struct in6_addr))) { break; } } // otherwise try to allocate new slot for storage if (next_hop == NEI_NUM_ENTRIES) { // no more slot available if (next_hop_count[socket_id] == NEI_NUM_ENTRIES - 1) { return -1; } next_hop = next_hop_count[socket_id]++; } rte_memcpy(&rlimit6_lookup_table[socket_id][next_hop].addr, &ip->addr.ipv6, sizeof(struct in6_addr)); rlimit6_lookup_table[socket_id][next_hop].num = num; if (rte_lpm6_lookup(ipv6_pktj_lookup_struct[socket_id], ip->addr.ipv6.s6_addr, (uint8_t*)&next_hop) == 0) { // set the max packet rate for this neighbor rlimit6_max[socket_id][next_hop] = num; } return 0; }
static int rte_table_lpm_ipv6_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; uint64_t pkts_out_mask = 0; uint32_t i; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_LPM_IPV6_STATS_PKTS_IN_ADD(lpm, n_pkts_in); pkts_out_mask = 0; for (i = 0; i < (uint32_t)(RTE_PORT_IN_BURST_SIZE_MAX - __builtin_clzll(pkts_mask)); i++) { uint64_t pkt_mask = 1LLU << i; if (pkt_mask & pkts_mask) { struct rte_mbuf *pkt = pkts[i]; uint8_t *ip = RTE_MBUF_METADATA_UINT8_PTR(pkt, lpm->offset); int status; uint32_t nht_pos; status = rte_lpm6_lookup(lpm->lpm, ip, &nht_pos); if (status == 0) { pkts_out_mask |= pkt_mask; entries[i] = (void *) &lpm->nht[nht_pos * lpm->entry_size]; } } } *lookup_hit_mask = pkts_out_mask; RTE_TABLE_LPM_IPV6_STATS_PKTS_LOOKUP_MISS(lpm, n_pkts_in - __builtin_popcountll(pkts_out_mask)); return 0; }
/* * Add a set of random routes with random depths. * Lookup different IP addresses that match the routes previously added. * Checks that the next hop is the expected one. * The routes, IP addresses and expected result for every case have been * precalculated by using a python script and stored in a .h file. */ int32_t test25(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; uint32_t i; uint8_t depth, next_hop_add, next_hop_return, next_hop_expected; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); for (i = 0; i < 1000; i++) { memcpy(ip, large_route_table[i].ip, 16); depth = large_route_table[i].depth; next_hop_add = large_route_table[i].next_hop; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); } for (i = 0; i < 100000; i++) { memcpy(ip, large_ips_table[i].ip, 16); next_hop_expected = large_ips_table[i].next_hop; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_expected)); } rte_lpm6_free(lpm); return PASS; }
static int neighbor6(neighbor_action_t action, int32_t port_id, struct in6_addr* addr, struct ether_addr* lladdr, uint8_t flags, __rte_unused uint16_t vlan_id, void* args) { // if port_id is not handled // ignore, return immediatly // if neighbor add // lookup neighbor // if exists // update lladdr, set flag as REACHABLE/STALE/DELAY // else // // This should not happen // insert new nexthop // set insert date=now, refcount = 0, flag=REACHABLE/STALE/DELAY // if neighbor delete // lookup neighbor // if exists // if refcount != 0 // set nexthop as invalid // else // set flag empty // else // do nothing // // this should not happen struct control_handle* handle = args; assert(handle != NULL); int s; uint16_t nexthop_id, find_id; int32_t socket_id = handle->socket_id; char ipbuf[INET6_ADDRSTRLEN]; assert(neighbor6_struct != NULL); if (addr == NULL) return -1; inet_ntop(AF_INET6, addr, ipbuf, INET6_ADDRSTRLEN); if (action == NEIGHBOR_ADD) { if (lladdr == NULL) return -1; char ibuf[IFNAMSIZ]; unsigned kni_vlan; if_indextoname(port_id, ibuf); s = sscanf(ibuf, "dpdk%10u.%10u", &port_id, &kni_vlan); if (s <= 0) { RTE_LOG(ERR, PKTJ_CTRL1, "received a neighbor " "announce for an unmanaged " "iface %s\n", ibuf); return -1; } s = neighbor6_lookup_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id); if (s < 0) { if (flags != NUD_NONE && flags != NUD_NOARP && flags != NUD_STALE) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to change state in neighbor6 " "table (state %d, %s)...\n", flags, ipbuf); return -1; } { RTE_LOG( DEBUG, PKTJ_CTRL1, "adding ipv6 neighbor %s with port_id %d " "vlan_id %d...\n", ipbuf, port_id, kni_vlan); } s = neighbor6_add_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id, NEI_ACTION_FWD); if (s < 0) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to add a " "nexthop in neighbor " "table...\n"); return -1; } // apply rate limit rule if next hop neighbor is in the // table apply_rate_limit_ipv6(addr, nexthop_id, socket_id); if (rte_lpm6_lookup(ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, &find_id) == 0) { s = rte_lpm6_add( ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, 128, nexthop_id); if (s < 0) { lpm6_stats[socket_id].nb_add_ko++; RTE_LOG(ERR, PKTJ_CTRL1, "failed to add a route in " "lpm during neighbor " "adding...\n"); return -1; } lpm6_stats[socket_id].nb_add_ok++; } } if (flags == NUD_FAILED) { neighbor6_set_action(neighbor6_struct[socket_id], nexthop_id, NEI_ACTION_KNI); } else { neighbor6_set_action(neighbor6_struct[socket_id], nexthop_id, NEI_ACTION_FWD); } RTE_LOG(DEBUG, PKTJ_CTRL1, "set neighbor6 with port_id %d state %d \n", port_id, flags); neighbor6_set_lladdr_port(neighbor6_struct[socket_id], nexthop_id, &ports_eth_addr[port_id], lladdr, port_id, kni_vlan); neighbor6_set_state(neighbor6_struct[socket_id], nexthop_id, flags); } if (action == NEIGHBOR_DELETE) { if (flags != NUD_FAILED && flags != NUD_STALE) { RTE_LOG( DEBUG, PKTJ_CTRL1, "neighbor6 delete ope failed, bad NUD state: %d \n", flags); return -1; } RTE_LOG(DEBUG, PKTJ_CTRL1, "deleting ipv6 neighbor...\n"); s = neighbor6_lookup_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id); if (s < 0) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to find a nexthop to " "delete in neighbor " "table...\n"); return 0; } neighbor6_delete(neighbor6_struct[socket_id], nexthop_id); // FIXME not thread safe if (neighbor6_struct[socket_id] ->entries.t6[nexthop_id] .neighbor.refcnt == 0) { s = rte_lpm6_delete(ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, 128); if (s < 0) { lpm6_stats[socket_id].nb_del_ko++; RTE_LOG(ERR, PKTJ_CTRL1, "failed to delete route...\n"); return -1; } // reset rate limit for this id rlimit6_max[socket_id][nexthop_id] = UINT32_MAX; lpm6_stats[socket_id].nb_del_ok++; } } RTE_LOG(DEBUG, PKTJ_CTRL1, "neigh %s ope success\n", ipbuf); return 0; }
/* * - Add & lookup to hit invalid TBL24 entry * - Add & lookup to hit valid TBL24 entry not extended * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry */ int32_t test18(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16], ip_1[16], ip_2[16]; uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* Add & lookup to hit invalid TBL24 entry */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Add & lookup to hit valid TBL24 entry not extended */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 23; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); depth = 24; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); depth = 24; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 23; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8 * entry. */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Add & lookup to hit valid extended TBL24 entry with valid TBL8 * entry */ IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth_1 = 25; next_hop_add_1 = 101; IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth_2 = 32; next_hop_add_2 = 102; next_hop_return = 0; status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2)); status = rte_lpm6_delete(lpm, ip_2, depth_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); status = rte_lpm6_delete(lpm, ip_1, depth_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; }
int32_t perf_test(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint64_t begin, total_time; unsigned i, j; uint8_t next_hop_add = 0xAA, next_hop_return = 0; int status = 0; int64_t count = 0; config.max_rules = 1000000; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; rte_srand(rte_rdtsc()); printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES); print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES); lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* Measure add. */ begin = rte_rdtsc(); for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { if (rte_lpm6_add(lpm, large_route_table[i].ip, large_route_table[i].depth, next_hop_add) == 0) status++; } /* End Timer. */ total_time = rte_rdtsc() - begin; printf("Unique added entries = %d\n", status); printf("Average LPM Add: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES); /* Measure single Lookup */ total_time = 0; count = 0; for (i = 0; i < ITERATIONS; i ++) { begin = rte_rdtsc(); for (j = 0; j < NUM_IPS_ENTRIES; j ++) { if (rte_lpm6_lookup(lpm, large_ips_table[j].ip, &next_hop_return) != 0) count++; } total_time += rte_rdtsc() - begin; } printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Measure bulk Lookup */ total_time = 0; count = 0; uint8_t ip_batch[NUM_IPS_ENTRIES][16]; int16_t next_hops[NUM_IPS_ENTRIES]; for (i = 0; i < NUM_IPS_ENTRIES; i++) memcpy(ip_batch[i], large_ips_table[i].ip, 16); for (i = 0; i < ITERATIONS; i ++) { /* Lookup per batch */ begin = rte_rdtsc(); rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hops, NUM_IPS_ENTRIES); total_time += rte_rdtsc() - begin; for (j = 0; j < NUM_IPS_ENTRIES; j++) if (next_hops[j] < 0) count++; } printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Delete */ status = 0; begin = rte_rdtsc(); for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { /* rte_lpm_delete(lpm, ip, depth) */ status += rte_lpm6_delete(lpm, large_route_table[i].ip, large_route_table[i].depth); } total_time += rte_rdtsc() - begin; printf("Average LPM Delete: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES); rte_lpm6_delete_all(lpm); rte_lpm6_free(lpm); return PASS; }
/* * Test for overwriting of tbl8: * - add rule /32 and lookup * - add new rule /24 and lookup * - add third rule /25 and lookup * - lookup /32 and /24 rule to ensure the table has not been overwritten. */ int32_t test26(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t d_ip_10_32 = 32; uint8_t d_ip_10_24 = 24; uint8_t d_ip_20_25 = 25; uint8_t next_hop_ip_10_32 = 100; uint8_t next_hop_ip_10_24 = 105; uint8_t next_hop_ip_20_25 = 111; uint8_t next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32)) < 0) return -1; status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); uint8_t test_hop_10_32 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24)) < 0) return -1; status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); uint8_t test_hop_10_24 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25)) < 0) return -1; status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return); uint8_t test_hop_20_25 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25); if (test_hop_10_32 == test_hop_10_24) { printf("Next hop return equal\n"); return -1; } if (test_hop_10_24 == test_hop_20_25){ printf("Next hop return equal\n"); return -1; } status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); rte_lpm6_free(lpm); return PASS; }
/* * - Add rule that covers a TBL24 range previously invalid & lookup (& delete & * lookup) * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup) * - Add rule that extends a TBL24 valid entry & lookup for both rules (& * delete & lookup) * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup) * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup) * - Delete a rule that is not present in the TBL24 & lookup * - Delete a rule that is not present in the TBL8 & lookup */ int32_t test19(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* Add rule that covers a TBL24 range previously invalid & lookup * (& delete & lookup) */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 16; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 25; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); rte_lpm6_delete_all(lpm); /* * Add rule that extends a TBL24 valid entry & lookup for both rules * (& delete & lookup) */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); next_hop_add = 100; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* * Add rule that updates the next hop in TBL24 & lookup * (& delete & lookup) */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* * Add rule that updates the next hop in TBL8 & lookup * (& delete & lookup) */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Delete a rule that is not present in the TBL24 & lookup */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status < 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Delete a rule that is not present in the TBL8 & lookup */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status < 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; }