diff options
Diffstat (limited to 'lib/routemap.c')
| -rw-r--r-- | lib/routemap.c | 196 |
1 files changed, 174 insertions, 22 deletions
diff --git a/lib/routemap.c b/lib/routemap.c index 9336154b1a..2fee3a479e 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -112,14 +112,14 @@ struct route_map_match_set_hooks { const char *arg, route_map_event_t type); - /* match ip next hop type */ + /* match ip next-hop type */ int (*match_ip_next_hop_type)(struct vty *vty, struct route_map_index *index, const char *command, const char *arg, route_map_event_t type); - /* no match ip next hop type */ + /* no match ip next-hop type */ int (*no_match_ip_next_hop_type)(struct vty *vty, struct route_map_index *index, const char *command, @@ -160,7 +160,7 @@ struct route_map_match_set_hooks { const char *arg, route_map_event_t type); - /* no match ipv6next-hop type */ + /* no match ipv6 next-hop type */ int (*no_match_ipv6_next_hop_type)(struct vty *vty, struct route_map_index *index, const char *command, const char *arg, @@ -303,7 +303,7 @@ void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)( rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func; } -/* match ip next hop type */ +/* match ip next-hop type */ void route_map_match_ip_next_hop_type_hook(int (*func)( struct vty *vty, struct route_map_index *index, const char *command, const char *arg, route_map_event_t type)) @@ -311,7 +311,7 @@ void route_map_match_ip_next_hop_type_hook(int (*func)( rmap_match_set_hook.match_ip_next_hop_type = func; } -/* no match ip next hop type */ +/* no match ip next-hop type */ void route_map_no_match_ip_next_hop_type_hook(int (*func)( struct vty *vty, struct route_map_index *index, const char *command, const char *arg, route_map_event_t type)) @@ -688,7 +688,7 @@ static unsigned int route_map_dep_hash_make_key(const void *p); static void route_map_clear_all_references(char *rmap_name); static void route_map_rule_delete(struct route_map_rule_list *, struct route_map_rule *); -static int rmap_debug = 0; +static bool rmap_debug; static void route_map_index_delete(struct route_map_index *, int); @@ -739,6 +739,9 @@ static struct route_map *route_map_add(const char *name) (*route_map_master.add_hook)(name); route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED); } + + if (rmap_debug) + zlog_debug("Add route-map %s", name); return map; } @@ -757,6 +760,9 @@ static void route_map_free_map(struct route_map *map) while ((index = map->head) != NULL) route_map_index_delete(index, 0); + if (rmap_debug) + zlog_debug("Deleting route-map %s", map->name); + list = &route_map_master; QOBJ_UNREG(map); @@ -921,6 +927,24 @@ static const char *route_map_type_str(enum route_map_type type) return ""; } +static const char *route_map_result_str(route_map_result_t res) +{ + switch (res) { + case RMAP_MATCH: + return "match"; + case RMAP_DENYMATCH: + return "deny"; + case RMAP_NOMATCH: + return "no match"; + case RMAP_ERROR: + return "error"; + case RMAP_OKAY: + return "okay"; + } + + return "invalid"; +} + static int route_map_empty(struct route_map *map) { if (map->head == NULL && map->tail == NULL) @@ -936,12 +960,12 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map) struct route_map_rule *rule; vty_out(vty, "route-map: %s Invoked: %" PRIu64 "\n", - map->name, map->applied); + map->name, map->applied - map->applied_clear); for (index = map->head; index; index = index->next) { vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n", route_map_type_str(index->type), index->pref, - index->applied); + index->applied - index->applied_clear); /* Description */ if (index->description) @@ -1066,6 +1090,10 @@ static void route_map_index_delete(struct route_map_index *index, int notify) QOBJ_UNREG(index); + if (rmap_debug) + zlog_debug("Deleting route-map %s sequence %d", + index->map->name, index->pref); + /* Free route match. */ while ((rule = index->match_list.head) != NULL) route_map_rule_delete(&index->match_list, rule); @@ -1152,6 +1180,11 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref) (*route_map_master.event_hook)(map->name); route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED); } + + if (rmap_debug) + zlog_debug("Route-map %s add sequence %d, type: %s", + map->name, pref, route_map_type_str(type)); + return index; } @@ -1612,6 +1645,7 @@ route_map_result_t route_map_apply(struct route_map *map, int ret = 0; struct route_map_index *index; struct route_map_rule *set; + char buf[PREFIX_STRLEN]; if (recursion > RMAP_RECURSION_LIMIT) { flog_warn( @@ -1622,8 +1656,10 @@ route_map_result_t route_map_apply(struct route_map *map, return RMAP_DENYMATCH; } - if (map == NULL) - return RMAP_DENYMATCH; + if (map == NULL) { + ret = RMAP_DENYMATCH; + goto route_map_apply_end; + } map->applied++; for (index = map->head; index; index = index->next) { @@ -1632,6 +1668,13 @@ route_map_result_t route_map_apply(struct route_map *map, 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_result_str(ret)); + } + /* Now we apply the matrix from above */ if (ret == RMAP_NOMATCH) /* 'cont' from matrix - continue to next route-map @@ -1666,12 +1709,12 @@ route_map_result_t route_map_apply(struct route_map *map, /* If nextrm returned 'deny', finish. */ if (ret == RMAP_DENYMATCH) - return ret; + goto route_map_apply_end; } switch (index->exitpolicy) { case RMAP_EXIT: - return ret; + goto route_map_apply_end; case RMAP_NEXT: continue; case RMAP_GOTO: { @@ -1686,19 +1729,30 @@ route_map_result_t route_map_apply(struct route_map *map, } if (next == NULL) { /* No clauses match! */ - return ret; + goto route_map_apply_end; } } } } else if (index->type == RMAP_DENY) /* 'deny' */ { - return RMAP_DENYMATCH; + ret = RMAP_DENYMATCH; + goto route_map_apply_end; } } } /* Finally route-map does not match at all. */ - return RMAP_DENYMATCH; + ret = RMAP_DENYMATCH; + +route_map_apply_end: + if (rmap_debug) { + zlog_debug("Route-map: %s, prefix: %s, result: %s", + (map ? map->name : "null"), + prefix2str(prefix, buf, sizeof(buf)), + route_map_result_str(ret)); + } + + return (ret); } void route_map_add_hook(void (*func)(const char *)) @@ -1835,8 +1889,8 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name, case RMAP_EVENT_CALL_ADDED: case RMAP_EVENT_FILTER_ADDED: if (rmap_debug) - zlog_debug("%s: Adding dependency for %s in %s", - __FUNCTION__, dep_name, rmap_name); + zlog_debug("Adding dependency for filter %s in route-map %s", + dep_name, rmap_name); dep = (struct route_map_dep *)hash_get( dephash, dname, route_map_dep_hash_alloc); if (!dep) { @@ -1864,8 +1918,8 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name, case RMAP_EVENT_CALL_DELETED: case RMAP_EVENT_FILTER_DELETED: if (rmap_debug) - zlog_debug("%s: Deleting dependency for %s in %s", - __FUNCTION__, dep_name, rmap_name); + zlog_debug("Deleting dependency for filter %s in route-map %s", + dep_name, rmap_name); dep = (struct route_map_dep *)hash_get(dephash, dname, NULL); if (!dep) { goto out; @@ -1979,8 +2033,7 @@ static void route_map_process_dependency(struct hash_bucket *bucket, void *data) rmap_name = dep_data->rname; if (rmap_debug) - zlog_debug("%s: Notifying %s of dependency", - __FUNCTION__, rmap_name); + zlog_debug("Notifying %s of dependency", rmap_name); if (route_map_master.event_hook) (*route_map_master.event_hook)(rmap_name); } @@ -2027,6 +2080,8 @@ void route_map_notify_dependencies(const char *affected_name, if (!dep->this_hash) dep->this_hash = upd8_hash; + if (rmap_debug) + zlog_debug("Filter %s updated", dep->dep_name); hash_iterate(dep->dep_rmap_hash, route_map_process_dependency, (void *)event); } @@ -2379,7 +2434,7 @@ DEFUN (no_match_ipv6_address_prefix_list, DEFUN(match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd, "match ipv6 next-hop type <blackhole>", MATCH_STR IPV6_STR - "Match address of route\n" + "Match next-hop address of route\n" "Match entries by type\n" "Blackhole\n") { @@ -2901,6 +2956,46 @@ DEFUN (no_rmap_continue, return no_rmap_onmatch_goto(self, vty, argc, argv); } +static void clear_route_map_helper(struct route_map *map) +{ + struct route_map_index *index; + + map->applied_clear = map->applied; + for (index = map->head; index; index = index->next) + index->applied_clear = index->applied; +} + +DEFUN (rmap_clear_counters, + rmap_clear_counters_cmd, + "clear route-map counters [WORD]", + CLEAR_STR + "route-map information\n" + "counters associated with the specified route-map\n" + "route-map name\n") +{ + int idx_word = 2; + struct route_map *map; + + const char *name = (argc == 3 ) ? argv[idx_word]->arg : NULL; + + if (name) { + map = route_map_lookup_by_name(name); + + if (map) + clear_route_map_helper(map); + else { + vty_out(vty, "%s: 'route-map %s' not found\n", + frr_protonameinst, name); + return CMD_SUCCESS; + } + } else { + for (map = route_map_master.head; map; map = map->next) + clear_route_map_helper(map); + } + + return CMD_SUCCESS; + +} DEFUN (rmap_show_name, rmap_show_name_cmd, @@ -3006,6 +3101,30 @@ DEFUN (no_rmap_description, return CMD_SUCCESS; } +DEFUN (debug_rmap, + debug_rmap_cmd, + "debug route-map", + DEBUG_STR + "Debug option set for route-maps\n") +{ + rmap_debug = true; + return CMD_SUCCESS; +} + +DEFUN (no_debug_rmap, + no_debug_rmap_cmd, + "no debug route-map", + NO_STR + DEBUG_STR + "Debug option set for route-maps\n") +{ + rmap_debug = false; + return CMD_SUCCESS; +} + +/* Debug node. */ +static struct cmd_node rmap_debug_node = {RMAP_DEBUG_NODE, "", 1}; + /* Configuration write function. */ static int route_map_config_write(struct vty *vty) { @@ -3014,8 +3133,15 @@ static int route_map_config_write(struct vty *vty) struct route_map_rule *rule; int first = 1; int write = 0; + struct listnode *ln; + struct list *maplist = list_new(); for (map = route_map_master.head; map; map = map->next) + listnode_add(maplist, map); + + list_sort(maplist, sort_route_map); + + for (ALL_LIST_ELEMENTS_RO(maplist, ln, map)) for (index = map->head; index; index = index->next) { if (!first) vty_out(vty, "!\n"); @@ -3048,6 +3174,20 @@ static int route_map_config_write(struct vty *vty) write++; } + + list_delete(&maplist); + return write; +} + +static int rmap_config_write_debug(struct vty *vty) +{ + int write = 0; + + if (rmap_debug) { + vty_out(vty, "debug route-map\n"); + write++; + } + return write; } @@ -3164,15 +3304,22 @@ void route_map_init(void) cmd_variable_handler_register(rmap_var_handlers); + rmap_debug = false; + /* Install route map top node. */ install_node(&rmap_node, route_map_config_write); + install_node(&rmap_debug_node, rmap_config_write_debug); + /* Install route map commands. */ install_default(RMAP_NODE); install_element(CONFIG_NODE, &route_map_cmd); install_element(CONFIG_NODE, &no_route_map_cmd); install_element(CONFIG_NODE, &no_route_map_all_cmd); + install_element(CONFIG_NODE, &debug_rmap_cmd); + install_element(CONFIG_NODE, &no_debug_rmap_cmd); + /* Install the on-match stuff */ install_element(RMAP_NODE, &route_map_cmd); install_element(RMAP_NODE, &rmap_onmatch_next_cmd); @@ -3193,9 +3340,14 @@ void route_map_init(void) install_element(RMAP_NODE, &no_rmap_description_cmd); /* Install show command */ + install_element(ENABLE_NODE, &rmap_clear_counters_cmd); + install_element(ENABLE_NODE, &rmap_show_name_cmd); install_element(ENABLE_NODE, &rmap_show_unused_cmd); + install_element(ENABLE_NODE, &debug_rmap_cmd); + install_element(ENABLE_NODE, &no_debug_rmap_cmd); + install_element(RMAP_NODE, &match_interface_cmd); install_element(RMAP_NODE, &no_match_interface_cmd); |
