xref: /dpdk/lib/lpm/rte_lpm.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
399a2dd95SBruce Richardson  * Copyright(c) 2020 Arm Limited
499a2dd95SBruce Richardson  */
599a2dd95SBruce Richardson 
699a2dd95SBruce Richardson #ifndef _RTE_LPM_H_
799a2dd95SBruce Richardson #define _RTE_LPM_H_
899a2dd95SBruce Richardson 
999a2dd95SBruce Richardson /**
1099a2dd95SBruce Richardson  * @file
1199a2dd95SBruce Richardson  * RTE Longest Prefix Match (LPM)
1299a2dd95SBruce Richardson  */
1399a2dd95SBruce Richardson 
1499a2dd95SBruce Richardson #include <errno.h>
15e9fd1ebfSTyler Retzlaff #include <stdalign.h>
1699a2dd95SBruce Richardson #include <stdint.h>
170cfa3ee6SStephen Hemminger 
1899a2dd95SBruce Richardson #include <rte_branch_prediction.h>
1999a2dd95SBruce Richardson #include <rte_byteorder.h>
2099a2dd95SBruce Richardson #include <rte_common.h>
2199a2dd95SBruce Richardson #include <rte_vect.h>
2299a2dd95SBruce Richardson #include <rte_rcu_qsbr.h>
2399a2dd95SBruce Richardson 
2499a2dd95SBruce Richardson #ifdef __cplusplus
2599a2dd95SBruce Richardson extern "C" {
2699a2dd95SBruce Richardson #endif
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson /** Max number of characters in LPM name. */
2999a2dd95SBruce Richardson #define RTE_LPM_NAMESIZE                32
3099a2dd95SBruce Richardson 
3199a2dd95SBruce Richardson /** Maximum depth value possible for IPv4 LPM. */
3299a2dd95SBruce Richardson #define RTE_LPM_MAX_DEPTH               32
3399a2dd95SBruce Richardson 
3499a2dd95SBruce Richardson /** @internal Total number of tbl24 entries. */
3599a2dd95SBruce Richardson #define RTE_LPM_TBL24_NUM_ENTRIES       (1 << 24)
3699a2dd95SBruce Richardson 
3799a2dd95SBruce Richardson /** @internal Number of entries in a tbl8 group. */
3899a2dd95SBruce Richardson #define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256
3999a2dd95SBruce Richardson 
4099a2dd95SBruce Richardson /** @internal Max number of tbl8 groups in the tbl8. */
4199a2dd95SBruce Richardson #define RTE_LPM_MAX_TBL8_NUM_GROUPS         (1 << 24)
4299a2dd95SBruce Richardson 
4399a2dd95SBruce Richardson /** @internal Total number of tbl8 groups in the tbl8. */
4499a2dd95SBruce Richardson #define RTE_LPM_TBL8_NUM_GROUPS         256
4599a2dd95SBruce Richardson 
4699a2dd95SBruce Richardson /** @internal Total number of tbl8 entries. */
4799a2dd95SBruce Richardson #define RTE_LPM_TBL8_NUM_ENTRIES        (RTE_LPM_TBL8_NUM_GROUPS * \
4899a2dd95SBruce Richardson 					RTE_LPM_TBL8_GROUP_NUM_ENTRIES)
4999a2dd95SBruce Richardson 
5099a2dd95SBruce Richardson /** @internal Macro to enable/disable run-time checks. */
5199a2dd95SBruce Richardson #if defined(RTE_LIBRTE_LPM_DEBUG)
5299a2dd95SBruce Richardson #define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \
5399a2dd95SBruce Richardson 	if (cond) return (retval);                \
5499a2dd95SBruce Richardson } while (0)
5599a2dd95SBruce Richardson #else
5699a2dd95SBruce Richardson #define RTE_LPM_RETURN_IF_TRUE(cond, retval)
5799a2dd95SBruce Richardson #endif
5899a2dd95SBruce Richardson 
5999a2dd95SBruce Richardson /** @internal bitmask with valid and valid_group fields set */
6099a2dd95SBruce Richardson #define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03000000
6199a2dd95SBruce Richardson 
6299a2dd95SBruce Richardson /** Bitmask used to indicate successful lookup */
6399a2dd95SBruce Richardson #define RTE_LPM_LOOKUP_SUCCESS          0x01000000
6499a2dd95SBruce Richardson 
6599a2dd95SBruce Richardson /** @internal Default RCU defer queue entries to reclaim in one go. */
6699a2dd95SBruce Richardson #define RTE_LPM_RCU_DQ_RECLAIM_MAX	16
6799a2dd95SBruce Richardson 
6899a2dd95SBruce Richardson /** RCU reclamation modes */
6999a2dd95SBruce Richardson enum rte_lpm_qsbr_mode {
7099a2dd95SBruce Richardson 	/** Create defer queue for reclaim. */
7199a2dd95SBruce Richardson 	RTE_LPM_QSBR_MODE_DQ = 0,
7299a2dd95SBruce Richardson 	/** Use blocking mode reclaim. No defer queue created. */
7399a2dd95SBruce Richardson 	RTE_LPM_QSBR_MODE_SYNC
7499a2dd95SBruce Richardson };
7599a2dd95SBruce Richardson 
7699a2dd95SBruce Richardson #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7799a2dd95SBruce Richardson /** @internal Tbl24 entry structure. */
7899a2dd95SBruce Richardson __extension__
7999a2dd95SBruce Richardson struct rte_lpm_tbl_entry {
8099a2dd95SBruce Richardson 	/**
8199a2dd95SBruce Richardson 	 * Stores Next hop (tbl8 or tbl24 when valid_group is not set) or
8299a2dd95SBruce Richardson 	 * a group index pointing to a tbl8 structure (tbl24 only, when
8399a2dd95SBruce Richardson 	 * valid_group is set)
8499a2dd95SBruce Richardson 	 */
8599a2dd95SBruce Richardson 	uint32_t next_hop    :24;
8699a2dd95SBruce Richardson 	/* Using single uint8_t to store 3 values. */
8799a2dd95SBruce Richardson 	uint32_t valid       :1;   /**< Validation flag. */
8899a2dd95SBruce Richardson 	/**
8999a2dd95SBruce Richardson 	 * For tbl24:
9099a2dd95SBruce Richardson 	 *  - valid_group == 0: entry stores a next hop
9199a2dd95SBruce Richardson 	 *  - valid_group == 1: entry stores a group_index pointing to a tbl8
9299a2dd95SBruce Richardson 	 * For tbl8:
9399a2dd95SBruce Richardson 	 *  - valid_group indicates whether the current tbl8 is in use or not
9499a2dd95SBruce Richardson 	 */
9599a2dd95SBruce Richardson 	uint32_t valid_group :1;
9699a2dd95SBruce Richardson 	uint32_t depth       :6; /**< Rule depth. */
9799a2dd95SBruce Richardson };
9899a2dd95SBruce Richardson 
9999a2dd95SBruce Richardson #else
10099a2dd95SBruce Richardson 
10199a2dd95SBruce Richardson __extension__
10299a2dd95SBruce Richardson struct rte_lpm_tbl_entry {
10399a2dd95SBruce Richardson 	uint32_t depth       :6;
10499a2dd95SBruce Richardson 	uint32_t valid_group :1;
10599a2dd95SBruce Richardson 	uint32_t valid       :1;
10699a2dd95SBruce Richardson 	uint32_t next_hop    :24;
10799a2dd95SBruce Richardson 
10899a2dd95SBruce Richardson };
10999a2dd95SBruce Richardson 
11099a2dd95SBruce Richardson #endif
11199a2dd95SBruce Richardson 
11299a2dd95SBruce Richardson /** LPM configuration structure. */
11399a2dd95SBruce Richardson struct rte_lpm_config {
11499a2dd95SBruce Richardson 	uint32_t max_rules;      /**< Max number of rules. */
11599a2dd95SBruce Richardson 	uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
11699a2dd95SBruce Richardson 	int flags;               /**< This field is currently unused. */
11799a2dd95SBruce Richardson };
11899a2dd95SBruce Richardson 
11999a2dd95SBruce Richardson /** @internal LPM structure. */
12099a2dd95SBruce Richardson struct rte_lpm {
12199a2dd95SBruce Richardson 	/* LPM Tables. */
122e9fd1ebfSTyler Retzlaff 	alignas(RTE_CACHE_LINE_SIZE) struct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES];
123e9fd1ebfSTyler Retzlaff 			/**< LPM tbl24 table. */
12499a2dd95SBruce Richardson 	struct rte_lpm_tbl_entry *tbl8; /**< LPM tbl8 table. */
12599a2dd95SBruce Richardson };
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson /** LPM RCU QSBR configuration structure. */
12899a2dd95SBruce Richardson struct rte_lpm_rcu_config {
12999a2dd95SBruce Richardson 	struct rte_rcu_qsbr *v;	/* RCU QSBR variable. */
13099a2dd95SBruce Richardson 	/* Mode of RCU QSBR. RTE_LPM_QSBR_MODE_xxx
13199a2dd95SBruce Richardson 	 * '0' for default: create defer queue for reclaim.
13299a2dd95SBruce Richardson 	 */
13399a2dd95SBruce Richardson 	enum rte_lpm_qsbr_mode mode;
13499a2dd95SBruce Richardson 	uint32_t dq_size;	/* RCU defer queue size.
13599a2dd95SBruce Richardson 				 * default: lpm->number_tbl8s.
13699a2dd95SBruce Richardson 				 */
13799a2dd95SBruce Richardson 	uint32_t reclaim_thd;	/* Threshold to trigger auto reclaim. */
13899a2dd95SBruce Richardson 	uint32_t reclaim_max;	/* Max entries to reclaim in one go.
13999a2dd95SBruce Richardson 				 * default: RTE_LPM_RCU_DQ_RECLAIM_MAX.
14099a2dd95SBruce Richardson 				 */
14199a2dd95SBruce Richardson };
14299a2dd95SBruce Richardson 
14399a2dd95SBruce Richardson /**
14499a2dd95SBruce Richardson  * Create an LPM object.
14599a2dd95SBruce Richardson  *
14699a2dd95SBruce Richardson  * @param name
14799a2dd95SBruce Richardson  *   LPM object name
14899a2dd95SBruce Richardson  * @param socket_id
14999a2dd95SBruce Richardson  *   NUMA socket ID for LPM table memory allocation
15099a2dd95SBruce Richardson  * @param config
15199a2dd95SBruce Richardson  *   Structure containing the configuration
15299a2dd95SBruce Richardson  * @return
15399a2dd95SBruce Richardson  *   Handle to LPM object on success, NULL otherwise with rte_errno set
15499a2dd95SBruce Richardson  *   to an appropriate values. Possible rte_errno values include:
15599a2dd95SBruce Richardson  *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
15699a2dd95SBruce Richardson  *    - E_RTE_SECONDARY - function was called from a secondary process instance
15799a2dd95SBruce Richardson  *    - EINVAL - invalid parameter passed to function
15899a2dd95SBruce Richardson  *    - ENOSPC - the maximum number of memzones has already been allocated
15999a2dd95SBruce Richardson  *    - EEXIST - a memzone with the same name already exists
16099a2dd95SBruce Richardson  *    - ENOMEM - no appropriate memory area found in which to create memzone
16199a2dd95SBruce Richardson  */
16299a2dd95SBruce Richardson struct rte_lpm *
16399a2dd95SBruce Richardson rte_lpm_create(const char *name, int socket_id,
16499a2dd95SBruce Richardson 		const struct rte_lpm_config *config);
16599a2dd95SBruce Richardson 
16699a2dd95SBruce Richardson /**
16799a2dd95SBruce Richardson  * Find an existing LPM object and return a pointer to it.
16899a2dd95SBruce Richardson  *
16999a2dd95SBruce Richardson  * @param name
17099a2dd95SBruce Richardson  *   Name of the lpm object as passed to rte_lpm_create()
17199a2dd95SBruce Richardson  * @return
17299a2dd95SBruce Richardson  *   Pointer to lpm object or NULL if object not found with rte_errno
17399a2dd95SBruce Richardson  *   set appropriately. Possible rte_errno values include:
17499a2dd95SBruce Richardson  *    - ENOENT - required entry not available to return.
17599a2dd95SBruce Richardson  */
17699a2dd95SBruce Richardson struct rte_lpm *
17799a2dd95SBruce Richardson rte_lpm_find_existing(const char *name);
17899a2dd95SBruce Richardson 
17999a2dd95SBruce Richardson /**
18099a2dd95SBruce Richardson  * Free an LPM object.
18199a2dd95SBruce Richardson  *
18299a2dd95SBruce Richardson  * @param lpm
18399a2dd95SBruce Richardson  *   LPM object handle
184448e01f1SStephen Hemminger  *   If lpm is NULL, no operation is performed.
18599a2dd95SBruce Richardson  */
18699a2dd95SBruce Richardson void
18799a2dd95SBruce Richardson rte_lpm_free(struct rte_lpm *lpm);
18899a2dd95SBruce Richardson 
18999a2dd95SBruce Richardson /**
19099a2dd95SBruce Richardson  * Associate RCU QSBR variable with an LPM object.
19199a2dd95SBruce Richardson  *
19299a2dd95SBruce Richardson  * @param lpm
19399a2dd95SBruce Richardson  *   the lpm object to add RCU QSBR
19499a2dd95SBruce Richardson  * @param cfg
19599a2dd95SBruce Richardson  *   RCU QSBR configuration
19699a2dd95SBruce Richardson  * @return
19799a2dd95SBruce Richardson  *   On success - 0
19899a2dd95SBruce Richardson  *   On error - 1 with error code set in rte_errno.
19999a2dd95SBruce Richardson  *   Possible rte_errno codes are:
20099a2dd95SBruce Richardson  *   - EINVAL - invalid pointer
20199a2dd95SBruce Richardson  *   - EEXIST - already added QSBR
20299a2dd95SBruce Richardson  *   - ENOMEM - memory allocation failure
20399a2dd95SBruce Richardson  */
20499a2dd95SBruce Richardson int rte_lpm_rcu_qsbr_add(struct rte_lpm *lpm, struct rte_lpm_rcu_config *cfg);
20599a2dd95SBruce Richardson 
20699a2dd95SBruce Richardson /**
20799a2dd95SBruce Richardson  * Add a rule to the LPM table.
20899a2dd95SBruce Richardson  *
20999a2dd95SBruce Richardson  * @param lpm
21099a2dd95SBruce Richardson  *   LPM object handle
21199a2dd95SBruce Richardson  * @param ip
21299a2dd95SBruce Richardson  *   IP of the rule to be added to the LPM table
21399a2dd95SBruce Richardson  * @param depth
21499a2dd95SBruce Richardson  *   Depth of the rule to be added to the LPM table
21599a2dd95SBruce Richardson  * @param next_hop
21699a2dd95SBruce Richardson  *   Next hop of the rule to be added to the LPM table
21799a2dd95SBruce Richardson  * @return
21899a2dd95SBruce Richardson  *   0 on success, negative value otherwise
21999a2dd95SBruce Richardson  */
22099a2dd95SBruce Richardson int
22199a2dd95SBruce Richardson rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint32_t next_hop);
22299a2dd95SBruce Richardson 
22399a2dd95SBruce Richardson /**
22499a2dd95SBruce Richardson  * Check if a rule is present in the LPM table,
22599a2dd95SBruce Richardson  * and provide its next hop if it is.
22699a2dd95SBruce Richardson  *
22799a2dd95SBruce Richardson  * @param lpm
22899a2dd95SBruce Richardson  *   LPM object handle
22999a2dd95SBruce Richardson  * @param ip
23099a2dd95SBruce Richardson  *   IP of the rule to be searched
23199a2dd95SBruce Richardson  * @param depth
23299a2dd95SBruce Richardson  *   Depth of the rule to searched
23399a2dd95SBruce Richardson  * @param next_hop
23499a2dd95SBruce Richardson  *   Next hop of the rule (valid only if it is found)
23599a2dd95SBruce Richardson  * @return
23699a2dd95SBruce Richardson  *   1 if the rule exists, 0 if it does not, a negative value on failure
23799a2dd95SBruce Richardson  */
23899a2dd95SBruce Richardson int
23999a2dd95SBruce Richardson rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
24099a2dd95SBruce Richardson uint32_t *next_hop);
24199a2dd95SBruce Richardson 
24299a2dd95SBruce Richardson /**
24399a2dd95SBruce Richardson  * Delete a rule from the LPM table.
24499a2dd95SBruce Richardson  *
24599a2dd95SBruce Richardson  * @param lpm
24699a2dd95SBruce Richardson  *   LPM object handle
24799a2dd95SBruce Richardson  * @param ip
24899a2dd95SBruce Richardson  *   IP of the rule to be deleted from the LPM table
24999a2dd95SBruce Richardson  * @param depth
25099a2dd95SBruce Richardson  *   Depth of the rule to be deleted from the LPM table
25199a2dd95SBruce Richardson  * @return
25299a2dd95SBruce Richardson  *   0 on success, negative value otherwise
25399a2dd95SBruce Richardson  */
25499a2dd95SBruce Richardson int
25599a2dd95SBruce Richardson rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
25699a2dd95SBruce Richardson 
25799a2dd95SBruce Richardson /**
25899a2dd95SBruce Richardson  * Delete all rules from the LPM table.
25999a2dd95SBruce Richardson  *
26099a2dd95SBruce Richardson  * @param lpm
26199a2dd95SBruce Richardson  *   LPM object handle
26299a2dd95SBruce Richardson  */
26399a2dd95SBruce Richardson void
26499a2dd95SBruce Richardson rte_lpm_delete_all(struct rte_lpm *lpm);
26599a2dd95SBruce Richardson 
26699a2dd95SBruce Richardson /**
26799a2dd95SBruce Richardson  * Lookup an IP into the LPM table.
26899a2dd95SBruce Richardson  *
26999a2dd95SBruce Richardson  * @param lpm
27099a2dd95SBruce Richardson  *   LPM object handle
27199a2dd95SBruce Richardson  * @param ip
27299a2dd95SBruce Richardson  *   IP to be looked up in the LPM table
27399a2dd95SBruce Richardson  * @param next_hop
27499a2dd95SBruce Richardson  *   Next hop of the most specific rule found for IP (valid on lookup hit only)
27599a2dd95SBruce Richardson  * @return
27699a2dd95SBruce Richardson  *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
27799a2dd95SBruce Richardson  */
27899a2dd95SBruce Richardson static inline int
2794036de27SStanislaw Kardach rte_lpm_lookup(const struct rte_lpm *lpm, uint32_t ip, uint32_t *next_hop)
28099a2dd95SBruce Richardson {
28199a2dd95SBruce Richardson 	unsigned tbl24_index = (ip >> 8);
28299a2dd95SBruce Richardson 	uint32_t tbl_entry;
28399a2dd95SBruce Richardson 	const uint32_t *ptbl;
28499a2dd95SBruce Richardson 
28599a2dd95SBruce Richardson 	/* DEBUG: Check user input arguments. */
28699a2dd95SBruce Richardson 	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
28799a2dd95SBruce Richardson 
28899a2dd95SBruce Richardson 	/* Copy tbl24 entry */
28999a2dd95SBruce Richardson 	ptbl = (const uint32_t *)(&lpm->tbl24[tbl24_index]);
29099a2dd95SBruce Richardson 	tbl_entry = *ptbl;
29199a2dd95SBruce Richardson 
29299a2dd95SBruce Richardson 	/* Memory ordering is not required in lookup. Because dataflow
29399a2dd95SBruce Richardson 	 * dependency exists, compiler or HW won't be able to re-order
29499a2dd95SBruce Richardson 	 * the operations.
29599a2dd95SBruce Richardson 	 */
29699a2dd95SBruce Richardson 	/* Copy tbl8 entry (only if needed) */
29799a2dd95SBruce Richardson 	if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
29899a2dd95SBruce Richardson 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
29999a2dd95SBruce Richardson 
30099a2dd95SBruce Richardson 		unsigned tbl8_index = (uint8_t)ip +
30199a2dd95SBruce Richardson 				(((uint32_t)tbl_entry & 0x00FFFFFF) *
30299a2dd95SBruce Richardson 						RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
30399a2dd95SBruce Richardson 
30499a2dd95SBruce Richardson 		ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
30599a2dd95SBruce Richardson 		tbl_entry = *ptbl;
30699a2dd95SBruce Richardson 	}
30799a2dd95SBruce Richardson 
30899a2dd95SBruce Richardson 	*next_hop = ((uint32_t)tbl_entry & 0x00FFFFFF);
30999a2dd95SBruce Richardson 	return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;
31099a2dd95SBruce Richardson }
31199a2dd95SBruce Richardson 
31299a2dd95SBruce Richardson /**
31399a2dd95SBruce Richardson  * Lookup multiple IP addresses in an LPM table. This may be implemented as a
31499a2dd95SBruce Richardson  * macro, so the address of the function should not be used.
31599a2dd95SBruce Richardson  *
31699a2dd95SBruce Richardson  * @param lpm
31799a2dd95SBruce Richardson  *   LPM object handle
31899a2dd95SBruce Richardson  * @param ips
31999a2dd95SBruce Richardson  *   Array of IPs to be looked up in the LPM table
32099a2dd95SBruce Richardson  * @param next_hops
32199a2dd95SBruce Richardson  *   Next hop of the most specific rule found for IP (valid on lookup hit only).
32299a2dd95SBruce Richardson  *   This is an array of two byte values. The most significant byte in each
32399a2dd95SBruce Richardson  *   value says whether the lookup was successful (bitmask
32499a2dd95SBruce Richardson  *   RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the
32599a2dd95SBruce Richardson  *   actual next hop.
32699a2dd95SBruce Richardson  * @param n
32799a2dd95SBruce Richardson  *   Number of elements in ips (and next_hops) array to lookup. This should be a
32899a2dd95SBruce Richardson  *   compile time constant, and divisible by 8 for best performance.
32999a2dd95SBruce Richardson  *  @return
33099a2dd95SBruce Richardson  *   -EINVAL for incorrect arguments, otherwise 0
33199a2dd95SBruce Richardson  */
33299a2dd95SBruce Richardson #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
33399a2dd95SBruce Richardson 		rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)
33499a2dd95SBruce Richardson 
33599a2dd95SBruce Richardson static inline int
33699a2dd95SBruce Richardson rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,
33799a2dd95SBruce Richardson 		uint32_t *next_hops, const unsigned n)
33899a2dd95SBruce Richardson {
33999a2dd95SBruce Richardson 	unsigned i;
34099a2dd95SBruce Richardson 	const uint32_t *ptbl;
34199a2dd95SBruce Richardson 
34299a2dd95SBruce Richardson 	/* DEBUG: Check user input arguments. */
34399a2dd95SBruce Richardson 	RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||
34499a2dd95SBruce Richardson 			(next_hops == NULL)), -EINVAL);
34599a2dd95SBruce Richardson 
34699a2dd95SBruce Richardson 	for (i = 0; i < n; i++) {
3472e306a09SStephen Hemminger 		unsigned int tbl24_index = ips[i] >> 8;
34899a2dd95SBruce Richardson 
34999a2dd95SBruce Richardson 		/* Simply copy tbl24 entry to output */
3502e306a09SStephen Hemminger 		ptbl = (const uint32_t *)&lpm->tbl24[tbl24_index];
35199a2dd95SBruce Richardson 		next_hops[i] = *ptbl;
35299a2dd95SBruce Richardson 
35399a2dd95SBruce Richardson 		/* Overwrite output with tbl8 entry if needed */
35499a2dd95SBruce Richardson 		if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
35599a2dd95SBruce Richardson 				RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
35699a2dd95SBruce Richardson 
35799a2dd95SBruce Richardson 			unsigned tbl8_index = (uint8_t)ips[i] +
35899a2dd95SBruce Richardson 					(((uint32_t)next_hops[i] & 0x00FFFFFF) *
35999a2dd95SBruce Richardson 					 RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
36099a2dd95SBruce Richardson 
36199a2dd95SBruce Richardson 			ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
36299a2dd95SBruce Richardson 			next_hops[i] = *ptbl;
36399a2dd95SBruce Richardson 		}
36499a2dd95SBruce Richardson 	}
36599a2dd95SBruce Richardson 	return 0;
36699a2dd95SBruce Richardson }
36799a2dd95SBruce Richardson 
36899a2dd95SBruce Richardson /* Mask four results. */
36999a2dd95SBruce Richardson #define	 RTE_LPM_MASKX4_RES	UINT64_C(0x00ffffff00ffffff)
37099a2dd95SBruce Richardson 
37199a2dd95SBruce Richardson /**
37299a2dd95SBruce Richardson  * Lookup four IP addresses in an LPM table.
37399a2dd95SBruce Richardson  *
37499a2dd95SBruce Richardson  * @param lpm
37599a2dd95SBruce Richardson  *   LPM object handle
37699a2dd95SBruce Richardson  * @param ip
37799a2dd95SBruce Richardson  *   Four IPs to be looked up in the LPM table
37899a2dd95SBruce Richardson  * @param hop
37999a2dd95SBruce Richardson  *   Next hop of the most specific rule found for IP (valid on lookup hit only).
38099a2dd95SBruce Richardson  *   This is an 4 elements array of two byte values.
38199a2dd95SBruce Richardson  *   If the lookup was successful for the given IP, then least significant byte
38299a2dd95SBruce Richardson  *   of the corresponding element is the  actual next hop and the most
38399a2dd95SBruce Richardson  *   significant byte is zero.
38499a2dd95SBruce Richardson  *   If the lookup for the given IP failed, then corresponding element would
38599a2dd95SBruce Richardson  *   contain default value, see description of then next parameter.
38699a2dd95SBruce Richardson  * @param defv
38799a2dd95SBruce Richardson  *   Default value to populate into corresponding element of hop[] array,
38899a2dd95SBruce Richardson  *   if lookup would fail.
38999a2dd95SBruce Richardson  */
39099a2dd95SBruce Richardson static inline void
39199a2dd95SBruce Richardson rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
39299a2dd95SBruce Richardson 	uint32_t defv);
39399a2dd95SBruce Richardson 
394*719834a6SMattias Rönnblom #ifdef __cplusplus
395*719834a6SMattias Rönnblom }
396*719834a6SMattias Rönnblom #endif
397*719834a6SMattias Rönnblom 
39899a2dd95SBruce Richardson #if defined(RTE_ARCH_ARM)
3995aa9189dSChengwen Feng #ifdef RTE_HAS_SVE_ACLE
40099a2dd95SBruce Richardson #include "rte_lpm_sve.h"
401b29ccbeaSRuifeng Wang #undef rte_lpm_lookup_bulk
402b29ccbeaSRuifeng Wang #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
403b29ccbeaSRuifeng Wang 		__rte_lpm_lookup_vec(lpm, ips, next_hops, n)
40499a2dd95SBruce Richardson #endif
405b29ccbeaSRuifeng Wang #include "rte_lpm_neon.h"
40699a2dd95SBruce Richardson #elif defined(RTE_ARCH_PPC_64)
40799a2dd95SBruce Richardson #include "rte_lpm_altivec.h"
408406937f8SMichal Mazurek #elif defined(RTE_ARCH_X86)
40999a2dd95SBruce Richardson #include "rte_lpm_sse.h"
410406937f8SMichal Mazurek #else
411406937f8SMichal Mazurek #include "rte_lpm_scalar.h"
41299a2dd95SBruce Richardson #endif
41399a2dd95SBruce Richardson 
41499a2dd95SBruce Richardson #endif /* _RTE_LPM_H_ */
415