Merge pull request #6403 from NaveenThanikachalam/FRR_RMAP_FIX

lib: Fix erroneous r-map behavior
This commit is contained in:
Donald Sharp 2020-07-10 08:07:04 -04:00 committed by GitHub
commit f24db7598e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -47,18 +47,12 @@ DEFINE_QOBJ_TYPE(route_map)
#define IPv4_PREFIX_LIST "ip address prefix-list" #define IPv4_PREFIX_LIST "ip address prefix-list"
#define IPv6_PREFIX_LIST "ipv6 address prefix-list" #define IPv6_PREFIX_LIST "ipv6 address prefix-list"
#define IPv4_MATCH_RULE "ip "
#define IPv6_MATCH_RULE "ipv6 "
#define IS_RULE_IPv4_PREFIX_LIST(S) \ #define IS_RULE_IPv4_PREFIX_LIST(S) \
(strncmp(S, IPv4_PREFIX_LIST, strlen(IPv4_PREFIX_LIST)) == 0) (strncmp(S, IPv4_PREFIX_LIST, strlen(IPv4_PREFIX_LIST)) == 0)
#define IS_RULE_IPv6_PREFIX_LIST(S) \ #define IS_RULE_IPv6_PREFIX_LIST(S) \
(strncmp(S, IPv6_PREFIX_LIST, strlen(IPv6_PREFIX_LIST)) == 0) (strncmp(S, IPv6_PREFIX_LIST, strlen(IPv6_PREFIX_LIST)) == 0)
#define IS_IPv4_RULE(S) \
(strncmp(S, IPv4_MATCH_RULE, strlen(IPv4_MATCH_RULE)) == 0)
#define IS_IPv6_RULE(S) \
(strncmp(S, IPv6_MATCH_RULE, strlen(IPv6_MATCH_RULE)) == 0)
struct route_map_pentry_dep { struct route_map_pentry_dep {
struct prefix_list_entry *pentry; struct prefix_list_entry *pentry;
const char *plist_name; const char *plist_name;
@ -86,8 +80,6 @@ static void route_map_del_plist_entries(afi_t afi,
struct route_map_index *index, struct route_map_index *index,
const char *plist_name, const char *plist_name,
struct prefix_list_entry *entry); struct prefix_list_entry *entry);
static bool route_map_is_ip_rule_present(struct route_map_index *index);
static bool route_map_is_ipv6_rule_present(struct route_map_index *index);
static struct hash *route_map_get_dep_hash(route_map_event_t event); static struct hash *route_map_get_dep_hash(route_map_event_t event);
@ -1370,26 +1362,6 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
} else if (IS_RULE_IPv6_PREFIX_LIST(match_name)) { } else if (IS_RULE_IPv6_PREFIX_LIST(match_name)) {
route_map_pfx_tbl_update(RMAP_EVENT_PLIST_ADDED, index, AFI_IP6, route_map_pfx_tbl_update(RMAP_EVENT_PLIST_ADDED, index, AFI_IP6,
match_arg); match_arg);
} else {
/* If IPv4 match criteria has been added to the route-map
* index, check for IPv6 prefix-list match rule presence and
* remove this index from the trie node created for each of the
* prefix-entry within the prefix-list. If no IPv6 prefix-list
* match rule is present, remove this index from the IPv6
* default route's trie node.
*/
if (IS_IPv4_RULE(match_name))
route_map_del_plist_entries(AFI_IP6, index, NULL, NULL);
/* If IPv6 match criteria has been added to the route-map
* index, check for IPv4 prefix-list match rule presence and
* remove this index from the trie node created for each of the
* prefix-entry within the prefix-list. If no IPv4 prefix-list
* match rule is present, remove this index from the IPv4
* default route's trie node.
*/
else if (IS_IPv6_RULE(match_name))
route_map_del_plist_entries(AFI_IP, index, NULL, NULL);
} }
/* Execute event hook. */ /* Execute event hook. */
@ -1441,7 +1413,7 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
route_map_rule_delete(&index->match_list, rule); route_map_rule_delete(&index->match_list, rule);
/* If IPv4 or IPv6 prefix-list match criteria /* If IPv4 or IPv6 prefix-list match criteria
* has been delete to the route-map index, update * has been delete from the route-map index, update
* the route-map's prefix table. * the route-map's prefix table.
*/ */
if (IS_RULE_IPv4_PREFIX_LIST(match_name)) { if (IS_RULE_IPv4_PREFIX_LIST(match_name)) {
@ -1452,30 +1424,6 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
route_map_pfx_tbl_update( route_map_pfx_tbl_update(
RMAP_EVENT_PLIST_DELETED, index, RMAP_EVENT_PLIST_DELETED, index,
AFI_IP6, match_arg); AFI_IP6, match_arg);
} else {
/* If no more IPv4 match rules are present in
* this index, check for IPv6 prefix-list match
* rule presence and add this index to trie node
* created for each of the prefix-entry within
* the prefix-list. If no IPv6 prefix-list match
* rule is present, add this index to the IPv6
* default route's trie node.
*/
if (!route_map_is_ip_rule_present(index))
route_map_add_plist_entries(
AFI_IP6, index, NULL, NULL);
/* If no more IPv6 match rules are present in
* this index, check for IPv4 prefix-list match
* rule presence and add this index to trie node
* created for each of the prefix-entry within
* the prefix-list. If no IPv6 prefix-list match
* rule is present, add this index to the IPv4
* default route's trie node.
*/
if (!route_map_is_ipv6_rule_present(index))
route_map_add_plist_entries(
AFI_IP, index, NULL, NULL);
} }
return RMAP_COMPILE_SUCCESS; return RMAP_COMPILE_SUCCESS;
@ -1921,33 +1869,34 @@ static void route_map_pfx_table_del(struct route_table *table,
route_unlock_node(rn); route_unlock_node(rn);
} }
/* This function checks for the presence of an IPv4 match rule /* This function checks for the presence of an IPv4 prefix-list
* in the given route-map index. * match rule in the given route-map index.
*/ */
static bool route_map_is_ip_rule_present(struct route_map_index *index) static bool route_map_is_ip_pfx_list_rule_present(struct route_map_index *index)
{ {
struct route_map_rule_list *match_list = NULL; struct route_map_rule_list *match_list = NULL;
struct route_map_rule *rule = NULL; struct route_map_rule *rule = NULL;
match_list = &index->match_list; match_list = &index->match_list;
for (rule = match_list->head; rule; rule = rule->next) for (rule = match_list->head; rule; rule = rule->next)
if (IS_IPv4_RULE(rule->cmd->str)) if (IS_RULE_IPv4_PREFIX_LIST(rule->cmd->str))
return true; return true;
return false; return false;
} }
/* This function checks for the presence of an IPv6 match rule /* This function checks for the presence of an IPv6 prefix-list
* in the given route-map index. * match rule in the given route-map index.
*/ */
static bool route_map_is_ipv6_rule_present(struct route_map_index *index) static bool
route_map_is_ipv6_pfx_list_rule_present(struct route_map_index *index)
{ {
struct route_map_rule_list *match_list = NULL; struct route_map_rule_list *match_list = NULL;
struct route_map_rule *rule = NULL; struct route_map_rule *rule = NULL;
match_list = &index->match_list; match_list = &index->match_list;
for (rule = match_list->head; rule; rule = rule->next) for (rule = match_list->head; rule; rule = rule->next)
if (IS_IPv6_RULE(rule->cmd->str)) if (IS_RULE_IPv6_PREFIX_LIST(rule->cmd->str))
return true; return true;
return false; return false;
@ -2118,7 +2067,7 @@ static void route_map_trie_update(afi_t afi, route_map_event_t event,
{ {
if (event == RMAP_EVENT_PLIST_ADDED) { if (event == RMAP_EVENT_PLIST_ADDED) {
if (afi == AFI_IP) { if (afi == AFI_IP) {
if (!route_map_is_ipv6_rule_present(index)) { if (!route_map_is_ipv6_pfx_list_rule_present(index)) {
route_map_pfx_table_del_default(AFI_IP6, index); route_map_pfx_table_del_default(AFI_IP6, index);
route_map_add_plist_entries(afi, index, route_map_add_plist_entries(afi, index,
plist_name, NULL); plist_name, NULL);
@ -2127,7 +2076,7 @@ static void route_map_trie_update(afi_t afi, route_map_event_t event,
NULL, NULL); NULL, NULL);
} }
} else { } else {
if (!route_map_is_ip_rule_present(index)) { if (!route_map_is_ip_pfx_list_rule_present(index)) {
route_map_pfx_table_del_default(AFI_IP, index); route_map_pfx_table_del_default(AFI_IP, index);
route_map_add_plist_entries(afi, index, route_map_add_plist_entries(afi, index,
plist_name, NULL); plist_name, NULL);
@ -2141,22 +2090,36 @@ static void route_map_trie_update(afi_t afi, route_map_event_t event,
route_map_del_plist_entries(afi, index, plist_name, route_map_del_plist_entries(afi, index, plist_name,
NULL); NULL);
if (!route_map_is_ipv6_rule_present(index)) /* If IPv6 prefix-list match rule is not present,
* add this index to the IPv4 default route's trie
* node.
* Also, add this index to the trie nodes created
* for each of the prefix-entries within the IPv6
* prefix-list, if the IPv6 prefix-list match rule
* is present. Else, add this index to the IPv6
* default route's trie node.
*/
if (!route_map_is_ipv6_pfx_list_rule_present(index))
route_map_pfx_table_add_default(afi, index); route_map_pfx_table_add_default(afi, index);
if (!route_map_is_ip_rule_present(index)) route_map_add_plist_entries(AFI_IP6, index, NULL, NULL);
route_map_add_plist_entries(AFI_IP6, index,
NULL, NULL);
} else { } else {
route_map_del_plist_entries(afi, index, plist_name, route_map_del_plist_entries(afi, index, plist_name,
NULL); NULL);
if (!route_map_is_ip_rule_present(index)) /* If IPv4 prefix-list match rule is not present,
* add this index to the IPv6 default route's trie
* node.
* Also, add this index to the trie nodes created
* for each of the prefix-entries within the IPv4
* prefix-list, if the IPv4 prefix-list match rule
* is present. Else, add this index to the IPv4
* default route's trie node.
*/
if (!route_map_is_ip_pfx_list_rule_present(index))
route_map_pfx_table_add_default(afi, index); route_map_pfx_table_add_default(afi, index);
if (!route_map_is_ipv6_rule_present(index)) route_map_add_plist_entries(AFI_IP, index, NULL, NULL);
route_map_add_plist_entries(AFI_IP, index, NULL,
NULL);
} }
} }
} }
@ -2229,30 +2192,27 @@ static void route_map_pentry_update(route_map_event_t event,
} }
if (event == RMAP_EVENT_PLIST_ADDED) { if (event == RMAP_EVENT_PLIST_ADDED) {
if (plist->count == 1) { if (afi == AFI_IP) {
if (afi == AFI_IP) { if (!route_map_is_ipv6_pfx_list_rule_present(index))
if (!route_map_is_ipv6_rule_present(index)) route_map_add_plist_entries(afi, index,
route_map_add_plist_entries( plist_name, pentry);
afi, index, plist_name, pentry);
} else {
if (!route_map_is_ip_rule_present(index))
route_map_add_plist_entries(
afi, index, plist_name, pentry);
}
} else { } else {
route_map_add_plist_entries(afi, index, plist_name, if (!route_map_is_ip_pfx_list_rule_present(index))
pentry); route_map_add_plist_entries(afi, index,
plist_name, pentry);
} }
} else if (event == RMAP_EVENT_PLIST_DELETED) { } else if (event == RMAP_EVENT_PLIST_DELETED) {
route_map_del_plist_entries(afi, index, plist_name, pentry); route_map_del_plist_entries(afi, index, plist_name, pentry);
if (plist->count == 1) { if (plist->count == 1) {
if (afi == AFI_IP) { if (afi == AFI_IP) {
if (!route_map_is_ipv6_rule_present(index)) if (!route_map_is_ipv6_pfx_list_rule_present(
index))
route_map_pfx_table_add_default(afi, route_map_pfx_table_add_default(afi,
index); index);
} else { } else {
if (!route_map_is_ip_rule_present(index)) if (!route_map_is_ip_pfx_list_rule_present(
index))
route_map_pfx_table_add_default(afi, route_map_pfx_table_add_default(afi,
index); index);
} }