Add the currently missing handling for the BPF_EXIST and BPF_NOEXIST flags. These flags can be specified by users and are relevant since LPM trie supports exact matches during update.
Unified · Split
| @@ -375,6 +375,10 @@ static long trie_update_elem(struct bpf_map *map, · 374 unmodified lines | ||
| 375 | 375 | * simply assign the @new_node to that slot and be done. |
| 376 | 376 | */ |
| 377 | 377 | if (!node) { |
| 378 | + if (flags == BPF_EXIST) { | |
| 379 | + ret = -ENOENT; | |
| 380 | + goto out; | |
| 381 | + } | |
| 378 | 382 | rcu_assign_pointer(*slot, new_node); |
| 379 | 383 | goto out; |
| 380 | 384 | } |
| @@ -383,18 +387,31 @@ static long trie_update_elem(struct bpf_map *map, · 2 unmodified lines | ||
| 383 | 387 | * which already has the correct data array set. |
| 384 | 388 | */ |
| 385 | 389 | if (node->prefixlen == matchlen) { |
| 390 | + if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) { | |
| 391 | + if (flags == BPF_NOEXIST) { | |
| 392 | + ret = -EEXIST; | |
| 393 | + goto out; | |
| 394 | + } | |
| 395 | + trie->n_entries--; | |
| 396 | + } else if (flags == BPF_EXIST) { | |
| 397 | + ret = -ENOENT; | |
| 398 | + goto out; | |
| 399 | + } | |
| 400 | + | |
| 386 | 401 | new_node->child[0] = node->child[0]; |
| 387 | 402 | new_node->child[1] = node->child[1]; |
| 388 | 403 | |
| 389 | − if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) | |
| 390 | − trie->n_entries--; | |
| 391 | − | |
| 392 | 404 | rcu_assign_pointer(*slot, new_node); |
| 393 | 405 | free_node = node; |
| 394 | 406 | |
| 395 | 407 | goto out; |
| 396 | 408 | } |
| 397 | 409 | |
| 410 | + if (flags == BPF_EXIST) { | |
| 411 | + ret = -ENOENT; | |
| 412 | + goto out; | |
| 413 | + } | |
| 414 | + | |
| 398 | 415 | /* If the new node matches the prefix completely, it must be inserted |
| 399 | 416 | * as an ancestor. Simply insert it between @node and *@slot. |
| 400 | 417 | */ |