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