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