2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "lib_errors.h"
39 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP
, "Route map");
40 DEFINE_MTYPE(LIB
, ROUTE_MAP_NAME
, "Route map name");
41 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_INDEX
, "Route map index");
42 DEFINE_MTYPE(LIB
, ROUTE_MAP_RULE
, "Route map rule");
43 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_RULE_STR
, "Route map rule str");
44 DEFINE_MTYPE(LIB
, ROUTE_MAP_COMPILED
, "Route map compiled");
45 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_DEP
, "Route map dependency");
46 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_DEP_DATA
, "Route map dependency data");
48 DEFINE_QOBJ_TYPE(route_map_index
);
49 DEFINE_QOBJ_TYPE(route_map
);
51 static int rmap_cmd_name_cmp(const struct route_map_rule_cmd_proxy
*a
,
52 const struct route_map_rule_cmd_proxy
*b
)
54 return strcmp(a
->cmd
->str
, b
->cmd
->str
);
57 static uint32_t rmap_cmd_name_hash(const struct route_map_rule_cmd_proxy
*item
)
59 return jhash(item
->cmd
->str
, strlen(item
->cmd
->str
), 0xbfd69320);
62 DECLARE_HASH(rmap_cmd_name
, struct route_map_rule_cmd_proxy
, itm
,
63 rmap_cmd_name_cmp
, rmap_cmd_name_hash
);
65 static struct rmap_cmd_name_head rmap_match_cmds
[1] = {
66 INIT_HASH(rmap_match_cmds
[0]),
68 static struct rmap_cmd_name_head rmap_set_cmds
[1] = {
69 INIT_HASH(rmap_set_cmds
[0]),
72 #define IPv4_PREFIX_LIST "ip address prefix-list"
73 #define IPv6_PREFIX_LIST "ipv6 address prefix-list"
75 #define IS_RULE_IPv4_PREFIX_LIST(S) \
76 (strncmp(S, IPv4_PREFIX_LIST, strlen(IPv4_PREFIX_LIST)) == 0)
77 #define IS_RULE_IPv6_PREFIX_LIST(S) \
78 (strncmp(S, IPv6_PREFIX_LIST, strlen(IPv6_PREFIX_LIST)) == 0)
80 struct route_map_pentry_dep
{
81 struct prefix_list_entry
*pentry
;
82 const char *plist_name
;
83 route_map_event_t event
;
86 static void route_map_pfx_tbl_update(route_map_event_t event
,
87 struct route_map_index
*index
, afi_t afi
,
88 const char *plist_name
);
89 static void route_map_pfx_table_add_default(afi_t afi
,
90 struct route_map_index
*index
);
91 static void route_map_pfx_table_del_default(afi_t afi
,
92 struct route_map_index
*index
);
93 static void route_map_add_plist_entries(afi_t afi
,
94 struct route_map_index
*index
,
95 const char *plist_name
,
96 struct prefix_list_entry
*entry
);
97 static void route_map_del_plist_entries(afi_t afi
,
98 struct route_map_index
*index
,
99 const char *plist_name
,
100 struct prefix_list_entry
*entry
);
102 static struct hash
*route_map_get_dep_hash(route_map_event_t event
);
103 static void route_map_free_map(struct route_map
*map
);
105 struct route_map_match_set_hooks rmap_match_set_hook
;
107 /* match interface */
108 void route_map_match_interface_hook(int (*func
)(
109 struct route_map_index
*index
, const char *command
,
110 const char *arg
, route_map_event_t type
,
111 char *errmsg
, size_t errmsg_len
))
113 rmap_match_set_hook
.match_interface
= func
;
116 /* no match interface */
117 void route_map_no_match_interface_hook(int (*func
)(
118 struct route_map_index
*index
, const char *command
,
119 const char *arg
, route_map_event_t type
,
120 char *errmsg
, size_t errmsg_len
))
122 rmap_match_set_hook
.no_match_interface
= func
;
125 /* match ip address */
126 void route_map_match_ip_address_hook(int (*func
)(
127 struct route_map_index
*index
, const char *command
,
128 const char *arg
, route_map_event_t type
,
129 char *errmsg
, size_t errmsg_len
))
131 rmap_match_set_hook
.match_ip_address
= func
;
134 /* no match ip address */
135 void route_map_no_match_ip_address_hook(int (*func
)(
136 struct route_map_index
*index
, const char *command
,
137 const char *arg
, route_map_event_t type
,
138 char *errmsg
, size_t errmsg_len
))
140 rmap_match_set_hook
.no_match_ip_address
= func
;
143 /* match ip address prefix list */
144 void route_map_match_ip_address_prefix_list_hook(int (*func
)(
145 struct route_map_index
*index
, const char *command
,
146 const char *arg
, route_map_event_t type
,
147 char *errmsg
, size_t errmsg_len
))
149 rmap_match_set_hook
.match_ip_address_prefix_list
= func
;
152 /* no match ip address prefix list */
153 void route_map_no_match_ip_address_prefix_list_hook(int (*func
)(
154 struct route_map_index
*index
, const char *command
,
155 const char *arg
, route_map_event_t type
,
156 char *errmsg
, size_t errmsg_len
))
158 rmap_match_set_hook
.no_match_ip_address_prefix_list
= func
;
161 /* match ip next hop */
162 void route_map_match_ip_next_hop_hook(int (*func
)(
163 struct route_map_index
*index
, const char *command
,
164 const char *arg
, route_map_event_t type
,
165 char *errmsg
, size_t errmsg_len
))
167 rmap_match_set_hook
.match_ip_next_hop
= func
;
170 /* no match ip next hop */
171 void route_map_no_match_ip_next_hop_hook(int (*func
)(
172 struct route_map_index
*index
, const char *command
,
173 const char *arg
, route_map_event_t type
,
174 char *errmsg
, size_t errmsg_len
))
176 rmap_match_set_hook
.no_match_ip_next_hop
= func
;
179 /* match ipv6 next-hop */
180 void route_map_match_ipv6_next_hop_hook(int (*func
)(
181 struct route_map_index
*index
, const char *command
, const char *arg
,
182 route_map_event_t type
, char *errmsg
, size_t errmsg_len
))
184 rmap_match_set_hook
.match_ipv6_next_hop
= func
;
187 /* no match ipv6 next-hop */
188 void route_map_no_match_ipv6_next_hop_hook(int (*func
)(
189 struct route_map_index
*index
, const char *command
, const char *arg
,
190 route_map_event_t type
, char *errmsg
, size_t errmsg_len
))
192 rmap_match_set_hook
.no_match_ipv6_next_hop
= func
;
195 /* match ip next hop prefix list */
196 void route_map_match_ip_next_hop_prefix_list_hook(int (*func
)(
197 struct route_map_index
*index
, const char *command
,
198 const char *arg
, route_map_event_t type
,
199 char *errmsg
, size_t errmsg_len
))
201 rmap_match_set_hook
.match_ip_next_hop_prefix_list
= func
;
204 /* no match ip next hop prefix list */
205 void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func
)(
206 struct route_map_index
*index
, const char *command
,
207 const char *arg
, route_map_event_t type
,
208 char *errmsg
, size_t errmsg_len
))
210 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
= func
;
213 /* match ip next-hop type */
214 void route_map_match_ip_next_hop_type_hook(int (*func
)(
215 struct route_map_index
*index
, const char *command
,
216 const char *arg
, route_map_event_t type
,
217 char *errmsg
, size_t errmsg_len
))
219 rmap_match_set_hook
.match_ip_next_hop_type
= func
;
222 /* no match ip next-hop type */
223 void route_map_no_match_ip_next_hop_type_hook(int (*func
)(
224 struct route_map_index
*index
, const char *command
,
225 const char *arg
, route_map_event_t type
,
226 char *errmsg
, size_t errmsg_len
))
228 rmap_match_set_hook
.no_match_ip_next_hop_type
= func
;
231 /* match ipv6 address */
232 void route_map_match_ipv6_address_hook(int (*func
)(
233 struct route_map_index
*index
, const char *command
,
234 const char *arg
, route_map_event_t type
,
235 char *errmsg
, size_t errmsg_len
))
237 rmap_match_set_hook
.match_ipv6_address
= func
;
240 /* no match ipv6 address */
241 void route_map_no_match_ipv6_address_hook(int (*func
)(
242 struct route_map_index
*index
, const char *command
,
243 const char *arg
, route_map_event_t type
,
244 char *errmsg
, size_t errmsg_len
))
246 rmap_match_set_hook
.no_match_ipv6_address
= func
;
250 /* match ipv6 address prefix list */
251 void route_map_match_ipv6_address_prefix_list_hook(int (*func
)(
252 struct route_map_index
*index
, const char *command
,
253 const char *arg
, route_map_event_t type
,
254 char *errmsg
, size_t errmsg_len
))
256 rmap_match_set_hook
.match_ipv6_address_prefix_list
= func
;
259 /* no match ipv6 address prefix list */
260 void route_map_no_match_ipv6_address_prefix_list_hook(int (*func
)(
261 struct route_map_index
*index
, const char *command
,
262 const char *arg
, route_map_event_t type
,
263 char *errmsg
, size_t errmsg_len
))
265 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
= func
;
268 /* match ipv6 next-hop type */
269 void route_map_match_ipv6_next_hop_type_hook(int (*func
)(
270 struct route_map_index
*index
, const char *command
,
271 const char *arg
, route_map_event_t type
,
272 char *errmsg
, size_t errmsg_len
))
274 rmap_match_set_hook
.match_ipv6_next_hop_type
= func
;
277 /* no match ipv6 next-hop type */
278 void route_map_no_match_ipv6_next_hop_type_hook(int (*func
)(
279 struct route_map_index
*index
, const char *command
,
280 const char *arg
, route_map_event_t type
,
281 char *errmsg
, size_t errmsg_len
))
283 rmap_match_set_hook
.no_match_ipv6_next_hop_type
= func
;
286 /* match ipv6 next-hop prefix-list */
287 void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func
)(
288 struct route_map_index
*index
, const char *command
, const char *arg
,
289 route_map_event_t type
, char *errmsg
, size_t errmsg_len
))
291 rmap_match_set_hook
.match_ipv6_next_hop_prefix_list
= func
;
294 /* no match ipv6 next-hop prefix-list */
295 void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func
)(
296 struct route_map_index
*index
, const char *command
, const char *arg
,
297 route_map_event_t type
, char *errmsg
, size_t errmsg_len
))
299 rmap_match_set_hook
.no_match_ipv6_next_hop_prefix_list
= func
;
303 void route_map_match_metric_hook(int (*func
)(
304 struct route_map_index
*index
, const char *command
,
305 const char *arg
, route_map_event_t type
,
306 char *errmsg
, size_t errmsg_len
))
308 rmap_match_set_hook
.match_metric
= func
;
311 /* no match metric */
312 void route_map_no_match_metric_hook(int (*func
)(
313 struct route_map_index
*index
, const char *command
,
314 const char *arg
, route_map_event_t type
,
315 char *errmsg
, size_t errmsg_len
))
317 rmap_match_set_hook
.no_match_metric
= func
;
321 void route_map_match_tag_hook(int (*func
)(struct route_map_index
*index
,
322 const char *command
, const char *arg
,
323 route_map_event_t type
,
324 char *errmsg
, size_t errmsg_len
))
326 rmap_match_set_hook
.match_tag
= func
;
330 void route_map_no_match_tag_hook(int (*func
)(
331 struct route_map_index
*index
, const char *command
,
332 const char *arg
, route_map_event_t type
,
333 char *errmsg
, size_t errmsg_len
))
335 rmap_match_set_hook
.no_match_tag
= func
;
338 /* set sr-te color */
339 void route_map_set_srte_color_hook(int (*func
)(struct route_map_index
*index
,
342 char *errmsg
, size_t errmsg_len
))
344 rmap_match_set_hook
.set_srte_color
= func
;
347 /* no set sr-te color */
348 void route_map_no_set_srte_color_hook(int (*func
)(struct route_map_index
*index
,
351 char *errmsg
, size_t errmsg_len
))
353 rmap_match_set_hook
.no_set_srte_color
= func
;
357 void route_map_set_ip_nexthop_hook(int (*func
)(struct route_map_index
*index
,
360 char *errmsg
, size_t errmsg_len
))
362 rmap_match_set_hook
.set_ip_nexthop
= func
;
365 /* no set ip nexthop */
366 void route_map_no_set_ip_nexthop_hook(int (*func
)(struct route_map_index
*index
,
372 rmap_match_set_hook
.no_set_ip_nexthop
= func
;
375 /* set ipv6 nexthop local */
376 void route_map_set_ipv6_nexthop_local_hook(
377 int (*func
)(struct route_map_index
*index
,
378 const char *command
, const char *arg
,
379 char *errmsg
, size_t errmsg_len
))
381 rmap_match_set_hook
.set_ipv6_nexthop_local
= func
;
384 /* no set ipv6 nexthop local */
385 void route_map_no_set_ipv6_nexthop_local_hook(
386 int (*func
)(struct route_map_index
*index
,
387 const char *command
, const char *arg
,
388 char *errmsg
, size_t errmsg_len
))
390 rmap_match_set_hook
.no_set_ipv6_nexthop_local
= func
;
394 void route_map_set_metric_hook(int (*func
)(struct route_map_index
*index
,
397 char *errmsg
, size_t errmsg_len
))
399 rmap_match_set_hook
.set_metric
= func
;
403 void route_map_no_set_metric_hook(int (*func
)(struct route_map_index
*index
,
406 char *errmsg
, size_t errmsg_len
))
408 rmap_match_set_hook
.no_set_metric
= func
;
412 void route_map_set_tag_hook(int (*func
)(struct route_map_index
*index
,
413 const char *command
, const char *arg
,
414 char *errmsg
, size_t errmsg_len
))
416 rmap_match_set_hook
.set_tag
= func
;
420 void route_map_no_set_tag_hook(int (*func
)(struct route_map_index
*index
,
423 char *errmsg
, size_t errmsg_len
))
425 rmap_match_set_hook
.no_set_tag
= func
;
428 int generic_match_add(struct route_map_index
*index
,
429 const char *command
, const char *arg
,
430 route_map_event_t type
,
431 char *errmsg
, size_t errmsg_len
)
433 enum rmap_compile_rets ret
;
435 ret
= route_map_add_match(index
, command
, arg
, type
);
437 case RMAP_RULE_MISSING
:
438 snprintf(errmsg
, errmsg_len
, "%% [%s] Can't find rule.",
440 return CMD_WARNING_CONFIG_FAILED
;
441 case RMAP_COMPILE_ERROR
:
442 snprintf(errmsg
, errmsg_len
,
443 "%% [%s] Argument form is unsupported or malformed.",
445 return CMD_WARNING_CONFIG_FAILED
;
446 case RMAP_COMPILE_SUCCESS
:
448 * Nothing to do here move along
456 int generic_match_delete(struct route_map_index
*index
,
457 const char *command
, const char *arg
,
458 route_map_event_t type
,
459 char *errmsg
, size_t errmsg_len
)
461 enum rmap_compile_rets ret
;
462 int retval
= CMD_SUCCESS
;
463 char *dep_name
= NULL
;
465 char *rmap_name
= NULL
;
467 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
468 /* ignore the mundane, the types without any dependency */
470 if ((tmpstr
= route_map_get_match_arg(index
, command
))
473 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
475 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
477 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
480 ret
= route_map_delete_match(index
, command
, dep_name
, type
);
482 case RMAP_RULE_MISSING
:
483 snprintf(errmsg
, errmsg_len
, "%% [%s] Can't find rule.",
485 retval
= CMD_WARNING_CONFIG_FAILED
;
487 case RMAP_COMPILE_ERROR
:
488 snprintf(errmsg
, errmsg_len
,
489 "%% [%s] Argument form is unsupported or malformed.",
491 retval
= CMD_WARNING_CONFIG_FAILED
;
493 case RMAP_COMPILE_SUCCESS
:
500 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
501 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
506 int generic_set_add(struct route_map_index
*index
,
507 const char *command
, const char *arg
,
508 char *errmsg
, size_t errmsg_len
)
510 enum rmap_compile_rets ret
;
512 ret
= route_map_add_set(index
, command
, arg
);
514 case RMAP_RULE_MISSING
:
515 snprintf(errmsg
, errmsg_len
,
516 "%% [%s] Can't find rule.", frr_protonameinst
);
517 return CMD_WARNING_CONFIG_FAILED
;
518 case RMAP_COMPILE_ERROR
:
519 snprintf(errmsg
, errmsg_len
,
520 "%% [%s] Argument form is unsupported or malformed.",
522 return CMD_WARNING_CONFIG_FAILED
;
523 case RMAP_COMPILE_SUCCESS
:
530 int generic_set_delete(struct route_map_index
*index
,
531 const char *command
, const char *arg
,
532 char *errmsg
, size_t errmsg_len
)
534 enum rmap_compile_rets ret
;
536 ret
= route_map_delete_set(index
, command
, arg
);
538 case RMAP_RULE_MISSING
:
539 snprintf(errmsg
, errmsg_len
, "%% [%s] Can't find rule.",
541 return CMD_WARNING_CONFIG_FAILED
;
542 case RMAP_COMPILE_ERROR
:
543 snprintf(errmsg
, errmsg_len
,
544 "%% [%s] Argument form is unsupported or malformed.",
546 return CMD_WARNING_CONFIG_FAILED
;
547 case RMAP_COMPILE_SUCCESS
:
555 /* Master list of route map. */
556 struct route_map_list route_map_master
= {NULL
, NULL
, NULL
, NULL
, NULL
};
557 struct hash
*route_map_master_hash
= NULL
;
559 static unsigned int route_map_hash_key_make(const void *p
)
561 const struct route_map
*map
= p
;
562 return string_hash_make(map
->name
);
565 static bool route_map_hash_cmp(const void *p1
, const void *p2
)
567 const struct route_map
*map1
= p1
;
568 const struct route_map
*map2
= p2
;
570 if (!strcmp(map1
->name
, map2
->name
))
576 enum route_map_upd8_type
{
581 /* all possible route-map dependency types */
582 enum route_map_dep_type
{
583 ROUTE_MAP_DEP_RMAP
= 1,
585 ROUTE_MAP_DEP_ECLIST
,
586 ROUTE_MAP_DEP_LCLIST
,
588 ROUTE_MAP_DEP_ASPATH
,
589 ROUTE_MAP_DEP_FILTER
,
593 struct route_map_dep
{
595 struct hash
*dep_rmap_hash
;
596 struct hash
*this_hash
; /* ptr to the hash structure this is part of */
599 struct route_map_dep_data
{
603 /* Count of number of sequences of this
604 * route-map that depend on the same entity.
609 /* Hashes maintaining dependency between various sublists used by route maps */
610 static struct hash
*route_map_dep_hash
[ROUTE_MAP_DEP_MAX
];
612 static unsigned int route_map_dep_hash_make_key(const void *p
);
613 static void route_map_clear_all_references(char *rmap_name
);
614 static void route_map_rule_delete(struct route_map_rule_list
*,
615 struct route_map_rule
*);
616 static bool rmap_debug
;
618 /* New route map allocation. Please note route map's name must be
620 static struct route_map
*route_map_new(const char *name
)
622 struct route_map
*new;
624 new = XCALLOC(MTYPE_ROUTE_MAP
, sizeof(struct route_map
));
625 new->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
626 QOBJ_REG(new, route_map
);
630 /* Add new name to route_map. */
631 static struct route_map
*route_map_add(const char *name
)
633 struct route_map
*map
, *exist
;
634 struct route_map_list
*list
;
636 map
= route_map_new(name
);
637 list
= &route_map_master
;
640 * Add map to the hash
642 * If the map already exists in the hash, then we know that
643 * FRR is now in a sequence of delete/create.
644 * All FRR needs to do here is set the to_be_processed
645 * bit (to inherit from the old one
647 exist
= hash_release(route_map_master_hash
, map
);
649 map
->to_be_processed
= exist
->to_be_processed
;
650 route_map_free_map(exist
);
652 hash_get(route_map_master_hash
, map
, hash_alloc_intern
);
654 /* Add new entry to the head of the list to match how it is added in the
655 * hash table. This is to ensure that if the same route-map has been
656 * created more than once and then marked for deletion (which can happen
657 * if prior deletions haven't completed as BGP hasn't yet done the
658 * route-map processing), the order of the entities is the same in both
659 * the list and the hash table. Otherwise, since there is nothing to
660 * distinguish between the two entries, the wrong entry could get freed.
661 * TODO: This needs to be re-examined to handle it better - e.g., revive
662 * a deleted entry if the route-map is created again.
665 map
->next
= list
->head
;
667 list
->head
->prev
= map
;
673 if (route_map_master
.add_hook
) {
674 (*route_map_master
.add_hook
)(name
);
675 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_ADDED
);
678 if (!map
->ipv4_prefix_table
)
679 map
->ipv4_prefix_table
= route_table_init();
681 if (!map
->ipv6_prefix_table
)
682 map
->ipv6_prefix_table
= route_table_init();
685 zlog_debug("Add route-map %s", name
);
689 /* this is supposed to be called post processing by
690 * the delete hook function. Don't invoke delete_hook
691 * again in this routine.
693 static void route_map_free_map(struct route_map
*map
)
695 struct route_map_list
*list
;
696 struct route_map_index
*index
;
701 while ((index
= map
->head
) != NULL
)
702 route_map_index_delete(index
, 0);
705 zlog_debug("Deleting route-map %s", map
->name
);
707 list
= &route_map_master
;
712 map
->next
->prev
= map
->prev
;
714 list
->tail
= map
->prev
;
717 map
->prev
->next
= map
->next
;
719 list
->head
= map
->next
;
721 hash_release(route_map_master_hash
, map
);
722 XFREE(MTYPE_ROUTE_MAP_NAME
, map
->name
);
723 XFREE(MTYPE_ROUTE_MAP
, map
);
726 /* Route map delete from list. */
727 void route_map_delete(struct route_map
*map
)
729 struct route_map_index
*index
;
732 while ((index
= map
->head
) != NULL
)
733 route_map_index_delete(index
, 0);
738 /* Clear all dependencies */
739 route_map_clear_all_references(name
);
741 /* Execute deletion hook. */
742 if (route_map_master
.delete_hook
) {
743 (*route_map_master
.delete_hook
)(name
);
744 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_DELETED
);
747 if (!map
->to_be_processed
) {
748 route_map_free_map(map
);
752 /* Lookup route map by route map name string. */
753 struct route_map
*route_map_lookup_by_name(const char *name
)
755 struct route_map
*map
;
756 struct route_map tmp_map
;
761 // map.deleted is false via memset
762 memset(&tmp_map
, 0, sizeof(struct route_map
));
763 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
764 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
765 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
767 if (map
&& map
->deleted
)
773 /* Simple helper to warn if route-map does not exist. */
774 struct route_map
*route_map_lookup_warn_noexist(struct vty
*vty
, const char *name
)
776 struct route_map
*route_map
= route_map_lookup_by_name(name
);
779 if (vty_shell_serv(vty
))
780 vty_out(vty
, "The route-map '%s' does not exist.\n", name
);
785 int route_map_mark_updated(const char *name
)
787 struct route_map
*map
;
789 struct route_map tmp_map
;
794 map
= route_map_lookup_by_name(name
);
796 /* If we did not find the routemap with deleted=false try again
800 memset(&tmp_map
, 0, sizeof(struct route_map
));
801 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
802 tmp_map
.deleted
= true;
803 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
804 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
808 map
->to_be_processed
= true;
815 static int route_map_clear_updated(struct route_map
*map
)
820 map
->to_be_processed
= false;
822 route_map_free_map(map
);
828 /* Lookup route map. If there isn't route map create one and return
830 struct route_map
*route_map_get(const char *name
)
832 struct route_map
*map
;
834 map
= route_map_lookup_by_name(name
);
836 map
= route_map_add(name
);
841 void route_map_walk_update_list(void (*route_map_update_fn
)(char *name
))
843 struct route_map
*node
;
844 struct route_map
*nnode
= NULL
;
846 for (node
= route_map_master
.head
; node
; node
= nnode
) {
847 if (node
->to_be_processed
) {
848 /* DD: Should we add any thread yield code here */
849 route_map_update_fn(node
->name
);
851 route_map_clear_updated(node
);
857 /* Return route map's type string. */
858 static const char *route_map_type_str(enum route_map_type type
)
872 static const char *route_map_cmd_result_str(enum route_map_cmd_result_t res
)
890 static const char *route_map_result_str(route_map_result_t res
)
895 case RMAP_PERMITMATCH
:
903 static void vty_show_route_map_entry(struct vty
*vty
, struct route_map
*map
,
906 struct route_map_index
*index
;
907 struct route_map_rule
*rule
;
908 json_object
*json_rmap
= NULL
;
909 json_object
*json_rules
= NULL
;
912 json_rmap
= json_object_new_object();
913 json_object_object_add(json
, map
->name
, json_rmap
);
915 json_rules
= json_object_new_array();
916 json_object_int_add(json_rmap
, "invoked",
917 map
->applied
- map
->applied_clear
);
918 json_object_boolean_add(json_rmap
, "disabledOptimization",
919 map
->optimization_disabled
);
920 json_object_boolean_add(json_rmap
, "processedChange",
921 map
->to_be_processed
);
922 json_object_object_add(json_rmap
, "rules", json_rules
);
925 "route-map: %s Invoked: %" PRIu64
926 " Optimization: %s Processed Change: %s\n",
927 map
->name
, map
->applied
- map
->applied_clear
,
928 map
->optimization_disabled
? "disabled" : "enabled",
929 map
->to_be_processed
? "true" : "false");
932 for (index
= map
->head
; index
; index
= index
->next
) {
934 json_object
*json_rule
;
935 json_object
*json_matches
;
936 json_object
*json_sets
;
937 char action
[BUFSIZ
] = {};
939 json_rule
= json_object_new_object();
940 json_object_array_add(json_rules
, json_rule
);
942 json_object_int_add(json_rule
, "sequenceNumber",
944 json_object_string_add(json_rule
, "type",
945 route_map_type_str(index
->type
));
946 json_object_int_add(json_rule
, "invoked",
948 - index
->applied_clear
);
951 if (index
->description
)
952 json_object_string_add(json_rule
, "description",
956 json_matches
= json_object_new_array();
957 json_object_object_add(json_rule
, "matchClauses",
959 for (rule
= index
->match_list
.head
; rule
;
963 snprintf(buf
, sizeof(buf
), "%s %s",
964 rule
->cmd
->str
, rule
->rule_str
);
965 json_array_string_add(json_matches
, buf
);
969 json_sets
= json_object_new_array();
970 json_object_object_add(json_rule
, "setClauses",
972 for (rule
= index
->set_list
.head
; rule
;
976 snprintf(buf
, sizeof(buf
), "%s %s",
977 rule
->cmd
->str
, rule
->rule_str
);
978 json_array_string_add(json_sets
, buf
);
983 json_object_string_add(json_rule
, "callClause",
987 if (index
->exitpolicy
== RMAP_GOTO
)
988 snprintf(action
, sizeof(action
), "Goto %d",
990 else if (index
->exitpolicy
== RMAP_NEXT
)
991 snprintf(action
, sizeof(action
),
992 "Continue to next entry");
993 else if (index
->exitpolicy
== RMAP_EXIT
)
994 snprintf(action
, sizeof(action
),
996 if (action
[0] != '\0')
997 json_object_string_add(json_rule
, "action",
1000 vty_out(vty
, " %s, sequence %d Invoked %" PRIu64
"\n",
1001 route_map_type_str(index
->type
), index
->pref
,
1002 index
->applied
- index
->applied_clear
);
1005 if (index
->description
)
1006 vty_out(vty
, " Description:\n %s\n",
1007 index
->description
);
1010 vty_out(vty
, " Match clauses:\n");
1011 for (rule
= index
->match_list
.head
; rule
;
1013 vty_out(vty
, " %s %s\n", rule
->cmd
->str
,
1017 vty_out(vty
, " Set clauses:\n");
1018 for (rule
= index
->set_list
.head
; rule
;
1020 vty_out(vty
, " %s %s\n", rule
->cmd
->str
,
1024 vty_out(vty
, " Call clause:\n");
1026 vty_out(vty
, " Call %s\n", index
->nextrm
);
1029 vty_out(vty
, " Action:\n");
1030 if (index
->exitpolicy
== RMAP_GOTO
)
1031 vty_out(vty
, " Goto %d\n", index
->nextpref
);
1032 else if (index
->exitpolicy
== RMAP_NEXT
)
1033 vty_out(vty
, " Continue to next entry\n");
1034 else if (index
->exitpolicy
== RMAP_EXIT
)
1035 vty_out(vty
, " Exit routemap\n");
1040 static int sort_route_map(const void **map1
, const void **map2
)
1042 const struct route_map
*m1
= *map1
;
1043 const struct route_map
*m2
= *map2
;
1045 return strcmp(m1
->name
, m2
->name
);
1048 static int vty_show_route_map(struct vty
*vty
, const char *name
, bool use_json
)
1050 struct route_map
*map
;
1051 json_object
*json
= NULL
;
1052 json_object
*json_proto
= NULL
;
1055 json
= json_object_new_object();
1056 json_proto
= json_object_new_object();
1057 json_object_object_add(json
, frr_protonameinst
, json_proto
);
1059 vty_out(vty
, "%s:\n", frr_protonameinst
);
1062 map
= route_map_lookup_by_name(name
);
1065 vty_show_route_map_entry(vty
, map
, json_proto
);
1067 } else if (!use_json
) {
1068 vty_out(vty
, "%s: 'route-map %s' not found\n",
1069 frr_protonameinst
, name
);
1073 struct list
*maplist
= list_new();
1074 struct listnode
*ln
;
1076 for (map
= route_map_master
.head
; map
; map
= map
->next
)
1077 listnode_add(maplist
, map
);
1079 list_sort(maplist
, sort_route_map
);
1081 for (ALL_LIST_ELEMENTS_RO(maplist
, ln
, map
))
1082 vty_show_route_map_entry(vty
, map
, json_proto
);
1084 list_delete(&maplist
);
1087 return vty_json(vty
, json
);
1090 /* Unused route map details */
1091 static int vty_show_unused_route_map(struct vty
*vty
)
1093 struct list
*maplist
= list_new();
1094 struct listnode
*ln
;
1095 struct route_map
*map
;
1097 for (map
= route_map_master
.head
; map
; map
= map
->next
) {
1098 /* If use_count is zero, No protocol is using this routemap.
1099 * so adding to the list.
1101 if (!map
->use_count
)
1102 listnode_add(maplist
, map
);
1105 if (maplist
->count
> 0) {
1106 vty_out(vty
, "\n%s:\n", frr_protonameinst
);
1107 list_sort(maplist
, sort_route_map
);
1109 for (ALL_LIST_ELEMENTS_RO(maplist
, ln
, map
))
1110 vty_show_route_map_entry(vty
, map
, NULL
);
1112 vty_out(vty
, "\n%s: None\n", frr_protonameinst
);
1115 list_delete(&maplist
);
1119 /* New route map allocation. Please note route map's name must be
1121 static struct route_map_index
*route_map_index_new(void)
1123 struct route_map_index
*new;
1125 new = XCALLOC(MTYPE_ROUTE_MAP_INDEX
, sizeof(struct route_map_index
));
1126 new->exitpolicy
= RMAP_EXIT
; /* Default to Cisco-style */
1127 TAILQ_INIT(&new->rhclist
);
1128 QOBJ_REG(new, route_map_index
);
1132 /* Free route map index. */
1133 void route_map_index_delete(struct route_map_index
*index
, int notify
)
1135 struct routemap_hook_context
*rhc
;
1136 struct route_map_rule
*rule
;
1141 zlog_debug("Deleting route-map %s sequence %d",
1142 index
->map
->name
, index
->pref
);
1144 /* Free route map entry description. */
1145 XFREE(MTYPE_TMP
, index
->description
);
1147 /* Free route map northbound hook contexts. */
1148 while ((rhc
= TAILQ_FIRST(&index
->rhclist
)) != NULL
)
1149 routemap_hook_context_free(rhc
);
1151 /* Free route match. */
1152 while ((rule
= index
->match_list
.head
) != NULL
) {
1153 if (IS_RULE_IPv4_PREFIX_LIST(rule
->cmd
->str
))
1154 route_map_pfx_tbl_update(RMAP_EVENT_PLIST_DELETED
,
1155 index
, AFI_IP
, rule
->rule_str
);
1156 else if (IS_RULE_IPv6_PREFIX_LIST(rule
->cmd
->str
))
1157 route_map_pfx_tbl_update(RMAP_EVENT_PLIST_DELETED
,
1161 route_map_rule_delete(&index
->match_list
, rule
);
1164 /* Free route set. */
1165 while ((rule
= index
->set_list
.head
) != NULL
)
1166 route_map_rule_delete(&index
->set_list
, rule
);
1168 /* Remove index from route map list. */
1170 index
->next
->prev
= index
->prev
;
1172 index
->map
->tail
= index
->prev
;
1175 index
->prev
->next
= index
->next
;
1177 index
->map
->head
= index
->next
;
1179 /* Free 'char *nextrm' if not NULL */
1180 XFREE(MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
1182 route_map_pfx_tbl_update(RMAP_EVENT_INDEX_DELETED
, index
, 0, NULL
);
1184 /* Execute event hook. */
1185 if (route_map_master
.event_hook
&& notify
) {
1186 (*route_map_master
.event_hook
)(index
->map
->name
);
1187 route_map_notify_dependencies(index
->map
->name
,
1188 RMAP_EVENT_CALL_ADDED
);
1190 XFREE(MTYPE_ROUTE_MAP_INDEX
, index
);
1193 /* Lookup index from route map. */
1194 static struct route_map_index
*route_map_index_lookup(struct route_map
*map
,
1195 enum route_map_type type
,
1198 struct route_map_index
*index
;
1200 for (index
= map
->head
; index
; index
= index
->next
)
1201 if ((index
->type
== type
|| type
== RMAP_ANY
)
1202 && index
->pref
== pref
)
1207 /* Add new index to route map. */
1208 static struct route_map_index
*
1209 route_map_index_add(struct route_map
*map
, enum route_map_type type
, int pref
)
1211 struct route_map_index
*index
;
1212 struct route_map_index
*point
;
1214 /* Allocate new route map inex. */
1215 index
= route_map_index_new();
1220 /* Compare preference. */
1221 for (point
= map
->head
; point
; point
= point
->next
)
1222 if (point
->pref
>= pref
)
1225 if (map
->head
== NULL
) {
1226 map
->head
= map
->tail
= index
;
1227 } else if (point
== NULL
) {
1228 index
->prev
= map
->tail
;
1229 map
->tail
->next
= index
;
1231 } else if (point
== map
->head
) {
1232 index
->next
= map
->head
;
1233 map
->head
->prev
= index
;
1236 index
->next
= point
;
1237 index
->prev
= point
->prev
;
1239 point
->prev
->next
= index
;
1240 point
->prev
= index
;
1243 route_map_pfx_tbl_update(RMAP_EVENT_INDEX_ADDED
, index
, 0, NULL
);
1245 /* Execute event hook. */
1246 if (route_map_master
.event_hook
) {
1247 (*route_map_master
.event_hook
)(map
->name
);
1248 route_map_notify_dependencies(map
->name
, RMAP_EVENT_CALL_ADDED
);
1252 zlog_debug("Route-map %s add sequence %d, type: %s",
1253 map
->name
, pref
, route_map_type_str(type
));
1258 /* Get route map index. */
1259 struct route_map_index
*
1260 route_map_index_get(struct route_map
*map
, enum route_map_type type
, int pref
)
1262 struct route_map_index
*index
;
1264 index
= route_map_index_lookup(map
, RMAP_ANY
, pref
);
1265 if (index
&& index
->type
!= type
) {
1266 /* Delete index from route map. */
1267 route_map_index_delete(index
, 1);
1271 index
= route_map_index_add(map
, type
, pref
);
1275 /* New route map rule */
1276 static struct route_map_rule
*route_map_rule_new(void)
1278 struct route_map_rule
*new;
1280 new = XCALLOC(MTYPE_ROUTE_MAP_RULE
, sizeof(struct route_map_rule
));
1284 /* Install rule command to the match list. */
1285 void _route_map_install_match(struct route_map_rule_cmd_proxy
*proxy
)
1287 rmap_cmd_name_add(rmap_match_cmds
, proxy
);
1290 /* Install rule command to the set list. */
1291 void _route_map_install_set(struct route_map_rule_cmd_proxy
*proxy
)
1293 rmap_cmd_name_add(rmap_set_cmds
, proxy
);
1296 /* Lookup rule command from match list. */
1297 static const struct route_map_rule_cmd
*route_map_lookup_match(const char *name
)
1299 struct route_map_rule_cmd refcmd
= {.str
= name
};
1300 struct route_map_rule_cmd_proxy ref
= {.cmd
= &refcmd
};
1301 struct route_map_rule_cmd_proxy
*res
;
1303 res
= rmap_cmd_name_find(rmap_match_cmds
, &ref
);
1309 /* Lookup rule command from set list. */
1310 static const struct route_map_rule_cmd
*route_map_lookup_set(const char *name
)
1312 struct route_map_rule_cmd refcmd
= {.str
= name
};
1313 struct route_map_rule_cmd_proxy ref
= {.cmd
= &refcmd
};
1314 struct route_map_rule_cmd_proxy
*res
;
1316 res
= rmap_cmd_name_find(rmap_set_cmds
, &ref
);
1322 /* Add match and set rule to rule list. */
1323 static void route_map_rule_add(struct route_map_rule_list
*list
,
1324 struct route_map_rule
*rule
)
1327 rule
->prev
= list
->tail
;
1329 list
->tail
->next
= rule
;
1335 /* Delete rule from rule list. */
1336 static void route_map_rule_delete(struct route_map_rule_list
*list
,
1337 struct route_map_rule
*rule
)
1339 if (rule
->cmd
->func_free
)
1340 (*rule
->cmd
->func_free
)(rule
->value
);
1342 XFREE(MTYPE_ROUTE_MAP_RULE_STR
, rule
->rule_str
);
1345 rule
->next
->prev
= rule
->prev
;
1347 list
->tail
= rule
->prev
;
1349 rule
->prev
->next
= rule
->next
;
1351 list
->head
= rule
->next
;
1353 XFREE(MTYPE_ROUTE_MAP_RULE
, rule
);
1356 /* strcmp wrapper function which don't crush even argument is NULL. */
1357 static int rulecmp(const char *dst
, const char *src
)
1368 return strcmp(dst
, src
);
1373 /* Use this to return the already specified argument for this match. This is
1374 * useful to get the specified argument with a route map match rule when the
1375 * rule is being deleted and the argument is not provided.
1377 const char *route_map_get_match_arg(struct route_map_index
*index
,
1378 const char *match_name
)
1380 struct route_map_rule
*rule
;
1381 const struct route_map_rule_cmd
*cmd
;
1383 /* First lookup rule for add match statement. */
1384 cmd
= route_map_lookup_match(match_name
);
1388 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1389 if (rule
->cmd
== cmd
&& rule
->rule_str
!= NULL
)
1390 return (rule
->rule_str
);
1395 static route_map_event_t
get_route_map_delete_event(route_map_event_t type
)
1398 case RMAP_EVENT_CALL_ADDED
:
1399 return RMAP_EVENT_CALL_DELETED
;
1400 case RMAP_EVENT_PLIST_ADDED
:
1401 return RMAP_EVENT_PLIST_DELETED
;
1402 case RMAP_EVENT_CLIST_ADDED
:
1403 return RMAP_EVENT_CLIST_DELETED
;
1404 case RMAP_EVENT_ECLIST_ADDED
:
1405 return RMAP_EVENT_ECLIST_DELETED
;
1406 case RMAP_EVENT_LLIST_ADDED
:
1407 return RMAP_EVENT_LLIST_DELETED
;
1408 case RMAP_EVENT_ASLIST_ADDED
:
1409 return RMAP_EVENT_ASLIST_DELETED
;
1410 case RMAP_EVENT_FILTER_ADDED
:
1411 return RMAP_EVENT_FILTER_DELETED
;
1412 case RMAP_EVENT_SET_ADDED
:
1413 case RMAP_EVENT_SET_DELETED
:
1414 case RMAP_EVENT_SET_REPLACED
:
1415 case RMAP_EVENT_MATCH_ADDED
:
1416 case RMAP_EVENT_MATCH_DELETED
:
1417 case RMAP_EVENT_MATCH_REPLACED
:
1418 case RMAP_EVENT_INDEX_ADDED
:
1419 case RMAP_EVENT_INDEX_DELETED
:
1420 case RMAP_EVENT_CALL_DELETED
:
1421 case RMAP_EVENT_PLIST_DELETED
:
1422 case RMAP_EVENT_CLIST_DELETED
:
1423 case RMAP_EVENT_ECLIST_DELETED
:
1424 case RMAP_EVENT_LLIST_DELETED
:
1425 case RMAP_EVENT_ASLIST_DELETED
:
1426 case RMAP_EVENT_FILTER_DELETED
:
1427 /* This function returns the appropriate 'deleted' event type
1428 * for every 'added' event type passed to this function.
1429 * This is done only for named entities used in the
1430 * route-map match commands.
1431 * This function is not to be invoked for any of the other event
1439 * Return to make c happy but if we get here something has gone
1440 * terribly terribly wrong, so yes this return makes no sense.
1442 return RMAP_EVENT_CALL_ADDED
;
1445 /* Add match statement to route map. */
1446 enum rmap_compile_rets
route_map_add_match(struct route_map_index
*index
,
1447 const char *match_name
,
1448 const char *match_arg
,
1449 route_map_event_t type
)
1451 struct route_map_rule
*rule
;
1452 struct route_map_rule
*next
;
1453 const struct route_map_rule_cmd
*cmd
;
1455 int8_t delete_rmap_event_type
= 0;
1456 const char *rule_key
;
1458 /* First lookup rule for add match statement. */
1459 cmd
= route_map_lookup_match(match_name
);
1461 return RMAP_RULE_MISSING
;
1463 /* Next call compile function for this match statement. */
1464 if (cmd
->func_compile
) {
1465 compile
= (*cmd
->func_compile
)(match_arg
);
1466 if (compile
== NULL
)
1467 return RMAP_COMPILE_ERROR
;
1470 /* use the compiled results if applicable */
1471 if (compile
&& cmd
->func_get_rmap_rule_key
)
1472 rule_key
= (*cmd
->func_get_rmap_rule_key
)
1475 rule_key
= match_arg
;
1477 /* If argument is completely same ignore it. */
1478 for (rule
= index
->match_list
.head
; rule
; rule
= next
) {
1480 if (rule
->cmd
== cmd
) {
1481 /* If the configured route-map match rule is exactly
1482 * the same as the existing configuration then,
1483 * ignore the duplicate configuration.
1485 if (rulecmp(match_arg
, rule
->rule_str
) == 0) {
1487 (*cmd
->func_free
)(compile
);
1489 return RMAP_COMPILE_SUCCESS
;
1492 /* If IPv4 or IPv6 prefix-list match criteria
1493 * has been delete to the route-map index, update
1494 * the route-map's prefix table.
1496 if (IS_RULE_IPv4_PREFIX_LIST(match_name
))
1497 route_map_pfx_tbl_update(
1498 RMAP_EVENT_PLIST_DELETED
, index
, AFI_IP
,
1500 else if (IS_RULE_IPv6_PREFIX_LIST(match_name
))
1501 route_map_pfx_tbl_update(
1502 RMAP_EVENT_PLIST_DELETED
, index
,
1503 AFI_IP6
, rule
->rule_str
);
1505 /* Remove the dependency of the route-map on the rule
1506 * that is being replaced.
1508 if (type
>= RMAP_EVENT_CALL_ADDED
) {
1509 delete_rmap_event_type
=
1510 get_route_map_delete_event(type
);
1511 route_map_upd8_dependency(
1512 delete_rmap_event_type
,
1517 route_map_rule_delete(&index
->match_list
, rule
);
1521 /* Add new route map match rule. */
1522 rule
= route_map_rule_new();
1524 rule
->value
= compile
;
1526 rule
->rule_str
= XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR
, match_arg
);
1528 rule
->rule_str
= NULL
;
1530 /* Add new route match rule to linked list. */
1531 route_map_rule_add(&index
->match_list
, rule
);
1533 /* If IPv4 or IPv6 prefix-list match criteria
1534 * has been added to the route-map index, update
1535 * the route-map's prefix table.
1537 if (IS_RULE_IPv4_PREFIX_LIST(match_name
)) {
1538 route_map_pfx_tbl_update(RMAP_EVENT_PLIST_ADDED
, index
, AFI_IP
,
1540 } else if (IS_RULE_IPv6_PREFIX_LIST(match_name
)) {
1541 route_map_pfx_tbl_update(RMAP_EVENT_PLIST_ADDED
, index
, AFI_IP6
,
1545 /* Execute event hook. */
1546 if (route_map_master
.event_hook
) {
1547 (*route_map_master
.event_hook
)(index
->map
->name
);
1548 route_map_notify_dependencies(index
->map
->name
,
1549 RMAP_EVENT_CALL_ADDED
);
1551 if (type
!= RMAP_EVENT_MATCH_ADDED
)
1552 route_map_upd8_dependency(type
, rule_key
, index
->map
->name
);
1554 return RMAP_COMPILE_SUCCESS
;
1557 /* Delete specified route match rule. */
1558 enum rmap_compile_rets
route_map_delete_match(struct route_map_index
*index
,
1559 const char *match_name
,
1560 const char *match_arg
,
1561 route_map_event_t type
)
1563 struct route_map_rule
*rule
;
1564 const struct route_map_rule_cmd
*cmd
;
1565 const char *rule_key
;
1567 cmd
= route_map_lookup_match(match_name
);
1569 return RMAP_RULE_MISSING
;
1571 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1572 if (rule
->cmd
== cmd
&& (rulecmp(rule
->rule_str
, match_arg
) == 0
1573 || match_arg
== NULL
)) {
1574 /* Execute event hook. */
1575 if (route_map_master
.event_hook
) {
1576 (*route_map_master
.event_hook
)(index
->map
->name
);
1577 route_map_notify_dependencies(
1579 RMAP_EVENT_CALL_ADDED
);
1581 if (cmd
->func_get_rmap_rule_key
)
1582 rule_key
= (*cmd
->func_get_rmap_rule_key
)
1585 rule_key
= match_arg
;
1587 if (type
!= RMAP_EVENT_MATCH_DELETED
&& rule_key
)
1588 route_map_upd8_dependency(type
, rule_key
,
1591 route_map_rule_delete(&index
->match_list
, rule
);
1593 /* If IPv4 or IPv6 prefix-list match criteria
1594 * has been delete from the route-map index, update
1595 * the route-map's prefix table.
1597 if (IS_RULE_IPv4_PREFIX_LIST(match_name
)) {
1598 route_map_pfx_tbl_update(
1599 RMAP_EVENT_PLIST_DELETED
, index
, AFI_IP
,
1601 } else if (IS_RULE_IPv6_PREFIX_LIST(match_name
)) {
1602 route_map_pfx_tbl_update(
1603 RMAP_EVENT_PLIST_DELETED
, index
,
1604 AFI_IP6
, match_arg
);
1607 return RMAP_COMPILE_SUCCESS
;
1609 /* Can't find matched rule. */
1610 return RMAP_RULE_MISSING
;
1613 /* Add route-map set statement to the route map. */
1614 enum rmap_compile_rets
route_map_add_set(struct route_map_index
*index
,
1615 const char *set_name
,
1616 const char *set_arg
)
1618 struct route_map_rule
*rule
;
1619 struct route_map_rule
*next
;
1620 const struct route_map_rule_cmd
*cmd
;
1623 cmd
= route_map_lookup_set(set_name
);
1625 return RMAP_RULE_MISSING
;
1627 /* Next call compile function for this match statement. */
1628 if (cmd
->func_compile
) {
1629 compile
= (*cmd
->func_compile
)(set_arg
);
1630 if (compile
== NULL
)
1631 return RMAP_COMPILE_ERROR
;
1635 /* Add by WJL. if old set command of same kind exist, delete it first
1636 to ensure only one set command of same kind exist under a
1638 for (rule
= index
->set_list
.head
; rule
; rule
= next
) {
1640 if (rule
->cmd
== cmd
)
1641 route_map_rule_delete(&index
->set_list
, rule
);
1644 /* Add new route map match rule. */
1645 rule
= route_map_rule_new();
1647 rule
->value
= compile
;
1649 rule
->rule_str
= XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR
, set_arg
);
1651 rule
->rule_str
= NULL
;
1653 /* Add new route match rule to linked list. */
1654 route_map_rule_add(&index
->set_list
, rule
);
1656 /* Execute event hook. */
1657 if (route_map_master
.event_hook
) {
1658 (*route_map_master
.event_hook
)(index
->map
->name
);
1659 route_map_notify_dependencies(index
->map
->name
,
1660 RMAP_EVENT_CALL_ADDED
);
1662 return RMAP_COMPILE_SUCCESS
;
1665 /* Delete route map set rule. */
1666 enum rmap_compile_rets
route_map_delete_set(struct route_map_index
*index
,
1667 const char *set_name
,
1668 const char *set_arg
)
1670 struct route_map_rule
*rule
;
1671 const struct route_map_rule_cmd
*cmd
;
1673 cmd
= route_map_lookup_set(set_name
);
1675 return RMAP_RULE_MISSING
;
1677 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1678 if ((rule
->cmd
== cmd
) && (rulecmp(rule
->rule_str
, set_arg
) == 0
1679 || set_arg
== NULL
)) {
1680 route_map_rule_delete(&index
->set_list
, rule
);
1681 /* Execute event hook. */
1682 if (route_map_master
.event_hook
) {
1683 (*route_map_master
.event_hook
)(index
->map
->name
);
1684 route_map_notify_dependencies(
1686 RMAP_EVENT_CALL_ADDED
);
1688 return RMAP_COMPILE_SUCCESS
;
1690 /* Can't find matched rule. */
1691 return RMAP_RULE_MISSING
;
1694 static enum route_map_cmd_result_t
1695 route_map_apply_match(struct route_map_rule_list
*match_list
,
1696 const struct prefix
*prefix
, void *object
)
1698 enum route_map_cmd_result_t ret
= RMAP_NOMATCH
;
1699 struct route_map_rule
*match
;
1700 bool is_matched
= false;
1703 /* Check all match rule and if there is no match rule, go to the
1705 if (!match_list
->head
)
1708 for (match
= match_list
->head
; match
; match
= match
->next
) {
1710 * Try each match statement. If any match does not
1711 * return RMAP_MATCH or RMAP_NOOP, return.
1712 * Otherwise continue on to next match statement.
1713 * All match statements must MATCH for
1714 * end-result to be a match.
1715 * (Exception:If match stmts result in a mix of
1716 * MATCH/NOOP, then also end-result is a match)
1717 * If all result in NOOP, end-result is NOOP.
1719 ret
= (*match
->cmd
->func_apply
)(match
->value
, prefix
,
1723 * If the consolidated result of func_apply is:
1724 * -----------------------------------------------
1725 * | MATCH | NOMATCH | NOOP | Final Result |
1726 * ------------------------------------------------
1727 * | yes | yes | yes | NOMATCH |
1728 * | no | no | yes | NOOP |
1729 * | yes | no | yes | MATCH |
1730 * | no | yes | yes | NOMATCH |
1731 * |-----------------------------------------------
1733 * Traditionally, all rules within route-map
1734 * should match for it to MATCH.
1735 * If there are noops within the route-map rules,
1736 * it follows the above matrix.
1738 * Eg: route-map rm1 permit 10
1743 * route-map rm1 permit 20
1771 static struct list
*route_map_get_index_list(struct route_node
**rn
,
1772 const struct prefix
*prefix
,
1773 struct route_table
*table
)
1775 struct route_node
*tmp_rn
= NULL
;
1778 *rn
= route_node_match(table
, prefix
);
1784 return (struct list
*)((*rn
)->info
);
1786 /* If rn->info is NULL, get the parent.
1787 * Store the rn in tmp_rn and unlock it later.
1793 *rn
= (*rn
)->parent
;
1795 route_unlock_node(tmp_rn
);
1801 route_lock_node(*rn
);
1802 return (struct list
*)((*rn
)->info
);
1804 } while (!(*rn
)->info
);
1810 * This function returns the route-map index that best matches the prefix.
1812 static struct route_map_index
*
1813 route_map_get_index(struct route_map
*map
, const struct prefix
*prefix
,
1814 void *object
, enum route_map_cmd_result_t
*match_ret
)
1816 enum route_map_cmd_result_t ret
= RMAP_NOMATCH
;
1817 struct list
*candidate_rmap_list
= NULL
;
1818 struct route_node
*rn
= NULL
;
1819 struct listnode
*ln
= NULL
, *nn
= NULL
;
1820 struct route_map_index
*index
= NULL
, *best_index
= NULL
;
1821 struct route_map_index
*head_index
= NULL
;
1822 struct route_table
*table
= NULL
;
1823 unsigned char family
= prefix
->family
;
1825 if (family
== AF_INET
)
1826 table
= map
->ipv4_prefix_table
;
1828 table
= map
->ipv6_prefix_table
;
1834 candidate_rmap_list
=
1835 route_map_get_index_list(&rn
, prefix
, table
);
1839 /* If the index at the head of the list is of seq higher
1840 * than that in best_index, ignore the list and get the
1841 * parent node's list.
1843 head_index
= (struct route_map_index
*)(listgetdata(
1844 listhead(candidate_rmap_list
)));
1845 if (best_index
&& head_index
1846 && (best_index
->pref
< head_index
->pref
)) {
1847 route_unlock_node(rn
);
1851 for (ALL_LIST_ELEMENTS(candidate_rmap_list
, ln
, nn
, index
)) {
1852 /* If the index is of seq higher than that in
1853 * best_index, ignore the list and get the parent
1856 if (best_index
&& (best_index
->pref
< index
->pref
))
1859 ret
= route_map_apply_match(&index
->match_list
, prefix
,
1862 if (ret
== RMAP_MATCH
) {
1866 } else if (ret
== RMAP_NOOP
) {
1868 * If match_ret is denymatch, even if we see
1869 * more noops, we retain this return value and
1870 * return this eventually if there are no
1872 * If a best match route-map index already
1873 * exists, do not reset the match_ret.
1875 if (!best_index
&& (*match_ret
!= RMAP_NOMATCH
))
1879 * ret is RMAP_NOMATCH.
1880 * If a best match route-map index already
1881 * exists, do not reset the match_ret.
1888 route_unlock_node(rn
);
1895 static int route_map_candidate_list_cmp(struct route_map_index
*idx1
,
1896 struct route_map_index
*idx2
)
1903 return (idx1
->pref
- idx2
->pref
);
1907 * This function adds the route-map index into the default route's
1908 * route-node in the route-map's IPv4/IPv6 prefix-table.
1910 static void route_map_pfx_table_add_default(afi_t afi
,
1911 struct route_map_index
*index
)
1913 struct route_node
*rn
= NULL
;
1914 struct list
*rmap_candidate_list
= NULL
;
1916 bool updated_rn
= false;
1917 struct route_table
*table
= NULL
;
1919 memset(&p
, 0, sizeof(p
));
1920 p
.family
= afi2family(afi
);
1923 if (p
.family
== AF_INET
) {
1924 table
= index
->map
->ipv4_prefix_table
;
1926 index
->map
->ipv4_prefix_table
= route_table_init();
1928 table
= index
->map
->ipv4_prefix_table
;
1930 table
= index
->map
->ipv6_prefix_table
;
1932 index
->map
->ipv6_prefix_table
= route_table_init();
1934 table
= index
->map
->ipv6_prefix_table
;
1937 /* Add default route to table */
1938 rn
= route_node_get(table
, &p
);
1944 rmap_candidate_list
= list_new();
1945 rmap_candidate_list
->cmp
=
1946 (int (*)(void *, void *))route_map_candidate_list_cmp
;
1947 rn
->info
= rmap_candidate_list
;
1949 rmap_candidate_list
= (struct list
*)rn
->info
;
1953 listnode_add_sort_nodup(rmap_candidate_list
, index
);
1955 route_unlock_node(rn
);
1959 * This function removes the route-map index from the default route's
1960 * route-node in the route-map's IPv4/IPv6 prefix-table.
1962 static void route_map_pfx_table_del_default(afi_t afi
,
1963 struct route_map_index
*index
)
1965 struct route_node
*rn
= NULL
;
1966 struct list
*rmap_candidate_list
= NULL
;
1968 struct route_table
*table
= NULL
;
1970 memset(&p
, 0, sizeof(p
));
1971 p
.family
= afi2family(afi
);
1974 if (p
.family
== AF_INET
)
1975 table
= index
->map
->ipv4_prefix_table
;
1977 table
= index
->map
->ipv6_prefix_table
;
1979 /* Remove RMAP index from default route in table */
1980 rn
= route_node_lookup(table
, &p
);
1981 if (!rn
|| !rn
->info
)
1984 rmap_candidate_list
= (struct list
*)rn
->info
;
1986 listnode_delete(rmap_candidate_list
, index
);
1988 if (listcount(rmap_candidate_list
) == 0) {
1989 list_delete(&rmap_candidate_list
);
1991 route_unlock_node(rn
);
1993 route_unlock_node(rn
);
1997 * This function adds the route-map index to the route-node for
1998 * the prefix-entry in the route-map's IPv4/IPv6 prefix-table.
2000 static void route_map_pfx_table_add(struct route_table
*table
,
2001 struct route_map_index
*index
,
2002 struct prefix_list_entry
*pentry
)
2004 struct route_node
*rn
= NULL
;
2005 struct list
*rmap_candidate_list
= NULL
;
2006 bool updated_rn
= false;
2008 rn
= route_node_get(table
, &pentry
->prefix
);
2013 rmap_candidate_list
= list_new();
2014 rmap_candidate_list
->cmp
=
2015 (int (*)(void *, void *))route_map_candidate_list_cmp
;
2016 rn
->info
= rmap_candidate_list
;
2018 rmap_candidate_list
= (struct list
*)rn
->info
;
2022 listnode_add_sort_nodup(rmap_candidate_list
, index
);
2024 route_unlock_node(rn
);
2028 * This function removes the route-map index from the route-node for
2029 * the prefix-entry in the route-map's IPv4/IPv6 prefix-table.
2031 static void route_map_pfx_table_del(struct route_table
*table
,
2032 struct route_map_index
*index
,
2033 struct prefix_list_entry
*pentry
)
2035 struct route_node
*rn
= NULL
;
2036 struct list
*rmap_candidate_list
= NULL
;
2038 rn
= route_node_lookup(table
, &pentry
->prefix
);
2039 if (!rn
|| !rn
->info
)
2042 rmap_candidate_list
= (struct list
*)rn
->info
;
2044 listnode_delete(rmap_candidate_list
, index
);
2046 if (listcount(rmap_candidate_list
) == 0) {
2047 list_delete(&rmap_candidate_list
);
2049 route_unlock_node(rn
);
2051 route_unlock_node(rn
);
2054 /* This function checks for the presence of an IPv4 prefix-list
2055 * match rule in the given route-map index.
2057 static bool route_map_is_ip_pfx_list_rule_present(struct route_map_index
*index
)
2059 struct route_map_rule_list
*match_list
= NULL
;
2060 struct route_map_rule
*rule
= NULL
;
2062 match_list
= &index
->match_list
;
2063 for (rule
= match_list
->head
; rule
; rule
= rule
->next
)
2064 if (IS_RULE_IPv4_PREFIX_LIST(rule
->cmd
->str
))
2070 /* This function checks for the presence of an IPv6 prefix-list
2071 * match rule in the given route-map index.
2074 route_map_is_ipv6_pfx_list_rule_present(struct route_map_index
*index
)
2076 struct route_map_rule_list
*match_list
= NULL
;
2077 struct route_map_rule
*rule
= NULL
;
2079 match_list
= &index
->match_list
;
2080 for (rule
= match_list
->head
; rule
; rule
= rule
->next
)
2081 if (IS_RULE_IPv6_PREFIX_LIST(rule
->cmd
->str
))
2087 /* This function does the following:
2088 * 1) If plist_name is not present, search for a IPv4 or IPv6 prefix-list
2089 * match clause (based on the afi passed to this foo) and get the
2091 * 2) Look up the prefix-list using the name.
2092 * 3) If the prefix-list is not found then, add the index to the IPv4/IPv6
2093 * default-route's node in the trie (based on the afi passed to this foo).
2094 * 4) If the prefix-list is found then, remove the index from the IPv4/IPv6
2095 * default-route's node in the trie (based on the afi passed to this foo).
2096 * 5) If a prefix-entry is passed then, create a route-node for this entry and
2097 * add this index to the route-node.
2098 * 6) If prefix-entry is not passed then, for every prefix-entry in the
2099 * prefix-list, create a route-node for this entry and
2100 * add this index to the route-node.
2102 static void route_map_add_plist_entries(afi_t afi
,
2103 struct route_map_index
*index
,
2104 const char *plist_name
,
2105 struct prefix_list_entry
*entry
)
2107 struct route_map_rule_list
*match_list
= NULL
;
2108 struct route_map_rule
*match
= NULL
;
2109 struct prefix_list
*plist
= NULL
;
2110 struct prefix_list_entry
*pentry
= NULL
;
2111 bool plist_rule_is_present
= false;
2114 match_list
= &index
->match_list
;
2116 for (match
= match_list
->head
; match
; match
= match
->next
) {
2117 if (afi
== AFI_IP
) {
2118 if (IS_RULE_IPv4_PREFIX_LIST(match
->cmd
->str
)) {
2119 plist_rule_is_present
= true;
2123 if (IS_RULE_IPv6_PREFIX_LIST(match
->cmd
->str
)) {
2124 plist_rule_is_present
= true;
2130 if (plist_rule_is_present
)
2131 plist
= prefix_list_lookup(afi
, match
->rule_str
);
2133 plist
= prefix_list_lookup(afi
, plist_name
);
2137 route_map_pfx_table_add_default(afi
, index
);
2141 /* Default entry should be deleted only if the first entry of the
2142 * prefix-list is created.
2145 if (plist
->count
== 1)
2146 route_map_pfx_table_del_default(afi
, index
);
2148 route_map_pfx_table_del_default(afi
, index
);
2152 if (afi
== AFI_IP
) {
2153 route_map_pfx_table_add(index
->map
->ipv4_prefix_table
,
2156 route_map_pfx_table_add(index
->map
->ipv6_prefix_table
,
2160 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
2161 if (afi
== AFI_IP
) {
2162 route_map_pfx_table_add(
2163 index
->map
->ipv4_prefix_table
, index
,
2166 route_map_pfx_table_add(
2167 index
->map
->ipv6_prefix_table
, index
,
2174 /* This function does the following:
2175 * 1) If plist_name is not present, search for a IPv4 or IPv6 prefix-list
2176 * match clause (based on the afi passed to this foo) and get the
2178 * 2) Look up the prefix-list using the name.
2179 * 3) If the prefix-list is not found then, delete the index from the IPv4/IPv6
2180 * default-route's node in the trie (based on the afi passed to this foo).
2181 * 4) If a prefix-entry is passed then, remove this index from the route-node
2182 * for the prefix in this prefix-entry.
2183 * 5) If prefix-entry is not passed then, for every prefix-entry in the
2184 * prefix-list, remove this index from the route-node
2185 * for the prefix in this prefix-entry.
2187 static void route_map_del_plist_entries(afi_t afi
,
2188 struct route_map_index
*index
,
2189 const char *plist_name
,
2190 struct prefix_list_entry
*entry
)
2192 struct route_map_rule_list
*match_list
= NULL
;
2193 struct route_map_rule
*match
= NULL
;
2194 struct prefix_list
*plist
= NULL
;
2195 struct prefix_list_entry
*pentry
= NULL
;
2196 bool plist_rule_is_present
= false;
2199 match_list
= &index
->match_list
;
2201 for (match
= match_list
->head
; match
; match
= match
->next
) {
2202 if (afi
== AFI_IP
) {
2203 if (IS_RULE_IPv4_PREFIX_LIST(match
->cmd
->str
)) {
2204 plist_rule_is_present
= true;
2208 if (IS_RULE_IPv6_PREFIX_LIST(match
->cmd
->str
)) {
2209 plist_rule_is_present
= true;
2215 if (plist_rule_is_present
)
2216 plist
= prefix_list_lookup(afi
, match
->rule_str
);
2218 plist
= prefix_list_lookup(afi
, plist_name
);
2222 route_map_pfx_table_del_default(afi
, index
);
2227 if (afi
== AFI_IP
) {
2228 route_map_pfx_table_del(index
->map
->ipv4_prefix_table
,
2231 route_map_pfx_table_del(index
->map
->ipv6_prefix_table
,
2235 for (pentry
= plist
->head
; pentry
; pentry
= pentry
->next
) {
2236 if (afi
== AFI_IP
) {
2237 route_map_pfx_table_del(
2238 index
->map
->ipv4_prefix_table
, index
,
2241 route_map_pfx_table_del(
2242 index
->map
->ipv6_prefix_table
, index
,
2250 * This function handles the cases where a prefix-list is added/removed
2251 * as a match command from a particular route-map index.
2252 * It updates the prefix-table of the route-map accordingly.
2254 static void route_map_trie_update(afi_t afi
, route_map_event_t event
,
2255 struct route_map_index
*index
,
2256 const char *plist_name
)
2258 if (event
== RMAP_EVENT_PLIST_ADDED
) {
2259 if (afi
== AFI_IP
) {
2260 if (!route_map_is_ipv6_pfx_list_rule_present(index
)) {
2261 route_map_pfx_table_del_default(AFI_IP6
, index
);
2262 route_map_add_plist_entries(afi
, index
,
2265 route_map_del_plist_entries(AFI_IP6
, index
,
2269 if (!route_map_is_ip_pfx_list_rule_present(index
)) {
2270 route_map_pfx_table_del_default(AFI_IP
, index
);
2271 route_map_add_plist_entries(afi
, index
,
2274 route_map_del_plist_entries(AFI_IP
, index
, NULL
,
2278 } else if (event
== RMAP_EVENT_PLIST_DELETED
) {
2279 if (afi
== AFI_IP
) {
2280 route_map_del_plist_entries(afi
, index
, plist_name
,
2283 /* If IPv6 prefix-list match rule is not present,
2284 * add this index to the IPv4 default route's trie
2286 * Also, add this index to the trie nodes created
2287 * for each of the prefix-entries within the IPv6
2288 * prefix-list, if the IPv6 prefix-list match rule
2289 * is present. Else, add this index to the IPv6
2290 * default route's trie node.
2292 if (!route_map_is_ipv6_pfx_list_rule_present(index
))
2293 route_map_pfx_table_add_default(afi
, index
);
2295 route_map_add_plist_entries(AFI_IP6
, index
, NULL
, NULL
);
2297 route_map_del_plist_entries(afi
, index
, plist_name
,
2300 /* If IPv4 prefix-list match rule is not present,
2301 * add this index to the IPv6 default route's trie
2303 * Also, add this index to the trie nodes created
2304 * for each of the prefix-entries within the IPv4
2305 * prefix-list, if the IPv4 prefix-list match rule
2306 * is present. Else, add this index to the IPv4
2307 * default route's trie node.
2309 if (!route_map_is_ip_pfx_list_rule_present(index
))
2310 route_map_pfx_table_add_default(afi
, index
);
2312 route_map_add_plist_entries(AFI_IP
, index
, NULL
, NULL
);
2318 * This function handles the cases where a route-map index and
2319 * prefix-list is added/removed.
2320 * It updates the prefix-table of the route-map accordingly.
2322 static void route_map_pfx_tbl_update(route_map_event_t event
,
2323 struct route_map_index
*index
, afi_t afi
,
2324 const char *plist_name
)
2326 struct route_map
*rmap
= NULL
;
2331 if (event
== RMAP_EVENT_INDEX_ADDED
) {
2332 route_map_pfx_table_add_default(AFI_IP
, index
);
2333 route_map_pfx_table_add_default(AFI_IP6
, index
);
2337 if (event
== RMAP_EVENT_INDEX_DELETED
) {
2338 route_map_pfx_table_del_default(AFI_IP
, index
);
2339 route_map_pfx_table_del_default(AFI_IP6
, index
);
2341 if ((index
->map
->head
== NULL
) && (index
->map
->tail
== NULL
)) {
2344 if (rmap
->ipv4_prefix_table
) {
2345 route_table_finish(rmap
->ipv4_prefix_table
);
2346 rmap
->ipv4_prefix_table
= NULL
;
2349 if (rmap
->ipv6_prefix_table
) {
2350 route_table_finish(rmap
->ipv6_prefix_table
);
2351 rmap
->ipv6_prefix_table
= NULL
;
2357 /* Handle prefix-list match rule addition/deletion.
2359 route_map_trie_update(afi
, event
, index
, plist_name
);
2363 * This function handles the cases where a new prefix-entry is added to
2364 * a prefix-list or, an existing prefix-entry is removed from the prefix-list.
2365 * It updates the prefix-table of the route-map accordingly.
2367 static void route_map_pentry_update(route_map_event_t event
,
2368 const char *plist_name
,
2369 struct route_map_index
*index
,
2370 struct prefix_list_entry
*pentry
)
2372 struct prefix_list
*plist
= NULL
;
2374 unsigned char family
= pentry
->prefix
.family
;
2376 if (family
== AF_INET
) {
2378 plist
= prefix_list_lookup(AFI_IP
, plist_name
);
2381 plist
= prefix_list_lookup(AFI_IP6
, plist_name
);
2384 if (event
== RMAP_EVENT_PLIST_ADDED
) {
2385 if (afi
== AFI_IP
) {
2386 if (!route_map_is_ipv6_pfx_list_rule_present(index
))
2387 route_map_add_plist_entries(afi
, index
,
2388 plist_name
, pentry
);
2390 if (!route_map_is_ip_pfx_list_rule_present(index
))
2391 route_map_add_plist_entries(afi
, index
,
2392 plist_name
, pentry
);
2394 } else if (event
== RMAP_EVENT_PLIST_DELETED
) {
2395 route_map_del_plist_entries(afi
, index
, plist_name
, pentry
);
2397 if (plist
->count
== 1) {
2398 if (afi
== AFI_IP
) {
2399 if (!route_map_is_ipv6_pfx_list_rule_present(
2401 route_map_pfx_table_add_default(afi
,
2404 if (!route_map_is_ip_pfx_list_rule_present(
2406 route_map_pfx_table_add_default(afi
,
2413 static void route_map_pentry_process_dependency(struct hash_bucket
*bucket
,
2416 char *rmap_name
= NULL
;
2417 struct route_map
*rmap
= NULL
;
2418 struct route_map_index
*index
= NULL
;
2419 struct route_map_rule_list
*match_list
= NULL
;
2420 struct route_map_rule
*match
= NULL
;
2421 struct route_map_dep_data
*dep_data
= NULL
;
2422 struct route_map_pentry_dep
*pentry_dep
=
2423 (struct route_map_pentry_dep
*)data
;
2424 unsigned char family
= pentry_dep
->pentry
->prefix
.family
;
2426 dep_data
= (struct route_map_dep_data
*)bucket
->data
;
2430 rmap_name
= dep_data
->rname
;
2431 rmap
= route_map_lookup_by_name(rmap_name
);
2432 if (!rmap
|| !rmap
->head
)
2435 for (index
= rmap
->head
; index
; index
= index
->next
) {
2436 match_list
= &index
->match_list
;
2441 for (match
= match_list
->head
; match
; match
= match
->next
) {
2442 if (strcmp(match
->rule_str
, pentry_dep
->plist_name
)
2444 if (IS_RULE_IPv4_PREFIX_LIST(match
->cmd
->str
)
2445 && family
== AF_INET
) {
2446 route_map_pentry_update(
2448 pentry_dep
->plist_name
, index
,
2449 pentry_dep
->pentry
);
2450 } else if (IS_RULE_IPv6_PREFIX_LIST(
2452 && family
== AF_INET6
) {
2453 route_map_pentry_update(
2455 pentry_dep
->plist_name
, index
,
2456 pentry_dep
->pentry
);
2463 void route_map_notify_pentry_dependencies(const char *affected_name
,
2464 struct prefix_list_entry
*pentry
,
2465 route_map_event_t event
)
2467 struct route_map_dep
*dep
= NULL
;
2468 struct hash
*upd8_hash
= NULL
;
2469 struct route_map_pentry_dep pentry_dep
;
2471 if (!affected_name
|| !pentry
)
2474 upd8_hash
= route_map_get_dep_hash(event
);
2478 dep
= (struct route_map_dep
*)hash_get(upd8_hash
, (void *)affected_name
,
2481 if (!dep
->this_hash
)
2482 dep
->this_hash
= upd8_hash
;
2484 memset(&pentry_dep
, 0, sizeof(struct route_map_pentry_dep
));
2485 pentry_dep
.pentry
= pentry
;
2486 pentry_dep
.plist_name
= affected_name
;
2487 pentry_dep
.event
= event
;
2489 hash_iterate(dep
->dep_rmap_hash
,
2490 route_map_pentry_process_dependency
,
2491 (void *)&pentry_dep
);
2495 /* Apply route map's each index to the object.
2497 The matrix for a route-map looks like this:
2498 (note, this includes the description for the "NEXT"
2499 and "GOTO" frobs now
2501 | Match | No Match | No op
2502 |-----------|--------------|-------
2503 permit | action | cont | cont.
2504 | | default:deny | default:permit
2505 -------------------+-----------------------
2506 | deny | cont | cont.
2507 deny | | default:deny | default:permit
2508 |-----------|--------------|--------
2511 -Apply Set statements, accept route
2512 -If Call statement is present jump to the specified route-map, if it
2513 denies the route we finish.
2514 -If NEXT is specified, goto NEXT statement
2515 -If GOTO is specified, goto the first clause where pref > nextpref
2516 -If nothing is specified, do as Cisco and finish
2518 -Route is denied by route-map.
2522 If we get no matches after we've processed all updates, then the route
2525 Some notes on the new "CALL", "NEXT" and "GOTO"
2526 call WORD - If this clause is matched, then the set statements
2527 are executed and then we jump to route-map 'WORD'. If
2528 this route-map denies the route, we finish, in other
2530 do whatever the exit policy (EXIT, NEXT or GOTO) tells.
2531 on-match next - If this clause is matched, then the set statements
2532 are executed and then we drop through to the next clause
2533 on-match goto n - If this clause is matched, then the set statements
2534 are executed and then we goto the nth clause, or the
2535 first clause greater than this. In order to ensure
2536 route-maps *always* exit, you cannot jump backwards.
2539 We need to make sure our route-map processing matches the above
2541 route_map_result_t
route_map_apply_ext(struct route_map
*map
,
2542 const struct prefix
*prefix
,
2543 void *match_object
, void *set_object
)
2545 static int recursion
= 0;
2546 enum route_map_cmd_result_t match_ret
= RMAP_NOMATCH
;
2547 route_map_result_t ret
= RMAP_PERMITMATCH
;
2548 struct route_map_index
*index
= NULL
;
2549 struct route_map_rule
*set
= NULL
;
2550 bool skip_match_clause
= false;
2552 if (recursion
> RMAP_RECURSION_LIMIT
) {
2554 EC_LIB_RMAP_RECURSION_LIMIT
,
2555 "route-map recursion limit (%d) reached, discarding route",
2556 RMAP_RECURSION_LIMIT
);
2558 return RMAP_DENYMATCH
;
2561 if (map
== NULL
|| map
->head
== NULL
) {
2562 ret
= RMAP_DENYMATCH
;
2563 goto route_map_apply_end
;
2568 if ((!map
->optimization_disabled
)
2569 && (map
->ipv4_prefix_table
|| map
->ipv6_prefix_table
)) {
2570 index
= route_map_get_index(map
, prefix
, match_object
,
2576 "Best match route-map: %s, sequence: %d for pfx: %pFX, result: %s",
2577 map
->name
, index
->pref
, prefix
,
2578 route_map_cmd_result_str(match_ret
));
2582 "No best match sequence for pfx: %pFX in route-map: %s, result: %s",
2584 route_map_cmd_result_str(match_ret
));
2586 * No index matches this prefix. Return deny unless,
2587 * match_ret = RMAP_NOOP.
2589 if (match_ret
== RMAP_NOOP
)
2590 ret
= RMAP_PERMITMATCH
;
2592 ret
= RMAP_DENYMATCH
;
2593 goto route_map_apply_end
;
2595 skip_match_clause
= true;
2600 for (; index
; index
= index
->next
) {
2601 if (!skip_match_clause
) {
2603 /* Apply this index. */
2604 match_ret
= route_map_apply_match(&index
->match_list
,
2605 prefix
, match_object
);
2608 "Route-map: %s, sequence: %d, prefix: %pFX, result: %s",
2609 map
->name
, index
->pref
, prefix
,
2610 route_map_cmd_result_str(match_ret
));
2613 skip_match_clause
= false;
2616 /* Now we apply the matrix from above */
2617 if (match_ret
== RMAP_NOOP
)
2619 * Do not change the return value. Retain the previous
2620 * return value. Previous values can be:
2621 * 1)permitmatch (if a nomatch was never
2622 * seen before in this route-map.)
2623 * 2)denymatch (if a nomatch was seen earlier in one
2624 * of the previous sequences)
2628 * 'cont' from matrix - continue to next route-map
2632 else if (match_ret
== RMAP_NOMATCH
) {
2635 * The return value is now changed to denymatch.
2636 * So from here on out, even if we see more noops,
2637 * we retain this return value and return this
2638 * eventually if there are no matches.
2640 ret
= RMAP_DENYMATCH
;
2643 * 'cont' from matrix - continue to next route-map
2647 } else if (match_ret
== RMAP_MATCH
) {
2648 if (index
->type
== RMAP_PERMIT
)
2651 /* Match succeeded, rmap is of type permit */
2652 ret
= RMAP_PERMITMATCH
;
2654 /* permit+match must execute sets */
2655 for (set
= index
->set_list
.head
; set
;
2658 * set cmds return RMAP_OKAY or
2659 * RMAP_ERROR. We do not care if
2660 * set succeeded or not. So, ignore
2663 (void)(*set
->cmd
->func_apply
)(
2664 set
->value
, prefix
, set_object
);
2666 /* Call another route-map if available */
2667 if (index
->nextrm
) {
2668 struct route_map
*nextrm
=
2669 route_map_lookup_by_name(
2672 if (nextrm
) /* Target route-map found,
2676 ret
= route_map_apply_ext(
2683 /* If nextrm returned 'deny', finish. */
2684 if (ret
== RMAP_DENYMATCH
)
2685 goto route_map_apply_end
;
2688 switch (index
->exitpolicy
) {
2690 goto route_map_apply_end
;
2694 /* Find the next clause to jump to */
2695 struct route_map_index
*next
=
2697 int nextpref
= index
->nextpref
;
2699 while (next
&& next
->pref
< nextpref
) {
2704 /* No clauses match! */
2705 goto route_map_apply_end
;
2709 } else if (index
->type
== RMAP_DENY
)
2712 ret
= RMAP_DENYMATCH
;
2713 goto route_map_apply_end
;
2718 route_map_apply_end
:
2720 zlog_debug("Route-map: %s, prefix: %pFX, result: %s",
2721 (map
? map
->name
: "null"), prefix
,
2722 route_map_result_str(ret
));
2727 void route_map_add_hook(void (*func
)(const char *))
2729 route_map_master
.add_hook
= func
;
2732 void route_map_delete_hook(void (*func
)(const char *))
2734 route_map_master
.delete_hook
= func
;
2737 void route_map_event_hook(void (*func
)(const char *name
))
2739 route_map_master
.event_hook
= func
;
2742 /* Routines for route map dependency lists and dependency processing */
2743 static bool route_map_rmap_hash_cmp(const void *p1
, const void *p2
)
2745 return strcmp(((const struct route_map_dep_data
*)p1
)->rname
,
2746 ((const struct route_map_dep_data
*)p2
)->rname
)
2750 static bool route_map_dep_hash_cmp(const void *p1
, const void *p2
)
2753 return (strcmp(((const struct route_map_dep
*)p1
)->dep_name
,
2758 static void route_map_clear_reference(struct hash_bucket
*bucket
, void *arg
)
2760 struct route_map_dep
*dep
= bucket
->data
;
2761 struct route_map_dep_data
*dep_data
= NULL
, tmp_dep_data
;
2763 memset(&tmp_dep_data
, 0, sizeof(struct route_map_dep_data
));
2764 tmp_dep_data
.rname
= arg
;
2765 dep_data
= hash_release(dep
->dep_rmap_hash
, &tmp_dep_data
);
2768 zlog_debug("Clearing reference for %s to %s count: %d",
2769 dep
->dep_name
, tmp_dep_data
.rname
,
2772 XFREE(MTYPE_ROUTE_MAP_NAME
, dep_data
->rname
);
2773 XFREE(MTYPE_ROUTE_MAP_DEP_DATA
, dep_data
);
2775 if (!dep
->dep_rmap_hash
->count
) {
2776 dep
= hash_release(dep
->this_hash
, (void *)dep
->dep_name
);
2777 hash_free(dep
->dep_rmap_hash
);
2778 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
2779 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
2783 static void route_map_clear_all_references(char *rmap_name
)
2788 zlog_debug("Clearing references for %s", rmap_name
);
2790 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++) {
2791 hash_iterate(route_map_dep_hash
[i
], route_map_clear_reference
,
2796 static unsigned int route_map_dep_data_hash_make_key(const void *p
)
2798 const struct route_map_dep_data
*dep_data
= p
;
2800 return string_hash_make(dep_data
->rname
);
2803 static void *route_map_dep_hash_alloc(void *p
)
2805 char *dep_name
= (char *)p
;
2806 struct route_map_dep
*dep_entry
;
2808 dep_entry
= XCALLOC(MTYPE_ROUTE_MAP_DEP
, sizeof(struct route_map_dep
));
2809 dep_entry
->dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
2810 dep_entry
->dep_rmap_hash
=
2811 hash_create_size(8, route_map_dep_data_hash_make_key
,
2812 route_map_rmap_hash_cmp
, "Route Map Dep Hash");
2813 dep_entry
->this_hash
= NULL
;
2818 static void *route_map_name_hash_alloc(void *p
)
2820 struct route_map_dep_data
*dep_data
= NULL
, *tmp_dep_data
= NULL
;
2822 dep_data
= XCALLOC(MTYPE_ROUTE_MAP_DEP_DATA
,
2823 sizeof(struct route_map_dep_data
));
2825 dep_data
->rname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, tmp_dep_data
->rname
);
2829 static unsigned int route_map_dep_hash_make_key(const void *p
)
2831 return (string_hash_make((char *)p
));
2834 static void route_map_print_dependency(struct hash_bucket
*bucket
, void *data
)
2836 struct route_map_dep_data
*dep_data
= bucket
->data
;
2837 char *rmap_name
= dep_data
->rname
;
2838 char *dep_name
= data
;
2840 zlog_debug("%s: Dependency for %s: %s", __func__
, dep_name
, rmap_name
);
2843 static int route_map_dep_update(struct hash
*dephash
, const char *dep_name
,
2844 const char *rmap_name
, route_map_event_t type
)
2846 struct route_map_dep
*dep
= NULL
;
2847 char *dname
, *rname
;
2849 struct route_map_dep_data
*dep_data
= NULL
, *ret_dep_data
= NULL
;
2850 struct route_map_dep_data tmp_dep_data
;
2852 dname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
2853 rname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
2856 case RMAP_EVENT_PLIST_ADDED
:
2857 case RMAP_EVENT_CLIST_ADDED
:
2858 case RMAP_EVENT_ECLIST_ADDED
:
2859 case RMAP_EVENT_ASLIST_ADDED
:
2860 case RMAP_EVENT_LLIST_ADDED
:
2861 case RMAP_EVENT_CALL_ADDED
:
2862 case RMAP_EVENT_FILTER_ADDED
:
2864 zlog_debug("Adding dependency for filter %s in route-map %s",
2865 dep_name
, rmap_name
);
2866 dep
= (struct route_map_dep
*)hash_get(
2867 dephash
, dname
, route_map_dep_hash_alloc
);
2873 if (!dep
->this_hash
)
2874 dep
->this_hash
= dephash
;
2876 memset(&tmp_dep_data
, 0, sizeof(struct route_map_dep_data
));
2877 tmp_dep_data
.rname
= rname
;
2878 dep_data
= hash_lookup(dep
->dep_rmap_hash
, &tmp_dep_data
);
2880 dep_data
= hash_get(dep
->dep_rmap_hash
, &tmp_dep_data
,
2881 route_map_name_hash_alloc
);
2885 case RMAP_EVENT_PLIST_DELETED
:
2886 case RMAP_EVENT_CLIST_DELETED
:
2887 case RMAP_EVENT_ECLIST_DELETED
:
2888 case RMAP_EVENT_ASLIST_DELETED
:
2889 case RMAP_EVENT_LLIST_DELETED
:
2890 case RMAP_EVENT_CALL_DELETED
:
2891 case RMAP_EVENT_FILTER_DELETED
:
2893 zlog_debug("Deleting dependency for filter %s in route-map %s",
2894 dep_name
, rmap_name
);
2895 dep
= (struct route_map_dep
*)hash_get(dephash
, dname
, NULL
);
2900 memset(&tmp_dep_data
, 0, sizeof(struct route_map_dep_data
));
2901 tmp_dep_data
.rname
= rname
;
2902 dep_data
= hash_lookup(dep
->dep_rmap_hash
, &tmp_dep_data
);
2904 * If dep_data is NULL then something has gone seriously
2905 * wrong in route-map handling. Note it and prevent
2910 "route-map dependency for route-map %s: %s is not correct",
2911 rmap_name
, dep_name
);
2917 if (!dep_data
->refcnt
) {
2918 ret_dep_data
= hash_release(dep
->dep_rmap_hash
,
2921 XFREE(MTYPE_ROUTE_MAP_NAME
,
2922 ret_dep_data
->rname
);
2923 XFREE(MTYPE_ROUTE_MAP_DEP_DATA
, ret_dep_data
);
2927 if (!dep
->dep_rmap_hash
->count
) {
2928 dep
= hash_release(dephash
, dname
);
2929 hash_free(dep
->dep_rmap_hash
);
2930 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
2931 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
2934 case RMAP_EVENT_SET_ADDED
:
2935 case RMAP_EVENT_SET_DELETED
:
2936 case RMAP_EVENT_SET_REPLACED
:
2937 case RMAP_EVENT_MATCH_ADDED
:
2938 case RMAP_EVENT_MATCH_DELETED
:
2939 case RMAP_EVENT_MATCH_REPLACED
:
2940 case RMAP_EVENT_INDEX_ADDED
:
2941 case RMAP_EVENT_INDEX_DELETED
:
2947 hash_iterate(dep
->dep_rmap_hash
,
2948 route_map_print_dependency
, dname
);
2952 XFREE(MTYPE_ROUTE_MAP_NAME
, rname
);
2953 XFREE(MTYPE_ROUTE_MAP_NAME
, dname
);
2957 static struct hash
*route_map_get_dep_hash(route_map_event_t event
)
2959 struct hash
*upd8_hash
= NULL
;
2962 case RMAP_EVENT_PLIST_ADDED
:
2963 case RMAP_EVENT_PLIST_DELETED
:
2964 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_PLIST
];
2966 case RMAP_EVENT_CLIST_ADDED
:
2967 case RMAP_EVENT_CLIST_DELETED
:
2968 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_CLIST
];
2970 case RMAP_EVENT_ECLIST_ADDED
:
2971 case RMAP_EVENT_ECLIST_DELETED
:
2972 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ECLIST
];
2974 case RMAP_EVENT_ASLIST_ADDED
:
2975 case RMAP_EVENT_ASLIST_DELETED
:
2976 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ASPATH
];
2978 case RMAP_EVENT_LLIST_ADDED
:
2979 case RMAP_EVENT_LLIST_DELETED
:
2980 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_LCLIST
];
2982 case RMAP_EVENT_CALL_ADDED
:
2983 case RMAP_EVENT_CALL_DELETED
:
2984 case RMAP_EVENT_MATCH_ADDED
:
2985 case RMAP_EVENT_MATCH_DELETED
:
2986 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_RMAP
];
2988 case RMAP_EVENT_FILTER_ADDED
:
2989 case RMAP_EVENT_FILTER_DELETED
:
2990 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_FILTER
];
2993 * Should we actually be ignoring these?
2994 * I am not sure but at this point in time, let
2995 * us get them into this switch and we can peel
2996 * them into the appropriate place in the future
2998 case RMAP_EVENT_SET_ADDED
:
2999 case RMAP_EVENT_SET_DELETED
:
3000 case RMAP_EVENT_SET_REPLACED
:
3001 case RMAP_EVENT_MATCH_REPLACED
:
3002 case RMAP_EVENT_INDEX_ADDED
:
3003 case RMAP_EVENT_INDEX_DELETED
:
3010 static void route_map_process_dependency(struct hash_bucket
*bucket
, void *data
)
3012 struct route_map_dep_data
*dep_data
= NULL
;
3013 char *rmap_name
= NULL
;
3015 dep_data
= bucket
->data
;
3016 rmap_name
= dep_data
->rname
;
3019 zlog_debug("Notifying %s of dependency", rmap_name
);
3020 if (route_map_master
.event_hook
)
3021 (*route_map_master
.event_hook
)(rmap_name
);
3024 void route_map_upd8_dependency(route_map_event_t type
, const char *arg
,
3025 const char *rmap_name
)
3027 struct hash
*upd8_hash
= NULL
;
3029 if ((upd8_hash
= route_map_get_dep_hash(type
))) {
3030 route_map_dep_update(upd8_hash
, arg
, rmap_name
, type
);
3032 if (type
== RMAP_EVENT_CALL_ADDED
) {
3034 if (route_map_master
.add_hook
)
3035 (*route_map_master
.add_hook
)(rmap_name
);
3036 } else if (type
== RMAP_EVENT_CALL_DELETED
) {
3038 if (route_map_master
.delete_hook
)
3039 (*route_map_master
.delete_hook
)(rmap_name
);
3044 void route_map_notify_dependencies(const char *affected_name
,
3045 route_map_event_t event
)
3047 struct route_map_dep
*dep
;
3048 struct hash
*upd8_hash
;
3054 name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, affected_name
);
3056 if ((upd8_hash
= route_map_get_dep_hash(event
)) == NULL
) {
3057 XFREE(MTYPE_ROUTE_MAP_NAME
, name
);
3061 dep
= (struct route_map_dep
*)hash_get(upd8_hash
, name
, NULL
);
3063 if (!dep
->this_hash
)
3064 dep
->this_hash
= upd8_hash
;
3067 zlog_debug("Filter %s updated", dep
->dep_name
);
3068 hash_iterate(dep
->dep_rmap_hash
, route_map_process_dependency
,
3072 XFREE(MTYPE_ROUTE_MAP_NAME
, name
);
3075 /* VTY related functions. */
3076 static void clear_route_map_helper(struct route_map
*map
)
3078 struct route_map_index
*index
;
3080 map
->applied_clear
= map
->applied
;
3081 for (index
= map
->head
; index
; index
= index
->next
)
3082 index
->applied_clear
= index
->applied
;
3085 DEFUN (rmap_clear_counters
,
3086 rmap_clear_counters_cmd
,
3087 "clear route-map counters [WORD]",
3089 "route-map information\n"
3090 "counters associated with the specified route-map\n"
3094 struct route_map
*map
;
3096 const char *name
= (argc
== 3 ) ? argv
[idx_word
]->arg
: NULL
;
3099 map
= route_map_lookup_by_name(name
);
3102 clear_route_map_helper(map
);
3104 vty_out(vty
, "%s: 'route-map %s' not found\n",
3105 frr_protonameinst
, name
);
3109 for (map
= route_map_master
.head
; map
; map
= map
->next
)
3110 clear_route_map_helper(map
);
3117 DEFUN (rmap_show_name
,
3119 "show route-map [WORD] [json]",
3121 "route-map information\n"
3125 bool uj
= use_json(argc
, argv
);
3127 const char *name
= NULL
;
3129 if (argv_find(argv
, argc
, "WORD", &idx
))
3130 name
= argv
[idx
]->arg
;
3132 return vty_show_route_map(vty
, name
, uj
);
3135 DEFUN (rmap_show_unused
,
3136 rmap_show_unused_cmd
,
3137 "show route-map-unused",
3139 "unused route-map information\n")
3141 return vty_show_unused_route_map(vty
);
3148 "Debug option set for route-maps\n")
3154 DEFUN (no_debug_rmap
,
3156 "no debug route-map",
3159 "Debug option set for route-maps\n")
3166 static int rmap_config_write_debug(struct vty
*vty
);
3167 static struct cmd_node rmap_debug_node
= {
3168 .name
= "route-map debug",
3169 .node
= RMAP_DEBUG_NODE
,
3171 .config_write
= rmap_config_write_debug
,
3174 /* Configuration write function. */
3175 static int rmap_config_write_debug(struct vty
*vty
)
3180 vty_out(vty
, "debug route-map\n");
3187 /* Common route map rules */
3189 void *route_map_rule_tag_compile(const char *arg
)
3191 unsigned long int tmp
;
3196 tmp
= strtoul(arg
, &endptr
, 0);
3197 if (arg
[0] == '\0' || *endptr
!= '\0' || errno
|| tmp
> ROUTE_TAG_MAX
)
3200 tag
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(*tag
));
3206 void route_map_rule_tag_free(void *rule
)
3208 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
3211 void route_map_finish(void)
3214 struct route_map_rule_cmd_proxy
*proxy
;
3216 /* these 2 hash tables have INIT_HASH initializers, so the "default"
3217 * state is "initialized & empty" => fini() followed by init() to
3218 * return to that same state
3220 while ((proxy
= rmap_cmd_name_pop(rmap_match_cmds
)))
3222 rmap_cmd_name_fini(rmap_match_cmds
);
3223 rmap_cmd_name_init(rmap_match_cmds
);
3225 while ((proxy
= rmap_cmd_name_pop(rmap_set_cmds
)))
3227 rmap_cmd_name_fini(rmap_set_cmds
);
3228 rmap_cmd_name_init(rmap_set_cmds
);
3231 * All protocols are setting these to NULL
3232 * by default on shutdown( route_map_finish )
3233 * Why are we making them do this work?
3235 route_map_master
.add_hook
= NULL
;
3236 route_map_master
.delete_hook
= NULL
;
3237 route_map_master
.event_hook
= NULL
;
3239 /* cleanup route_map */
3240 while (route_map_master
.head
) {
3241 struct route_map
*map
= route_map_master
.head
;
3242 map
->to_be_processed
= false;
3243 route_map_delete(map
);
3246 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++) {
3247 hash_free(route_map_dep_hash
[i
]);
3248 route_map_dep_hash
[i
] = NULL
;
3251 hash_free(route_map_master_hash
);
3252 route_map_master_hash
= NULL
;
3255 /* Increment the use_count counter while attaching the route map */
3256 void route_map_counter_increment(struct route_map
*map
)
3262 /* Decrement the use_count counter while detaching the route map. */
3263 void route_map_counter_decrement(struct route_map
*map
)
3266 if (map
->use_count
<= 0)
3272 DEFUN_HIDDEN(show_route_map_pfx_tbl
, show_route_map_pfx_tbl_cmd
,
3273 "show route-map WORD prefix-table",
3277 "internal prefix-table\n")
3279 const char *rmap_name
= argv
[2]->arg
;
3280 struct route_map
*rmap
= NULL
;
3281 struct route_table
*rm_pfx_tbl4
= NULL
;
3282 struct route_table
*rm_pfx_tbl6
= NULL
;
3283 struct route_node
*rn
= NULL
, *prn
= NULL
;
3284 struct list
*rmap_index_list
= NULL
;
3285 struct listnode
*ln
= NULL
, *nln
= NULL
;
3286 struct route_map_index
*index
= NULL
;
3289 vty_out(vty
, "%s:\n", frr_protonameinst
);
3290 rmap
= route_map_lookup_by_name(rmap_name
);
3292 rm_pfx_tbl4
= rmap
->ipv4_prefix_table
;
3294 vty_out(vty
, "\n%s%43s%s\n", "IPv4 Prefix", "",
3295 "Route-map Index List");
3296 vty_out(vty
, "%s%39s%s\n", "_______________", "",
3297 "____________________");
3298 for (rn
= route_top(rm_pfx_tbl4
); rn
;
3299 rn
= route_next(rn
)) {
3300 vty_out(vty
, " %pRN (%d)\n", rn
,
3301 route_node_get_lock_count(rn
));
3303 vty_out(vty
, "(P) ");
3306 vty_out(vty
, "%pRN\n", prn
);
3310 rmap_index_list
= (struct list
*)rn
->info
;
3311 if (!rmap_index_list
3312 || !listcount(rmap_index_list
))
3313 vty_out(vty
, "%*s%s\n", len
, "", "-");
3315 for (ALL_LIST_ELEMENTS(rmap_index_list
,
3318 vty_out(vty
, "%*s%s seq %d\n",
3327 rm_pfx_tbl6
= rmap
->ipv6_prefix_table
;
3329 vty_out(vty
, "\n%s%43s%s\n", "IPv6 Prefix", "",
3330 "Route-map Index List");
3331 vty_out(vty
, "%s%39s%s\n", "_______________", "",
3332 "____________________");
3333 for (rn
= route_top(rm_pfx_tbl6
); rn
;
3334 rn
= route_next(rn
)) {
3335 vty_out(vty
, " %pRN (%d)\n", rn
,
3336 route_node_get_lock_count(rn
));
3338 vty_out(vty
, "(P) ");
3341 vty_out(vty
, "%pRN\n", prn
);
3345 rmap_index_list
= (struct list
*)rn
->info
;
3346 if (!rmap_index_list
3347 || !listcount(rmap_index_list
))
3348 vty_out(vty
, "%*s%s\n", len
, "", "-");
3350 for (ALL_LIST_ELEMENTS(rmap_index_list
,
3353 vty_out(vty
, "%*s%s seq %d\n",
3367 /* Initialization of route map vector. */
3368 void route_map_init(void)
3372 route_map_master_hash
=
3373 hash_create_size(8, route_map_hash_key_make
, route_map_hash_cmp
,
3374 "Route Map Master Hash");
3376 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
3377 route_map_dep_hash
[i
] = hash_create_size(
3378 8, route_map_dep_hash_make_key
, route_map_dep_hash_cmp
,
3379 "Route Map Dep Hash");
3383 route_map_cli_init();
3385 /* Install route map top node. */
3386 install_node(&rmap_debug_node
);
3388 /* Install route map commands. */
3389 install_element(CONFIG_NODE
, &debug_rmap_cmd
);
3390 install_element(CONFIG_NODE
, &no_debug_rmap_cmd
);
3392 /* Install show command */
3393 install_element(ENABLE_NODE
, &rmap_clear_counters_cmd
);
3395 install_element(ENABLE_NODE
, &rmap_show_name_cmd
);
3396 install_element(ENABLE_NODE
, &rmap_show_unused_cmd
);
3398 install_element(ENABLE_NODE
, &debug_rmap_cmd
);
3399 install_element(ENABLE_NODE
, &no_debug_rmap_cmd
);
3401 install_element(ENABLE_NODE
, &show_route_map_pfx_tbl_cmd
);