| 237 | } |
| 238 | |
| 239 | struct rte_rib_node * |
| 240 | rte_rib_insert(struct rte_rib *rib, uint32_t ip, uint8_t depth) |
| 241 | { |
| 242 | struct rte_rib_node **tmp; |
| 243 | struct rte_rib_node *prev = NULL; |
| 244 | struct rte_rib_node *new_node = NULL; |
| 245 | struct rte_rib_node *common_node = NULL; |
| 246 | int d = 0; |
| 247 | uint32_t common_prefix; |
| 248 | uint8_t common_depth; |
| 249 | |
| 250 | if (unlikely(rib == NULL || depth > RIB_MAXDEPTH)) { |
| 251 | rte_errno = EINVAL; |
| 252 | return NULL; |
| 253 | } |
| 254 | |
| 255 | tmp = &rib->tree; |
| 256 | ip &= rte_rib_depth_to_mask(depth); |
| 257 | new_node = __rib_lookup_exact(rib, ip, depth); |
| 258 | if (new_node != NULL) { |
| 259 | rte_errno = EEXIST; |
| 260 | return NULL; |
| 261 | } |
| 262 | |
| 263 | new_node = node_alloc(rib); |
| 264 | if (new_node == NULL) { |
| 265 | rte_errno = ENOMEM; |
| 266 | return NULL; |
| 267 | } |
| 268 | new_node->left = NULL; |
| 269 | new_node->right = NULL; |
| 270 | new_node->parent = NULL; |
| 271 | new_node->ip = ip; |
| 272 | new_node->depth = depth; |
| 273 | new_node->flag = RTE_RIB_VALID_NODE; |
| 274 | |
| 275 | /* traverse down the tree to find matching node or closest matching */ |
| 276 | while (1) { |
| 277 | /* insert as the last node in the branch */ |
| 278 | if (*tmp == NULL) { |
| 279 | *tmp = new_node; |
| 280 | new_node->parent = prev; |
| 281 | ++rib->cur_routes; |
| 282 | return *tmp; |
| 283 | } |
| 284 | /* |
| 285 | * Intermediate node found. |
| 286 | * Previous rte_rib_lookup_exact() returned NULL |
| 287 | * but node with proper search criteria is found. |
| 288 | * Validate intermediate node and return. |
| 289 | */ |
| 290 | if ((ip == (*tmp)->ip) && (depth == (*tmp)->depth)) { |
| 291 | node_free(rib, new_node); |
| 292 | (*tmp)->flag |= RTE_RIB_VALID_NODE; |
| 293 | ++rib->cur_routes; |
| 294 | return *tmp; |
| 295 | } |
| 296 | d = (*tmp)->depth; |