xref: /dpdk/lib/fib/dir24_8.h (revision 96c3d06a354753cdef9177e0c204c2e9361f31d5)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
399a2dd95SBruce Richardson  * Copyright(c) 2019 Intel Corporation
499a2dd95SBruce Richardson  */
599a2dd95SBruce Richardson 
699a2dd95SBruce Richardson #ifndef _DIR24_8_H_
799a2dd95SBruce Richardson #define _DIR24_8_H_
899a2dd95SBruce Richardson 
9e9fd1ebfSTyler Retzlaff #include <stdalign.h>
10e194f3cdSVladimir Medvedkin #include <stdbool.h>
11e9fd1ebfSTyler Retzlaff 
12e194f3cdSVladimir Medvedkin #include <rte_byteorder.h>
1399a2dd95SBruce Richardson #include <rte_prefetch.h>
1499a2dd95SBruce Richardson #include <rte_branch_prediction.h>
15*96c3d06aSVladimir Medvedkin #include <rte_rcu_qsbr.h>
1699a2dd95SBruce Richardson 
1799a2dd95SBruce Richardson /**
1899a2dd95SBruce Richardson  * @file
1999a2dd95SBruce Richardson  * DIR24_8 algorithm
2099a2dd95SBruce Richardson  */
2199a2dd95SBruce Richardson 
2299a2dd95SBruce Richardson #define DIR24_8_TBL24_NUM_ENT		(1 << 24)
2399a2dd95SBruce Richardson #define DIR24_8_TBL8_GRP_NUM_ENT	256U
2499a2dd95SBruce Richardson #define DIR24_8_EXT_ENT			1
2599a2dd95SBruce Richardson #define DIR24_8_TBL24_MASK		0xffffff00
2699a2dd95SBruce Richardson 
2799a2dd95SBruce Richardson #define BITMAP_SLAB_BIT_SIZE_LOG2	6
2899a2dd95SBruce Richardson #define BITMAP_SLAB_BIT_SIZE		(1 << BITMAP_SLAB_BIT_SIZE_LOG2)
2999a2dd95SBruce Richardson #define BITMAP_SLAB_BITMASK		(BITMAP_SLAB_BIT_SIZE - 1)
3099a2dd95SBruce Richardson 
3199a2dd95SBruce Richardson struct dir24_8_tbl {
3299a2dd95SBruce Richardson 	uint32_t	number_tbl8s;	/**< Total number of tbl8s */
3399a2dd95SBruce Richardson 	uint32_t	rsvd_tbl8s;	/**< Number of reserved tbl8s */
3499a2dd95SBruce Richardson 	uint32_t	cur_tbl8s;	/**< Current number of tbl8s */
3599a2dd95SBruce Richardson 	enum rte_fib_dir24_8_nh_sz	nh_sz;	/**< Size of nexthop entry */
36*96c3d06aSVladimir Medvedkin 	/* RCU config. */
37*96c3d06aSVladimir Medvedkin 	enum rte_fib_qsbr_mode rcu_mode;/* Blocking, defer queue. */
38*96c3d06aSVladimir Medvedkin 	struct rte_rcu_qsbr *v;		/* RCU QSBR variable. */
39*96c3d06aSVladimir Medvedkin 	struct rte_rcu_qsbr_dq *dq;	/* RCU QSBR defer queue. */
4099a2dd95SBruce Richardson 	uint64_t	def_nh;		/**< Default next hop */
4199a2dd95SBruce Richardson 	uint64_t	*tbl8;		/**< tbl8 table. */
4299a2dd95SBruce Richardson 	uint64_t	*tbl8_idxes;	/**< bitmap containing free tbl8 idxes*/
4399a2dd95SBruce Richardson 	/* tbl24 table. */
4496f25531STyler Retzlaff 	alignas(RTE_CACHE_LINE_SIZE) uint64_t	tbl24[];
4599a2dd95SBruce Richardson };
4699a2dd95SBruce Richardson 
4799a2dd95SBruce Richardson static inline void *
4899a2dd95SBruce Richardson get_tbl24_p(struct dir24_8_tbl *dp, uint32_t ip, uint8_t nh_sz)
4999a2dd95SBruce Richardson {
5099a2dd95SBruce Richardson 	return (void *)&((uint8_t *)dp->tbl24)[(ip &
5199a2dd95SBruce Richardson 		DIR24_8_TBL24_MASK) >> (8 - nh_sz)];
5299a2dd95SBruce Richardson }
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson static inline  uint8_t
5599a2dd95SBruce Richardson bits_in_nh(uint8_t nh_sz)
5699a2dd95SBruce Richardson {
5799a2dd95SBruce Richardson 	return 8 * (1 << nh_sz);
5899a2dd95SBruce Richardson }
5999a2dd95SBruce Richardson 
6099a2dd95SBruce Richardson static inline uint64_t
6199a2dd95SBruce Richardson get_max_nh(uint8_t nh_sz)
6299a2dd95SBruce Richardson {
6399a2dd95SBruce Richardson 	return ((1ULL << (bits_in_nh(nh_sz) - 1)) - 1);
6499a2dd95SBruce Richardson }
6599a2dd95SBruce Richardson 
6699a2dd95SBruce Richardson static  inline uint32_t
6799a2dd95SBruce Richardson get_tbl24_idx(uint32_t ip)
6899a2dd95SBruce Richardson {
6999a2dd95SBruce Richardson 	return ip >> 8;
7099a2dd95SBruce Richardson }
7199a2dd95SBruce Richardson 
7299a2dd95SBruce Richardson static  inline uint32_t
7399a2dd95SBruce Richardson get_tbl8_idx(uint32_t res, uint32_t ip)
7499a2dd95SBruce Richardson {
7599a2dd95SBruce Richardson 	return (res >> 1) * DIR24_8_TBL8_GRP_NUM_ENT + (uint8_t)ip;
7699a2dd95SBruce Richardson }
7799a2dd95SBruce Richardson 
7899a2dd95SBruce Richardson static inline uint64_t
7999a2dd95SBruce Richardson lookup_msk(uint8_t nh_sz)
8099a2dd95SBruce Richardson {
8199a2dd95SBruce Richardson 	return ((1ULL << ((1 << (nh_sz + 3)) - 1)) << 1) - 1;
8299a2dd95SBruce Richardson }
8399a2dd95SBruce Richardson 
8499a2dd95SBruce Richardson static inline uint8_t
8599a2dd95SBruce Richardson get_psd_idx(uint32_t val, uint8_t nh_sz)
8699a2dd95SBruce Richardson {
8799a2dd95SBruce Richardson 	return val & ((1 << (3 - nh_sz)) - 1);
8899a2dd95SBruce Richardson }
8999a2dd95SBruce Richardson 
9099a2dd95SBruce Richardson static inline uint32_t
9199a2dd95SBruce Richardson get_tbl_idx(uint32_t val, uint8_t nh_sz)
9299a2dd95SBruce Richardson {
9399a2dd95SBruce Richardson 	return val >> (3 - nh_sz);
9499a2dd95SBruce Richardson }
9599a2dd95SBruce Richardson 
9699a2dd95SBruce Richardson static inline uint64_t
9799a2dd95SBruce Richardson get_tbl24(struct dir24_8_tbl *dp, uint32_t ip, uint8_t nh_sz)
9899a2dd95SBruce Richardson {
9999a2dd95SBruce Richardson 	return ((dp->tbl24[get_tbl_idx(get_tbl24_idx(ip), nh_sz)] >>
10099a2dd95SBruce Richardson 		(get_psd_idx(get_tbl24_idx(ip), nh_sz) *
10199a2dd95SBruce Richardson 		bits_in_nh(nh_sz))) & lookup_msk(nh_sz));
10299a2dd95SBruce Richardson }
10399a2dd95SBruce Richardson 
10499a2dd95SBruce Richardson static inline uint64_t
10599a2dd95SBruce Richardson get_tbl8(struct dir24_8_tbl *dp, uint32_t res, uint32_t ip, uint8_t nh_sz)
10699a2dd95SBruce Richardson {
10799a2dd95SBruce Richardson 	return ((dp->tbl8[get_tbl_idx(get_tbl8_idx(res, ip), nh_sz)] >>
10899a2dd95SBruce Richardson 		(get_psd_idx(get_tbl8_idx(res, ip), nh_sz) *
10999a2dd95SBruce Richardson 		bits_in_nh(nh_sz))) & lookup_msk(nh_sz));
11099a2dd95SBruce Richardson }
11199a2dd95SBruce Richardson 
11299a2dd95SBruce Richardson static inline int
11399a2dd95SBruce Richardson is_entry_extended(uint64_t ent)
11499a2dd95SBruce Richardson {
11599a2dd95SBruce Richardson 	return (ent & DIR24_8_EXT_ENT) == DIR24_8_EXT_ENT;
11699a2dd95SBruce Richardson }
11799a2dd95SBruce Richardson 
11899a2dd95SBruce Richardson #define LOOKUP_FUNC(suffix, type, bulk_prefetch, nh_sz)			\
11999a2dd95SBruce Richardson static inline void dir24_8_lookup_bulk_##suffix(void *p, const uint32_t *ips, \
12099a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n)			\
12199a2dd95SBruce Richardson {									\
12299a2dd95SBruce Richardson 	struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;		\
12399a2dd95SBruce Richardson 	uint64_t tmp;							\
12499a2dd95SBruce Richardson 	uint32_t i;							\
12599a2dd95SBruce Richardson 	uint32_t prefetch_offset =					\
12699a2dd95SBruce Richardson 		RTE_MIN((unsigned int)bulk_prefetch, n);		\
12799a2dd95SBruce Richardson 									\
12899a2dd95SBruce Richardson 	for (i = 0; i < prefetch_offset; i++)				\
12999a2dd95SBruce Richardson 		rte_prefetch0(get_tbl24_p(dp, ips[i], nh_sz));		\
13099a2dd95SBruce Richardson 	for (i = 0; i < (n - prefetch_offset); i++) {			\
13199a2dd95SBruce Richardson 		rte_prefetch0(get_tbl24_p(dp,				\
13299a2dd95SBruce Richardson 			ips[i + prefetch_offset], nh_sz));		\
13399a2dd95SBruce Richardson 		tmp = ((type *)dp->tbl24)[ips[i] >> 8];			\
13499a2dd95SBruce Richardson 		if (unlikely(is_entry_extended(tmp)))			\
13599a2dd95SBruce Richardson 			tmp = ((type *)dp->tbl8)[(uint8_t)ips[i] +	\
13699a2dd95SBruce Richardson 				((tmp >> 1) * DIR24_8_TBL8_GRP_NUM_ENT)]; \
13799a2dd95SBruce Richardson 		next_hops[i] = tmp >> 1;				\
13899a2dd95SBruce Richardson 	}								\
13999a2dd95SBruce Richardson 	for (; i < n; i++) {						\
14099a2dd95SBruce Richardson 		tmp = ((type *)dp->tbl24)[ips[i] >> 8];			\
14199a2dd95SBruce Richardson 		if (unlikely(is_entry_extended(tmp)))			\
14299a2dd95SBruce Richardson 			tmp = ((type *)dp->tbl8)[(uint8_t)ips[i] +	\
14399a2dd95SBruce Richardson 				((tmp >> 1) * DIR24_8_TBL8_GRP_NUM_ENT)]; \
14499a2dd95SBruce Richardson 		next_hops[i] = tmp >> 1;				\
14599a2dd95SBruce Richardson 	}								\
14699a2dd95SBruce Richardson }									\
14799a2dd95SBruce Richardson 
14899a2dd95SBruce Richardson LOOKUP_FUNC(1b, uint8_t, 5, 0)
14999a2dd95SBruce Richardson LOOKUP_FUNC(2b, uint16_t, 6, 1)
15099a2dd95SBruce Richardson LOOKUP_FUNC(4b, uint32_t, 15, 2)
15199a2dd95SBruce Richardson LOOKUP_FUNC(8b, uint64_t, 12, 3)
15299a2dd95SBruce Richardson 
15399a2dd95SBruce Richardson static inline void
15499a2dd95SBruce Richardson dir24_8_lookup_bulk(struct dir24_8_tbl *dp, const uint32_t *ips,
15599a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n, uint8_t nh_sz)
15699a2dd95SBruce Richardson {
15799a2dd95SBruce Richardson 	uint64_t tmp;
15899a2dd95SBruce Richardson 	uint32_t i;
15999a2dd95SBruce Richardson 	uint32_t prefetch_offset = RTE_MIN(15U, n);
16099a2dd95SBruce Richardson 
16199a2dd95SBruce Richardson 	for (i = 0; i < prefetch_offset; i++)
16299a2dd95SBruce Richardson 		rte_prefetch0(get_tbl24_p(dp, ips[i], nh_sz));
16399a2dd95SBruce Richardson 	for (i = 0; i < (n - prefetch_offset); i++) {
16499a2dd95SBruce Richardson 		rte_prefetch0(get_tbl24_p(dp, ips[i + prefetch_offset],
16599a2dd95SBruce Richardson 			nh_sz));
16699a2dd95SBruce Richardson 		tmp = get_tbl24(dp, ips[i], nh_sz);
16799a2dd95SBruce Richardson 		if (unlikely(is_entry_extended(tmp)))
16899a2dd95SBruce Richardson 			tmp = get_tbl8(dp, tmp, ips[i], nh_sz);
16999a2dd95SBruce Richardson 
17099a2dd95SBruce Richardson 		next_hops[i] = tmp >> 1;
17199a2dd95SBruce Richardson 	}
17299a2dd95SBruce Richardson 	for (; i < n; i++) {
17399a2dd95SBruce Richardson 		tmp = get_tbl24(dp, ips[i], nh_sz);
17499a2dd95SBruce Richardson 		if (unlikely(is_entry_extended(tmp)))
17599a2dd95SBruce Richardson 			tmp = get_tbl8(dp, tmp, ips[i], nh_sz);
17699a2dd95SBruce Richardson 
17799a2dd95SBruce Richardson 		next_hops[i] = tmp >> 1;
17899a2dd95SBruce Richardson 	}
17999a2dd95SBruce Richardson }
18099a2dd95SBruce Richardson 
18199a2dd95SBruce Richardson static inline void
18299a2dd95SBruce Richardson dir24_8_lookup_bulk_0(void *p, const uint32_t *ips,
18399a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n)
18499a2dd95SBruce Richardson {
18599a2dd95SBruce Richardson 	struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
18699a2dd95SBruce Richardson 
18799a2dd95SBruce Richardson 	dir24_8_lookup_bulk(dp, ips, next_hops, n, 0);
18899a2dd95SBruce Richardson }
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson static inline void
19199a2dd95SBruce Richardson dir24_8_lookup_bulk_1(void *p, const uint32_t *ips,
19299a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n)
19399a2dd95SBruce Richardson {
19499a2dd95SBruce Richardson 	struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
19599a2dd95SBruce Richardson 
19699a2dd95SBruce Richardson 	dir24_8_lookup_bulk(dp, ips, next_hops, n, 1);
19799a2dd95SBruce Richardson }
19899a2dd95SBruce Richardson 
19999a2dd95SBruce Richardson static inline void
20099a2dd95SBruce Richardson dir24_8_lookup_bulk_2(void *p, const uint32_t *ips,
20199a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n)
20299a2dd95SBruce Richardson {
20399a2dd95SBruce Richardson 	struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	dir24_8_lookup_bulk(dp, ips, next_hops, n, 2);
20699a2dd95SBruce Richardson }
20799a2dd95SBruce Richardson 
20899a2dd95SBruce Richardson static inline void
20999a2dd95SBruce Richardson dir24_8_lookup_bulk_3(void *p, const uint32_t *ips,
21099a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n)
21199a2dd95SBruce Richardson {
21299a2dd95SBruce Richardson 	struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
21399a2dd95SBruce Richardson 
21499a2dd95SBruce Richardson 	dir24_8_lookup_bulk(dp, ips, next_hops, n, 3);
21599a2dd95SBruce Richardson }
21699a2dd95SBruce Richardson 
21799a2dd95SBruce Richardson static inline void
21899a2dd95SBruce Richardson dir24_8_lookup_bulk_uni(void *p, const uint32_t *ips,
21999a2dd95SBruce Richardson 	uint64_t *next_hops, const unsigned int n)
22099a2dd95SBruce Richardson {
22199a2dd95SBruce Richardson 	struct dir24_8_tbl *dp = (struct dir24_8_tbl *)p;
22299a2dd95SBruce Richardson 	uint64_t tmp;
22399a2dd95SBruce Richardson 	uint32_t i;
22499a2dd95SBruce Richardson 	uint32_t prefetch_offset = RTE_MIN(15U, n);
22599a2dd95SBruce Richardson 	uint8_t nh_sz = dp->nh_sz;
22699a2dd95SBruce Richardson 
22799a2dd95SBruce Richardson 	for (i = 0; i < prefetch_offset; i++)
22899a2dd95SBruce Richardson 		rte_prefetch0(get_tbl24_p(dp, ips[i], nh_sz));
22999a2dd95SBruce Richardson 	for (i = 0; i < (n - prefetch_offset); i++) {
23099a2dd95SBruce Richardson 		rte_prefetch0(get_tbl24_p(dp, ips[i + prefetch_offset],
23199a2dd95SBruce Richardson 			nh_sz));
23299a2dd95SBruce Richardson 		tmp = get_tbl24(dp, ips[i], nh_sz);
23399a2dd95SBruce Richardson 		if (unlikely(is_entry_extended(tmp)))
23499a2dd95SBruce Richardson 			tmp = get_tbl8(dp, tmp, ips[i], nh_sz);
23599a2dd95SBruce Richardson 
23699a2dd95SBruce Richardson 		next_hops[i] = tmp >> 1;
23799a2dd95SBruce Richardson 	}
23899a2dd95SBruce Richardson 	for (; i < n; i++) {
23999a2dd95SBruce Richardson 		tmp = get_tbl24(dp, ips[i], nh_sz);
24099a2dd95SBruce Richardson 		if (unlikely(is_entry_extended(tmp)))
24199a2dd95SBruce Richardson 			tmp = get_tbl8(dp, tmp, ips[i], nh_sz);
24299a2dd95SBruce Richardson 
24399a2dd95SBruce Richardson 		next_hops[i] = tmp >> 1;
24499a2dd95SBruce Richardson 	}
24599a2dd95SBruce Richardson }
24699a2dd95SBruce Richardson 
247e194f3cdSVladimir Medvedkin #define BSWAP_MAX_LENGTH	64
248e194f3cdSVladimir Medvedkin 
249e194f3cdSVladimir Medvedkin typedef void (*dir24_8_lookup_bulk_be_cb)(void *p, const uint32_t *ips, uint64_t *next_hops,
250e194f3cdSVladimir Medvedkin 	const unsigned int n);
251e194f3cdSVladimir Medvedkin 
252e194f3cdSVladimir Medvedkin static inline void
253e194f3cdSVladimir Medvedkin dir24_8_lookup_bulk_be(void *p, const uint32_t *ips, uint64_t *next_hops, const unsigned int n,
254e194f3cdSVladimir Medvedkin 	dir24_8_lookup_bulk_be_cb cb)
255e194f3cdSVladimir Medvedkin {
256e194f3cdSVladimir Medvedkin 	uint32_t le_ips[BSWAP_MAX_LENGTH];
257e194f3cdSVladimir Medvedkin 	unsigned int i;
258e194f3cdSVladimir Medvedkin 
259e194f3cdSVladimir Medvedkin #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
260e194f3cdSVladimir Medvedkin 	cb(p, ips, next_hops, n);
261e194f3cdSVladimir Medvedkin #else
262e194f3cdSVladimir Medvedkin 	for (i = 0; i < n; i += BSWAP_MAX_LENGTH) {
263e194f3cdSVladimir Medvedkin 		int j;
264e194f3cdSVladimir Medvedkin 		for (j = 0; j < BSWAP_MAX_LENGTH && i + j < n; j++)
265e194f3cdSVladimir Medvedkin 			le_ips[j] = rte_be_to_cpu_32(ips[i + j]);
266e194f3cdSVladimir Medvedkin 
267e194f3cdSVladimir Medvedkin 		cb(p, le_ips, next_hops + i, j);
268e194f3cdSVladimir Medvedkin 	}
269e194f3cdSVladimir Medvedkin #endif
270e194f3cdSVladimir Medvedkin }
271e194f3cdSVladimir Medvedkin 
272e194f3cdSVladimir Medvedkin #define DECLARE_BE_LOOKUP_FN(name) \
273e194f3cdSVladimir Medvedkin static inline void \
274e194f3cdSVladimir Medvedkin name##_be(void *p, const uint32_t *ips, uint64_t *next_hops, const unsigned int n) \
275e194f3cdSVladimir Medvedkin { \
276e194f3cdSVladimir Medvedkin 	dir24_8_lookup_bulk_be(p, ips, next_hops, n, name); \
277e194f3cdSVladimir Medvedkin }
278e194f3cdSVladimir Medvedkin 
279e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_1b)
280e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_2b)
281e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_4b)
282e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_8b)
283e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_0)
284e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_1)
285e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_2)
286e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_3)
287e194f3cdSVladimir Medvedkin DECLARE_BE_LOOKUP_FN(dir24_8_lookup_bulk_uni)
288e194f3cdSVladimir Medvedkin 
28999a2dd95SBruce Richardson void *
29099a2dd95SBruce Richardson dir24_8_create(const char *name, int socket_id, struct rte_fib_conf *conf);
29199a2dd95SBruce Richardson 
29299a2dd95SBruce Richardson void
29399a2dd95SBruce Richardson dir24_8_free(void *p);
29499a2dd95SBruce Richardson 
29599a2dd95SBruce Richardson rte_fib_lookup_fn_t
296e194f3cdSVladimir Medvedkin dir24_8_get_lookup_fn(void *p, enum rte_fib_lookup_type type, bool be_addr);
29799a2dd95SBruce Richardson 
29899a2dd95SBruce Richardson int
29999a2dd95SBruce Richardson dir24_8_modify(struct rte_fib *fib, uint32_t ip, uint8_t depth,
30099a2dd95SBruce Richardson 	uint64_t next_hop, int op);
30199a2dd95SBruce Richardson 
302*96c3d06aSVladimir Medvedkin int
303*96c3d06aSVladimir Medvedkin dir24_8_rcu_qsbr_add(struct dir24_8_tbl *dp, struct rte_fib_rcu_config *cfg,
304*96c3d06aSVladimir Medvedkin 	const char *name);
305*96c3d06aSVladimir Medvedkin 
30699a2dd95SBruce Richardson #endif /* _DIR24_8_H_ */
307