Skip to content

Commit

Permalink
lib: don't announce prefix delete for duplicates
Browse files Browse the repository at this point in the history
When deleting a duplicated prefix list entry don't announce the change
to route map listeners, otherwise they will be removing rules that
shouldn't be removed causing the prefix that still exist in the
prefix-list to be not evaluated anymore.

Signed-off-by: Rafael Zalamena <[email protected]>
  • Loading branch information
rzalamena committed Sep 22, 2023
1 parent 71fb99d commit aed94c8
Showing 1 changed file with 51 additions and 4 deletions.
55 changes: 51 additions & 4 deletions lib/plist.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,55 @@ static void prefix_list_trie_del(struct prefix_list *plist,
}
}

/**
* Find duplicated prefix entry (same prefix but different entry) in prefix
* list.
*/
static bool prefix_list_entry_is_duplicated(struct prefix_list *list,
struct prefix_list_entry *entry)
{
size_t depth, maxdepth = list->master->trie_depth;
uint8_t byte, *bytes = entry->prefix.u.val;
size_t validbits = entry->prefix.prefixlen;
struct pltrie_table *table = list->trie;
struct prefix_list_entry *pentry;

for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
byte = bytes[depth];
if (!table->entries[byte].next_table)
return NULL;

table = table->entries[byte].next_table;
validbits -= PLC_BITS;
}

byte = bytes[depth];
if (validbits > PLC_BITS)
pentry = table->entries[byte].final_chain;
else
pentry = table->entries[byte].up_chain;

for (; pentry; pentry = pentry->next_best) {
if (pentry == entry)
continue;
if (prefix_same(&pentry->prefix, &entry->prefix))
return true;
}

return false;
}

void prefix_list_entry_delete(struct prefix_list *plist,
struct prefix_list_entry *pentry,
int update_list)
{
bool duplicate;

if (plist == NULL || pentry == NULL)
return;

duplicate = prefix_list_entry_is_duplicated(plist, pentry);

prefix_list_trie_del(plist, pentry);

if (pentry->prev)
Expand All @@ -421,8 +462,10 @@ void prefix_list_entry_delete(struct prefix_list *plist,
else
plist->tail = pentry->prev;

route_map_notify_pentry_dependencies(plist->name, pentry,
RMAP_EVENT_PLIST_DELETED);
if (!duplicate)
route_map_notify_pentry_dependencies(plist->name, pentry,
RMAP_EVENT_PLIST_DELETED);

prefix_list_entry_free(pentry);

plist->count--;
Expand Down Expand Up @@ -557,11 +600,14 @@ static void prefix_list_entry_add(struct prefix_list *plist,
void prefix_list_entry_update_start(struct prefix_list_entry *ple)
{
struct prefix_list *pl = ple->pl;
bool duplicate;

/* Not installed, nothing to do. */
if (!ple->installed)
return;

duplicate = prefix_list_entry_is_duplicated(pl, ple);

prefix_list_trie_del(pl, ple);

/* List manipulation: shameless copy from `prefix_list_entry_delete`. */
Expand All @@ -574,8 +620,9 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple)
else
pl->tail = ple->prev;

route_map_notify_pentry_dependencies(pl->name, ple,
RMAP_EVENT_PLIST_DELETED);
if (!duplicate)
route_map_notify_pentry_dependencies(pl->name, ple,
RMAP_EVENT_PLIST_DELETED);
pl->count--;

route_map_notify_dependencies(pl->name, RMAP_EVENT_PLIST_DELETED);
Expand Down

0 comments on commit aed94c8

Please sign in to comment.