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