Skip to content

Commit

Permalink
lib: Optimizing route-maps - Part-2
Browse files Browse the repository at this point in the history
This commit introduces the logic that computes the best-match route-map index
for a given prefix.

Signed-off-by: NaveenThanikachalam <nthanikachal@vmware.com>
  • Loading branch information
NaveenThanikachalam committed Nov 2, 2019
1 parent de20581 commit 2026fc4
Showing 1 changed file with 150 additions and 11 deletions.
161 changes: 150 additions & 11 deletions lib/routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,115 @@ route_map_apply_match(struct route_map_rule_list *match_list,
return ret;
}

static struct list *
route_map_get_index_list(struct route_node **rn,
const struct prefix *prefix,
struct route_table *table)
{
struct route_node *tmp_rn = NULL;

if (!(*rn)) {
*rn = route_node_match(table, prefix);

if (!(*rn))
return NULL;

if ((*rn)->info)
return (struct list *)((*rn)->info);

/* If rn->info is NULL, get the parent.
* Store the rn in tmp_rn and unlock it later.
*/
tmp_rn = *rn;
}

do {
*rn = (*rn)->parent;
if (tmp_rn)
route_unlock_node(tmp_rn);

if (!(*rn))
break;

if ((*rn)->info) {
route_lock_node(*rn);
return (struct list *)((*rn)->info);
}
} while (!(*rn)->info);

return NULL;
}

/*
* This function returns the route-map index that best matches the prefix.
*/
static struct route_map_index *
route_map_get_index(struct route_map *map,
const struct prefix *prefix,
route_map_object_t type,
void *object,
uint8_t *match_ret)
{
int ret = 0;
struct list *candidate_rmap_list = NULL;
struct route_node *rn = NULL;
struct listnode *ln = NULL, *nn = NULL;
struct route_map_index *index = NULL, *best_index = NULL;
struct route_map_index *head_index = NULL;
struct route_table *table = NULL;
unsigned char family = prefix->family;

if (family == AF_INET)
table = map->ipv4_prefix_table;
else
table = map->ipv6_prefix_table;

if (!table)
return NULL;

do {
candidate_rmap_list = route_map_get_index_list(&rn, prefix,
table);
if (!rn)
break;

/* If the index at the head of the list is of seq higher
* than that in best_index, ignore the list and get the
* parent node's list.
*/
head_index = (struct route_map_index *)
(listgetdata(listhead(candidate_rmap_list)));
if (best_index && head_index &&
(best_index->pref < head_index->pref)) {
route_unlock_node(rn);
continue;
}

for (ALL_LIST_ELEMENTS(candidate_rmap_list, ln, nn, index)) {
/* If the index is of seq higher than that in
* best_index, ignore the list and get the parent
* node's list.
*/
if (best_index && (best_index->pref < index->pref))
break;

ret = route_map_apply_match(&index->match_list,
prefix, type, object);

if (ret != RMAP_NOMATCH) {
best_index = index;
*match_ret = ret;
break;
}
}

route_unlock_node(rn);

} while (rn);

return best_index;
}

static int
route_map_candidate_list_cmp(struct route_map_index *idx1,
struct route_map_index *idx2)
Expand Down Expand Up @@ -2511,9 +2620,10 @@ route_map_result_t route_map_apply(struct route_map *map,
static int recursion = 0;
enum route_map_cmd_result_t match_ret = RMAP_NOMATCH;
route_map_result_t ret = RMAP_PERMITMATCH;
struct route_map_index *index;
struct route_map_rule *set;
struct route_map_index *index = NULL;
struct route_map_rule *set = NULL;
char buf[PREFIX_STRLEN];
bool skip_match_clause = false;

if (recursion > RMAP_RECURSION_LIMIT) {
flog_warn(
Expand All @@ -2530,18 +2640,45 @@ route_map_result_t route_map_apply(struct route_map *map,
}

map->applied++;
for (index = map->head; index; index = index->next) {
/* Apply this index. */
index->applied++;
match_ret = route_map_apply_match(&index->match_list, prefix,
type, object);

if ((!map->optimization_disabled) &&
(map->ipv4_prefix_table ||
map->ipv6_prefix_table)) {
index = route_map_get_index(map, prefix,
type, object,
(uint8_t *)&match_ret);
if (rmap_debug) {
zlog_debug("Route-map: %s, sequence: %d, prefix: %s, result: %s",
map->name, index->pref,
prefix2str(prefix, buf, sizeof(buf)),
route_map_cmd_result_str(match_ret));
if (index) {
zlog_debug(
"Best match route-map: %s, sequence: %d for pfx: %s, result: %s",
map->name, index->pref,
prefix2str(prefix, buf, sizeof(buf)),
route_map_cmd_result_str(match_ret));
} else
zlog_debug("No match for pfx: %s in route-map: %s",
prefix2str(prefix, buf, sizeof(buf)),
map->name);
}
skip_match_clause = true;
} else {
index = map->head;
}

for (; index; index = index->next) {
if (skip_match_clause == false) {
/* Apply this index. */
match_ret = route_map_apply_match(&index->match_list,
prefix, type, object);
if (rmap_debug) {
zlog_debug(
"Route-map: %s, sequence: %d, prefix: %s, result: %s",
map->name, index->pref,
prefix2str(prefix, buf, sizeof(buf)),
route_map_cmd_result_str(match_ret));
}
} else
skip_match_clause = false;


/* Now we apply the matrix from above */
if (match_ret == RMAP_NOOP)
Expand Down Expand Up @@ -2645,6 +2782,8 @@ route_map_result_t route_map_apply(struct route_map *map,
}
}

ret = RMAP_DENYMATCH;

route_map_apply_end:
if (rmap_debug) {
zlog_debug("Route-map: %s, prefix: %s, result: %s",
Expand Down

0 comments on commit 2026fc4

Please sign in to comment.