summaryrefslogtreecommitdiff
path: root/lib/routemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/routemap.c')
-rw-r--r--lib/routemap.c196
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);