Skip to content

Commit

Permalink
lib/rib: enhance the longer iterator
Browse files Browse the repository at this point in the history
Add an option to bound RIB's longer iterator to the child prefixes
of the parent prefix.
  • Loading branch information
AltraMayor committed Jan 24, 2023
1 parent 5ef71ad commit 1ceee64
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 10 deletions.
2 changes: 1 addition & 1 deletion cps/rd.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ rd_getroute_family(const char *daemon, struct cps_config *cps_conf,
int ret;

spinlock_lock_with_yield(lock, cps_conf);
ret = rib_longer_iterator_state_init(&state, rib, NULL, 0);
ret = rib_longer_iterator_state_init(&state, rib, NULL, 0, false);
if (unlikely(ret < 0)) {
rte_spinlock_unlock_tm(lock);
G_LOG(ERR, "%s(): failed to initialize the %s RIB iterator (errno=%i): %s\n",
Expand Down
14 changes: 12 additions & 2 deletions gk/rt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1547,7 +1547,17 @@ check_longer_prefixes(const char *context, const struct rib_head *rib,
const char *prefix_str, enum gk_fib_action prefix_action)
{
struct rib_longer_iterator_state state;
int ret = rib_longer_iterator_state_init(&state, rib, ip, depth);
/*
* @stop_at_children can be true because
*
* (1) if a child is not GK_FWD_GRANTOR, nor GK_DROP,
* the test will already fail;
*
* (2) if a child is either GK_FWD_GRANTOR, or GK_DROP,
* the grand-children (if they exist) must be safe.
* Otherwise, the child would not have been eadded.
*/
int ret = rib_longer_iterator_state_init(&state, rib, ip, depth, true);
if (unlikely(ret < 0)) {
G_LOG(ERR, "%s(%s): failed to initialize the %s RIB iterator (errno=%i): %s\n",
__func__, prefix_str, context, -ret, strerror(-ret));
Expand Down Expand Up @@ -2104,7 +2114,7 @@ list_fib_entries(lua_State *l, const char *context, const struct rib_head *rib,
int ret;

rte_spinlock_lock_tm(lock);
ret = rib_longer_iterator_state_init(&state, rib, NULL, 0);
ret = rib_longer_iterator_state_init(&state, rib, NULL, 0, false);
if (unlikely(ret < 0)) {
rte_spinlock_unlock_tm(lock);
luaL_error(l, "%s(): failed to initialize the %s RIB iterator (errno=%d): %s",
Expand Down
33 changes: 27 additions & 6 deletions include/gatekeeper_rib.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define _GATEKEEPER_GK_RIB_H_

#include <stdint.h>
#include <stdbool.h>
#include <setjmp.h>

#include <rte_mempool.h>
Expand Down Expand Up @@ -210,6 +211,11 @@ struct rib_longer_iterator_state {
struct rib_node_info start_info;
/* The minimum depth of prefix in field @next_address; the scope. */
uint8_t min_depth;
/*
* If true, do not enumerate prefixes longer than the child prefixes
* of the parent prefix.
*/
bool stop_at_children;

/*
* The following fields are used in between calls of
Expand All @@ -229,8 +235,8 @@ struct rib_longer_iterator_state {
bool has_ended;

/*
* The following fields are set and only valid while execution is in
* rib_longer_iterator_next().
* The following fields are set and only valid while the execution is
* in rib_longer_iterator_next().
*/

/* When true, keep looking for prefixes greater than @next_address. */
Expand All @@ -252,13 +258,27 @@ struct rib_longer_iterator_state {
* The first call of rib_longer_iterator_next() returns a rule whose prefix
* is at least as deeper as @depth.
*
* Passing @address = NULL (or any other value) and @depth = 0 iterates
* over the whole RIB; including the default rule
* (i.e. the zero-length prefix).
* Rules are returned such that prefixes are in increasing order
* (e.g. 10.2/16 > 10.1/16). Longer prefixes are greater than
* shorter sub-prefixes (e.g. 10.2/16 > 10/8).
* Notice that 10.2/16 is greater than 10.1.255.255/32.
*
* Passing @address = NULL (or any other value) and @depth = 0 and
* @stop_at_children = false iterates over the whole RIB;
* including the default rule (i.e. the zero-length prefix).
*
* @address is in network order (big endian).
* @address == NULL is equivalent to the all-zero address.
*
* When @stop_at_children is true, only the prefix @address/@depth
* (if it exists) and its children prefixes are enumerated.
* In a RIB with 10/8, 10.1/16, 10.2/16, 10.2.2/24, the longer iterator
* will list all prefixes when @address = 10.X.X.X and @depth = 8 and
* @stop_at_children = false, but will not list 10.2.2/24 when
* @stop_at_children = true.
*
* The parent prefix is @address/@depth.
*
* If the RIB changes (i.e. rules are added or deleted)
* between the call of this function and the call of
* rib_longer_iterator_next(), or between two consecutive calls of
Expand All @@ -267,7 +287,8 @@ struct rib_longer_iterator_state {
* the initial prefix) and that are after the next rule.
*/
int rib_longer_iterator_state_init(struct rib_longer_iterator_state *state,
const struct rib_head *rib, const uint8_t *address, uint8_t depth);
const struct rib_head *rib, const uint8_t *address, uint8_t depth,
bool stop_at_children);

/*
* When a rule is found, this function updates @rule and returns zero.
Expand Down
11 changes: 10 additions & 1 deletion lib/rib.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,8 @@ scope_longer_iterator(struct rib_longer_iterator_state *state)

int
rib_longer_iterator_state_init(struct rib_longer_iterator_state *state,
const struct rib_head *rib, const uint8_t *address, uint8_t depth)
const struct rib_head *rib, const uint8_t *address, uint8_t depth,
bool stop_at_children)
{
int ret;

Expand All @@ -853,6 +854,7 @@ rib_longer_iterator_state_init(struct rib_longer_iterator_state *state,

state->rib = rib;
state->min_depth = depth;
state->stop_at_children = stop_at_children;
state->next_depth = depth;
state->has_ended = false;
scope_longer_iterator(state);
Expand Down Expand Up @@ -966,6 +968,13 @@ __rib_longer_iterator_next(struct rib_longer_iterator_state *state,
state->rule->depth = info.depth;
state->rule->next_hop = cur_node->next_hop;
/* Still missing the next rule after the found rule. */

/*
* The test info.depth > state->min_depth is needed to
* avoid only listing the parent prefix if it exists.
*/
if (state->stop_at_children && info.depth > state->min_depth)
return;
}

__rib_longer_iterator_next(state, cur_node->branch[false], info);
Expand Down

0 comments on commit 1ceee64

Please sign in to comment.