const char *arg,
route_map_event_t 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 */
+ int (*no_match_ip_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type);
+
/* match ipv6 address */
int (*match_ipv6_address)(struct vty *vty,
struct route_map_index *index,
const char *arg,
route_map_event_t type);
+ /* match ipv6 next-hop type */
+ int (*match_ipv6_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type);
+
+ /* no match ipv6next-hop type */
+ int (*no_match_ipv6_next_hop_type)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command, const char *arg,
+ route_map_event_t type);
+
/* match metric */
int (*match_metric)(struct vty *vty, struct route_map_index *index,
const char *command, const char *arg,
rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func;
}
+/* 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))
+{
+ rmap_match_set_hook.match_ip_next_hop_type = func;
+}
+
+/* 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))
+{
+ rmap_match_set_hook.no_match_ip_next_hop_type = func;
+}
+
/* match ipv6 address */
void route_map_match_ipv6_address_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
rmap_match_set_hook.no_match_ipv6_address_prefix_list = func;
}
+/* match ipv6 next-hop type */
+void route_map_match_ipv6_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))
+{
+ rmap_match_set_hook.match_ipv6_next_hop_type = func;
+}
+
+/* no match ipv6 next-hop type */
+void route_map_no_match_ipv6_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))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
+}
+
/* match metric */
void route_map_match_metric_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
return string_hash_make(map->name);
}
-static int route_map_hash_cmp(const void *p1, const void *p2)
+static bool route_map_hash_cmp(const void *p1, const void *p2)
{
const struct route_map *map1 = p1;
const struct route_map *map2 = p2;
if (map1->deleted == map2->deleted) {
if (map1->name && map2->name) {
if (!strcmp(map1->name, map2->name)) {
- return 1;
+ return true;
}
} else if (!map1->name && !map2->name) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
enum route_map_upd8_type {
struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX];
static unsigned int route_map_dep_hash_make_key(void *p);
-static int route_map_dep_hash_cmp(const void *p1, const void *p2);
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 *);
return map;
}
+/* Simple helper to warn if route-map does not exist. */
+struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *name)
+{
+ struct route_map *route_map = route_map_lookup_by_name(name);
+
+ if (!route_map)
+ if (vty_shell_serv(vty))
+ vty_out(vty, "The route-map '%s' does not exist.\n", name);
+
+ return route_map;
+}
+
int route_map_mark_updated(const char *name)
{
struct route_map *map;
struct route_map_index *index;
struct route_map_rule *rule;
- vty_out(vty, "%s:\n", frr_protonameinst);
+ vty_out(vty, "route-map: %s Invoked: %" PRIu64 "\n",
+ map->name, map->applied);
for (index = map->head; index; index = index->next) {
- vty_out(vty, "route-map %s, %s, sequence %d\n", map->name,
- route_map_type_str(index->type), index->pref);
+ vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n",
+ route_map_type_str(index->type), index->pref,
+ index->applied);
/* Description */
if (index->description)
{
struct route_map *map;
+ vty_out(vty, "%s:\n", frr_protonameinst);
+
if (name) {
map = route_map_lookup_by_name(name);
for (ALL_LIST_ELEMENTS_RO(maplist, ln, map))
vty_show_route_map_entry(vty, map);
- list_delete_and_null(&maplist);
+ list_delete(&maplist);
}
return CMD_SUCCESS;
}
if (recursion > RMAP_RECURSION_LIMIT) {
flog_warn(
- LIB_WARN_RMAP_RECURSION_LIMIT,
+ EC_LIB_RMAP_RECURSION_LIMIT,
"route-map recursion limit (%d) reached, discarding route",
RMAP_RECURSION_LIMIT);
recursion = 0;
if (map == NULL)
return RMAP_DENYMATCH;
+ map->applied++;
for (index = map->head; index; index = index->next) {
/* Apply this index. */
+ index->applied++;
ret = route_map_apply_match(&index->match_list, prefix, type,
object);
}
/* Routines for route map dependency lists and dependency processing */
-static int route_map_rmap_hash_cmp(const void *p1, const void *p2)
+static bool route_map_rmap_hash_cmp(const void *p1, const void *p2)
{
return (strcmp((const char *)p1, (const char *)p2) == 0);
}
-static int route_map_dep_hash_cmp(const void *p1, const void *p2)
+static bool route_map_dep_hash_cmp(const void *p1, const void *p2)
{
return (strcmp(((const struct route_map_dep *)p1)->dep_name,
{
struct hash *upd8_hash = NULL;
- if ((upd8_hash = route_map_get_dep_hash(type)))
+ if ((upd8_hash = route_map_get_dep_hash(type))) {
route_map_dep_update(upd8_hash, arg, rmap_name, type);
+
+ if (type == RMAP_EVENT_CALL_ADDED) {
+ /* Execute hook. */
+ if (route_map_master.add_hook)
+ (*route_map_master.add_hook)(rmap_name);
+ } else if (type == RMAP_EVENT_CALL_DELETED) {
+ /* Execute hook. */
+ if (route_map_master.delete_hook)
+ (*route_map_master.delete_hook)(rmap_name);
+ }
+ }
}
void route_map_notify_dependencies(const char *affected_name,
return CMD_SUCCESS;
}
+DEFUN(match_ip_next_hop_type, match_ip_next_hop_type_cmd,
+ "match ip next-hop type <blackhole>",
+ MATCH_STR IP_STR
+ "Match next-hop address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 4;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.match_ip_next_hop_type)
+ return rmap_match_set_hook.match_ip_next_hop_type(
+ vty, index, "ip next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_ADDED);
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_match_ip_next_hop_type, no_match_ip_next_hop_type_cmd,
+ "no match ip next-hop type [<blackhole>]",
+ NO_STR MATCH_STR IP_STR
+ "Match next-hop address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 5;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.no_match_ip_next_hop) {
+ if (argc <= idx_word)
+ return rmap_match_set_hook.no_match_ip_next_hop(
+ vty, index, "ip next-hop type", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+ return rmap_match_set_hook.no_match_ip_next_hop(
+ vty, index, "ip next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_DELETED);
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (match_ipv6_address,
match_ipv6_address_cmd,
return CMD_SUCCESS;
}
+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 entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 4;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.match_ipv6_next_hop_type)
+ return rmap_match_set_hook.match_ipv6_next_hop_type(
+ vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_ADDED);
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd,
+ "no match ipv6 next-hop type [<blackhole>]",
+ NO_STR MATCH_STR IPV6_STR
+ "Match address of route\n"
+ "Match entries by type\n"
+ "Blackhole\n")
+{
+ int idx_word = 5;
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ if (rmap_match_set_hook.no_match_ipv6_next_hop_type)
+ return rmap_match_set_hook.no_match_ipv6_next_hop_type(
+ vty, index, "ipv6 next-hop type",
+ (argc <= idx_word) ? NULL : argv[idx_word]->arg,
+ RMAP_EVENT_MATCH_DELETED);
+ return CMD_SUCCESS;
+}
DEFUN (match_metric,
match_metric_cmd,
install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
+ install_element(RMAP_NODE, &match_ip_next_hop_type_cmd);
+ install_element(RMAP_NODE, &no_match_ip_next_hop_type_cmd);
+
install_element(RMAP_NODE, &match_ipv6_address_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_type_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_next_hop_type_cmd);
+
install_element(RMAP_NODE, &match_metric_cmd);
install_element(RMAP_NODE, &no_match_metric_cmd);