4b284c913c70bb9845b7385530aec6a08e1f8eed
[dpdk.git] / lib / librte_rib / rte_rib6.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
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  * @warning
15  * @b EXPERIMENTAL:
16  * All functions in this file may be changed or removed without prior notice.
17  *
18  * Level compressed tree implementation for IPv6 Longest Prefix Match
19  */
20
21 #include <rte_memcpy.h>
22 #include <rte_compat.h>
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
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
80 rte_rib6_is_equal(uint8_t *ip1, 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
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 __rte_experimental
126 struct rte_rib6_node *
127 rte_rib6_lookup(struct rte_rib6 *rib,
128         const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE]);
129
130 /**
131  * Lookup less specific route into the RIB structure
132  *
133  * @param ent
134  *  Pointer to struct rte_rib6_node that represents target route
135  * @return
136  *  pointer to struct rte_rib6_node that represents
137  *   less specific route on success
138  *  NULL otherwise
139  */
140 __rte_experimental
141 struct rte_rib6_node *
142 rte_rib6_lookup_parent(struct rte_rib6_node *ent);
143
144 /**
145  * Provides exact mach lookup of the prefix into the RIB structure
146  *
147  * @param rib
148  *  RIB object handle
149  * @param ip
150  *  net to be looked up in the RIB
151  * @param depth
152  *  prefix length
153  * @return
154  *  pointer to struct rte_rib6_node on success
155  *  NULL otherwise
156  */
157 __rte_experimental
158 struct rte_rib6_node *
159 rte_rib6_lookup_exact(struct rte_rib6 *rib,
160         const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
161
162 /**
163  * Retrieve next more specific prefix from the RIB
164  * that is covered by ip/depth supernet in an ascending order
165  *
166  * @param rib
167  *  RIB object handle
168  * @param ip
169  *  net address of supernet prefix that covers returned more specific prefixes
170  * @param depth
171  *  supernet prefix length
172  * @param last
173  *   pointer to the last returned prefix to get next prefix
174  *   or
175  *   NULL to get first more specific prefix
176  * @param flag
177  *  -RTE_RIB6_GET_NXT_ALL
178  *   get all prefixes from subtrie
179  *  -RTE_RIB6_GET_NXT_COVER
180  *   get only first more specific prefix even if it have more specifics
181  * @return
182  *  pointer to the next more specific prefix
183  *  NULL if there is no prefixes left
184  */
185 __rte_experimental
186 struct rte_rib6_node *
187 rte_rib6_get_nxt(struct rte_rib6 *rib,
188         const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE],
189         uint8_t depth, struct rte_rib6_node *last, int flag);
190
191 /**
192  * Remove prefix from the RIB
193  *
194  * @param rib
195  *  RIB object handle
196  * @param ip
197  *  net to be removed from the RIB
198  * @param depth
199  *  prefix length
200  */
201 __rte_experimental
202 void
203 rte_rib6_remove(struct rte_rib6 *rib,
204         const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
205
206 /**
207  * Insert prefix into the RIB
208  *
209  * @param rib
210  *  RIB object handle
211  * @param ip
212  *  net to be inserted to the RIB
213  * @param depth
214  *  prefix length
215  * @return
216  *  pointer to new rte_rib6_node on success
217  *  NULL otherwise
218  */
219 __rte_experimental
220 struct rte_rib6_node *
221 rte_rib6_insert(struct rte_rib6 *rib,
222         const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
223
224 /**
225  * Get an ip from rte_rib6_node
226  *
227  * @param node
228  *  pointer to the rib6 node
229  * @param ip
230  *  pointer to the ipv6 to save
231  * @return
232  *  0 on success
233  *  -1 on failure with rte_errno indicating reason for failure.
234  */
235 __rte_experimental
236 int
237 rte_rib6_get_ip(struct rte_rib6_node *node,
238         uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE]);
239
240 /**
241  * Get a depth from rte_rib6_node
242  *
243  * @param node
244  *  pointer to the rib6 node
245  * @param depth
246  *  pointer to the depth to save
247  * @return
248  *  0 on success
249  *  -1 on failure with rte_errno indicating reason for failure.
250  */
251 __rte_experimental
252 int
253 rte_rib6_get_depth(struct rte_rib6_node *node, uint8_t *depth);
254
255 /**
256  * Get ext field from the rte_rib6_node
257  * It is caller responsibility to make sure there are necessary space
258  * for the ext field inside rib6 node.
259  *
260  * @param node
261  *  pointer to the rte_rib6_node
262  * @return
263  *  pointer to the ext
264  */
265 __rte_experimental
266 void *
267 rte_rib6_get_ext(struct rte_rib6_node *node);
268
269 /**
270  * Get nexthop from the rte_rib6_node
271  *
272  * @param node
273  *  pointer to the rib6 node
274  * @param nh
275  *  pointer to the nexthop to save
276  * @return
277  *  0 on success
278  *  -1 on failure, with rte_errno indicating reason for failure.
279  */
280 __rte_experimental
281 int
282 rte_rib6_get_nh(struct rte_rib6_node *node, uint64_t *nh);
283
284 /**
285  * Set nexthop into the rte_rib6_node
286  *
287  * @param node
288  *  pointer to the rib6 node
289  * @param nh
290  *  nexthop value to set to the rib6 node
291  * @return
292  *  0 on success
293  *  -1 on failure, with rte_errno indicating reason for failure.
294  */
295 __rte_experimental
296 int
297 rte_rib6_set_nh(struct rte_rib6_node *node, uint64_t nh);
298
299 /**
300  * Create RIB
301  *
302  * @param name
303  *  RIB name
304  * @param socket_id
305  *  NUMA socket ID for RIB table memory allocation
306  * @param conf
307  *  Structure containing the configuration
308  * @return
309  *  Pointer to RIB object on success
310  *  NULL otherwise with rte_errno indicating reason for failure.
311  */
312 __rte_experimental
313 struct rte_rib6 *
314 rte_rib6_create(const char *name, int socket_id, struct rte_rib6_conf *conf);
315
316 /**
317  * Find an existing RIB object and return a pointer to it.
318  *
319  * @param name
320  *  Name of the rib object as passed to rte_rib_create()
321  * @return
322  *  Pointer to RIB object on success
323  *  NULL otherwise with rte_errno indicating reason for failure.
324  */
325 __rte_experimental
326 struct rte_rib6 *
327 rte_rib6_find_existing(const char *name);
328
329 /**
330  * Free an RIB object.
331  *
332  * @param rib
333  *   RIB object handle
334  * @return
335  *   None
336  */
337 __rte_experimental
338 void
339 rte_rib6_free(struct rte_rib6 *rib);
340
341 #endif /* _RTE_RIB_H_ */