Skip to content
Permalink
Browse files

Merge pull request #2818 from kssoman/rmap_fix

Zebra does not properly track which route-maps are changed (#2493)
  • Loading branch information...
donaldsharp committed Aug 22, 2018
2 parents 46a67d2 + 01ba450 commit dca5ef30533ab2a7a5573f065537e7a05067bec7
Showing with 139 additions and 22 deletions.
  1. +3 −4 zebra/redistribute.c
  2. +1 −2 zebra/redistribute.h
  3. +2 −0 zebra/rib.h
  4. +9 −4 zebra/zebra_rib.c
  5. +124 −12 zebra/zebra_routemap.c
@@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty)
return write;
}

void zebra_import_table_rm_update()
void zebra_import_table_rm_update(const char *rmap)
{
afi_t afi;
int i;
@@ -730,9 +730,8 @@ void zebra_import_table_rm_update()
continue;

rmap_name = zebra_get_import_table_route_map(afi, i);
if (!rmap_name)
return;

if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
continue;
table = zebra_vrf_other_route_table(afi, i,
VRF_DEFAULT);
for (rn = route_top(table); rn; rn = route_next(rn)) {
@@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id);

extern int zebra_import_table_config(struct vty *);

extern void zebra_import_table_rm_update(void);

extern void zebra_import_table_rm_update(const char *rmap);
#endif /* _ZEBRA_REDISTRIBUTE_H */
@@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
vrf_id_t vrf_id);

extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
extern void rib_update_table(struct route_table *table,
rib_update_event_t event);
extern void rib_sweep_route(void);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);
@@ -2651,8 +2651,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}

/* Schedule routes of a particular table (address-family) based on event. */
static void rib_update_table(struct route_table *table,
rib_update_event_t event)
void rib_update_table(struct route_table *table, rib_update_event_t event)
{
struct route_node *rn;
struct route_entry *re, *next;
@@ -2732,12 +2731,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event)

/* Process routes of interested address-families. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
if (table)
if (table) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP event %d", __func__, event);
rib_update_table(table, event);
}

table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
if (table)
if (table) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP6 event %d", __func__, event);
rib_update_table(table, event);
}
}

/* Delete self installed routes after zebra is relaunched. */
@@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */

static route_map_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
route_match_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object, afi_t afi)
{
struct prefix_list *plist;

if (type == RMAP_ZEBRA) {
plist = prefix_list_lookup(AFI_IP, (char *)rule);
plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL)
return RMAP_NOMATCH;

@@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
return RMAP_NOMATCH;
}

static void *route_match_ip_address_prefix_list_compile(const char *arg)
static route_map_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
return (route_match_address_prefix_list(rule, prefix, type, object,
AFI_IP));
}

static void *route_match_address_prefix_list_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}

static void route_match_ip_address_prefix_list_free(void *rule)
static void route_match_address_prefix_list_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}

static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
"ip address prefix-list", route_match_ip_address_prefix_list,
route_match_ip_address_prefix_list_compile,
route_match_ip_address_prefix_list_free};
route_match_address_prefix_list_compile,
route_match_address_prefix_list_free};

static route_map_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
return (route_match_address_prefix_list(rule, prefix, type, object,
AFI_IP6));
}

static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
"ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
route_match_address_prefix_list_compile,
route_match_address_prefix_list_free};

/* `match ip address prefix-len PREFIXLEN' */

@@ -1281,11 +1301,101 @@ static struct route_map_rule_cmd route_set_src_cmd = {
"src", route_set_src, route_set_src_compile, route_set_src_free,
};

/* The function checks if the changed routemap specified by parameter rmap
* matches the configured protocol routemaps in proto_rm table. If there is
* a match then rib_update_table() to process the routes.
*/
static void zebra_rib_table_rm_update(const char *rmap)
{
int i = 0;
struct route_table *table;
char *rmap_name;
char afi_ip = 0;
char afi_ipv6 = 0;

for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
/* Check for ip routemap table */
rmap_name = proto_rm[AFI_IP][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP rmap %s, route type %s",
__func__, rmap, zebra_route_string(i));
/* There is single rib table for all protocols */
if (afi_ip == 0) {
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST,
VRF_DEFAULT);
if (table) {
afi_ip = 1;
rib_update_table(table,
RIB_UPDATE_RMAP_CHANGE);
}
}
}

/* Check for ipv6 routemap table */
rmap_name = proto_rm[AFI_IP6][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP6 rmap %s,route type %s",
__func__, rmap, zebra_route_string(i));
if (afi_ipv6 == 0) {
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST,
VRF_DEFAULT);
if (table) {
afi_ipv6 = 1;
rib_update_table(table,
RIB_UPDATE_RMAP_CHANGE);
}
}
}
}
}

/* The function checks if the changed routemap specified by parameter rmap
* matches the configured protocol routemaps in nht_rm table. If there is
* a match then zebra_evaluate_rnh() to process the nexthops.
*/
static void zebra_nht_rm_update(const char *rmap)
{
int i = 0;
char *rmap_name;
char afi_ip = 0;
char afi_ipv6 = 0;

for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
rmap_name = nht_rm[AFI_IP][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP rmap %s route type %s",
__func__, rmap, zebra_route_string(i));
if (afi_ip == 0) {
afi_ip = 1;
zebra_evaluate_rnh(0, AF_INET, 1,
RNH_NEXTHOP_TYPE, NULL);
}
}
rmap_name = nht_rm[AFI_IP6][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP6 rmap %s route type %s",
__func__, rmap, zebra_route_string(i));
if (afi_ipv6 == 0) {
afi_ipv6 = 1;
zebra_evaluate_rnh(0, AF_INET6, 1,
RNH_NEXTHOP_TYPE, NULL);
}
}
}
}

static void zebra_route_map_process_update_cb(char *rmap_name)
{
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("Event handler for route-map: %s",
rmap_name);
zebra_import_table_rm_update(rmap_name);
zebra_rib_table_rm_update(rmap_name);
zebra_nht_rm_update(rmap_name);
}

static int zebra_route_map_update_timer(struct thread *thread)
@@ -1307,11 +1417,6 @@ static int zebra_route_map_update_timer(struct thread *thread)
* 1) VRF Aware <sigh>
* 2) Route-map aware
*/
zebra_import_table_rm_update();
rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);

return (0);
}

@@ -1555,12 +1660,19 @@ void zebra_route_map_init()
route_map_match_tag_hook(generic_match_add);
route_map_no_match_tag_hook(generic_match_delete);

route_map_match_ipv6_address_hook(generic_match_add);
route_map_no_match_ipv6_address_hook(generic_match_delete);

route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);

route_map_install_match(&route_match_tag_cmd);
route_map_install_match(&route_match_interface_cmd);
route_map_install_match(&route_match_ip_next_hop_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_cmd);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_prefix_len_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);

0 comments on commit dca5ef3

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.