diff options
Diffstat (limited to 'lib/plist.c')
| -rw-r--r-- | lib/plist.c | 109 |
1 files changed, 85 insertions, 24 deletions
diff --git a/lib/plist.c b/lib/plist.c index e286a32f92..618d92b549 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -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) @@ -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--; @@ -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`. */ @@ -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); @@ -1182,7 +1229,7 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name, DEFPY (show_ip_prefix_list, show_ip_prefix_list_cmd, - "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]] [json$uj]", + "show ip prefix-list [PREFIXLIST4_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]", SHOW_STR IP_STR PREFIX_LIST_STR @@ -1195,13 +1242,13 @@ DEFPY (show_ip_prefix_list, if (dseq) dtype = sequential_display; - return vty_show_prefix_list(vty, AFI_IP, prefix_list, arg_str, dtype, + return vty_show_prefix_list(vty, AFI_IP, name, arg_str, dtype, !!uj); } DEFPY (show_ip_prefix_list_prefix, show_ip_prefix_list_prefix_cmd, - "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]", + "show ip prefix-list PREFIXLIST4_NAME$name A.B.C.D/M$prefix [longer$dl|first-match$dfm]", SHOW_STR IP_STR PREFIX_LIST_STR @@ -1216,13 +1263,13 @@ DEFPY (show_ip_prefix_list_prefix, else if (dfm) dtype = first_match_display; - return vty_show_prefix_list_prefix(vty, AFI_IP, prefix_list, prefix_str, + return vty_show_prefix_list_prefix(vty, AFI_IP, name, prefix_str, dtype); } DEFPY (show_ip_prefix_list_summary, show_ip_prefix_list_summary_cmd, - "show ip prefix-list summary [WORD$prefix_list] [json$uj]", + "show ip prefix-list summary [PREFIXLIST4_NAME$name] [json$uj]", SHOW_STR IP_STR PREFIX_LIST_STR @@ -1230,13 +1277,13 @@ DEFPY (show_ip_prefix_list_summary, "Name of a prefix list\n" JSON_STR) { - return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL, + return vty_show_prefix_list(vty, AFI_IP, name, NULL, summary_display, !!uj); } DEFPY (show_ip_prefix_list_detail, show_ip_prefix_list_detail_cmd, - "show ip prefix-list detail [WORD$prefix_list] [json$uj]", + "show ip prefix-list detail [PREFIXLIST4_NAME$name] [json$uj]", SHOW_STR IP_STR PREFIX_LIST_STR @@ -1244,25 +1291,25 @@ DEFPY (show_ip_prefix_list_detail, "Name of a prefix list\n" JSON_STR) { - return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL, + return vty_show_prefix_list(vty, AFI_IP, name, NULL, detail_display, !!uj); } DEFPY (clear_ip_prefix_list, clear_ip_prefix_list_cmd, - "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]", + "clear ip prefix-list [PREFIXLIST4_NAME$name [A.B.C.D/M$prefix]]", CLEAR_STR IP_STR PREFIX_LIST_STR "Name of a prefix list\n" "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") { - return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str); + return vty_clear_prefix_list(vty, AFI_IP, name, prefix_str); } DEFPY (show_ipv6_prefix_list, show_ipv6_prefix_list_cmd, - "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]] [json$uj]", + "show ipv6 prefix-list [PREFIXLIST6_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]", SHOW_STR IPV6_STR PREFIX_LIST_STR @@ -1275,13 +1322,13 @@ DEFPY (show_ipv6_prefix_list, if (dseq) dtype = sequential_display; - return vty_show_prefix_list(vty, AFI_IP6, prefix_list, arg_str, dtype, + return vty_show_prefix_list(vty, AFI_IP6, name, arg_str, dtype, !!uj); } DEFPY (show_ipv6_prefix_list_prefix, show_ipv6_prefix_list_prefix_cmd, - "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]", + "show ipv6 prefix-list PREFIXLIST6_NAME$name X:X::X:X/M$prefix [longer$dl|first-match$dfm]", SHOW_STR IPV6_STR PREFIX_LIST_STR @@ -1296,13 +1343,13 @@ DEFPY (show_ipv6_prefix_list_prefix, else if (dfm) dtype = first_match_display; - return vty_show_prefix_list_prefix(vty, AFI_IP6, prefix_list, + return vty_show_prefix_list_prefix(vty, AFI_IP6, name, prefix_str, dtype); } DEFPY (show_ipv6_prefix_list_summary, show_ipv6_prefix_list_summary_cmd, - "show ipv6 prefix-list summary [WORD$prefix-list] [json$uj]", + "show ipv6 prefix-list summary [PREFIXLIST6_NAME$name] [json$uj]", SHOW_STR IPV6_STR PREFIX_LIST_STR @@ -1310,13 +1357,13 @@ DEFPY (show_ipv6_prefix_list_summary, "Name of a prefix list\n" JSON_STR) { - return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL, + return vty_show_prefix_list(vty, AFI_IP6, name, NULL, summary_display, !!uj); } DEFPY (show_ipv6_prefix_list_detail, show_ipv6_prefix_list_detail_cmd, - "show ipv6 prefix-list detail [WORD$prefix-list] [json$uj]", + "show ipv6 prefix-list detail [PREFIXLIST6_NAME$name] [json$uj]", SHOW_STR IPV6_STR PREFIX_LIST_STR @@ -1324,20 +1371,20 @@ DEFPY (show_ipv6_prefix_list_detail, "Name of a prefix list\n" JSON_STR) { - return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL, + return vty_show_prefix_list(vty, AFI_IP6, name, NULL, detail_display, !!uj); } DEFPY (clear_ipv6_prefix_list, clear_ipv6_prefix_list_cmd, - "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]", + "clear ipv6 prefix-list [PREFIXLIST6_NAME$name [X:X::X:X/M$prefix]]", CLEAR_STR IPV6_STR PREFIX_LIST_STR "Name of a prefix list\n" "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") { - return vty_clear_prefix_list(vty, AFI_IP6, prefix_list, prefix_str); + return vty_clear_prefix_list(vty, AFI_IP6, name, prefix_str); } DEFPY (debug_prefix_list_match, @@ -1585,12 +1632,26 @@ static void plist_autocomplete(vector comps, struct cmd_token *token) plist_autocomplete_afi(AFI_IP6, comps, token); } +static void plist4_autocomplete(vector comps, struct cmd_token *token) +{ + plist_autocomplete_afi(AFI_IP, comps, token); +} + +static void plist6_autocomplete(vector comps, struct cmd_token *token) +{ + plist_autocomplete_afi(AFI_IP6, comps, token); +} + static const struct cmd_variable_handler plist_var_handlers[] = { {/* "prefix-list WORD" */ .varname = "prefix_list", .completions = plist_autocomplete}, {.tokenname = "PREFIXLIST_NAME", .completions = plist_autocomplete}, + {.tokenname = "PREFIXLIST4_NAME", + .completions = plist4_autocomplete}, + {.tokenname = "PREFIXLIST6_NAME", + .completions = plist6_autocomplete}, {.completions = NULL}}; |
