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 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP
, "Route map")
35 DEFINE_MTYPE( LIB
, ROUTE_MAP_NAME
, "Route map name")
36 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_INDEX
, "Route map index")
37 DEFINE_MTYPE( LIB
, ROUTE_MAP_RULE
, "Route map rule")
38 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_RULE_STR
, "Route map rule str")
39 DEFINE_MTYPE( LIB
, ROUTE_MAP_COMPILED
, "Route map compiled")
40 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_DEP
, "Route map dependency")
42 DEFINE_QOBJ_TYPE(route_map_index
)
43 DEFINE_QOBJ_TYPE(route_map
)
45 /* Vector for route match rules. */
46 static vector route_match_vec
;
48 /* Vector for route set rules. */
49 static vector route_set_vec
;
51 struct route_map_match_set_hooks
54 int (*match_interface
) (struct vty
*vty
,
55 struct route_map_index
*index
,
58 route_map_event_t type
);
60 /* no match interface */
61 int (*no_match_interface
) (struct vty
*vty
,
62 struct route_map_index
*index
,
65 route_map_event_t type
);
67 /* match ip address */
68 int (*match_ip_address
) (struct vty
*vty
,
69 struct route_map_index
*index
,
72 route_map_event_t type
);
74 /* no match ip address */
75 int (*no_match_ip_address
) (struct vty
*vty
,
76 struct route_map_index
*index
,
79 route_map_event_t type
);
81 /* match ip address prefix list */
82 int (*match_ip_address_prefix_list
) (struct vty
*vty
,
83 struct route_map_index
*index
,
86 route_map_event_t type
);
88 /* no match ip address prefix list */
89 int (*no_match_ip_address_prefix_list
) (struct vty
*vty
,
90 struct route_map_index
*index
,
93 route_map_event_t type
);
95 /* match ip next hop */
96 int (*match_ip_next_hop
) (struct vty
*vty
,
97 struct route_map_index
*index
,
100 route_map_event_t type
);
102 /* no match ip next hop */
103 int (*no_match_ip_next_hop
) (struct vty
*vty
,
104 struct route_map_index
*index
,
107 route_map_event_t type
);
109 /* match ip next hop prefix list */
110 int (*match_ip_next_hop_prefix_list
) (struct vty
*vty
,
111 struct route_map_index
*index
,
114 route_map_event_t type
);
116 /* no match ip next hop prefix list */
117 int (*no_match_ip_next_hop_prefix_list
) (struct vty
*vty
,
118 struct route_map_index
*index
,
121 route_map_event_t type
);
123 /* match ipv6 address */
124 int (*match_ipv6_address
) (struct vty
*vty
,
125 struct route_map_index
*index
,
128 route_map_event_t type
);
130 /* no match ipv6 address */
131 int (*no_match_ipv6_address
) (struct vty
*vty
,
132 struct route_map_index
*index
,
135 route_map_event_t type
);
138 /* match ipv6 address prefix list */
139 int (*match_ipv6_address_prefix_list
) (struct vty
*vty
,
140 struct route_map_index
*index
,
143 route_map_event_t type
);
145 /* no match ipv6 address prefix list */
146 int (*no_match_ipv6_address_prefix_list
) (struct vty
*vty
,
147 struct route_map_index
*index
,
150 route_map_event_t type
);
153 int (*match_metric
) (struct vty
*vty
,
154 struct route_map_index
*index
,
157 route_map_event_t type
);
159 /* no match metric */
160 int (*no_match_metric
) (struct vty
*vty
,
161 struct route_map_index
*index
,
164 route_map_event_t type
);
167 int (*match_tag
) (struct vty
*vty
,
168 struct route_map_index
*index
,
171 route_map_event_t type
);
174 int (*no_match_tag
) (struct vty
*vty
,
175 struct route_map_index
*index
,
178 route_map_event_t type
);
181 int (*set_ip_nexthop
) (struct vty
*vty
,
182 struct route_map_index
*index
,
186 /* no set ip nexthop */
187 int (*no_set_ip_nexthop
) (struct vty
*vty
,
188 struct route_map_index
*index
,
192 /* set ipv6 nexthop local */
193 int (*set_ipv6_nexthop_local
) (struct vty
*vty
,
194 struct route_map_index
*index
,
198 /* no set ipv6 nexthop local */
199 int (*no_set_ipv6_nexthop_local
) (struct vty
*vty
,
200 struct route_map_index
*index
,
205 int (*set_metric
) (struct vty
*vty
,
206 struct route_map_index
*index
,
211 int (*no_set_metric
) (struct vty
*vty
,
212 struct route_map_index
*index
,
217 int (*set_tag
) (struct vty
*vty
,
218 struct route_map_index
*index
,
223 int (*no_set_tag
) (struct vty
*vty
,
224 struct route_map_index
*index
,
230 struct route_map_match_set_hooks rmap_match_set_hook
;
232 /* match interface */
234 route_map_match_interface_hook (int (*func
) (struct vty
*vty
,
235 struct route_map_index
*index
,
238 route_map_event_t type
))
240 rmap_match_set_hook
.match_interface
= func
;
243 /* no match interface */
245 route_map_no_match_interface_hook (int (*func
) (struct vty
*vty
,
246 struct route_map_index
*index
,
249 route_map_event_t type
))
251 rmap_match_set_hook
.no_match_interface
= func
;
254 /* match ip address */
256 route_map_match_ip_address_hook (int (*func
) (struct vty
*vty
,
257 struct route_map_index
*index
,
260 route_map_event_t type
))
262 rmap_match_set_hook
.match_ip_address
= func
;
265 /* no match ip address */
267 route_map_no_match_ip_address_hook (int (*func
) (struct vty
*vty
,
268 struct route_map_index
*index
,
271 route_map_event_t type
))
273 rmap_match_set_hook
.no_match_ip_address
= func
;
276 /* match ip address prefix list */
278 route_map_match_ip_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
279 struct route_map_index
*index
,
282 route_map_event_t type
))
284 rmap_match_set_hook
.match_ip_address_prefix_list
= func
;
287 /* no match ip address prefix list */
289 route_map_no_match_ip_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
290 struct route_map_index
*index
,
293 route_map_event_t type
))
295 rmap_match_set_hook
.no_match_ip_address_prefix_list
= func
;
298 /* match ip next hop */
300 route_map_match_ip_next_hop_hook (int (*func
) (struct vty
*vty
,
301 struct route_map_index
*index
,
304 route_map_event_t type
))
306 rmap_match_set_hook
.match_ip_next_hop
= func
;
309 /* no match ip next hop */
311 route_map_no_match_ip_next_hop_hook (int (*func
) (struct vty
*vty
,
312 struct route_map_index
*index
,
315 route_map_event_t type
))
317 rmap_match_set_hook
.no_match_ip_next_hop
= func
;
320 /* match ip next hop prefix list */
322 route_map_match_ip_next_hop_prefix_list_hook (int (*func
) (struct vty
*vty
,
323 struct route_map_index
*index
,
326 route_map_event_t type
))
328 rmap_match_set_hook
.match_ip_next_hop_prefix_list
= func
;
331 /* no match ip next hop prefix list */
333 route_map_no_match_ip_next_hop_prefix_list_hook (int (*func
) (struct vty
*vty
,
334 struct route_map_index
*index
,
337 route_map_event_t type
))
339 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
= func
;
342 /* match ipv6 address */
344 route_map_match_ipv6_address_hook (int (*func
) (struct vty
*vty
,
345 struct route_map_index
*index
,
348 route_map_event_t type
))
350 rmap_match_set_hook
.match_ipv6_address
= func
;
353 /* no match ipv6 address */
355 route_map_no_match_ipv6_address_hook (int (*func
) (struct vty
*vty
,
356 struct route_map_index
*index
,
359 route_map_event_t type
))
361 rmap_match_set_hook
.no_match_ipv6_address
= func
;
365 /* match ipv6 address prefix list */
367 route_map_match_ipv6_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
368 struct route_map_index
*index
,
371 route_map_event_t type
))
373 rmap_match_set_hook
.match_ipv6_address_prefix_list
= func
;
376 /* no match ipv6 address prefix list */
378 route_map_no_match_ipv6_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
379 struct route_map_index
*index
,
382 route_map_event_t type
))
384 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
= func
;
389 route_map_match_metric_hook (int (*func
) (struct vty
*vty
,
390 struct route_map_index
*index
,
393 route_map_event_t type
))
395 rmap_match_set_hook
.match_metric
= func
;
398 /* no match metric */
400 route_map_no_match_metric_hook (int (*func
) (struct vty
*vty
,
401 struct route_map_index
*index
,
404 route_map_event_t type
))
406 rmap_match_set_hook
.no_match_metric
= func
;
411 route_map_match_tag_hook (int (*func
) (struct vty
*vty
,
412 struct route_map_index
*index
,
415 route_map_event_t type
))
417 rmap_match_set_hook
.match_tag
= func
;
422 route_map_no_match_tag_hook (int (*func
) (struct vty
*vty
,
423 struct route_map_index
*index
,
426 route_map_event_t type
))
428 rmap_match_set_hook
.no_match_tag
= func
;
433 route_map_set_ip_nexthop_hook (int (*func
) (struct vty
*vty
,
434 struct route_map_index
*index
,
438 rmap_match_set_hook
.set_ip_nexthop
= func
;
441 /* no set ip nexthop */
443 route_map_no_set_ip_nexthop_hook (int (*func
) (struct vty
*vty
,
444 struct route_map_index
*index
,
448 rmap_match_set_hook
.no_set_ip_nexthop
= func
;
451 /* set ipv6 nexthop local */
453 route_map_set_ipv6_nexthop_local_hook (int (*func
) (struct vty
*vty
,
454 struct route_map_index
*index
,
458 rmap_match_set_hook
.set_ipv6_nexthop_local
= func
;
461 /* no set ipv6 nexthop local */
463 route_map_no_set_ipv6_nexthop_local_hook (int (*func
) (struct vty
*vty
,
464 struct route_map_index
*index
,
468 rmap_match_set_hook
.no_set_ipv6_nexthop_local
= func
;
473 route_map_set_metric_hook (int (*func
) (struct vty
*vty
,
474 struct route_map_index
*index
,
478 rmap_match_set_hook
.set_metric
= func
;
483 route_map_no_set_metric_hook (int (*func
) (struct vty
*vty
,
484 struct route_map_index
*index
,
488 rmap_match_set_hook
.no_set_metric
= func
;
493 route_map_set_tag_hook (int (*func
) (struct vty
*vty
,
494 struct route_map_index
*index
,
498 rmap_match_set_hook
.set_tag
= func
;
503 route_map_no_set_tag_hook (int (*func
) (struct vty
*vty
,
504 struct route_map_index
*index
,
508 rmap_match_set_hook
.no_set_tag
= func
;
512 generic_match_add (struct vty
*vty
, struct route_map_index
*index
,
513 const char *command
, const char *arg
,
514 route_map_event_t type
)
518 ret
= route_map_add_match (index
, command
, arg
);
523 case RMAP_RULE_MISSING
:
524 vty_out (vty
, "%% Can't find rule.%s", VTY_NEWLINE
);
526 case RMAP_COMPILE_ERROR
:
527 vty_out (vty
, "%% Argument is malformed.%s", VTY_NEWLINE
);
532 if (type
!= RMAP_EVENT_MATCH_ADDED
)
534 route_map_upd8_dependency (type
, arg
, index
->map
->name
);
540 generic_match_delete (struct vty
*vty
, struct route_map_index
*index
,
541 const char *command
, const char *arg
,
542 route_map_event_t type
)
545 char *dep_name
= NULL
;
547 char *rmap_name
= NULL
;
549 if (type
!= RMAP_EVENT_MATCH_DELETED
)
551 /* ignore the mundane, the types without any dependency */
554 if ((tmpstr
= route_map_get_match_arg(index
, command
)) != NULL
)
555 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
559 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
561 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
564 ret
= route_map_delete_match (index
, command
, dep_name
);
569 case RMAP_RULE_MISSING
:
570 vty_out (vty
, "%% BGP Can't find rule.%s", VTY_NEWLINE
);
572 case RMAP_COMPILE_ERROR
:
573 vty_out (vty
, "%% BGP Argument is malformed.%s", VTY_NEWLINE
);
577 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
579 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
583 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
584 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
587 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
589 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
595 generic_set_add (struct vty
*vty
, struct route_map_index
*index
,
596 const char *command
, const char *arg
)
600 ret
= route_map_add_set (index
, command
, arg
);
605 case RMAP_RULE_MISSING
:
606 vty_out (vty
, "%% Can't find rule.%s", VTY_NEWLINE
);
608 case RMAP_COMPILE_ERROR
:
609 vty_out (vty
, "%% Argument is malformed.%s", VTY_NEWLINE
);
617 generic_set_delete (struct vty
*vty
, struct route_map_index
*index
,
618 const char *command
, const char *arg
)
622 ret
= route_map_delete_set (index
, command
, arg
);
627 case RMAP_RULE_MISSING
:
628 vty_out (vty
, "%% Can't find rule.%s", VTY_NEWLINE
);
630 case RMAP_COMPILE_ERROR
:
631 vty_out (vty
, "%% Argument is malformed.%s", VTY_NEWLINE
);
639 /* Route map rule. This rule has both `match' rule and `set' rule. */
640 struct route_map_rule
643 struct route_map_rule_cmd
*cmd
;
645 /* For pretty printing. */
648 /* Pre-compiled match rule. */
652 struct route_map_rule
*next
;
653 struct route_map_rule
*prev
;
656 /* Making route map list. */
657 struct route_map_list
659 struct route_map
*head
;
660 struct route_map
*tail
;
662 void (*add_hook
) (const char *);
663 void (*delete_hook
) (const char *);
664 void (*event_hook
) (route_map_event_t
, const char *);
667 /* Master list of route map. */
668 static struct route_map_list route_map_master
= { NULL
, NULL
, NULL
, NULL
, NULL
};
669 struct hash
*route_map_master_hash
= NULL
;
672 route_map_hash_key_make (void *p
)
674 const struct route_map
*map
= p
;
675 return string_hash_make (map
->name
);
679 route_map_hash_cmp(const void *p1
, const void *p2
)
681 const struct route_map
*map1
= p1
;
682 const struct route_map
*map2
= p2
;
684 if (map1
->deleted
== map2
->deleted
)
686 if (map1
->name
&& map2
->name
)
688 if (!strcmp (map1
->name
, map2
->name
))
693 else if (!map1
->name
&& !map2
->name
)
702 enum route_map_upd8_type
708 /* all possible route-map dependency types */
709 enum route_map_dep_type
711 ROUTE_MAP_DEP_RMAP
= 1,
713 ROUTE_MAP_DEP_ECLIST
,
714 ROUTE_MAP_DEP_LCLIST
,
716 ROUTE_MAP_DEP_ASPATH
,
717 ROUTE_MAP_DEP_FILTER
,
724 struct hash
*dep_rmap_hash
;
725 struct hash
*this_hash
; /* ptr to the hash structure this is part of */
728 /* Hashes maintaining dependency between various sublists used by route maps */
729 struct hash
*route_map_dep_hash
[ROUTE_MAP_DEP_MAX
];
731 static unsigned int route_map_dep_hash_make_key (void *p
);
732 static int route_map_dep_hash_cmp (const void *p1
, const void *p2
);
733 static void route_map_clear_all_references (char *rmap_name
);
734 static void route_map_rule_delete (struct route_map_rule_list
*,
735 struct route_map_rule
*);
736 static int rmap_debug
= 0;
739 route_map_index_delete (struct route_map_index
*, int);
741 /* New route map allocation. Please note route map's name must be
743 static struct route_map
*
744 route_map_new (const char *name
)
746 struct route_map
*new;
748 new = XCALLOC (MTYPE_ROUTE_MAP
, sizeof (struct route_map
));
749 new->name
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, name
);
750 QOBJ_REG (new, route_map
);
754 /* Add new name to route_map. */
755 static struct route_map
*
756 route_map_add (const char *name
)
758 struct route_map
*map
;
759 struct route_map_list
*list
;
761 map
= route_map_new (name
);
762 list
= &route_map_master
;
764 /* Add map to the hash */
765 hash_get(route_map_master_hash
, map
, hash_alloc_intern
);
767 /* Add new entry to the head of the list to match how it is added in the
768 * hash table. This is to ensure that if the same route-map has been
769 * created more than once and then marked for deletion (which can happen
770 * if prior deletions haven't completed as BGP hasn't yet done the
771 * route-map processing), the order of the entities is the same in both
772 * the list and the hash table. Otherwise, since there is nothing to
773 * distinguish between the two entries, the wrong entry could get freed.
774 * TODO: This needs to be re-examined to handle it better - e.g., revive
775 * a deleted entry if the route-map is created again.
778 map
->next
= list
->head
;
780 list
->head
->prev
= map
;
786 if (route_map_master
.add_hook
)
788 (*route_map_master
.add_hook
) (name
);
789 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_ADDED
);
794 /* this is supposed to be called post processing by
795 * the delete hook function. Don't invoke delete_hook
796 * again in this routine.
799 route_map_free_map (struct route_map
*map
)
801 struct route_map_list
*list
;
802 struct route_map_index
*index
;
807 while ((index
= map
->head
) != NULL
)
808 route_map_index_delete (index
, 0);
810 list
= &route_map_master
;
815 map
->next
->prev
= map
->prev
;
817 list
->tail
= map
->prev
;
820 map
->prev
->next
= map
->next
;
822 list
->head
= map
->next
;
824 hash_release(route_map_master_hash
, map
);
825 XFREE (MTYPE_ROUTE_MAP_NAME
, map
->name
);
826 XFREE (MTYPE_ROUTE_MAP
, map
);
829 /* Route map delete from list. */
831 route_map_delete (struct route_map
*map
)
833 struct route_map_index
*index
;
836 while ((index
= map
->head
) != NULL
)
837 route_map_index_delete (index
, 0);
842 /* Clear all dependencies */
843 route_map_clear_all_references(name
);
845 /* Execute deletion hook. */
846 if (route_map_master
.delete_hook
)
848 (*route_map_master
.delete_hook
) (name
);
849 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_DELETED
);
852 if (!map
->to_be_processed
)
854 route_map_free_map (map
);
858 /* Lookup route map by route map name string. */
860 route_map_lookup_by_name (const char *name
)
862 struct route_map
*map
;
863 struct route_map tmp_map
;
868 // map.deleted is 0 via memset
869 memset(&tmp_map
, 0, sizeof(struct route_map
));
870 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
871 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
872 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
877 route_map_mark_updated (const char *name
, int del_later
)
879 struct route_map
*map
;
881 struct route_map tmp_map
;
886 map
= route_map_lookup_by_name(name
);
888 /* If we did not find the routemap with deleted=0 try again
893 memset(&tmp_map
, 0, sizeof(struct route_map
));
894 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
896 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
897 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
902 map
->to_be_processed
= 1;
910 route_map_clear_updated (struct route_map
*map
)
916 map
->to_be_processed
= 0;
918 route_map_free_map(map
);
924 /* Lookup route map. If there isn't route map create one and return
926 static struct route_map
*
927 route_map_get (const char *name
)
929 struct route_map
*map
;
931 map
= route_map_lookup_by_name (name
);
933 map
= route_map_add (name
);
939 route_map_walk_update_list (int (*route_map_update_fn
) (char *name
))
941 struct route_map
*node
;
942 struct route_map
*nnode
= NULL
;
944 for (node
= route_map_master
.head
; node
; node
= nnode
)
946 if (node
->to_be_processed
)
948 /* DD: Should we add any thread yield code here */
949 route_map_update_fn(node
->name
);
951 route_map_clear_updated(node
);
958 /* Return route map's type string. */
960 route_map_type_str (enum route_map_type type
)
977 route_map_empty (struct route_map
*map
)
979 if (map
->head
== NULL
&& map
->tail
== NULL
)
987 vty_show_route_map_entry (struct vty
*vty
, struct route_map
*map
)
989 struct route_map_index
*index
;
990 struct route_map_rule
*rule
;
992 vty_out (vty
, "%s:%s", frr_protonameinst
, VTY_NEWLINE
);
994 for (index
= map
->head
; index
; index
= index
->next
)
996 vty_out (vty
, "route-map %s, %s, sequence %d%s",
997 map
->name
, route_map_type_str (index
->type
),
998 index
->pref
, VTY_NEWLINE
);
1001 if (index
->description
)
1002 vty_out (vty
, " Description:%s %s%s", VTY_NEWLINE
,
1003 index
->description
, VTY_NEWLINE
);
1006 vty_out (vty
, " Match clauses:%s", VTY_NEWLINE
);
1007 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1008 vty_out (vty
, " %s %s%s",
1009 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
1011 vty_out (vty
, " Set clauses:%s", VTY_NEWLINE
);
1012 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1013 vty_out (vty
, " %s %s%s",
1014 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
1017 vty_out (vty
, " Call clause:%s", VTY_NEWLINE
);
1019 vty_out (vty
, " Call %s%s", index
->nextrm
, VTY_NEWLINE
);
1022 vty_out (vty
, " Action:%s", VTY_NEWLINE
);
1023 if (index
->exitpolicy
== RMAP_GOTO
)
1024 vty_out (vty
, " Goto %d%s", index
->nextpref
, VTY_NEWLINE
);
1025 else if (index
->exitpolicy
== RMAP_NEXT
)
1026 vty_out (vty
, " Continue to next entry%s", VTY_NEWLINE
);
1027 else if (index
->exitpolicy
== RMAP_EXIT
)
1028 vty_out (vty
, " Exit routemap%s", VTY_NEWLINE
);
1033 vty_show_route_map (struct vty
*vty
, const char *name
)
1035 struct route_map
*map
;
1039 map
= route_map_lookup_by_name (name
);
1043 vty_show_route_map_entry (vty
, map
);
1048 vty_out (vty
, "%s: 'route-map %s' not found%s", frr_protonameinst
,
1055 for (map
= route_map_master
.head
; map
; map
= map
->next
)
1057 vty_show_route_map_entry (vty
, map
);
1063 /* New route map allocation. Please note route map's name must be
1065 static struct route_map_index
*
1066 route_map_index_new (void)
1068 struct route_map_index
*new;
1070 new = XCALLOC (MTYPE_ROUTE_MAP_INDEX
, sizeof (struct route_map_index
));
1071 new->exitpolicy
= RMAP_EXIT
; /* Default to Cisco-style */
1072 QOBJ_REG (new, route_map_index
);
1076 /* Free route map index. */
1078 route_map_index_delete (struct route_map_index
*index
, int notify
)
1080 struct route_map_rule
*rule
;
1084 /* Free route match. */
1085 while ((rule
= index
->match_list
.head
) != NULL
)
1086 route_map_rule_delete (&index
->match_list
, rule
);
1088 /* Free route set. */
1089 while ((rule
= index
->set_list
.head
) != NULL
)
1090 route_map_rule_delete (&index
->set_list
, rule
);
1092 /* Remove index from route map list. */
1094 index
->next
->prev
= index
->prev
;
1096 index
->map
->tail
= index
->prev
;
1099 index
->prev
->next
= index
->next
;
1101 index
->map
->head
= index
->next
;
1103 /* Free 'char *nextrm' if not NULL */
1105 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
1107 /* Execute event hook. */
1108 if (route_map_master
.event_hook
&& notify
)
1110 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_DELETED
,
1112 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1114 XFREE (MTYPE_ROUTE_MAP_INDEX
, index
);
1117 /* Lookup index from route map. */
1118 static struct route_map_index
*
1119 route_map_index_lookup (struct route_map
*map
, enum route_map_type type
,
1122 struct route_map_index
*index
;
1124 for (index
= map
->head
; index
; index
= index
->next
)
1125 if ((index
->type
== type
|| type
== RMAP_ANY
)
1126 && index
->pref
== pref
)
1131 /* Add new index to route map. */
1132 static struct route_map_index
*
1133 route_map_index_add (struct route_map
*map
, enum route_map_type type
,
1136 struct route_map_index
*index
;
1137 struct route_map_index
*point
;
1139 /* Allocate new route map inex. */
1140 index
= route_map_index_new ();
1145 /* Compare preference. */
1146 for (point
= map
->head
; point
; point
= point
->next
)
1147 if (point
->pref
>= pref
)
1150 if (map
->head
== NULL
)
1152 map
->head
= map
->tail
= index
;
1154 else if (point
== NULL
)
1156 index
->prev
= map
->tail
;
1157 map
->tail
->next
= index
;
1160 else if (point
== map
->head
)
1162 index
->next
= map
->head
;
1163 map
->head
->prev
= index
;
1168 index
->next
= point
;
1169 index
->prev
= point
->prev
;
1171 point
->prev
->next
= index
;
1172 point
->prev
= index
;
1175 /* Execute event hook. */
1176 if (route_map_master
.event_hook
)
1178 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_ADDED
,
1180 route_map_notify_dependencies (map
->name
, RMAP_EVENT_CALL_ADDED
);
1185 /* Get route map index. */
1186 static struct route_map_index
*
1187 route_map_index_get (struct route_map
*map
, enum route_map_type type
,
1190 struct route_map_index
*index
;
1192 index
= route_map_index_lookup (map
, RMAP_ANY
, pref
);
1193 if (index
&& index
->type
!= type
)
1195 /* Delete index from route map. */
1196 route_map_index_delete (index
, 1);
1200 index
= route_map_index_add (map
, type
, pref
);
1204 /* New route map rule */
1205 static struct route_map_rule
*
1206 route_map_rule_new (void)
1208 struct route_map_rule
*new;
1210 new = XCALLOC (MTYPE_ROUTE_MAP_RULE
, sizeof (struct route_map_rule
));
1214 /* Install rule command to the match list. */
1216 route_map_install_match (struct route_map_rule_cmd
*cmd
)
1218 vector_set (route_match_vec
, cmd
);
1221 /* Install rule command to the set list. */
1223 route_map_install_set (struct route_map_rule_cmd
*cmd
)
1225 vector_set (route_set_vec
, cmd
);
1228 /* Lookup rule command from match list. */
1229 static struct route_map_rule_cmd
*
1230 route_map_lookup_match (const char *name
)
1233 struct route_map_rule_cmd
*rule
;
1235 for (i
= 0; i
< vector_active (route_match_vec
); i
++)
1236 if ((rule
= vector_slot (route_match_vec
, i
)) != NULL
)
1237 if (strcmp (rule
->str
, name
) == 0)
1242 /* Lookup rule command from set list. */
1243 static struct route_map_rule_cmd
*
1244 route_map_lookup_set (const char *name
)
1247 struct route_map_rule_cmd
*rule
;
1249 for (i
= 0; i
< vector_active (route_set_vec
); i
++)
1250 if ((rule
= vector_slot (route_set_vec
, i
)) != NULL
)
1251 if (strcmp (rule
->str
, name
) == 0)
1256 /* Add match and set rule to rule list. */
1258 route_map_rule_add (struct route_map_rule_list
*list
,
1259 struct route_map_rule
*rule
)
1262 rule
->prev
= list
->tail
;
1264 list
->tail
->next
= rule
;
1270 /* Delete rule from rule list. */
1272 route_map_rule_delete (struct route_map_rule_list
*list
,
1273 struct route_map_rule
*rule
)
1275 if (rule
->cmd
->func_free
)
1276 (*rule
->cmd
->func_free
) (rule
->value
);
1279 XFREE (MTYPE_ROUTE_MAP_RULE_STR
, rule
->rule_str
);
1282 rule
->next
->prev
= rule
->prev
;
1284 list
->tail
= rule
->prev
;
1286 rule
->prev
->next
= rule
->next
;
1288 list
->head
= rule
->next
;
1290 XFREE (MTYPE_ROUTE_MAP_RULE
, rule
);
1293 /* strcmp wrapper function which don't crush even argument is NULL. */
1295 rulecmp (const char *dst
, const char *src
)
1309 return strcmp (dst
, src
);
1314 /* Use this to return the already specified argument for this match. This is
1315 * useful to get the specified argument with a route map match rule when the
1316 * rule is being deleted and the argument is not provided.
1319 route_map_get_match_arg(struct route_map_index
*index
, const char *match_name
)
1321 struct route_map_rule
*rule
;
1322 struct route_map_rule_cmd
*cmd
;
1324 /* First lookup rule for add match statement. */
1325 cmd
= route_map_lookup_match (match_name
);
1329 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1330 if (rule
->cmd
== cmd
&& rule
->rule_str
!= NULL
)
1331 return (rule
->rule_str
);
1336 /* Add match statement to route map. */
1338 route_map_add_match (struct route_map_index
*index
, const char *match_name
,
1339 const char *match_arg
)
1341 struct route_map_rule
*rule
;
1342 struct route_map_rule
*next
;
1343 struct route_map_rule_cmd
*cmd
;
1347 /* First lookup rule for add match statement. */
1348 cmd
= route_map_lookup_match (match_name
);
1350 return RMAP_RULE_MISSING
;
1352 /* Next call compile function for this match statement. */
1353 if (cmd
->func_compile
)
1355 compile
= (*cmd
->func_compile
)(match_arg
);
1356 if (compile
== NULL
)
1357 return RMAP_COMPILE_ERROR
;
1362 /* If argument is completely same ignore it. */
1363 for (rule
= index
->match_list
.head
; rule
; rule
= next
)
1366 if (rule
->cmd
== cmd
)
1368 route_map_rule_delete (&index
->match_list
, rule
);
1373 /* Add new route map match rule. */
1374 rule
= route_map_rule_new ();
1376 rule
->value
= compile
;
1378 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, match_arg
);
1380 rule
->rule_str
= NULL
;
1382 /* Add new route match rule to linked list. */
1383 route_map_rule_add (&index
->match_list
, rule
);
1385 /* Execute event hook. */
1386 if (route_map_master
.event_hook
)
1388 (*route_map_master
.event_hook
) (replaced
?
1389 RMAP_EVENT_MATCH_REPLACED
:
1390 RMAP_EVENT_MATCH_ADDED
,
1392 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1398 /* Delete specified route match rule. */
1400 route_map_delete_match (struct route_map_index
*index
, const char *match_name
,
1401 const char *match_arg
)
1403 struct route_map_rule
*rule
;
1404 struct route_map_rule_cmd
*cmd
;
1406 cmd
= route_map_lookup_match (match_name
);
1410 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1411 if (rule
->cmd
== cmd
&&
1412 (rulecmp (rule
->rule_str
, match_arg
) == 0 || match_arg
== NULL
))
1414 route_map_rule_delete (&index
->match_list
, rule
);
1415 /* Execute event hook. */
1416 if (route_map_master
.event_hook
)
1418 (*route_map_master
.event_hook
) (RMAP_EVENT_MATCH_DELETED
,
1420 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1424 /* Can't find matched rule. */
1428 /* Add route-map set statement to the route map. */
1430 route_map_add_set (struct route_map_index
*index
, const char *set_name
,
1431 const char *set_arg
)
1433 struct route_map_rule
*rule
;
1434 struct route_map_rule
*next
;
1435 struct route_map_rule_cmd
*cmd
;
1439 cmd
= route_map_lookup_set (set_name
);
1441 return RMAP_RULE_MISSING
;
1443 /* Next call compile function for this match statement. */
1444 if (cmd
->func_compile
)
1446 compile
= (*cmd
->func_compile
)(set_arg
);
1447 if (compile
== NULL
)
1448 return RMAP_COMPILE_ERROR
;
1453 /* Add by WJL. if old set command of same kind exist, delete it first
1454 to ensure only one set command of same kind exist under a
1456 for (rule
= index
->set_list
.head
; rule
; rule
= next
)
1459 if (rule
->cmd
== cmd
)
1461 route_map_rule_delete (&index
->set_list
, rule
);
1466 /* Add new route map match rule. */
1467 rule
= route_map_rule_new ();
1469 rule
->value
= compile
;
1471 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, set_arg
);
1473 rule
->rule_str
= NULL
;
1475 /* Add new route match rule to linked list. */
1476 route_map_rule_add (&index
->set_list
, rule
);
1478 /* Execute event hook. */
1479 if (route_map_master
.event_hook
)
1481 (*route_map_master
.event_hook
) (replaced
?
1482 RMAP_EVENT_SET_REPLACED
:
1483 RMAP_EVENT_SET_ADDED
,
1485 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1490 /* Delete route map set rule. */
1492 route_map_delete_set (struct route_map_index
*index
, const char *set_name
,
1493 const char *set_arg
)
1495 struct route_map_rule
*rule
;
1496 struct route_map_rule_cmd
*cmd
;
1498 cmd
= route_map_lookup_set (set_name
);
1502 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1503 if ((rule
->cmd
== cmd
) &&
1504 (rulecmp (rule
->rule_str
, set_arg
) == 0 || set_arg
== NULL
))
1506 route_map_rule_delete (&index
->set_list
, rule
);
1507 /* Execute event hook. */
1508 if (route_map_master
.event_hook
)
1510 (*route_map_master
.event_hook
) (RMAP_EVENT_SET_DELETED
,
1512 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1516 /* Can't find matched rule. */
1520 /* Apply route map's each index to the object.
1522 The matrix for a route-map looks like this:
1523 (note, this includes the description for the "NEXT"
1524 and "GOTO" frobs now
1528 permit action | cont
1530 ------------------+---------------
1536 -Apply Set statements, accept route
1537 -If Call statement is present jump to the specified route-map, if it
1538 denies the route we finish.
1539 -If NEXT is specified, goto NEXT statement
1540 -If GOTO is specified, goto the first clause where pref > nextpref
1541 -If nothing is specified, do as Cisco and finish
1543 -Route is denied by route-map.
1547 If we get no matches after we've processed all updates, then the route
1550 Some notes on the new "CALL", "NEXT" and "GOTO"
1551 call WORD - If this clause is matched, then the set statements
1552 are executed and then we jump to route-map 'WORD'. If
1553 this route-map denies the route, we finish, in other case we
1554 do whatever the exit policy (EXIT, NEXT or GOTO) tells.
1555 on-match next - If this clause is matched, then the set statements
1556 are executed and then we drop through to the next clause
1557 on-match goto n - If this clause is matched, then the set statments
1558 are executed and then we goto the nth clause, or the
1559 first clause greater than this. In order to ensure
1560 route-maps *always* exit, you cannot jump backwards.
1563 We need to make sure our route-map processing matches the above
1566 static route_map_result_t
1567 route_map_apply_match (struct route_map_rule_list
*match_list
,
1568 struct prefix
*prefix
, route_map_object_t type
,
1571 route_map_result_t ret
= RMAP_NOMATCH
;
1572 struct route_map_rule
*match
;
1575 /* Check all match rule and if there is no match rule, go to the
1577 if (!match_list
->head
)
1581 for (match
= match_list
->head
; match
; match
= match
->next
)
1583 /* Try each match statement in turn, If any do not return
1584 RMAP_MATCH, return, otherwise continue on to next match
1585 statement. All match statements must match for end-result
1587 ret
= (*match
->cmd
->func_apply
) (match
->value
, prefix
,
1589 if (ret
!= RMAP_MATCH
)
1596 /* Apply route map to the object. */
1598 route_map_apply (struct route_map
*map
, struct prefix
*prefix
,
1599 route_map_object_t type
, void *object
)
1601 static int recursion
= 0;
1603 struct route_map_index
*index
;
1604 struct route_map_rule
*set
;
1606 if (recursion
> RMAP_RECURSION_LIMIT
)
1608 zlog_warn("route-map recursion limit (%d) reached, discarding route",
1609 RMAP_RECURSION_LIMIT
);
1611 return RMAP_DENYMATCH
;
1615 return RMAP_DENYMATCH
;
1617 for (index
= map
->head
; index
; index
= index
->next
)
1619 /* Apply this index. */
1620 ret
= route_map_apply_match (&index
->match_list
, prefix
, type
, object
);
1622 /* Now we apply the matrix from above */
1623 if (ret
== RMAP_NOMATCH
)
1624 /* 'cont' from matrix - continue to next route-map sequence */
1626 else if (ret
== RMAP_MATCH
)
1628 if (index
->type
== RMAP_PERMIT
)
1631 /* permit+match must execute sets */
1632 for (set
= index
->set_list
.head
; set
; set
= set
->next
)
1633 ret
= (*set
->cmd
->func_apply
) (set
->value
, prefix
,
1636 /* Call another route-map if available */
1639 struct route_map
*nextrm
=
1640 route_map_lookup_by_name (index
->nextrm
);
1642 if (nextrm
) /* Target route-map found, jump to it */
1645 ret
= route_map_apply (nextrm
, prefix
, type
, object
);
1649 /* If nextrm returned 'deny', finish. */
1650 if (ret
== RMAP_DENYMATCH
)
1654 switch (index
->exitpolicy
)
1662 /* Find the next clause to jump to */
1663 struct route_map_index
*next
= index
->next
;
1664 int nextpref
= index
->nextpref
;
1666 while (next
&& next
->pref
< nextpref
)
1673 /* No clauses match! */
1679 else if (index
->type
== RMAP_DENY
)
1682 return RMAP_DENYMATCH
;
1686 /* Finally route-map does not match at all. */
1687 return RMAP_DENYMATCH
;
1691 route_map_add_hook (void (*func
) (const char *))
1693 route_map_master
.add_hook
= func
;
1697 route_map_delete_hook (void (*func
) (const char *))
1699 route_map_master
.delete_hook
= func
;
1703 route_map_event_hook (void (*func
) (route_map_event_t
, const char *))
1705 route_map_master
.event_hook
= func
;
1708 /* Routines for route map dependency lists and dependency processing */
1710 route_map_rmap_hash_cmp (const void *p1
, const void *p2
)
1712 return (strcmp((const char *)p1
, (const char *)p2
) == 0);
1716 route_map_dep_hash_cmp (const void *p1
, const void *p2
)
1719 return (strcmp (((const struct route_map_dep
*)p1
)->dep_name
, (const char *)p2
) == 0);
1723 route_map_clear_reference(struct hash_backet
*backet
, void *arg
)
1725 struct route_map_dep
*dep
= (struct route_map_dep
*)backet
->data
;
1730 rmap_name
= (char *)hash_release(dep
->dep_rmap_hash
, (void *)arg
);
1733 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1735 if (!dep
->dep_rmap_hash
->count
)
1737 dep
= hash_release(dep
->this_hash
, (void *)dep
->dep_name
);
1738 hash_free(dep
->dep_rmap_hash
);
1739 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1740 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1746 route_map_clear_all_references (char *rmap_name
)
1750 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
1752 hash_iterate(route_map_dep_hash
[i
], route_map_clear_reference
,
1758 route_map_dep_hash_alloc(void *p
)
1760 char *dep_name
= (char *)p
;
1761 struct route_map_dep
*dep_entry
;
1763 dep_entry
= XCALLOC(MTYPE_ROUTE_MAP_DEP
, sizeof(struct route_map_dep
));
1764 dep_entry
->dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1765 dep_entry
->dep_rmap_hash
= hash_create(route_map_dep_hash_make_key
,
1766 route_map_rmap_hash_cmp
);
1767 dep_entry
->this_hash
= NULL
;
1769 return((void *)dep_entry
);
1773 route_map_name_hash_alloc(void *p
)
1775 return((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME
, (const char *)p
));
1779 route_map_dep_hash_make_key (void *p
)
1781 return (string_hash_make((char *)p
));
1785 route_map_print_dependency (struct hash_backet
*backet
, void *data
)
1787 char *rmap_name
= (char *)backet
->data
;
1788 char *dep_name
= (char *)data
;
1791 zlog_debug("%s: Dependency for %s: %s", __FUNCTION__
, dep_name
, rmap_name
);
1795 route_map_dep_update (struct hash
*dephash
, const char *dep_name
,
1796 const char *rmap_name
,
1797 route_map_event_t type
)
1799 struct route_map_dep
*dep
= NULL
;
1801 char *dname
, *rname
;
1804 dname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1805 rname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1809 case RMAP_EVENT_PLIST_ADDED
:
1810 case RMAP_EVENT_CLIST_ADDED
:
1811 case RMAP_EVENT_ECLIST_ADDED
:
1812 case RMAP_EVENT_ASLIST_ADDED
:
1813 case RMAP_EVENT_LLIST_ADDED
:
1814 case RMAP_EVENT_CALL_ADDED
:
1815 case RMAP_EVENT_FILTER_ADDED
:
1817 zlog_debug("%s: Adding dependency for %s in %s", __FUNCTION__
,
1818 dep_name
, rmap_name
);
1819 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
,
1820 route_map_dep_hash_alloc
);
1826 if (!dep
->this_hash
)
1827 dep
->this_hash
= dephash
;
1829 hash_get(dep
->dep_rmap_hash
, rname
, route_map_name_hash_alloc
);
1831 case RMAP_EVENT_PLIST_DELETED
:
1832 case RMAP_EVENT_CLIST_DELETED
:
1833 case RMAP_EVENT_ECLIST_DELETED
:
1834 case RMAP_EVENT_ASLIST_DELETED
:
1835 case RMAP_EVENT_LLIST_DELETED
:
1836 case RMAP_EVENT_CALL_DELETED
:
1837 case RMAP_EVENT_FILTER_DELETED
:
1839 zlog_debug("%s: Deleting dependency for %s in %s", __FUNCTION__
,
1840 dep_name
, rmap_name
);
1841 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
, NULL
);
1846 ret_map_name
= (char *)hash_release(dep
->dep_rmap_hash
, rname
);
1848 XFREE(MTYPE_ROUTE_MAP_NAME
, ret_map_name
);
1850 if (!dep
->dep_rmap_hash
->count
)
1852 dep
= hash_release(dephash
, dname
);
1853 hash_free(dep
->dep_rmap_hash
);
1854 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1855 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1866 hash_iterate (dep
->dep_rmap_hash
, route_map_print_dependency
, dname
);
1870 XFREE(MTYPE_ROUTE_MAP_NAME
, rname
);
1871 XFREE(MTYPE_ROUTE_MAP_NAME
, dname
);
1875 static struct hash
*
1876 route_map_get_dep_hash (route_map_event_t event
)
1878 struct hash
*upd8_hash
= NULL
;
1882 case RMAP_EVENT_PLIST_ADDED
:
1883 case RMAP_EVENT_PLIST_DELETED
:
1884 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_PLIST
];
1886 case RMAP_EVENT_CLIST_ADDED
:
1887 case RMAP_EVENT_CLIST_DELETED
:
1888 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_CLIST
];
1890 case RMAP_EVENT_ECLIST_ADDED
:
1891 case RMAP_EVENT_ECLIST_DELETED
:
1892 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ECLIST
];
1894 case RMAP_EVENT_ASLIST_ADDED
:
1895 case RMAP_EVENT_ASLIST_DELETED
:
1896 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ASPATH
];
1898 case RMAP_EVENT_LLIST_ADDED
:
1899 case RMAP_EVENT_LLIST_DELETED
:
1900 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_LCLIST
];
1902 case RMAP_EVENT_CALL_ADDED
:
1903 case RMAP_EVENT_CALL_DELETED
:
1904 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_RMAP
];
1906 case RMAP_EVENT_FILTER_ADDED
:
1907 case RMAP_EVENT_FILTER_DELETED
:
1908 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_FILTER
];
1918 route_map_process_dependency (struct hash_backet
*backet
, void *data
)
1921 route_map_event_t type
= (route_map_event_t
)(ptrdiff_t)data
;
1923 rmap_name
= (char *)backet
->data
;
1928 zlog_debug("%s: Notifying %s of dependency", __FUNCTION__
,
1930 if (route_map_master
.event_hook
)
1931 (*route_map_master
.event_hook
) (type
, rmap_name
);
1936 route_map_upd8_dependency (route_map_event_t type
, const char *arg
,
1937 const char *rmap_name
)
1939 struct hash
*upd8_hash
= NULL
;
1941 if ((upd8_hash
= route_map_get_dep_hash(type
)))
1942 route_map_dep_update (upd8_hash
, arg
, rmap_name
, type
);
1946 route_map_notify_dependencies (const char *affected_name
, route_map_event_t event
)
1948 struct route_map_dep
*dep
;
1949 struct hash
*upd8_hash
;
1955 name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, affected_name
);
1957 if ((upd8_hash
= route_map_get_dep_hash(event
)) == NULL
)
1959 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1963 dep
= (struct route_map_dep
*)hash_get (upd8_hash
, name
,
1967 if (!dep
->this_hash
)
1968 dep
->this_hash
= upd8_hash
;
1970 hash_iterate (dep
->dep_rmap_hash
, route_map_process_dependency
, (void *)event
);
1973 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1977 /* VTY related functions. */
1978 DEFUN (match_interface
,
1979 match_interface_cmd
,
1980 "match interface WORD",
1982 "match first hop interface of route\n"
1986 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
1988 if (rmap_match_set_hook
.match_interface
)
1989 return rmap_match_set_hook
.match_interface (vty
, index
, "interface", argv
[idx_word
]->arg
, RMAP_EVENT_MATCH_ADDED
);
1993 DEFUN (no_match_interface
,
1994 no_match_interface_cmd
,
1995 "no match interface [WORD]",
1998 "Match first hop interface of route\n"
2001 char *iface
= (argc
== 4) ? argv
[3]->arg
: NULL
;
2002 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2004 if (rmap_match_set_hook
.no_match_interface
)
2005 return rmap_match_set_hook
.no_match_interface (vty
, index
, "interface", iface
, RMAP_EVENT_MATCH_DELETED
);
2010 DEFUN (match_ip_address
,
2011 match_ip_address_cmd
,
2012 "match ip address <(1-199)|(1300-2699)|WORD>",
2015 "Match address of route\n"
2016 "IP access-list number\n"
2017 "IP access-list number (expanded range)\n"
2018 "IP Access-list name\n")
2021 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2023 if (rmap_match_set_hook
.match_ip_address
)
2024 return rmap_match_set_hook
.match_ip_address (vty
, index
, "ip address", argv
[idx_acl
]->arg
,
2025 RMAP_EVENT_FILTER_ADDED
);
2030 DEFUN (no_match_ip_address
,
2031 no_match_ip_address_cmd
,
2032 "no match ip address [<(1-199)|(1300-2699)|WORD>]",
2036 "Match address of route\n"
2037 "IP access-list number\n"
2038 "IP access-list number (expanded range)\n"
2039 "IP Access-list name\n")
2042 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2044 if (rmap_match_set_hook
.no_match_ip_address
)
2046 if (argc
<= idx_word
)
2047 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", NULL
,
2048 RMAP_EVENT_FILTER_DELETED
);
2049 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", argv
[idx_word
]->arg
,
2050 RMAP_EVENT_FILTER_DELETED
);
2056 DEFUN (match_ip_address_prefix_list
,
2057 match_ip_address_prefix_list_cmd
,
2058 "match ip address prefix-list WORD",
2061 "Match address of route\n"
2062 "Match entries of prefix-lists\n"
2063 "IP prefix-list name\n")
2066 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2068 if (rmap_match_set_hook
.match_ip_address_prefix_list
)
2069 return rmap_match_set_hook
.match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2070 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2075 DEFUN (no_match_ip_address_prefix_list
,
2076 no_match_ip_address_prefix_list_cmd
,
2077 "no match ip address prefix-list [WORD]",
2081 "Match address of route\n"
2082 "Match entries of prefix-lists\n"
2083 "IP prefix-list name\n")
2086 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2088 if (rmap_match_set_hook
.no_match_ip_address_prefix_list
)
2090 if (argc
<= idx_word
)
2091 return rmap_match_set_hook
.no_match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2092 NULL
, RMAP_EVENT_PLIST_DELETED
);
2093 return rmap_match_set_hook
.no_match_ip_address_prefix_list(vty
, index
, "ip address prefix-list",
2094 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2100 DEFUN (match_ip_next_hop
,
2101 match_ip_next_hop_cmd
,
2102 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
2105 "Match next-hop address of route\n"
2106 "IP access-list number\n"
2107 "IP access-list number (expanded range)\n"
2108 "IP Access-list name\n")
2111 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2113 if (rmap_match_set_hook
.match_ip_next_hop
)
2114 return rmap_match_set_hook
.match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_acl
]->arg
,
2115 RMAP_EVENT_FILTER_ADDED
);
2120 DEFUN (no_match_ip_next_hop
,
2121 no_match_ip_next_hop_cmd
,
2122 "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]",
2126 "Match next-hop address of route\n"
2127 "IP access-list number\n"
2128 "IP access-list number (expanded range)\n"
2129 "IP Access-list name\n")
2132 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2134 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2136 if (argc
<= idx_word
)
2137 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", NULL
,
2138 RMAP_EVENT_FILTER_DELETED
);
2139 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_word
]->arg
,
2140 RMAP_EVENT_FILTER_DELETED
);
2146 DEFUN (match_ip_next_hop_prefix_list
,
2147 match_ip_next_hop_prefix_list_cmd
,
2148 "match ip next-hop prefix-list WORD",
2151 "Match next-hop address of route\n"
2152 "Match entries of prefix-lists\n"
2153 "IP prefix-list name\n")
2156 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2158 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
)
2159 return rmap_match_set_hook
.match_ip_next_hop_prefix_list (vty
, index
, "ip next-hop prefix-list",
2160 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2164 DEFUN (no_match_ip_next_hop_prefix_list
,
2165 no_match_ip_next_hop_prefix_list_cmd
,
2166 "no match ip next-hop prefix-list [WORD]",
2170 "Match next-hop address of route\n"
2171 "Match entries of prefix-lists\n"
2172 "IP prefix-list name\n")
2175 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2177 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2179 if (argc
<= idx_word
)
2180 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2181 NULL
, RMAP_EVENT_PLIST_DELETED
);
2182 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2183 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2189 DEFUN (match_ipv6_address
,
2190 match_ipv6_address_cmd
,
2191 "match ipv6 address WORD",
2194 "Match IPv6 address of route\n"
2195 "IPv6 access-list name\n")
2198 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2200 if (rmap_match_set_hook
.match_ipv6_address
)
2201 return rmap_match_set_hook
.match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2202 RMAP_EVENT_FILTER_ADDED
);
2206 DEFUN (no_match_ipv6_address
,
2207 no_match_ipv6_address_cmd
,
2208 "no match ipv6 address WORD",
2212 "Match IPv6 address of route\n"
2213 "IPv6 access-list name\n")
2216 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2218 if (rmap_match_set_hook
.no_match_ipv6_address
)
2219 return rmap_match_set_hook
.no_match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2220 RMAP_EVENT_FILTER_DELETED
);
2225 DEFUN (match_ipv6_address_prefix_list
,
2226 match_ipv6_address_prefix_list_cmd
,
2227 "match ipv6 address prefix-list WORD",
2230 "Match address of route\n"
2231 "Match entries of prefix-lists\n"
2232 "IP prefix-list name\n")
2235 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2237 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
)
2238 return rmap_match_set_hook
.match_ipv6_address_prefix_list (vty
, index
, "ipv6 address prefix-list",
2239 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2243 DEFUN (no_match_ipv6_address_prefix_list
,
2244 no_match_ipv6_address_prefix_list_cmd
,
2245 "no match ipv6 address prefix-list WORD",
2249 "Match address of route\n"
2250 "Match entries of prefix-lists\n"
2251 "IP prefix-list name\n")
2254 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2256 if (rmap_match_set_hook
.no_match_ipv6_address_prefix_list
)
2257 return rmap_match_set_hook
.no_match_ipv6_address_prefix_list(vty
, index
, "ipv6 address prefix-list",
2258 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2263 DEFUN (match_metric
,
2265 "match metric (0-4294967295)",
2267 "Match metric of route\n"
2271 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2273 if (rmap_match_set_hook
.match_metric
)
2274 return rmap_match_set_hook
.match_metric(vty
, index
, "metric", argv
[idx_number
]->arg
,
2275 RMAP_EVENT_MATCH_ADDED
);
2280 DEFUN (no_match_metric
,
2281 no_match_metric_cmd
,
2282 "no match metric [(0-4294967295)]",
2285 "Match metric of route\n"
2289 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2291 if (rmap_match_set_hook
.no_match_metric
)
2293 if (argc
<= idx_number
)
2294 return rmap_match_set_hook
.no_match_metric (vty
, index
, "metric",
2295 NULL
, RMAP_EVENT_MATCH_DELETED
);
2296 return rmap_match_set_hook
.no_match_metric(vty
, index
, "metric",
2297 argv
[idx_number
]->arg
,
2298 RMAP_EVENT_MATCH_DELETED
);
2306 "match tag (1-4294967295)",
2308 "Match tag of route\n"
2312 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2314 if (rmap_match_set_hook
.match_tag
)
2315 return rmap_match_set_hook
.match_tag(vty
, index
, "tag", argv
[idx_number
]->arg
,
2316 RMAP_EVENT_MATCH_ADDED
);
2321 DEFUN (no_match_tag
,
2323 "no match tag [(1-4294967295)]",
2326 "Match tag of route\n"
2329 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2332 char *arg
= argv_find (argv
, argc
, "(1-4294967295)", &idx
) ?
2333 argv
[idx
]->arg
: NULL
;
2335 if (rmap_match_set_hook
.no_match_tag
)
2336 return rmap_match_set_hook
.no_match_tag (vty
, index
, "tag", arg
,
2337 RMAP_EVENT_MATCH_DELETED
);
2342 DEFUN (set_ip_nexthop
,
2344 "set ip next-hop A.B.C.D",
2347 "Next hop address\n"
2348 "IP address of next hop\n")
2353 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2355 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
2358 vty_out (vty
, "%% Malformed nexthop address%s", VTY_NEWLINE
);
2361 if (su
.sin
.sin_addr
.s_addr
== 0 ||
2362 IPV4_CLASS_DE(su
.sin
.sin_addr
.s_addr
))
2364 vty_out (vty
, "%% nexthop address cannot be 0.0.0.0, multicast "
2365 "or reserved%s", VTY_NEWLINE
);
2369 if (rmap_match_set_hook
.set_ip_nexthop
)
2370 return rmap_match_set_hook
.set_ip_nexthop(vty
, index
, "ip next-hop", argv
[idx_ipv4
]->arg
);
2375 DEFUN (no_set_ip_nexthop
,
2376 no_set_ip_nexthop_cmd
,
2377 "no set ip next-hop [<peer-address|A.B.C.D>]",
2381 "Next hop address\n"
2382 "Use peer address (for BGP only)\n"
2383 "IP address of next hop\n")
2386 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2388 if (rmap_match_set_hook
.no_set_ip_nexthop
)
2390 if (argc
<= idx_peer
)
2391 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", NULL
);
2392 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", argv
[idx_peer
]->arg
);
2398 DEFUN (set_ipv6_nexthop_local
,
2399 set_ipv6_nexthop_local_cmd
,
2400 "set ipv6 next-hop local X:X::X:X",
2403 "IPv6 next-hop address\n"
2404 "IPv6 local address\n"
2405 "IPv6 address of next hop\n")
2408 struct in6_addr addr
;
2410 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2412 ret
= inet_pton (AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
2415 vty_out (vty
, "%% Malformed nexthop address%s", VTY_NEWLINE
);
2418 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
2420 vty_out (vty
, "%% Invalid link-local nexthop address%s", VTY_NEWLINE
);
2424 if (rmap_match_set_hook
.set_ipv6_nexthop_local
)
2425 return rmap_match_set_hook
.set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[idx_ipv6
]->arg
);
2430 DEFUN (no_set_ipv6_nexthop_local
,
2431 no_set_ipv6_nexthop_local_cmd
,
2432 "no set ipv6 next-hop local [X:X::X:X]",
2436 "IPv6 next-hop address\n"
2437 "IPv6 local address\n"
2438 "IPv6 address of next hop\n")
2441 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2443 if (rmap_match_set_hook
.no_set_ipv6_nexthop_local
)
2445 if (argc
<= idx_ipv6
)
2446 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", NULL
);
2447 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[5]->arg
);
2454 "set metric <(0-4294967295)|rtt|+rtt|-rtt|+metric|-metric>",
2456 "Metric value for destination routing protocol\n"
2458 "Assign round trip time\n"
2459 "Add round trip time\n"
2460 "Subtract round trip time\n"
2462 "Subtract metric\n")
2465 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2467 if (rmap_match_set_hook
.set_metric
)
2468 return rmap_match_set_hook
.set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2473 DEFUN (no_set_metric
,
2475 "no set metric [(0-4294967295)]",
2478 "Metric value for destination routing protocol\n"
2482 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2484 if (rmap_match_set_hook
.no_set_metric
)
2486 if (argc
<= idx_number
)
2487 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", NULL
);
2488 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2496 "set tag (1-4294967295)",
2498 "Tag value for routing protocol\n"
2501 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2504 if (rmap_match_set_hook
.set_tag
)
2505 return rmap_match_set_hook
.set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2512 "no set tag [(1-4294967295)]",
2515 "Tag value for routing protocol\n"
2518 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2521 if (rmap_match_set_hook
.no_set_tag
)
2523 if (argc
<= idx_number
)
2524 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", NULL
);
2525 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2532 DEFUN_NOSH (route_map
,
2534 "route-map WORD <deny|permit> (1-65535)",
2535 "Create route-map or enter route-map command mode\n"
2537 "Route map denies set operations\n"
2538 "Route map permits set operations\n"
2539 "Sequence to insert to/delete from existing route-map entry\n")
2542 int idx_permit_deny
= 2;
2544 struct route_map
*map
;
2545 struct route_map_index
*index
;
2546 char *endptr
= NULL
;
2547 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2548 unsigned long pref
= strtoul (argv
[idx_number
]->arg
, &endptr
, 10);
2549 const char *mapname
= argv
[idx_word
]->arg
;
2551 /* Get route map. */
2552 map
= route_map_get (mapname
);
2553 index
= route_map_index_get (map
, permit
, pref
);
2555 VTY_PUSH_CONTEXT (RMAP_NODE
, index
);
2559 DEFUN (no_route_map_all
,
2560 no_route_map_all_cmd
,
2561 "no route-map WORD",
2563 "Create route-map or enter route-map command mode\n"
2567 const char *mapname
= argv
[idx_word
]->arg
;
2568 struct route_map
*map
;
2570 map
= route_map_lookup_by_name (mapname
);
2573 vty_out (vty
, "%% Could not find route-map %s%s", mapname
, VTY_NEWLINE
);
2577 route_map_delete (map
);
2582 DEFUN (no_route_map
,
2584 "no route-map WORD <deny|permit> (1-65535)",
2586 "Create route-map or enter route-map command mode\n"
2588 "Route map denies set operations\n"
2589 "Route map permits set operations\n"
2590 "Sequence to insert to/delete from existing route-map entry\n")
2593 int idx_permit_deny
= 3;
2595 struct route_map
*map
;
2596 struct route_map_index
*index
;
2597 char *endptr
= NULL
;
2598 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2599 const char *prefstr
= argv
[idx_number
]->arg
;
2600 const char *mapname
= argv
[idx_word
]->arg
;
2601 unsigned long pref
= strtoul (prefstr
, &endptr
, 10);
2603 /* Existence check. */
2604 map
= route_map_lookup_by_name (mapname
);
2607 vty_out (vty
, "%% Could not find route-map %s%s", mapname
, VTY_NEWLINE
);
2611 /* Lookup route map index. */
2612 index
= route_map_index_lookup (map
, permit
, pref
);
2615 vty_out (vty
, "%% Could not find route-map entry %s %s%s",
2616 mapname
, prefstr
, VTY_NEWLINE
);
2620 /* Delete index from route map. */
2621 route_map_index_delete (index
, 1);
2623 /* If this route rule is the last one, delete route map itself. */
2624 if (route_map_empty (map
))
2625 route_map_delete (map
);
2630 DEFUN (rmap_onmatch_next
,
2631 rmap_onmatch_next_cmd
,
2633 "Exit policy on matches\n"
2636 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2640 if (index
->type
== RMAP_DENY
)
2642 /* Under a deny clause, match means it's finished. No need to set next */
2643 vty_out (vty
, "on-match next not supported under route-map deny%s",
2647 index
->exitpolicy
= RMAP_NEXT
;
2652 DEFUN (no_rmap_onmatch_next
,
2653 no_rmap_onmatch_next_cmd
,
2656 "Exit policy on matches\n"
2659 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2662 index
->exitpolicy
= RMAP_EXIT
;
2667 DEFUN (rmap_onmatch_goto
,
2668 rmap_onmatch_goto_cmd
,
2669 "on-match goto (1-65535)",
2670 "Exit policy on matches\n"
2671 "Goto Clause number\n"
2675 char *num
= argv_find (argv
, argc
, "(1-65535)", &idx
) ? argv
[idx
]->arg
: NULL
;
2677 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2682 if (index
->type
== RMAP_DENY
)
2684 /* Under a deny clause, match means it's finished. No need to go anywhere */
2685 vty_out (vty
, "on-match goto not supported under route-map deny%s",
2691 VTY_GET_INTEGER_RANGE("route-map index", d
, num
, 1, 65535);
2693 d
= index
->pref
+ 1;
2695 if (d
<= index
->pref
)
2697 /* Can't allow you to do that, Dave */
2698 vty_out (vty
, "can't jump backwards in route-maps%s", VTY_NEWLINE
);
2703 index
->exitpolicy
= RMAP_GOTO
;
2704 index
->nextpref
= d
;
2710 DEFUN (no_rmap_onmatch_goto
,
2711 no_rmap_onmatch_goto_cmd
,
2714 "Exit policy on matches\n"
2715 "Goto Clause number\n")
2717 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2720 index
->exitpolicy
= RMAP_EXIT
;
2725 /* Cisco/GNU Zebra compatibility aliases */
2727 DEFUN (rmap_continue
,
2729 "continue (1-65535)",
2730 "Continue on a different entry within the route-map\n"
2731 "Route-map entry sequence number\n")
2733 return rmap_onmatch_goto (self
, vty
, argc
, argv
);
2737 DEFUN (no_rmap_continue
,
2738 no_rmap_continue_cmd
,
2739 "no continue [(1-65535)]",
2741 "Continue on a different entry within the route-map\n"
2742 "Route-map entry sequence number\n")
2744 return no_rmap_onmatch_goto (self
, vty
, argc
, argv
);
2748 DEFUN (rmap_show_name
,
2750 "show route-map [WORD]",
2752 "route-map information\n"
2756 const char *name
= (argc
== 3) ? argv
[idx_word
]->arg
: NULL
;
2757 return vty_show_route_map (vty
, name
);
2763 "Jump to another Route-Map after match+set\n"
2764 "Target route-map name\n")
2767 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2768 const char *rmap
= argv
[idx_word
]->arg
;
2774 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2777 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2779 index
->nextrm
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
2781 /* Execute event hook. */
2782 route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED
,
2788 DEFUN (no_rmap_call
,
2792 "Jump to another Route-Map after match+set\n")
2794 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2798 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2801 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2802 index
->nextrm
= NULL
;
2808 DEFUN (rmap_description
,
2809 rmap_description_cmd
,
2810 "description LINE...",
2811 "Route-map comment\n"
2812 "Comment describing this route-map rule\n")
2815 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2819 if (index
->description
)
2820 XFREE (MTYPE_TMP
, index
->description
);
2821 index
->description
= argv_concat (argv
, argc
, idx_line
);
2826 DEFUN (no_rmap_description
,
2827 no_rmap_description_cmd
,
2830 "Route-map comment\n")
2832 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2836 if (index
->description
)
2837 XFREE (MTYPE_TMP
, index
->description
);
2838 index
->description
= NULL
;
2843 /* Configuration write function. */
2845 route_map_config_write (struct vty
*vty
)
2847 struct route_map
*map
;
2848 struct route_map_index
*index
;
2849 struct route_map_rule
*rule
;
2853 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2854 for (index
= map
->head
; index
; index
= index
->next
)
2857 vty_out (vty
, "!%s", VTY_NEWLINE
);
2861 vty_out (vty
, "route-map %s %s %d%s",
2863 route_map_type_str (index
->type
),
2864 index
->pref
, VTY_NEWLINE
);
2866 if (index
->description
)
2867 vty_out (vty
, " description %s%s", index
->description
, VTY_NEWLINE
);
2869 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
2870 vty_out (vty
, " match %s %s%s", rule
->cmd
->str
,
2871 rule
->rule_str
? rule
->rule_str
: "",
2874 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
2875 vty_out (vty
, " set %s %s%s", rule
->cmd
->str
,
2876 rule
->rule_str
? rule
->rule_str
: "",
2879 vty_out (vty
, " call %s%s", index
->nextrm
, VTY_NEWLINE
);
2880 if (index
->exitpolicy
== RMAP_GOTO
)
2881 vty_out (vty
, " on-match goto %d%s", index
->nextpref
, VTY_NEWLINE
);
2882 if (index
->exitpolicy
== RMAP_NEXT
)
2883 vty_out (vty
," on-match next%s", VTY_NEWLINE
);
2890 /* Route map node structure. */
2891 static struct cmd_node rmap_node
=
2894 "%s(config-route-map)# ",
2898 /* Common route map rules */
2901 route_map_rule_tag_compile (const char *arg
)
2903 unsigned long int tmp
;
2908 tmp
= strtoul(arg
, &endptr
, 0);
2909 if (arg
[0] == '\0' || *endptr
!= '\0' || errno
|| tmp
> ROUTE_TAG_MAX
)
2912 tag
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(*tag
));
2919 route_map_rule_tag_free (void *rule
)
2921 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
2925 route_map_finish (void)
2929 vector_free (route_match_vec
);
2930 route_match_vec
= NULL
;
2931 vector_free (route_set_vec
);
2932 route_set_vec
= NULL
;
2934 /* cleanup route_map */
2935 while (route_map_master
.head
)
2937 struct route_map
*map
= route_map_master
.head
;
2938 map
->to_be_processed
= 0;
2939 route_map_delete (map
);
2942 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2944 hash_free(route_map_dep_hash
[i
]);
2945 route_map_dep_hash
[i
] = NULL
;
2948 hash_free (route_map_master_hash
);
2949 route_map_master_hash
= NULL
;
2952 static void rmap_autocomplete(vector comps
, struct cmd_token
*token
)
2954 struct route_map
*map
;
2956 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2957 vector_set (comps
, XSTRDUP (MTYPE_COMPLETION
, map
->name
));
2960 static const struct cmd_variable_handler rmap_var_handlers
[] = {
2962 /* "route-map WORD" */
2963 .varname
= "route_map",
2964 .completions
= rmap_autocomplete
2966 .tokenname
= "ROUTEMAP_NAME",
2967 .completions
= rmap_autocomplete
2969 .tokenname
= "RMAP_NAME",
2970 .completions
= rmap_autocomplete
2976 /* Initialization of route map vector. */
2978 route_map_init (void)
2982 /* Make vector for match and set. */
2983 route_match_vec
= vector_init (1);
2984 route_set_vec
= vector_init (1);
2985 route_map_master_hash
= hash_create(route_map_hash_key_make
, route_map_hash_cmp
);
2987 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2988 route_map_dep_hash
[i
] = hash_create(route_map_dep_hash_make_key
,
2989 route_map_dep_hash_cmp
);
2991 cmd_variable_handler_register(rmap_var_handlers
);
2993 /* Install route map top node. */
2994 install_node (&rmap_node
, route_map_config_write
);
2996 /* Install route map commands. */
2997 install_default (RMAP_NODE
);
2998 install_element (CONFIG_NODE
, &route_map_cmd
);
2999 install_element (CONFIG_NODE
, &no_route_map_cmd
);
3000 install_element (CONFIG_NODE
, &no_route_map_all_cmd
);
3002 /* Install the on-match stuff */
3003 install_element (RMAP_NODE
, &route_map_cmd
);
3004 install_element (RMAP_NODE
, &rmap_onmatch_next_cmd
);
3005 install_element (RMAP_NODE
, &no_rmap_onmatch_next_cmd
);
3006 install_element (RMAP_NODE
, &rmap_onmatch_goto_cmd
);
3007 install_element (RMAP_NODE
, &no_rmap_onmatch_goto_cmd
);
3008 install_element (RMAP_NODE
, &rmap_continue_cmd
);
3009 install_element (RMAP_NODE
, &no_rmap_continue_cmd
);
3011 /* Install the continue stuff (ALIAS of on-match). */
3013 /* Install the call stuff. */
3014 install_element (RMAP_NODE
, &rmap_call_cmd
);
3015 install_element (RMAP_NODE
, &no_rmap_call_cmd
);
3017 /* Install description commands. */
3018 install_element (RMAP_NODE
, &rmap_description_cmd
);
3019 install_element (RMAP_NODE
, &no_rmap_description_cmd
);
3021 /* Install show command */
3022 install_element (ENABLE_NODE
, &rmap_show_name_cmd
);
3024 install_element (RMAP_NODE
, &match_interface_cmd
);
3025 install_element (RMAP_NODE
, &no_match_interface_cmd
);
3027 install_element (RMAP_NODE
, &match_ip_address_cmd
);
3028 install_element (RMAP_NODE
, &no_match_ip_address_cmd
);
3030 install_element (RMAP_NODE
, &match_ip_address_prefix_list_cmd
);
3031 install_element (RMAP_NODE
, &no_match_ip_address_prefix_list_cmd
);
3033 install_element (RMAP_NODE
, &match_ip_next_hop_cmd
);
3034 install_element (RMAP_NODE
, &no_match_ip_next_hop_cmd
);
3036 install_element (RMAP_NODE
, &match_ip_next_hop_prefix_list_cmd
);
3037 install_element (RMAP_NODE
, &no_match_ip_next_hop_prefix_list_cmd
);
3039 install_element (RMAP_NODE
, &match_ipv6_address_cmd
);
3040 install_element (RMAP_NODE
, &no_match_ipv6_address_cmd
);
3042 install_element (RMAP_NODE
, &match_ipv6_address_prefix_list_cmd
);
3043 install_element (RMAP_NODE
, &no_match_ipv6_address_prefix_list_cmd
);
3045 install_element (RMAP_NODE
, &match_metric_cmd
);
3046 install_element (RMAP_NODE
, &no_match_metric_cmd
);
3048 install_element (RMAP_NODE
, &match_tag_cmd
);
3049 install_element (RMAP_NODE
, &no_match_tag_cmd
);
3051 install_element (RMAP_NODE
, &set_ip_nexthop_cmd
);
3052 install_element (RMAP_NODE
, &no_set_ip_nexthop_cmd
);
3054 install_element (RMAP_NODE
, &set_ipv6_nexthop_local_cmd
);
3055 install_element (RMAP_NODE
, &no_set_ipv6_nexthop_local_cmd
);
3057 install_element (RMAP_NODE
, &set_metric_cmd
);
3058 install_element (RMAP_NODE
, &no_set_metric_cmd
);
3060 install_element (RMAP_NODE
, &set_tag_cmd
);
3061 install_element (RMAP_NODE
, &no_set_tag_cmd
);