xref: /dpdk/examples/l3fwd/l3fwd_fib.c (revision d5c4897ecfb2540dc4990d9b367ddbe5013d0e66)
19510dd1fSConor Walsh /* SPDX-License-Identifier: BSD-3-Clause
29510dd1fSConor Walsh  * Copyright(c) 2021 Intel Corporation
39510dd1fSConor Walsh  */
49510dd1fSConor Walsh 
56a094e32SConor Walsh #include <stdio.h>
66a094e32SConor Walsh #include <stddef.h>
76a094e32SConor Walsh #include <stdint.h>
86a094e32SConor Walsh #include <sys/socket.h>
96a094e32SConor Walsh #include <arpa/inet.h>
106a094e32SConor Walsh 
119510dd1fSConor Walsh #include <rte_fib.h>
129510dd1fSConor Walsh #include <rte_fib6.h>
139510dd1fSConor Walsh 
149510dd1fSConor Walsh #include "l3fwd.h"
156a094e32SConor Walsh #if defined RTE_ARCH_X86
166a094e32SConor Walsh #include "l3fwd_sse.h"
176a094e32SConor Walsh #elif defined __ARM_NEON
186a094e32SConor Walsh #include "l3fwd_neon.h"
196a094e32SConor Walsh #elif defined RTE_ARCH_PPC_64
206a094e32SConor Walsh #include "l3fwd_altivec.h"
213cc97770SStanislaw Kardach #else
223cc97770SStanislaw Kardach #include "l3fwd_common.h"
236a094e32SConor Walsh #endif
249510dd1fSConor Walsh #include "l3fwd_event.h"
259510dd1fSConor Walsh #include "l3fwd_route.h"
269510dd1fSConor Walsh 
276a094e32SConor Walsh /* Configure how many packets ahead to prefetch for fib. */
286a094e32SConor Walsh #define FIB_PREFETCH_OFFSET 4
296a094e32SConor Walsh 
306a094e32SConor Walsh /* A non-existent portid is needed to denote a default hop for fib. */
316a094e32SConor Walsh #define FIB_DEFAULT_HOP 999
326a094e32SConor Walsh 
336a094e32SConor Walsh /*
346a094e32SConor Walsh  * If the machine has SSE, NEON or PPC 64 then multiple packets
356a094e32SConor Walsh  * can be sent at once if not only single packets will be sent
366a094e32SConor Walsh  */
376a094e32SConor Walsh #if defined RTE_ARCH_X86 || defined __ARM_NEON \
386a094e32SConor Walsh 		|| defined RTE_ARCH_PPC_64
396a094e32SConor Walsh #define FIB_SEND_MULTI
406a094e32SConor Walsh #endif
416a094e32SConor Walsh 
426a094e32SConor Walsh static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
436a094e32SConor Walsh static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
446a094e32SConor Walsh 
456a094e32SConor Walsh /* Parse packet type and ip address. */
466a094e32SConor Walsh static inline void
476a094e32SConor Walsh fib_parse_packet(struct rte_mbuf *mbuf,
486a094e32SConor Walsh 		uint32_t *ipv4, uint32_t *ipv4_cnt,
496cb10a9bSRobin Jarry 		struct rte_ipv6_addr *ipv6,
506a094e32SConor Walsh 		uint32_t *ipv6_cnt, uint8_t *ip_type)
516a094e32SConor Walsh {
526a094e32SConor Walsh 	struct rte_ether_hdr *eth_hdr;
536a094e32SConor Walsh 	struct rte_ipv4_hdr *ipv4_hdr;
546a094e32SConor Walsh 	struct rte_ipv6_hdr *ipv6_hdr;
556a094e32SConor Walsh 
566a094e32SConor Walsh 	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
576a094e32SConor Walsh 	/* IPv4 */
586a094e32SConor Walsh 	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
596a094e32SConor Walsh 		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
606a094e32SConor Walsh 		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
616a094e32SConor Walsh 		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
626a094e32SConor Walsh 		*ip_type = 1;
636a094e32SConor Walsh 		(*ipv4_cnt)++;
646a094e32SConor Walsh 	}
656a094e32SConor Walsh 	/* IPv6 */
666a094e32SConor Walsh 	else {
676a094e32SConor Walsh 		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
686cb10a9bSRobin Jarry 		*ipv6 = ipv6_hdr->dst_addr;
696a094e32SConor Walsh 		*ip_type = 0;
706a094e32SConor Walsh 		(*ipv6_cnt)++;
716a094e32SConor Walsh 	}
726a094e32SConor Walsh }
736a094e32SConor Walsh 
746a094e32SConor Walsh /*
756a094e32SConor Walsh  * If the machine does not have SSE, NEON or PPC 64 then the packets
766a094e32SConor Walsh  * are sent one at a time using send_single_packet()
776a094e32SConor Walsh  */
786a094e32SConor Walsh #if !defined FIB_SEND_MULTI
796a094e32SConor Walsh static inline void
8081476d0fSPavan Nikhilesh process_packet(struct rte_mbuf *pkt, uint16_t *hop)
8181476d0fSPavan Nikhilesh {
8281476d0fSPavan Nikhilesh 	struct rte_ether_hdr *eth_hdr;
8381476d0fSPavan Nikhilesh 
8481476d0fSPavan Nikhilesh 	/* Run rfc1812 if packet is ipv4 and checks enabled. */
8581476d0fSPavan Nikhilesh #if defined DO_RFC_1812_CHECKS
8681476d0fSPavan Nikhilesh 	rfc1812_process(
8781476d0fSPavan Nikhilesh 		(struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
8881476d0fSPavan Nikhilesh 						pkt, struct rte_ether_hdr *) +
8981476d0fSPavan Nikhilesh 					1),
9081476d0fSPavan Nikhilesh 		hop, pkt->packet_type);
9181476d0fSPavan Nikhilesh #endif
9281476d0fSPavan Nikhilesh 
9381476d0fSPavan Nikhilesh 	/* Set MAC addresses. */
9481476d0fSPavan Nikhilesh 	eth_hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
9581476d0fSPavan Nikhilesh 	*(uint64_t *)&eth_hdr->dst_addr = dest_eth_addr[*hop];
9681476d0fSPavan Nikhilesh 	rte_ether_addr_copy(&ports_eth_addr[*hop], &eth_hdr->src_addr);
9781476d0fSPavan Nikhilesh }
9881476d0fSPavan Nikhilesh 
9981476d0fSPavan Nikhilesh static inline void
1006a094e32SConor Walsh fib_send_single(int nb_tx, struct lcore_conf *qconf,
1016a094e32SConor Walsh 		struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
1026a094e32SConor Walsh {
1036a094e32SConor Walsh 	int32_t j;
1046a094e32SConor Walsh 
1056a094e32SConor Walsh 	for (j = 0; j < nb_tx; j++) {
10681476d0fSPavan Nikhilesh 		process_packet(pkts_burst[j], &hops[j]);
10781476d0fSPavan Nikhilesh 		if (hops[j] == BAD_PORT) {
10881476d0fSPavan Nikhilesh 			rte_pktmbuf_free(pkts_burst[j]);
10981476d0fSPavan Nikhilesh 			continue;
11081476d0fSPavan Nikhilesh 		}
1116a094e32SConor Walsh 		/* Send single packet. */
1126a094e32SConor Walsh 		send_single_packet(qconf, pkts_burst[j], hops[j]);
1136a094e32SConor Walsh 	}
1146a094e32SConor Walsh }
1156a094e32SConor Walsh #endif
1166a094e32SConor Walsh 
1176a094e32SConor Walsh /* Bulk parse, fib lookup and send. */
1186a094e32SConor Walsh static inline void
1196a094e32SConor Walsh fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
1206a094e32SConor Walsh 		uint16_t portid, struct lcore_conf *qconf)
1216a094e32SConor Walsh {
1226a094e32SConor Walsh 	uint32_t ipv4_arr[nb_rx];
1236cb10a9bSRobin Jarry 	struct rte_ipv6_addr ipv6_arr[nb_rx];
124ebab0e8bSKonstantin Ananyev 	uint16_t hops[SENDM_PORT_OVERHEAD(nb_rx)];
1256a094e32SConor Walsh 	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
1266a094e32SConor Walsh 	uint8_t type_arr[nb_rx];
1276a094e32SConor Walsh 	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
1286a094e32SConor Walsh 	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
1296a094e32SConor Walsh 	uint16_t nh;
1306a094e32SConor Walsh 	int32_t i;
1316a094e32SConor Walsh 
1326a094e32SConor Walsh 	/* Prefetch first packets. */
1336a094e32SConor Walsh 	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
1346a094e32SConor Walsh 		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
1356a094e32SConor Walsh 
1366a094e32SConor Walsh 	/* Parse packet info and prefetch. */
1376a094e32SConor Walsh 	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
1386a094e32SConor Walsh 		/* Prefetch packet. */
1396a094e32SConor Walsh 		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
1406a094e32SConor Walsh 				i + FIB_PREFETCH_OFFSET], void *));
1416a094e32SConor Walsh 		fib_parse_packet(pkts_burst[i],
1426a094e32SConor Walsh 				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
1436cb10a9bSRobin Jarry 				&ipv6_arr[ipv6_cnt], &ipv6_cnt,
1446a094e32SConor Walsh 				&type_arr[i]);
1456a094e32SConor Walsh 	}
1466a094e32SConor Walsh 
1476a094e32SConor Walsh 	/* Parse remaining packet info. */
1486a094e32SConor Walsh 	for (; i < nb_rx; i++)
1496a094e32SConor Walsh 		fib_parse_packet(pkts_burst[i],
1506a094e32SConor Walsh 				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
1516cb10a9bSRobin Jarry 				&ipv6_arr[ipv6_cnt], &ipv6_cnt,
1526a094e32SConor Walsh 				&type_arr[i]);
1536a094e32SConor Walsh 
1546a094e32SConor Walsh 	/* Lookup IPv4 hops if IPv4 packets are present. */
1556a094e32SConor Walsh 	if (likely(ipv4_cnt > 0))
1566a094e32SConor Walsh 		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
1576a094e32SConor Walsh 				ipv4_arr, hopsv4, ipv4_cnt);
1586a094e32SConor Walsh 
1596a094e32SConor Walsh 	/* Lookup IPv6 hops if IPv6 packets are present. */
1606a094e32SConor Walsh 	if (ipv6_cnt > 0)
1616a094e32SConor Walsh 		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
1626a094e32SConor Walsh 				ipv6_arr, hopsv6, ipv6_cnt);
1636a094e32SConor Walsh 
1646a094e32SConor Walsh 	/* Add IPv4 and IPv6 hops to one array depending on type. */
1656a094e32SConor Walsh 	for (i = 0; i < nb_rx; i++) {
1666a094e32SConor Walsh 		if (type_arr[i])
1676a094e32SConor Walsh 			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
1686a094e32SConor Walsh 		else
1696a094e32SConor Walsh 			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
1706a094e32SConor Walsh 		hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
1716a094e32SConor Walsh 	}
1726a094e32SConor Walsh 
1736a094e32SConor Walsh #if defined FIB_SEND_MULTI
1746a094e32SConor Walsh 	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
1756a094e32SConor Walsh #else
1766a094e32SConor Walsh 	fib_send_single(nb_rx, qconf, pkts_burst, hops);
1776a094e32SConor Walsh #endif
1786a094e32SConor Walsh }
1796a094e32SConor Walsh 
1809510dd1fSConor Walsh /* Main fib processing loop. */
1819510dd1fSConor Walsh int
1829510dd1fSConor Walsh fib_main_loop(__rte_unused void *dummy)
1839510dd1fSConor Walsh {
1846a094e32SConor Walsh 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1856a094e32SConor Walsh 	unsigned int lcore_id;
1866a094e32SConor Walsh 	uint64_t prev_tsc, diff_tsc, cur_tsc;
1876a094e32SConor Walsh 	int i, nb_rx;
1886a094e32SConor Walsh 	uint16_t portid;
189b23c5bd7SSivaprasad Tummala 	uint16_t queueid;
1906a094e32SConor Walsh 	struct lcore_conf *qconf;
1916a094e32SConor Walsh 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
1926a094e32SConor Walsh 			US_PER_S * BURST_TX_DRAIN_US;
1936a094e32SConor Walsh 
1946a094e32SConor Walsh 	lcore_id = rte_lcore_id();
1956a094e32SConor Walsh 	qconf = &lcore_conf[lcore_id];
1966a094e32SConor Walsh 
1976018b5acSConor Walsh 	const uint16_t n_rx_q = qconf->n_rx_queue;
1986018b5acSConor Walsh 	const uint16_t n_tx_p = qconf->n_tx_port;
1996018b5acSConor Walsh 	if (n_rx_q == 0) {
2006a094e32SConor Walsh 		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
2019510dd1fSConor Walsh 		return 0;
2029510dd1fSConor Walsh 	}
2039510dd1fSConor Walsh 
2046a094e32SConor Walsh 	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
2056a094e32SConor Walsh 
2066018b5acSConor Walsh 	for (i = 0; i < n_rx_q; i++) {
2076a094e32SConor Walsh 
2086a094e32SConor Walsh 		portid = qconf->rx_queue_list[i].port_id;
2096a094e32SConor Walsh 		queueid = qconf->rx_queue_list[i].queue_id;
2106a094e32SConor Walsh 		RTE_LOG(INFO, L3FWD,
211b23c5bd7SSivaprasad Tummala 				" -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n",
2126a094e32SConor Walsh 				lcore_id, portid, queueid);
2136a094e32SConor Walsh 	}
2146a094e32SConor Walsh 
2156a094e32SConor Walsh 	cur_tsc = rte_rdtsc();
21691470c0dSConor Walsh 	prev_tsc = cur_tsc;
21791470c0dSConor Walsh 
21891470c0dSConor Walsh 	while (!force_quit) {
2196a094e32SConor Walsh 
2206a094e32SConor Walsh 		/* TX burst queue drain. */
2216a094e32SConor Walsh 		diff_tsc = cur_tsc - prev_tsc;
2226a094e32SConor Walsh 		if (unlikely(diff_tsc > drain_tsc)) {
2236a094e32SConor Walsh 
2246018b5acSConor Walsh 			for (i = 0; i < n_tx_p; ++i) {
2256a094e32SConor Walsh 				portid = qconf->tx_port_id[i];
2266a094e32SConor Walsh 				if (qconf->tx_mbufs[portid].len == 0)
2276a094e32SConor Walsh 					continue;
2286a094e32SConor Walsh 				send_burst(qconf,
2296a094e32SConor Walsh 					qconf->tx_mbufs[portid].len,
2306a094e32SConor Walsh 					portid);
2316a094e32SConor Walsh 				qconf->tx_mbufs[portid].len = 0;
2326a094e32SConor Walsh 			}
2336a094e32SConor Walsh 
2346a094e32SConor Walsh 			prev_tsc = cur_tsc;
2356a094e32SConor Walsh 		}
2366a094e32SConor Walsh 
2376a094e32SConor Walsh 		/* Read packet from RX queues. */
2386018b5acSConor Walsh 		for (i = 0; i < n_rx_q; ++i) {
2396a094e32SConor Walsh 			portid = qconf->rx_queue_list[i].port_id;
2406a094e32SConor Walsh 			queueid = qconf->rx_queue_list[i].queue_id;
2416a094e32SConor Walsh 			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
242*d5c4897eSJie Hai 					nb_pkt_per_burst);
2436a094e32SConor Walsh 			if (nb_rx == 0)
2446a094e32SConor Walsh 				continue;
2456a094e32SConor Walsh 
2466a094e32SConor Walsh 			/* Use fib to lookup port IDs and transmit them. */
2476a094e32SConor Walsh 			fib_send_packets(nb_rx, pkts_burst,	portid, qconf);
2486a094e32SConor Walsh 		}
24991470c0dSConor Walsh 
25091470c0dSConor Walsh 		cur_tsc = rte_rdtsc();
2516a094e32SConor Walsh 	}
2526a094e32SConor Walsh 
2536a094e32SConor Walsh 	return 0;
2546a094e32SConor Walsh }
2556a094e32SConor Walsh 
256ef827078SBruce Richardson #ifdef RTE_LIB_EVENTDEV
2576a094e32SConor Walsh /* One eventdev loop for single and burst using fib. */
2586a094e32SConor Walsh static __rte_always_inline void
2596a094e32SConor Walsh fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
2606a094e32SConor Walsh 		const uint8_t flags)
2616a094e32SConor Walsh {
2626a094e32SConor Walsh 	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
2636a094e32SConor Walsh 	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
2646a094e32SConor Walsh 			evt_rsrc->evq.nb_queues - 1];
2656a094e32SConor Walsh 	const uint8_t event_d_id = evt_rsrc->event_d_id;
2666a094e32SConor Walsh 	const uint16_t deq_len = evt_rsrc->deq_depth;
2676a094e32SConor Walsh 	struct rte_event events[MAX_PKT_BURST];
26855b22fb3SPavan Nikhilesh 	int i, nb_enq = 0, nb_deq = 0;
2696a094e32SConor Walsh 	struct lcore_conf *lconf;
2706a094e32SConor Walsh 	unsigned int lcore_id;
2716a094e32SConor Walsh 
2726a094e32SConor Walsh 	uint32_t ipv4_arr[MAX_PKT_BURST];
2736cb10a9bSRobin Jarry 	struct rte_ipv6_addr ipv6_arr[MAX_PKT_BURST];
2746a094e32SConor Walsh 	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
27581476d0fSPavan Nikhilesh 	uint16_t nh, hops[MAX_PKT_BURST];
2766a094e32SConor Walsh 	uint8_t type_arr[MAX_PKT_BURST];
2776a094e32SConor Walsh 	uint32_t ipv4_cnt, ipv6_cnt;
2786a094e32SConor Walsh 	uint32_t ipv4_arr_assem, ipv6_arr_assem;
2796a094e32SConor Walsh 
2806a094e32SConor Walsh 	if (event_p_id < 0)
2816a094e32SConor Walsh 		return;
2826a094e32SConor Walsh 
2836a094e32SConor Walsh 	lcore_id = rte_lcore_id();
2846a094e32SConor Walsh 
2856a094e32SConor Walsh 	lconf = &lcore_conf[lcore_id];
2866a094e32SConor Walsh 
2876a094e32SConor Walsh 	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
2886a094e32SConor Walsh 
2896a094e32SConor Walsh 	while (!force_quit) {
2906a094e32SConor Walsh 		/* Read events from RX queues. */
2916a094e32SConor Walsh 		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
2926a094e32SConor Walsh 				events, deq_len, 0);
2936a094e32SConor Walsh 		if (nb_deq == 0) {
2946a094e32SConor Walsh 			rte_pause();
2956a094e32SConor Walsh 			continue;
2966a094e32SConor Walsh 		}
2976a094e32SConor Walsh 
2986a094e32SConor Walsh 		/* Reset counters. */
2996a094e32SConor Walsh 		ipv4_cnt = 0;
3006a094e32SConor Walsh 		ipv6_cnt = 0;
3016a094e32SConor Walsh 		ipv4_arr_assem = 0;
3026a094e32SConor Walsh 		ipv6_arr_assem = 0;
3036a094e32SConor Walsh 
3046a094e32SConor Walsh 		/* Prefetch first packets. */
3056a094e32SConor Walsh 		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
3066a094e32SConor Walsh 			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
3076a094e32SConor Walsh 
3086a094e32SConor Walsh 		/* Parse packet info and prefetch. */
3096a094e32SConor Walsh 		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
3106a094e32SConor Walsh 			if (flags & L3FWD_EVENT_TX_ENQ) {
3116a094e32SConor Walsh 				events[i].queue_id = tx_q_id;
3126a094e32SConor Walsh 				events[i].op = RTE_EVENT_OP_FORWARD;
3136a094e32SConor Walsh 			}
3146a094e32SConor Walsh 
3156a094e32SConor Walsh 			if (flags & L3FWD_EVENT_TX_DIRECT)
3166a094e32SConor Walsh 				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
3176a094e32SConor Walsh 						0);
3186a094e32SConor Walsh 
3196a094e32SConor Walsh 			/* Prefetch packet. */
3206a094e32SConor Walsh 			rte_prefetch0(rte_pktmbuf_mtod(events[
3216a094e32SConor Walsh 					i + FIB_PREFETCH_OFFSET].mbuf,
3226a094e32SConor Walsh 					void *));
3236a094e32SConor Walsh 
3246a094e32SConor Walsh 			fib_parse_packet(events[i].mbuf,
3256a094e32SConor Walsh 					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
3266cb10a9bSRobin Jarry 					&ipv6_arr[ipv6_cnt], &ipv6_cnt,
3276a094e32SConor Walsh 					&type_arr[i]);
3286a094e32SConor Walsh 		}
3296a094e32SConor Walsh 
3306a094e32SConor Walsh 		/* Parse remaining packet info. */
3316a094e32SConor Walsh 		for (; i < nb_deq; i++) {
3326a094e32SConor Walsh 			if (flags & L3FWD_EVENT_TX_ENQ) {
3336a094e32SConor Walsh 				events[i].queue_id = tx_q_id;
3346a094e32SConor Walsh 				events[i].op = RTE_EVENT_OP_FORWARD;
3356a094e32SConor Walsh 			}
3366a094e32SConor Walsh 
3376a094e32SConor Walsh 			if (flags & L3FWD_EVENT_TX_DIRECT)
3386a094e32SConor Walsh 				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
3396a094e32SConor Walsh 						0);
3406a094e32SConor Walsh 
3416a094e32SConor Walsh 			fib_parse_packet(events[i].mbuf,
3426a094e32SConor Walsh 					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
3436cb10a9bSRobin Jarry 					&ipv6_arr[ipv6_cnt], &ipv6_cnt,
3446a094e32SConor Walsh 					&type_arr[i]);
3456a094e32SConor Walsh 		}
3466a094e32SConor Walsh 
3476a094e32SConor Walsh 		/* Lookup IPv4 hops if IPv4 packets are present. */
3486a094e32SConor Walsh 		if (likely(ipv4_cnt > 0))
3496a094e32SConor Walsh 			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
3506a094e32SConor Walsh 					ipv4_arr, hopsv4, ipv4_cnt);
3516a094e32SConor Walsh 
3526a094e32SConor Walsh 		/* Lookup IPv6 hops if IPv6 packets are present. */
3536a094e32SConor Walsh 		if (ipv6_cnt > 0)
3546a094e32SConor Walsh 			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
3556a094e32SConor Walsh 					ipv6_arr, hopsv6, ipv6_cnt);
3566a094e32SConor Walsh 
3576a094e32SConor Walsh 		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
3586a094e32SConor Walsh 		for (i = 0; i < nb_deq; i++) {
3596a094e32SConor Walsh 			if (type_arr[i])
3606a094e32SConor Walsh 				nh = (uint16_t)hopsv4[ipv4_arr_assem++];
3616a094e32SConor Walsh 			else
3626a094e32SConor Walsh 				nh = (uint16_t)hopsv6[ipv6_arr_assem++];
3639a518054SMohammad Iqbal Ahmad 
36481476d0fSPavan Nikhilesh 			hops[i] = nh != FIB_DEFAULT_HOP ?
36581476d0fSPavan Nikhilesh 				  nh :
36681476d0fSPavan Nikhilesh 				  events[i].mbuf->port;
36781476d0fSPavan Nikhilesh 			process_packet(events[i].mbuf, &hops[i]);
36881476d0fSPavan Nikhilesh 			events[i].mbuf->port = hops[i] != BAD_PORT ?
36981476d0fSPavan Nikhilesh 						       hops[i] :
37081476d0fSPavan Nikhilesh 						       events[i].mbuf->port;
3716a094e32SConor Walsh 		}
3726a094e32SConor Walsh 
3736a094e32SConor Walsh 		if (flags & L3FWD_EVENT_TX_ENQ) {
3746a094e32SConor Walsh 			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
3756a094e32SConor Walsh 					events, nb_deq);
3766a094e32SConor Walsh 			while (nb_enq < nb_deq && !force_quit)
3776a094e32SConor Walsh 				nb_enq += rte_event_enqueue_burst(event_d_id,
3786a094e32SConor Walsh 						event_p_id, events + nb_enq,
3796a094e32SConor Walsh 						nb_deq - nb_enq);
3806a094e32SConor Walsh 		}
3816a094e32SConor Walsh 
3826a094e32SConor Walsh 		if (flags & L3FWD_EVENT_TX_DIRECT) {
3836a094e32SConor Walsh 			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
3846a094e32SConor Walsh 					event_p_id, events, nb_deq, 0);
3856a094e32SConor Walsh 			while (nb_enq < nb_deq && !force_quit)
3866a094e32SConor Walsh 				nb_enq += rte_event_eth_tx_adapter_enqueue(
3876a094e32SConor Walsh 						event_d_id, event_p_id,
3886a094e32SConor Walsh 						events + nb_enq,
3896a094e32SConor Walsh 						nb_deq - nb_enq, 0);
3906a094e32SConor Walsh 		}
3916a094e32SConor Walsh 	}
39255b22fb3SPavan Nikhilesh 
39355b22fb3SPavan Nikhilesh 	l3fwd_event_worker_cleanup(event_d_id, event_p_id, events, nb_enq,
39455b22fb3SPavan Nikhilesh 				   nb_deq, 0);
3956a094e32SConor Walsh }
3966a094e32SConor Walsh 
3979510dd1fSConor Walsh int __rte_noinline
3989510dd1fSConor Walsh fib_event_main_loop_tx_d(__rte_unused void *dummy)
3999510dd1fSConor Walsh {
4006a094e32SConor Walsh 	struct l3fwd_event_resources *evt_rsrc =
4016a094e32SConor Walsh 			l3fwd_get_eventdev_rsrc();
4026a094e32SConor Walsh 
4036a094e32SConor Walsh 	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
4049510dd1fSConor Walsh 	return 0;
4059510dd1fSConor Walsh }
4069510dd1fSConor Walsh 
4079510dd1fSConor Walsh int __rte_noinline
4089510dd1fSConor Walsh fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
4099510dd1fSConor Walsh {
4106a094e32SConor Walsh 	struct l3fwd_event_resources *evt_rsrc =
4116a094e32SConor Walsh 			l3fwd_get_eventdev_rsrc();
4126a094e32SConor Walsh 
4136a094e32SConor Walsh 	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
4149510dd1fSConor Walsh 	return 0;
4159510dd1fSConor Walsh }
4169510dd1fSConor Walsh 
4179510dd1fSConor Walsh int __rte_noinline
4189510dd1fSConor Walsh fib_event_main_loop_tx_q(__rte_unused void *dummy)
4199510dd1fSConor Walsh {
4206a094e32SConor Walsh 	struct l3fwd_event_resources *evt_rsrc =
4216a094e32SConor Walsh 			l3fwd_get_eventdev_rsrc();
4226a094e32SConor Walsh 
4236a094e32SConor Walsh 	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
4249510dd1fSConor Walsh 	return 0;
4259510dd1fSConor Walsh }
4269510dd1fSConor Walsh 
4279510dd1fSConor Walsh int __rte_noinline
4289510dd1fSConor Walsh fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
4299510dd1fSConor Walsh {
4306a094e32SConor Walsh 	struct l3fwd_event_resources *evt_rsrc =
4316a094e32SConor Walsh 			l3fwd_get_eventdev_rsrc();
4326a094e32SConor Walsh 
4336a094e32SConor Walsh 	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
4349510dd1fSConor Walsh 	return 0;
4359510dd1fSConor Walsh }
4369510dd1fSConor Walsh 
437e8adca19SShijith Thotton static __rte_always_inline void
43881476d0fSPavan Nikhilesh fib_process_event_vector(struct rte_event_vector *vec, uint8_t *type_arr,
4396cb10a9bSRobin Jarry 			 struct rte_ipv6_addr *ipv6_arr, uint64_t *hopsv4, uint64_t *hopsv6,
44081476d0fSPavan Nikhilesh 			 uint32_t *ipv4_arr, uint16_t *hops)
441e8adca19SShijith Thotton {
442e8adca19SShijith Thotton 	uint32_t ipv4_arr_assem, ipv6_arr_assem;
443e8adca19SShijith Thotton 	struct rte_mbuf **mbufs = vec->mbufs;
444e8adca19SShijith Thotton 	uint32_t ipv4_cnt, ipv6_cnt;
445e8adca19SShijith Thotton 	struct lcore_conf *lconf;
446e8adca19SShijith Thotton 	uint16_t nh;
447e8adca19SShijith Thotton 	int i;
448e8adca19SShijith Thotton 
449e8adca19SShijith Thotton 	lconf = &lcore_conf[rte_lcore_id()];
450e8adca19SShijith Thotton 
451e8adca19SShijith Thotton 	/* Reset counters. */
452e8adca19SShijith Thotton 	ipv4_cnt = 0;
453e8adca19SShijith Thotton 	ipv6_cnt = 0;
454e8adca19SShijith Thotton 	ipv4_arr_assem = 0;
455e8adca19SShijith Thotton 	ipv6_arr_assem = 0;
456e8adca19SShijith Thotton 
457e8adca19SShijith Thotton 	/* Prefetch first packets. */
458e8adca19SShijith Thotton 	for (i = 0; i < FIB_PREFETCH_OFFSET && i < vec->nb_elem; i++)
459e8adca19SShijith Thotton 		rte_prefetch0(rte_pktmbuf_mtod(mbufs[i], void *));
460e8adca19SShijith Thotton 
461e8adca19SShijith Thotton 	/* Parse packet info and prefetch. */
462e8adca19SShijith Thotton 	for (i = 0; i < (vec->nb_elem - FIB_PREFETCH_OFFSET); i++) {
463e8adca19SShijith Thotton 		rte_prefetch0(rte_pktmbuf_mtod(mbufs[i + FIB_PREFETCH_OFFSET],
464e8adca19SShijith Thotton 					       void *));
465e8adca19SShijith Thotton 		fib_parse_packet(mbufs[i], &ipv4_arr[ipv4_cnt], &ipv4_cnt,
4666cb10a9bSRobin Jarry 				 &ipv6_arr[ipv6_cnt], &ipv6_cnt, &type_arr[i]);
467e8adca19SShijith Thotton 	}
468e8adca19SShijith Thotton 
469e8adca19SShijith Thotton 	/* Parse remaining packet info. */
470e8adca19SShijith Thotton 	for (; i < vec->nb_elem; i++)
471e8adca19SShijith Thotton 		fib_parse_packet(mbufs[i], &ipv4_arr[ipv4_cnt], &ipv4_cnt,
4726cb10a9bSRobin Jarry 				 &ipv6_arr[ipv6_cnt], &ipv6_cnt, &type_arr[i]);
473e8adca19SShijith Thotton 
474e8adca19SShijith Thotton 	/* Lookup IPv4 hops if IPv4 packets are present. */
475e8adca19SShijith Thotton 	if (likely(ipv4_cnt > 0))
476e8adca19SShijith Thotton 		rte_fib_lookup_bulk(lconf->ipv4_lookup_struct, ipv4_arr, hopsv4,
477e8adca19SShijith Thotton 				    ipv4_cnt);
478e8adca19SShijith Thotton 
479e8adca19SShijith Thotton 	/* Lookup IPv6 hops if IPv6 packets are present. */
480e8adca19SShijith Thotton 	if (ipv6_cnt > 0)
48181476d0fSPavan Nikhilesh 		rte_fib6_lookup_bulk(
48281476d0fSPavan Nikhilesh 			lconf->ipv6_lookup_struct,
4836cb10a9bSRobin Jarry 			ipv6_arr, hopsv6,
48481476d0fSPavan Nikhilesh 			ipv6_cnt);
485e8adca19SShijith Thotton 
486e8adca19SShijith Thotton 	/* Assign ports looked up in fib depending on IPv4 or IPv6 */
487e8adca19SShijith Thotton 	for (i = 0; i < vec->nb_elem; i++) {
488e8adca19SShijith Thotton 		if (type_arr[i])
489e8adca19SShijith Thotton 			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
490e8adca19SShijith Thotton 		else
491e8adca19SShijith Thotton 			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
492e8adca19SShijith Thotton 		if (nh != FIB_DEFAULT_HOP)
49381476d0fSPavan Nikhilesh 			hops[i] = nh;
49481476d0fSPavan Nikhilesh 		else
49581476d0fSPavan Nikhilesh 			hops[i] = vec->attr_valid ? vec->port :
49681476d0fSPavan Nikhilesh 						    vec->mbufs[i]->port;
497e8adca19SShijith Thotton 	}
49881476d0fSPavan Nikhilesh 
49981476d0fSPavan Nikhilesh #if defined FIB_SEND_MULTI
50081476d0fSPavan Nikhilesh 	uint16_t k;
50181476d0fSPavan Nikhilesh 	k = RTE_ALIGN_FLOOR(vec->nb_elem, FWDSTEP);
50281476d0fSPavan Nikhilesh 
50381476d0fSPavan Nikhilesh 	for (i = 0; i != k; i += FWDSTEP)
50481476d0fSPavan Nikhilesh 		processx4_step3(&vec->mbufs[i], &hops[i]);
50581476d0fSPavan Nikhilesh 	for (; i < vec->nb_elem; i++)
50681476d0fSPavan Nikhilesh 		process_packet(vec->mbufs[i], &hops[i]);
50781476d0fSPavan Nikhilesh #else
50881476d0fSPavan Nikhilesh 	for (i = 0; i < vec->nb_elem; i++)
50981476d0fSPavan Nikhilesh 		process_packet(vec->mbufs[i], &hops[i]);
51081476d0fSPavan Nikhilesh #endif
51181476d0fSPavan Nikhilesh 
51281476d0fSPavan Nikhilesh 	process_event_vector(vec, hops);
513e8adca19SShijith Thotton }
514e8adca19SShijith Thotton 
515e8adca19SShijith Thotton static __rte_always_inline void
516e8adca19SShijith Thotton fib_event_loop_vector(struct l3fwd_event_resources *evt_rsrc,
517e8adca19SShijith Thotton 		      const uint8_t flags)
518e8adca19SShijith Thotton {
519e8adca19SShijith Thotton 	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
520e8adca19SShijith Thotton 	const uint8_t tx_q_id =
521e8adca19SShijith Thotton 		evt_rsrc->evq.event_q_id[evt_rsrc->evq.nb_queues - 1];
522e8adca19SShijith Thotton 	const uint8_t event_d_id = evt_rsrc->event_d_id;
523e8adca19SShijith Thotton 	const uint16_t deq_len = evt_rsrc->deq_depth;
524e8adca19SShijith Thotton 	struct rte_event events[MAX_PKT_BURST];
5256cb10a9bSRobin Jarry 	uint8_t *type_arr;
5266cb10a9bSRobin Jarry 	struct rte_ipv6_addr *ipv6_arr;
52755b22fb3SPavan Nikhilesh 	int nb_enq = 0, nb_deq = 0, i;
52881476d0fSPavan Nikhilesh 	uint64_t *hopsv4, *hopsv6;
52981476d0fSPavan Nikhilesh 	uint32_t *ipv4_arr;
53081476d0fSPavan Nikhilesh 	uint16_t *hops;
53181476d0fSPavan Nikhilesh 	uintptr_t mem;
532e8adca19SShijith Thotton 
53381476d0fSPavan Nikhilesh 	mem = (uintptr_t)rte_zmalloc(
53481476d0fSPavan Nikhilesh 		"vector_fib",
53581476d0fSPavan Nikhilesh 		(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint64_t) +
53681476d0fSPavan Nikhilesh 		 sizeof(uint64_t) + sizeof(uint16_t) + sizeof(uint8_t *) +
5376cb10a9bSRobin Jarry 		 sizeof(struct rte_ipv6_addr)) *
53881476d0fSPavan Nikhilesh 			evt_rsrc->vector_size,
53981476d0fSPavan Nikhilesh 		RTE_CACHE_LINE_SIZE);
54081476d0fSPavan Nikhilesh 	if (mem == 0)
541e8adca19SShijith Thotton 		return;
54281476d0fSPavan Nikhilesh 	ipv4_arr = (uint32_t *)mem;
54381476d0fSPavan Nikhilesh 	type_arr = (uint8_t *)&ipv4_arr[evt_rsrc->vector_size];
54481476d0fSPavan Nikhilesh 	hopsv4 = (uint64_t *)&type_arr[evt_rsrc->vector_size];
54581476d0fSPavan Nikhilesh 	hopsv6 = (uint64_t *)&hopsv4[evt_rsrc->vector_size];
54681476d0fSPavan Nikhilesh 	hops = (uint16_t *)&hopsv6[evt_rsrc->vector_size];
5476cb10a9bSRobin Jarry 	ipv6_arr = (struct rte_ipv6_addr *)&hops[evt_rsrc->vector_size];
54881476d0fSPavan Nikhilesh 
54981476d0fSPavan Nikhilesh 	if (event_p_id < 0) {
55081476d0fSPavan Nikhilesh 		rte_free((void *)mem);
55181476d0fSPavan Nikhilesh 		return;
55281476d0fSPavan Nikhilesh 	}
553e8adca19SShijith Thotton 
554e8adca19SShijith Thotton 	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__,
555e8adca19SShijith Thotton 		rte_lcore_id());
556e8adca19SShijith Thotton 
557e8adca19SShijith Thotton 	while (!force_quit) {
558e8adca19SShijith Thotton 		/* Read events from RX queues. */
559e8adca19SShijith Thotton 		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id, events,
560e8adca19SShijith Thotton 						 deq_len, 0);
561e8adca19SShijith Thotton 		if (nb_deq == 0) {
562e8adca19SShijith Thotton 			rte_pause();
563e8adca19SShijith Thotton 			continue;
564e8adca19SShijith Thotton 		}
565e8adca19SShijith Thotton 
566e8adca19SShijith Thotton 		for (i = 0; i < nb_deq; i++) {
567e8adca19SShijith Thotton 			if (flags & L3FWD_EVENT_TX_ENQ) {
568e8adca19SShijith Thotton 				events[i].queue_id = tx_q_id;
569e8adca19SShijith Thotton 				events[i].op = RTE_EVENT_OP_FORWARD;
570e8adca19SShijith Thotton 			}
571e8adca19SShijith Thotton 
57281476d0fSPavan Nikhilesh 			fib_process_event_vector(events[i].vec, type_arr,
57381476d0fSPavan Nikhilesh 						 ipv6_arr, hopsv4, hopsv6,
57481476d0fSPavan Nikhilesh 						 ipv4_arr, hops);
575e8adca19SShijith Thotton 		}
576e8adca19SShijith Thotton 
577e8adca19SShijith Thotton 		if (flags & L3FWD_EVENT_TX_ENQ) {
578e8adca19SShijith Thotton 			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
579e8adca19SShijith Thotton 							 events, nb_deq);
580e8adca19SShijith Thotton 			while (nb_enq < nb_deq && !force_quit)
581e8adca19SShijith Thotton 				nb_enq += rte_event_enqueue_burst(
582e8adca19SShijith Thotton 					event_d_id, event_p_id, events + nb_enq,
583e8adca19SShijith Thotton 					nb_deq - nb_enq);
584e8adca19SShijith Thotton 		}
585e8adca19SShijith Thotton 
586e8adca19SShijith Thotton 		if (flags & L3FWD_EVENT_TX_DIRECT) {
587e8adca19SShijith Thotton 			nb_enq = rte_event_eth_tx_adapter_enqueue(
588e8adca19SShijith Thotton 				event_d_id, event_p_id, events, nb_deq, 0);
589e8adca19SShijith Thotton 			while (nb_enq < nb_deq && !force_quit)
590e8adca19SShijith Thotton 				nb_enq += rte_event_eth_tx_adapter_enqueue(
591e8adca19SShijith Thotton 					event_d_id, event_p_id, events + nb_enq,
592e8adca19SShijith Thotton 					nb_deq - nb_enq, 0);
593e8adca19SShijith Thotton 		}
594e8adca19SShijith Thotton 	}
59555b22fb3SPavan Nikhilesh 
59655b22fb3SPavan Nikhilesh 	l3fwd_event_worker_cleanup(event_d_id, event_p_id, events, nb_enq,
59755b22fb3SPavan Nikhilesh 				   nb_deq, 1);
59881476d0fSPavan Nikhilesh 	rte_free((void *)mem);
599e8adca19SShijith Thotton }
600e8adca19SShijith Thotton 
601e8adca19SShijith Thotton int __rte_noinline
602e8adca19SShijith Thotton fib_event_main_loop_tx_d_vector(__rte_unused void *dummy)
603e8adca19SShijith Thotton {
604e8adca19SShijith Thotton 	struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
605e8adca19SShijith Thotton 
606e8adca19SShijith Thotton 	fib_event_loop_vector(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
607e8adca19SShijith Thotton 	return 0;
608e8adca19SShijith Thotton }
609e8adca19SShijith Thotton 
610e8adca19SShijith Thotton int __rte_noinline
611e8adca19SShijith Thotton fib_event_main_loop_tx_d_burst_vector(__rte_unused void *dummy)
612e8adca19SShijith Thotton {
613e8adca19SShijith Thotton 	struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
614e8adca19SShijith Thotton 
615e8adca19SShijith Thotton 	fib_event_loop_vector(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
616e8adca19SShijith Thotton 	return 0;
617e8adca19SShijith Thotton }
618e8adca19SShijith Thotton 
619e8adca19SShijith Thotton int __rte_noinline
620e8adca19SShijith Thotton fib_event_main_loop_tx_q_vector(__rte_unused void *dummy)
621e8adca19SShijith Thotton {
622e8adca19SShijith Thotton 	struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
623e8adca19SShijith Thotton 
624e8adca19SShijith Thotton 	fib_event_loop_vector(evt_rsrc, L3FWD_EVENT_TX_ENQ);
625e8adca19SShijith Thotton 	return 0;
626e8adca19SShijith Thotton }
627e8adca19SShijith Thotton 
628e8adca19SShijith Thotton int __rte_noinline
629e8adca19SShijith Thotton fib_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy)
630e8adca19SShijith Thotton {
631e8adca19SShijith Thotton 	struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
632e8adca19SShijith Thotton 
633e8adca19SShijith Thotton 	fib_event_loop_vector(evt_rsrc, L3FWD_EVENT_TX_ENQ);
634e8adca19SShijith Thotton 	return 0;
635e8adca19SShijith Thotton }
636ef827078SBruce Richardson #endif
637e8adca19SShijith Thotton 
6389a212dc0SConor Fogarty /* Function to setup fib. 8< */
6399510dd1fSConor Walsh void
6406a094e32SConor Walsh setup_fib(const int socketid)
6416a094e32SConor Walsh {
642fc89b4c8SPavan Nikhilesh 	struct rte_eth_dev_info dev_info;
6436a094e32SConor Walsh 	struct rte_fib6_conf config;
644e194f3cdSVladimir Medvedkin 	struct rte_fib_conf config_ipv4 = { 0 };
64552def963SSean Morrissey 	int i;
6466a094e32SConor Walsh 	int ret;
6476a094e32SConor Walsh 	char s[64];
6486a094e32SConor Walsh 	char abuf[INET6_ADDRSTRLEN];
6496a094e32SConor Walsh 
6506a094e32SConor Walsh 	/* Create the fib IPv4 table. */
6516a094e32SConor Walsh 	config_ipv4.type = RTE_FIB_DIR24_8;
6526a094e32SConor Walsh 	config_ipv4.max_routes = (1 << 16);
65311c5b9b5SVladimir Medvedkin 	config_ipv4.rib_ext_sz = 0;
6546a094e32SConor Walsh 	config_ipv4.default_nh = FIB_DEFAULT_HOP;
6556a094e32SConor Walsh 	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
6566a094e32SConor Walsh 	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
6576a094e32SConor Walsh 	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
6586a094e32SConor Walsh 	ipv4_l3fwd_fib_lookup_struct[socketid] =
6596a094e32SConor Walsh 			rte_fib_create(s, socketid, &config_ipv4);
6606a094e32SConor Walsh 	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
6616a094e32SConor Walsh 		rte_exit(EXIT_FAILURE,
6626a094e32SConor Walsh 			"Unable to create the l3fwd FIB table on socket %d\n",
6636a094e32SConor Walsh 			socketid);
6646a094e32SConor Walsh 
66552def963SSean Morrissey 
6666a094e32SConor Walsh 	/* Populate the fib ipv4 table. */
66752def963SSean Morrissey 	for (i = 0; i < route_num_v4; i++) {
6686a094e32SConor Walsh 		struct in_addr in;
6696a094e32SConor Walsh 
6706a094e32SConor Walsh 		/* Skip unused ports. */
67152def963SSean Morrissey 		if ((1 << route_base_v4[i].if_out &
6726a094e32SConor Walsh 				enabled_port_mask) == 0)
6736a094e32SConor Walsh 			continue;
6746a094e32SConor Walsh 
675a937954eSStephen Hemminger 		ret = rte_eth_dev_info_get(route_base_v4[i].if_out, &dev_info);
676a937954eSStephen Hemminger 		if (ret < 0)
677a937954eSStephen Hemminger 			rte_exit(EXIT_FAILURE,
678a937954eSStephen Hemminger 				 "Unable to get device info for port %u\n",
679a937954eSStephen Hemminger 				 route_base_v4[i].if_out);
680a937954eSStephen Hemminger 
6816a094e32SConor Walsh 		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
68252def963SSean Morrissey 			route_base_v4[i].ip,
68352def963SSean Morrissey 			route_base_v4[i].depth,
68452def963SSean Morrissey 			route_base_v4[i].if_out);
6856a094e32SConor Walsh 
6866a094e32SConor Walsh 		if (ret < 0) {
68752def963SSean Morrissey 			free(route_base_v4);
6886a094e32SConor Walsh 			rte_exit(EXIT_FAILURE,
6896a094e32SConor Walsh 					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
6906a094e32SConor Walsh 					i, socketid);
6916a094e32SConor Walsh 		}
6926a094e32SConor Walsh 
69352def963SSean Morrissey 		in.s_addr = htonl(route_base_v4[i].ip);
6946a094e32SConor Walsh 		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
695fc89b4c8SPavan Nikhilesh 			printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
69652def963SSean Morrissey 			       route_base_v4[i].depth,
69752def963SSean Morrissey 			       route_base_v4[i].if_out,
698ec5ecd7eSDavid Marchand 			       rte_dev_name(dev_info.device));
6996a094e32SConor Walsh 		} else {
700fc89b4c8SPavan Nikhilesh 			printf("FIB: IPv4 route added to port %d [%s]\n",
70152def963SSean Morrissey 			       route_base_v4[i].if_out,
702ec5ecd7eSDavid Marchand 			       rte_dev_name(dev_info.device));
7036a094e32SConor Walsh 		}
7046a094e32SConor Walsh 	}
7059a212dc0SConor Fogarty 	/* >8 End of setup fib. */
7066a094e32SConor Walsh 
7076a094e32SConor Walsh 	/* Create the fib IPv6 table. */
7086a094e32SConor Walsh 	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
7096a094e32SConor Walsh 
7106a094e32SConor Walsh 	config.type = RTE_FIB6_TRIE;
7116a094e32SConor Walsh 	config.max_routes = (1 << 16) - 1;
71211c5b9b5SVladimir Medvedkin 	config.rib_ext_sz = 0;
7136a094e32SConor Walsh 	config.default_nh = FIB_DEFAULT_HOP;
7146a094e32SConor Walsh 	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
7156a094e32SConor Walsh 	config.trie.num_tbl8 = (1 << 15);
7166a094e32SConor Walsh 	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
7176a094e32SConor Walsh 			&config);
71852def963SSean Morrissey 	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL) {
71952def963SSean Morrissey 		free(route_base_v4);
7206a094e32SConor Walsh 		rte_exit(EXIT_FAILURE,
7216a094e32SConor Walsh 				"Unable to create the l3fwd FIB table on socket %d\n",
7226a094e32SConor Walsh 				socketid);
72352def963SSean Morrissey 	}
7246a094e32SConor Walsh 
7256a094e32SConor Walsh 	/* Populate the fib IPv6 table. */
72652def963SSean Morrissey 	for (i = 0; i < route_num_v6; i++) {
7276a094e32SConor Walsh 
7286a094e32SConor Walsh 		/* Skip unused ports. */
72952def963SSean Morrissey 		if ((1 << route_base_v6[i].if_out &
7306a094e32SConor Walsh 				enabled_port_mask) == 0)
7316a094e32SConor Walsh 			continue;
7326a094e32SConor Walsh 
733a937954eSStephen Hemminger 		ret = rte_eth_dev_info_get(route_base_v6[i].if_out, &dev_info);
734a937954eSStephen Hemminger 		if (ret < 0)
735a937954eSStephen Hemminger 			rte_exit(EXIT_FAILURE,
736a937954eSStephen Hemminger 				 "Unable to get device info for port %u\n",
737a937954eSStephen Hemminger 				 route_base_v6[i].if_out);
738a937954eSStephen Hemminger 
7396a094e32SConor Walsh 		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
7406cb10a9bSRobin Jarry 			&route_base_v6[i].ip6,
74152def963SSean Morrissey 			route_base_v6[i].depth,
74252def963SSean Morrissey 			route_base_v6[i].if_out);
7436a094e32SConor Walsh 
7446a094e32SConor Walsh 		if (ret < 0) {
74552def963SSean Morrissey 			free(route_base_v4);
74652def963SSean Morrissey 			free(route_base_v6);
7476a094e32SConor Walsh 			rte_exit(EXIT_FAILURE,
7486a094e32SConor Walsh 					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
7496a094e32SConor Walsh 					i, socketid);
7506a094e32SConor Walsh 		}
7516a094e32SConor Walsh 
7526cb10a9bSRobin Jarry 		if (inet_ntop(AF_INET6, &route_base_v6[i].ip6,
7536a094e32SConor Walsh 				abuf, sizeof(abuf)) != NULL) {
754fc89b4c8SPavan Nikhilesh 			printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
75552def963SSean Morrissey 			       route_base_v6[i].depth,
75652def963SSean Morrissey 			       route_base_v6[i].if_out,
757ec5ecd7eSDavid Marchand 			       rte_dev_name(dev_info.device));
7586a094e32SConor Walsh 		} else {
759fc89b4c8SPavan Nikhilesh 			printf("FIB: IPv6 route added to port %d [%s]\n",
76052def963SSean Morrissey 			       route_base_v6[i].if_out,
761ec5ecd7eSDavid Marchand 			       rte_dev_name(dev_info.device));
7626a094e32SConor Walsh 		}
7636a094e32SConor Walsh 	}
7646a094e32SConor Walsh }
7659510dd1fSConor Walsh 
7669510dd1fSConor Walsh /* Return ipv4 fib lookup struct. */
7679510dd1fSConor Walsh void *
7686a094e32SConor Walsh fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
7699510dd1fSConor Walsh {
7706a094e32SConor Walsh 	return ipv4_l3fwd_fib_lookup_struct[socketid];
7719510dd1fSConor Walsh }
7729510dd1fSConor Walsh 
7739510dd1fSConor Walsh /* Return ipv6 fib lookup struct. */
7749510dd1fSConor Walsh void *
7756a094e32SConor Walsh fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
7769510dd1fSConor Walsh {
7776a094e32SConor Walsh 	return ipv6_l3fwd_fib_lookup_struct[socketid];
7789510dd1fSConor Walsh }
779