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