X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_node%2Fip4_lookup.c;h=d083a725fcb05e94c0b0047a4afa6946f7235d24;hb=b9a396b0fd4e04c107254768199007c3963510ee;hp=39c8d8db07f723e0f98e924688739e739750ce09;hpb=11afaa84d087dddb3583bfc509759927ba576c9c;p=dpdk.git diff --git a/lib/librte_node/ip4_lookup.c b/lib/librte_node/ip4_lookup.c index 39c8d8db07..d083a725fc 100644 --- a/lib/librte_node/ip4_lookup.c +++ b/lib/librte_node/ip4_lookup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "rte_node_ip4_api.h" @@ -28,22 +29,40 @@ struct ip4_lookup_node_main { struct rte_lpm *lpm_tbl[RTE_MAX_NUMA_NODES]; }; -#if defined(RTE_MACHINE_CPUFLAG_NEON) +struct ip4_lookup_node_ctx { + /* Socket's LPM table */ + struct rte_lpm *lpm; + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; +}; + +int node_mbuf_priv1_dynfield_offset = -1; + +static struct ip4_lookup_node_main ip4_lookup_nm; + +#define IP4_LOOKUP_NODE_LPM(ctx) \ + (((struct ip4_lookup_node_ctx *)ctx)->lpm) + +#define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ + (((struct ip4_lookup_node_ctx *)ctx)->mbuf_priv1_off) + +#if defined(__ARM_NEON) #include "ip4_lookup_neon.h" #elif defined(RTE_ARCH_X86) #include "ip4_lookup_sse.h" -#else +#endif static uint16_t -ip4_lookup_node_process(struct rte_graph *graph, struct rte_node *node, +ip4_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) { + struct rte_lpm *lpm = IP4_LOOKUP_NODE_LPM(node->ctx); + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); struct rte_ipv4_hdr *ipv4_hdr; void **to_next, **from; uint16_t last_spec = 0; struct rte_mbuf *mbuf; rte_edge_t next_index; - struct rte_lpm *lpm; uint16_t held = 0; uint32_t drop_nh; int i, rc; @@ -52,9 +71,6 @@ ip4_lookup_node_process(struct rte_graph *graph, struct rte_node *node, next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; /* Drop node */ drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << 16; - - /* Get socket specific LPM from ctx */ - lpm = *((struct rte_lpm **)node->ctx); from = objs; /* Get stream for the speculated next node */ @@ -69,14 +85,14 @@ ip4_lookup_node_process(struct rte_graph *graph, struct rte_node *node, ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); /* Extract cksum, ttl as ipv4 hdr is in cache */ - node_mbuf_priv1(mbuf)->cksum = ipv4_hdr->hdr_checksum; - node_mbuf_priv1(mbuf)->ttl = ipv4_hdr->time_to_live; + node_mbuf_priv1(mbuf, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf, dyn)->ttl = ipv4_hdr->time_to_live; rc = rte_lpm_lookup(lpm, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop); next_hop = (rc == 0) ? next_hop : drop_nh; - node_mbuf_priv1(mbuf)->nh = (uint16_t)next_hop; + node_mbuf_priv1(mbuf, dyn)->nh = (uint16_t)next_hop; next_hop = next_hop >> 16; next = (uint16_t)next_hop; @@ -107,13 +123,101 @@ ip4_lookup_node_process(struct rte_graph *graph, struct rte_node *node, return nb_objs; } -#endif +int +rte_node_ip4_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip4_lookup_next next_node) +{ + char abuf[INET6_ADDRSTRLEN]; + struct in_addr in; + uint8_t socket; + uint32_t val; + int ret; + + in.s_addr = htonl(ip); + inet_ntop(AF_INET, &in, abuf, sizeof(abuf)); + /* Embedded next node id into 24 bit next hop */ + val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1); + node_dbg("ip4_lookup", "LPM: Adding route %s / %d nh (0x%x)", abuf, + depth, val); + + for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { + if (!ip4_lookup_nm.lpm_tbl[socket]) + continue; + + ret = rte_lpm_add(ip4_lookup_nm.lpm_tbl[socket], + ip, depth, val); + if (ret < 0) { + node_err("ip4_lookup", + "Unable to add entry %s / %d nh (%x) to LPM table on sock %d, rc=%d\n", + abuf, depth, val, socket, ret); + return ret; + } + } + + return 0; +} + +static int +setup_lpm(struct ip4_lookup_node_main *nm, int socket) +{ + struct rte_lpm_config config_ipv4; + char s[RTE_LPM_NAMESIZE]; + + /* One LPM table per socket */ + if (nm->lpm_tbl[socket]) + return 0; + + /* create the LPM table */ + config_ipv4.max_rules = IPV4_L3FWD_LPM_MAX_RULES; + config_ipv4.number_tbl8s = IPV4_L3FWD_LPM_NUMBER_TBL8S; + config_ipv4.flags = 0; + snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socket); + nm->lpm_tbl[socket] = rte_lpm_create(s, socket, &config_ipv4); + if (nm->lpm_tbl[socket] == NULL) + return -rte_errno; + + return 0; +} static int ip4_lookup_node_init(const struct rte_graph *graph, struct rte_node *node) { + uint16_t socket, lcore_id; + static uint8_t init_once; + int rc; + RTE_SET_USED(graph); - RTE_SET_USED(node); + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + + /* Setup LPM tables for all sockets */ + RTE_LCORE_FOREACH(lcore_id) + { + socket = rte_lcore_to_socket_id(lcore_id); + rc = setup_lpm(&ip4_lookup_nm, socket); + if (rc) { + node_err("ip4_lookup", + "Failed to setup lpm tbl for sock %u, rc=%d", + socket, rc); + return rc; + } + } + init_once = 1; + } + + /* Update socket's LPM and mbuf dyn priv1 offset in node ctx */ + IP4_LOOKUP_NODE_LPM(node->ctx) = ip4_lookup_nm.lpm_tbl[graph->socket]; + IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + +#if defined(__ARM_NEON) || defined(RTE_ARCH_X86) + if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) + node->process = ip4_lookup_node_process_vec; +#endif node_dbg("ip4_lookup", "Initialized ip4_lookup node"); @@ -121,7 +225,7 @@ ip4_lookup_node_init(const struct rte_graph *graph, struct rte_node *node) } static struct rte_node_register ip4_lookup_node = { - .process = ip4_lookup_node_process, + .process = ip4_lookup_node_process_scalar, .name = "ip4_lookup", .init = ip4_lookup_node_init,