1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Vladimir Medvedkin <[email protected]>
3 * Copyright(c) 2019 Intel Corporation
4 */
5
6 #ifndef _RTE_RIB6_H_
7 #define _RTE_RIB6_H_
8
9 /**
10 * @file
11 *
12 * RTE rib6 library.
13 *
14 * Level compressed tree implementation for IPv6 Longest Prefix Match
15 */
16
17 #include <rte_memcpy.h>
18 #include <rte_common.h>
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23
24 #define RTE_RIB6_IPV6_ADDR_SIZE 16
25
26 /**
27 * rte_rib6_get_nxt() flags
28 */
29 enum {
30 /** flag to get all subroutes in a RIB tree */
31 RTE_RIB6_GET_NXT_ALL,
32 /** flag to get first matched subroutes in a RIB tree */
33 RTE_RIB6_GET_NXT_COVER
34 };
35
36 struct rte_rib6;
37 struct rte_rib6_node;
38
39 /** RIB configuration structure */
40 struct rte_rib6_conf {
41 /**
42 * Size of extension block inside rte_rib_node.
43 * This space could be used to store additional user
44 * defined data.
45 */
46 size_t ext_sz;
47 /* size of rte_rib_node's pool */
48 int max_nodes;
49 };
50
51 /**
52 * Copy IPv6 address from one location to another
53 *
54 * @param dst
55 * pointer to the place to copy
56 * @param src
57 * pointer from where to copy
58 */
59 static inline void
rte_rib6_copy_addr(uint8_t * dst,const uint8_t * src)60 rte_rib6_copy_addr(uint8_t *dst, const uint8_t *src)
61 {
62 if ((dst == NULL) || (src == NULL))
63 return;
64 rte_memcpy(dst, src, RTE_RIB6_IPV6_ADDR_SIZE);
65 }
66
67 /**
68 * Compare two IPv6 addresses
69 *
70 * @param ip1
71 * pointer to the first ipv6 address
72 * @param ip2
73 * pointer to the second ipv6 address
74 *
75 * @return
76 * 1 if equal
77 * 0 otherwise
78 */
79 static inline int
rte_rib6_is_equal(const uint8_t * ip1,const uint8_t * ip2)80 rte_rib6_is_equal(const uint8_t *ip1, const uint8_t *ip2) {
81 int i;
82
83 if ((ip1 == NULL) || (ip2 == NULL))
84 return 0;
85 for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++) {
86 if (ip1[i] != ip2[i])
87 return 0;
88 }
89 return 1;
90 }
91
92 /**
93 * Get 8-bit part of 128-bit IPv6 mask
94 *
95 * @param depth
96 * ipv6 prefix length
97 * @param byte
98 * position of a 8-bit chunk in the 128-bit mask
99 *
100 * @return
101 * 8-bit chunk of the 128-bit IPv6 mask
102 */
103 static inline uint8_t
get_msk_part(uint8_t depth,int byte)104 get_msk_part(uint8_t depth, int byte) {
105 uint8_t part;
106
107 byte &= 0xf;
108 depth = RTE_MIN(depth, 128);
109 part = RTE_MAX((int16_t)depth - (byte * 8), 0);
110 part = (part > 8) ? 8 : part;
111 return (uint16_t)(~UINT8_MAX) >> part;
112 }
113
114 /**
115 * Lookup an IP into the RIB structure
116 *
117 * @param rib
118 * RIB object handle
119 * @param ip
120 * IP to be looked up in the RIB
121 * @return
122 * pointer to struct rte_rib6_node on success
123 * NULL otherwise
124 */
125 struct rte_rib6_node *
126 rte_rib6_lookup(struct rte_rib6 *rib,
127 const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE]);
128
129 /**
130 * Lookup less specific route into the RIB structure
131 *
132 * @param ent
133 * Pointer to struct rte_rib6_node that represents target route
134 * @return
135 * pointer to struct rte_rib6_node that represents
136 * less specific route on success
137 * NULL otherwise
138 */
139 struct rte_rib6_node *
140 rte_rib6_lookup_parent(struct rte_rib6_node *ent);
141
142 /**
143 * Provides exact mach lookup of the prefix into the RIB structure
144 *
145 * @param rib
146 * RIB object handle
147 * @param ip
148 * net to be looked up in the RIB
149 * @param depth
150 * prefix length
151 * @return
152 * pointer to struct rte_rib6_node on success
153 * NULL otherwise
154 */
155 struct rte_rib6_node *
156 rte_rib6_lookup_exact(struct rte_rib6 *rib,
157 const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
158
159 /**
160 * Retrieve next more specific prefix from the RIB
161 * that is covered by ip/depth supernet in an ascending order
162 *
163 * @param rib
164 * RIB object handle
165 * @param ip
166 * net address of supernet prefix that covers returned more specific prefixes
167 * @param depth
168 * supernet prefix length
169 * @param last
170 * pointer to the last returned prefix to get next prefix
171 * or
172 * NULL to get first more specific prefix
173 * @param flag
174 * -RTE_RIB6_GET_NXT_ALL
175 * get all prefixes from subtrie
176 * -RTE_RIB6_GET_NXT_COVER
177 * get only first more specific prefix even if it have more specifics
178 * @return
179 * pointer to the next more specific prefix
180 * NULL if there is no prefixes left
181 */
182 struct rte_rib6_node *
183 rte_rib6_get_nxt(struct rte_rib6 *rib,
184 const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE],
185 uint8_t depth, struct rte_rib6_node *last, int flag);
186
187 /**
188 * Remove prefix from the RIB
189 *
190 * @param rib
191 * RIB object handle
192 * @param ip
193 * net to be removed from the RIB
194 * @param depth
195 * prefix length
196 */
197 void
198 rte_rib6_remove(struct rte_rib6 *rib,
199 const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
200
201 /**
202 * Insert prefix into the RIB
203 *
204 * @param rib
205 * RIB object handle
206 * @param ip
207 * net to be inserted to the RIB
208 * @param depth
209 * prefix length
210 * @return
211 * pointer to new rte_rib6_node on success
212 * NULL otherwise
213 */
214 struct rte_rib6_node *
215 rte_rib6_insert(struct rte_rib6 *rib,
216 const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
217
218 /**
219 * Get an ip from rte_rib6_node
220 *
221 * @param node
222 * pointer to the rib6 node
223 * @param ip
224 * pointer to the ipv6 to save
225 * @return
226 * 0 on success
227 * -1 on failure with rte_errno indicating reason for failure.
228 */
229 int
230 rte_rib6_get_ip(const struct rte_rib6_node *node,
231 uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE]);
232
233 /**
234 * Get a depth from rte_rib6_node
235 *
236 * @param node
237 * pointer to the rib6 node
238 * @param depth
239 * pointer to the depth to save
240 * @return
241 * 0 on success
242 * -1 on failure with rte_errno indicating reason for failure.
243 */
244 int
245 rte_rib6_get_depth(const struct rte_rib6_node *node, uint8_t *depth);
246
247 /**
248 * Get ext field from the rte_rib6_node
249 * It is caller responsibility to make sure there are necessary space
250 * for the ext field inside rib6 node.
251 *
252 * @param node
253 * pointer to the rte_rib6_node
254 * @return
255 * pointer to the ext
256 */
257 void *
258 rte_rib6_get_ext(struct rte_rib6_node *node);
259
260 /**
261 * Get nexthop from the rte_rib6_node
262 *
263 * @param node
264 * pointer to the rib6 node
265 * @param nh
266 * pointer to the nexthop to save
267 * @return
268 * 0 on success
269 * -1 on failure, with rte_errno indicating reason for failure.
270 */
271 int
272 rte_rib6_get_nh(const struct rte_rib6_node *node, uint64_t *nh);
273
274 /**
275 * Set nexthop into the rte_rib6_node
276 *
277 * @param node
278 * pointer to the rib6 node
279 * @param nh
280 * nexthop value to set to the rib6 node
281 * @return
282 * 0 on success
283 * -1 on failure, with rte_errno indicating reason for failure.
284 */
285 int
286 rte_rib6_set_nh(struct rte_rib6_node *node, uint64_t nh);
287
288 /**
289 * Create RIB
290 *
291 * @param name
292 * RIB name
293 * @param socket_id
294 * NUMA socket ID for RIB table memory allocation
295 * @param conf
296 * Structure containing the configuration
297 * @return
298 * Pointer to RIB object on success
299 * NULL otherwise with rte_errno indicating reason for failure.
300 */
301 struct rte_rib6 *
302 rte_rib6_create(const char *name, int socket_id,
303 const struct rte_rib6_conf *conf);
304
305 /**
306 * Find an existing RIB object and return a pointer to it.
307 *
308 * @param name
309 * Name of the rib object as passed to rte_rib_create()
310 * @return
311 * Pointer to RIB object on success
312 * NULL otherwise with rte_errno indicating reason for failure.
313 */
314 struct rte_rib6 *
315 rte_rib6_find_existing(const char *name);
316
317 /**
318 * Free an RIB object.
319 *
320 * @param rib
321 * RIB object handle
322 * @return
323 * None
324 */
325 void
326 rte_rib6_free(struct rte_rib6 *rib);
327
328 #ifdef __cplusplus
329 }
330 #endif
331
332 #endif /* _RTE_RIB6_H_ */
333