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 /* Print the name of the protocol */
995 vty_out (vty
, "%s", zlog_protoname());
996 if (zlog_default
->instance
)
997 vty_out (vty
, " %d", zlog_default
->instance
);
999 vty_out (vty
, ":%s", VTY_NEWLINE
);
1001 for (index
= map
->head
; index
; index
= index
->next
)
1003 vty_out (vty
, "route-map %s, %s, sequence %d%s",
1004 map
->name
, route_map_type_str (index
->type
),
1005 index
->pref
, VTY_NEWLINE
);
1008 if (index
->description
)
1009 vty_out (vty
, " Description:%s %s%s", VTY_NEWLINE
,
1010 index
->description
, VTY_NEWLINE
);
1013 vty_out (vty
, " Match clauses:%s", VTY_NEWLINE
);
1014 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1015 vty_out (vty
, " %s %s%s",
1016 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
1018 vty_out (vty
, " Set clauses:%s", VTY_NEWLINE
);
1019 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1020 vty_out (vty
, " %s %s%s",
1021 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
1024 vty_out (vty
, " Call clause:%s", VTY_NEWLINE
);
1026 vty_out (vty
, " Call %s%s", index
->nextrm
, VTY_NEWLINE
);
1029 vty_out (vty
, " Action:%s", VTY_NEWLINE
);
1030 if (index
->exitpolicy
== RMAP_GOTO
)
1031 vty_out (vty
, " Goto %d%s", index
->nextpref
, VTY_NEWLINE
);
1032 else if (index
->exitpolicy
== RMAP_NEXT
)
1033 vty_out (vty
, " Continue to next entry%s", VTY_NEWLINE
);
1034 else if (index
->exitpolicy
== RMAP_EXIT
)
1035 vty_out (vty
, " Exit routemap%s", VTY_NEWLINE
);
1040 vty_show_route_map (struct vty
*vty
, const char *name
)
1042 struct route_map
*map
;
1046 map
= route_map_lookup_by_name (name
);
1050 vty_show_route_map_entry (vty
, map
);
1055 vty_out (vty
, "%s", zlog_protoname());
1056 if (zlog_default
&& zlog_default
->instance
)
1057 vty_out (vty
, " %d", zlog_default
->instance
);
1058 vty_out (vty
, ": 'route-map %s' not found%s", name
, VTY_NEWLINE
);
1064 for (map
= route_map_master
.head
; map
; map
= map
->next
)
1066 vty_show_route_map_entry (vty
, map
);
1072 /* New route map allocation. Please note route map's name must be
1074 static struct route_map_index
*
1075 route_map_index_new (void)
1077 struct route_map_index
*new;
1079 new = XCALLOC (MTYPE_ROUTE_MAP_INDEX
, sizeof (struct route_map_index
));
1080 new->exitpolicy
= RMAP_EXIT
; /* Default to Cisco-style */
1081 QOBJ_REG (new, route_map_index
);
1085 /* Free route map index. */
1087 route_map_index_delete (struct route_map_index
*index
, int notify
)
1089 struct route_map_rule
*rule
;
1093 /* Free route match. */
1094 while ((rule
= index
->match_list
.head
) != NULL
)
1095 route_map_rule_delete (&index
->match_list
, rule
);
1097 /* Free route set. */
1098 while ((rule
= index
->set_list
.head
) != NULL
)
1099 route_map_rule_delete (&index
->set_list
, rule
);
1101 /* Remove index from route map list. */
1103 index
->next
->prev
= index
->prev
;
1105 index
->map
->tail
= index
->prev
;
1108 index
->prev
->next
= index
->next
;
1110 index
->map
->head
= index
->next
;
1112 /* Free 'char *nextrm' if not NULL */
1114 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
1116 /* Execute event hook. */
1117 if (route_map_master
.event_hook
&& notify
)
1119 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_DELETED
,
1121 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1123 XFREE (MTYPE_ROUTE_MAP_INDEX
, index
);
1126 /* Lookup index from route map. */
1127 static struct route_map_index
*
1128 route_map_index_lookup (struct route_map
*map
, enum route_map_type type
,
1131 struct route_map_index
*index
;
1133 for (index
= map
->head
; index
; index
= index
->next
)
1134 if ((index
->type
== type
|| type
== RMAP_ANY
)
1135 && index
->pref
== pref
)
1140 /* Add new index to route map. */
1141 static struct route_map_index
*
1142 route_map_index_add (struct route_map
*map
, enum route_map_type type
,
1145 struct route_map_index
*index
;
1146 struct route_map_index
*point
;
1148 /* Allocate new route map inex. */
1149 index
= route_map_index_new ();
1154 /* Compare preference. */
1155 for (point
= map
->head
; point
; point
= point
->next
)
1156 if (point
->pref
>= pref
)
1159 if (map
->head
== NULL
)
1161 map
->head
= map
->tail
= index
;
1163 else if (point
== NULL
)
1165 index
->prev
= map
->tail
;
1166 map
->tail
->next
= index
;
1169 else if (point
== map
->head
)
1171 index
->next
= map
->head
;
1172 map
->head
->prev
= index
;
1177 index
->next
= point
;
1178 index
->prev
= point
->prev
;
1180 point
->prev
->next
= index
;
1181 point
->prev
= index
;
1184 /* Execute event hook. */
1185 if (route_map_master
.event_hook
)
1187 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_ADDED
,
1189 route_map_notify_dependencies (map
->name
, RMAP_EVENT_CALL_ADDED
);
1194 /* Get route map index. */
1195 static struct route_map_index
*
1196 route_map_index_get (struct route_map
*map
, enum route_map_type type
,
1199 struct route_map_index
*index
;
1201 index
= route_map_index_lookup (map
, RMAP_ANY
, pref
);
1202 if (index
&& index
->type
!= type
)
1204 /* Delete index from route map. */
1205 route_map_index_delete (index
, 1);
1209 index
= route_map_index_add (map
, type
, pref
);
1213 /* New route map rule */
1214 static struct route_map_rule
*
1215 route_map_rule_new (void)
1217 struct route_map_rule
*new;
1219 new = XCALLOC (MTYPE_ROUTE_MAP_RULE
, sizeof (struct route_map_rule
));
1223 /* Install rule command to the match list. */
1225 route_map_install_match (struct route_map_rule_cmd
*cmd
)
1227 vector_set (route_match_vec
, cmd
);
1230 /* Install rule command to the set list. */
1232 route_map_install_set (struct route_map_rule_cmd
*cmd
)
1234 vector_set (route_set_vec
, cmd
);
1237 /* Lookup rule command from match list. */
1238 static struct route_map_rule_cmd
*
1239 route_map_lookup_match (const char *name
)
1242 struct route_map_rule_cmd
*rule
;
1244 for (i
= 0; i
< vector_active (route_match_vec
); i
++)
1245 if ((rule
= vector_slot (route_match_vec
, i
)) != NULL
)
1246 if (strcmp (rule
->str
, name
) == 0)
1251 /* Lookup rule command from set list. */
1252 static struct route_map_rule_cmd
*
1253 route_map_lookup_set (const char *name
)
1256 struct route_map_rule_cmd
*rule
;
1258 for (i
= 0; i
< vector_active (route_set_vec
); i
++)
1259 if ((rule
= vector_slot (route_set_vec
, i
)) != NULL
)
1260 if (strcmp (rule
->str
, name
) == 0)
1265 /* Add match and set rule to rule list. */
1267 route_map_rule_add (struct route_map_rule_list
*list
,
1268 struct route_map_rule
*rule
)
1271 rule
->prev
= list
->tail
;
1273 list
->tail
->next
= rule
;
1279 /* Delete rule from rule list. */
1281 route_map_rule_delete (struct route_map_rule_list
*list
,
1282 struct route_map_rule
*rule
)
1284 if (rule
->cmd
->func_free
)
1285 (*rule
->cmd
->func_free
) (rule
->value
);
1288 XFREE (MTYPE_ROUTE_MAP_RULE_STR
, rule
->rule_str
);
1291 rule
->next
->prev
= rule
->prev
;
1293 list
->tail
= rule
->prev
;
1295 rule
->prev
->next
= rule
->next
;
1297 list
->head
= rule
->next
;
1299 XFREE (MTYPE_ROUTE_MAP_RULE
, rule
);
1302 /* strcmp wrapper function which don't crush even argument is NULL. */
1304 rulecmp (const char *dst
, const char *src
)
1318 return strcmp (dst
, src
);
1323 /* Use this to return the already specified argument for this match. This is
1324 * useful to get the specified argument with a route map match rule when the
1325 * rule is being deleted and the argument is not provided.
1328 route_map_get_match_arg(struct route_map_index
*index
, const char *match_name
)
1330 struct route_map_rule
*rule
;
1331 struct route_map_rule_cmd
*cmd
;
1333 /* First lookup rule for add match statement. */
1334 cmd
= route_map_lookup_match (match_name
);
1338 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1339 if (rule
->cmd
== cmd
&& rule
->rule_str
!= NULL
)
1340 return (rule
->rule_str
);
1345 /* Add match statement to route map. */
1347 route_map_add_match (struct route_map_index
*index
, const char *match_name
,
1348 const char *match_arg
)
1350 struct route_map_rule
*rule
;
1351 struct route_map_rule
*next
;
1352 struct route_map_rule_cmd
*cmd
;
1356 /* First lookup rule for add match statement. */
1357 cmd
= route_map_lookup_match (match_name
);
1359 return RMAP_RULE_MISSING
;
1361 /* Next call compile function for this match statement. */
1362 if (cmd
->func_compile
)
1364 compile
= (*cmd
->func_compile
)(match_arg
);
1365 if (compile
== NULL
)
1366 return RMAP_COMPILE_ERROR
;
1371 /* If argument is completely same ignore it. */
1372 for (rule
= index
->match_list
.head
; rule
; rule
= next
)
1375 if (rule
->cmd
== cmd
)
1377 route_map_rule_delete (&index
->match_list
, rule
);
1382 /* Add new route map match rule. */
1383 rule
= route_map_rule_new ();
1385 rule
->value
= compile
;
1387 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, match_arg
);
1389 rule
->rule_str
= NULL
;
1391 /* Add new route match rule to linked list. */
1392 route_map_rule_add (&index
->match_list
, rule
);
1394 /* Execute event hook. */
1395 if (route_map_master
.event_hook
)
1397 (*route_map_master
.event_hook
) (replaced
?
1398 RMAP_EVENT_MATCH_REPLACED
:
1399 RMAP_EVENT_MATCH_ADDED
,
1401 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1407 /* Delete specified route match rule. */
1409 route_map_delete_match (struct route_map_index
*index
, const char *match_name
,
1410 const char *match_arg
)
1412 struct route_map_rule
*rule
;
1413 struct route_map_rule_cmd
*cmd
;
1415 cmd
= route_map_lookup_match (match_name
);
1419 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1420 if (rule
->cmd
== cmd
&&
1421 (rulecmp (rule
->rule_str
, match_arg
) == 0 || match_arg
== NULL
))
1423 route_map_rule_delete (&index
->match_list
, rule
);
1424 /* Execute event hook. */
1425 if (route_map_master
.event_hook
)
1427 (*route_map_master
.event_hook
) (RMAP_EVENT_MATCH_DELETED
,
1429 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1433 /* Can't find matched rule. */
1437 /* Add route-map set statement to the route map. */
1439 route_map_add_set (struct route_map_index
*index
, const char *set_name
,
1440 const char *set_arg
)
1442 struct route_map_rule
*rule
;
1443 struct route_map_rule
*next
;
1444 struct route_map_rule_cmd
*cmd
;
1448 cmd
= route_map_lookup_set (set_name
);
1450 return RMAP_RULE_MISSING
;
1452 /* Next call compile function for this match statement. */
1453 if (cmd
->func_compile
)
1455 compile
= (*cmd
->func_compile
)(set_arg
);
1456 if (compile
== NULL
)
1457 return RMAP_COMPILE_ERROR
;
1462 /* Add by WJL. if old set command of same kind exist, delete it first
1463 to ensure only one set command of same kind exist under a
1465 for (rule
= index
->set_list
.head
; rule
; rule
= next
)
1468 if (rule
->cmd
== cmd
)
1470 route_map_rule_delete (&index
->set_list
, rule
);
1475 /* Add new route map match rule. */
1476 rule
= route_map_rule_new ();
1478 rule
->value
= compile
;
1480 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, set_arg
);
1482 rule
->rule_str
= NULL
;
1484 /* Add new route match rule to linked list. */
1485 route_map_rule_add (&index
->set_list
, rule
);
1487 /* Execute event hook. */
1488 if (route_map_master
.event_hook
)
1490 (*route_map_master
.event_hook
) (replaced
?
1491 RMAP_EVENT_SET_REPLACED
:
1492 RMAP_EVENT_SET_ADDED
,
1494 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1499 /* Delete route map set rule. */
1501 route_map_delete_set (struct route_map_index
*index
, const char *set_name
,
1502 const char *set_arg
)
1504 struct route_map_rule
*rule
;
1505 struct route_map_rule_cmd
*cmd
;
1507 cmd
= route_map_lookup_set (set_name
);
1511 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1512 if ((rule
->cmd
== cmd
) &&
1513 (rulecmp (rule
->rule_str
, set_arg
) == 0 || set_arg
== NULL
))
1515 route_map_rule_delete (&index
->set_list
, rule
);
1516 /* Execute event hook. */
1517 if (route_map_master
.event_hook
)
1519 (*route_map_master
.event_hook
) (RMAP_EVENT_SET_DELETED
,
1521 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1525 /* Can't find matched rule. */
1529 /* Apply route map's each index to the object.
1531 The matrix for a route-map looks like this:
1532 (note, this includes the description for the "NEXT"
1533 and "GOTO" frobs now
1537 permit action | cont
1539 ------------------+---------------
1545 -Apply Set statements, accept route
1546 -If Call statement is present jump to the specified route-map, if it
1547 denies the route we finish.
1548 -If NEXT is specified, goto NEXT statement
1549 -If GOTO is specified, goto the first clause where pref > nextpref
1550 -If nothing is specified, do as Cisco and finish
1552 -Route is denied by route-map.
1556 If we get no matches after we've processed all updates, then the route
1559 Some notes on the new "CALL", "NEXT" and "GOTO"
1560 call WORD - If this clause is matched, then the set statements
1561 are executed and then we jump to route-map 'WORD'. If
1562 this route-map denies the route, we finish, in other case we
1563 do whatever the exit policy (EXIT, NEXT or GOTO) tells.
1564 on-match next - If this clause is matched, then the set statements
1565 are executed and then we drop through to the next clause
1566 on-match goto n - If this clause is matched, then the set statments
1567 are executed and then we goto the nth clause, or the
1568 first clause greater than this. In order to ensure
1569 route-maps *always* exit, you cannot jump backwards.
1572 We need to make sure our route-map processing matches the above
1575 static route_map_result_t
1576 route_map_apply_match (struct route_map_rule_list
*match_list
,
1577 struct prefix
*prefix
, route_map_object_t type
,
1580 route_map_result_t ret
= RMAP_NOMATCH
;
1581 struct route_map_rule
*match
;
1584 /* Check all match rule and if there is no match rule, go to the
1586 if (!match_list
->head
)
1590 for (match
= match_list
->head
; match
; match
= match
->next
)
1592 /* Try each match statement in turn, If any do not return
1593 RMAP_MATCH, return, otherwise continue on to next match
1594 statement. All match statements must match for end-result
1596 ret
= (*match
->cmd
->func_apply
) (match
->value
, prefix
,
1598 if (ret
!= RMAP_MATCH
)
1605 /* Apply route map to the object. */
1607 route_map_apply (struct route_map
*map
, struct prefix
*prefix
,
1608 route_map_object_t type
, void *object
)
1610 static int recursion
= 0;
1612 struct route_map_index
*index
;
1613 struct route_map_rule
*set
;
1615 if (recursion
> RMAP_RECURSION_LIMIT
)
1617 zlog_warn("route-map recursion limit (%d) reached, discarding route",
1618 RMAP_RECURSION_LIMIT
);
1620 return RMAP_DENYMATCH
;
1624 return RMAP_DENYMATCH
;
1626 for (index
= map
->head
; index
; index
= index
->next
)
1628 /* Apply this index. */
1629 ret
= route_map_apply_match (&index
->match_list
, prefix
, type
, object
);
1631 /* Now we apply the matrix from above */
1632 if (ret
== RMAP_NOMATCH
)
1633 /* 'cont' from matrix - continue to next route-map sequence */
1635 else if (ret
== RMAP_MATCH
)
1637 if (index
->type
== RMAP_PERMIT
)
1640 /* permit+match must execute sets */
1641 for (set
= index
->set_list
.head
; set
; set
= set
->next
)
1642 ret
= (*set
->cmd
->func_apply
) (set
->value
, prefix
,
1645 /* Call another route-map if available */
1648 struct route_map
*nextrm
=
1649 route_map_lookup_by_name (index
->nextrm
);
1651 if (nextrm
) /* Target route-map found, jump to it */
1654 ret
= route_map_apply (nextrm
, prefix
, type
, object
);
1658 /* If nextrm returned 'deny', finish. */
1659 if (ret
== RMAP_DENYMATCH
)
1663 switch (index
->exitpolicy
)
1671 /* Find the next clause to jump to */
1672 struct route_map_index
*next
= index
->next
;
1673 int nextpref
= index
->nextpref
;
1675 while (next
&& next
->pref
< nextpref
)
1682 /* No clauses match! */
1688 else if (index
->type
== RMAP_DENY
)
1691 return RMAP_DENYMATCH
;
1695 /* Finally route-map does not match at all. */
1696 return RMAP_DENYMATCH
;
1700 route_map_add_hook (void (*func
) (const char *))
1702 route_map_master
.add_hook
= func
;
1706 route_map_delete_hook (void (*func
) (const char *))
1708 route_map_master
.delete_hook
= func
;
1712 route_map_event_hook (void (*func
) (route_map_event_t
, const char *))
1714 route_map_master
.event_hook
= func
;
1717 /* Routines for route map dependency lists and dependency processing */
1719 route_map_rmap_hash_cmp (const void *p1
, const void *p2
)
1721 return (strcmp((const char *)p1
, (const char *)p2
) == 0);
1725 route_map_dep_hash_cmp (const void *p1
, const void *p2
)
1728 return (strcmp (((const struct route_map_dep
*)p1
)->dep_name
, (const char *)p2
) == 0);
1732 route_map_clear_reference(struct hash_backet
*backet
, void *arg
)
1734 struct route_map_dep
*dep
= (struct route_map_dep
*)backet
->data
;
1739 rmap_name
= (char *)hash_release(dep
->dep_rmap_hash
, (void *)arg
);
1742 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1744 if (!dep
->dep_rmap_hash
->count
)
1746 dep
= hash_release(dep
->this_hash
, (void *)dep
->dep_name
);
1747 hash_free(dep
->dep_rmap_hash
);
1748 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1749 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1755 route_map_clear_all_references (char *rmap_name
)
1759 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
1761 hash_iterate(route_map_dep_hash
[i
], route_map_clear_reference
,
1767 route_map_dep_hash_alloc(void *p
)
1769 char *dep_name
= (char *)p
;
1770 struct route_map_dep
*dep_entry
;
1772 dep_entry
= XCALLOC(MTYPE_ROUTE_MAP_DEP
, sizeof(struct route_map_dep
));
1773 dep_entry
->dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1774 dep_entry
->dep_rmap_hash
= hash_create(route_map_dep_hash_make_key
,
1775 route_map_rmap_hash_cmp
);
1776 dep_entry
->this_hash
= NULL
;
1778 return((void *)dep_entry
);
1782 route_map_name_hash_alloc(void *p
)
1784 return((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME
, (const char *)p
));
1788 route_map_dep_hash_make_key (void *p
)
1790 return (string_hash_make((char *)p
));
1794 route_map_print_dependency (struct hash_backet
*backet
, void *data
)
1796 char *rmap_name
= (char *)backet
->data
;
1797 char *dep_name
= (char *)data
;
1800 zlog_debug("%s: Dependency for %s: %s", __FUNCTION__
, dep_name
, rmap_name
);
1804 route_map_dep_update (struct hash
*dephash
, const char *dep_name
,
1805 const char *rmap_name
,
1806 route_map_event_t type
)
1808 struct route_map_dep
*dep
= NULL
;
1810 char *dname
, *rname
;
1813 dname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1814 rname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1818 case RMAP_EVENT_PLIST_ADDED
:
1819 case RMAP_EVENT_CLIST_ADDED
:
1820 case RMAP_EVENT_ECLIST_ADDED
:
1821 case RMAP_EVENT_ASLIST_ADDED
:
1822 case RMAP_EVENT_LLIST_ADDED
:
1823 case RMAP_EVENT_CALL_ADDED
:
1824 case RMAP_EVENT_FILTER_ADDED
:
1826 zlog_debug("%s: Adding dependency for %s in %s", __FUNCTION__
,
1827 dep_name
, rmap_name
);
1828 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
,
1829 route_map_dep_hash_alloc
);
1835 if (!dep
->this_hash
)
1836 dep
->this_hash
= dephash
;
1838 hash_get(dep
->dep_rmap_hash
, rname
, route_map_name_hash_alloc
);
1840 case RMAP_EVENT_PLIST_DELETED
:
1841 case RMAP_EVENT_CLIST_DELETED
:
1842 case RMAP_EVENT_ECLIST_DELETED
:
1843 case RMAP_EVENT_ASLIST_DELETED
:
1844 case RMAP_EVENT_LLIST_DELETED
:
1845 case RMAP_EVENT_CALL_DELETED
:
1846 case RMAP_EVENT_FILTER_DELETED
:
1848 zlog_debug("%s: Deleting dependency for %s in %s", __FUNCTION__
,
1849 dep_name
, rmap_name
);
1850 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
, NULL
);
1855 ret_map_name
= (char *)hash_release(dep
->dep_rmap_hash
, rname
);
1857 XFREE(MTYPE_ROUTE_MAP_NAME
, ret_map_name
);
1859 if (!dep
->dep_rmap_hash
->count
)
1861 dep
= hash_release(dephash
, dname
);
1862 hash_free(dep
->dep_rmap_hash
);
1863 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1864 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1875 hash_iterate (dep
->dep_rmap_hash
, route_map_print_dependency
, dname
);
1879 XFREE(MTYPE_ROUTE_MAP_NAME
, rname
);
1880 XFREE(MTYPE_ROUTE_MAP_NAME
, dname
);
1884 static struct hash
*
1885 route_map_get_dep_hash (route_map_event_t event
)
1887 struct hash
*upd8_hash
= NULL
;
1891 case RMAP_EVENT_PLIST_ADDED
:
1892 case RMAP_EVENT_PLIST_DELETED
:
1893 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_PLIST
];
1895 case RMAP_EVENT_CLIST_ADDED
:
1896 case RMAP_EVENT_CLIST_DELETED
:
1897 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_CLIST
];
1899 case RMAP_EVENT_ECLIST_ADDED
:
1900 case RMAP_EVENT_ECLIST_DELETED
:
1901 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ECLIST
];
1903 case RMAP_EVENT_ASLIST_ADDED
:
1904 case RMAP_EVENT_ASLIST_DELETED
:
1905 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ASPATH
];
1907 case RMAP_EVENT_LLIST_ADDED
:
1908 case RMAP_EVENT_LLIST_DELETED
:
1909 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_LCLIST
];
1911 case RMAP_EVENT_CALL_ADDED
:
1912 case RMAP_EVENT_CALL_DELETED
:
1913 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_RMAP
];
1915 case RMAP_EVENT_FILTER_ADDED
:
1916 case RMAP_EVENT_FILTER_DELETED
:
1917 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_FILTER
];
1927 route_map_process_dependency (struct hash_backet
*backet
, void *data
)
1930 route_map_event_t type
= (route_map_event_t
)(ptrdiff_t)data
;
1932 rmap_name
= (char *)backet
->data
;
1937 zlog_debug("%s: Notifying %s of dependency", __FUNCTION__
,
1939 if (route_map_master
.event_hook
)
1940 (*route_map_master
.event_hook
) (type
, rmap_name
);
1945 route_map_upd8_dependency (route_map_event_t type
, const char *arg
,
1946 const char *rmap_name
)
1948 struct hash
*upd8_hash
= NULL
;
1950 if ((upd8_hash
= route_map_get_dep_hash(type
)))
1951 route_map_dep_update (upd8_hash
, arg
, rmap_name
, type
);
1955 route_map_notify_dependencies (const char *affected_name
, route_map_event_t event
)
1957 struct route_map_dep
*dep
;
1958 struct hash
*upd8_hash
;
1964 name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, affected_name
);
1966 if ((upd8_hash
= route_map_get_dep_hash(event
)) == NULL
)
1968 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1972 dep
= (struct route_map_dep
*)hash_get (upd8_hash
, name
,
1976 if (!dep
->this_hash
)
1977 dep
->this_hash
= upd8_hash
;
1979 hash_iterate (dep
->dep_rmap_hash
, route_map_process_dependency
, (void *)event
);
1982 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1986 /* VTY related functions. */
1987 DEFUN (match_interface
,
1988 match_interface_cmd
,
1989 "match interface WORD",
1991 "match first hop interface of route\n"
1995 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
1997 if (rmap_match_set_hook
.match_interface
)
1998 return rmap_match_set_hook
.match_interface (vty
, index
, "interface", argv
[idx_word
]->arg
, RMAP_EVENT_MATCH_ADDED
);
2002 DEFUN (no_match_interface
,
2003 no_match_interface_cmd
,
2004 "no match interface [WORD]",
2007 "Match first hop interface of route\n"
2010 char *iface
= (argc
== 4) ? argv
[3]->arg
: NULL
;
2011 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2013 if (rmap_match_set_hook
.no_match_interface
)
2014 return rmap_match_set_hook
.no_match_interface (vty
, index
, "interface", iface
, RMAP_EVENT_MATCH_DELETED
);
2019 DEFUN (match_ip_address
,
2020 match_ip_address_cmd
,
2021 "match ip address <(1-199)|(1300-2699)|WORD>",
2024 "Match address of route\n"
2025 "IP access-list number\n"
2026 "IP access-list number (expanded range)\n"
2027 "IP Access-list name\n")
2030 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2032 if (rmap_match_set_hook
.match_ip_address
)
2033 return rmap_match_set_hook
.match_ip_address (vty
, index
, "ip address", argv
[idx_acl
]->arg
,
2034 RMAP_EVENT_FILTER_ADDED
);
2039 DEFUN (no_match_ip_address
,
2040 no_match_ip_address_cmd
,
2041 "no match ip address [<(1-199)|(1300-2699)|WORD>]",
2045 "Match address of route\n"
2046 "IP access-list number\n"
2047 "IP access-list number (expanded range)\n"
2048 "IP Access-list name\n")
2051 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2053 if (rmap_match_set_hook
.no_match_ip_address
)
2055 if (argc
<= idx_word
)
2056 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", NULL
,
2057 RMAP_EVENT_FILTER_DELETED
);
2058 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", argv
[idx_word
]->arg
,
2059 RMAP_EVENT_FILTER_DELETED
);
2065 DEFUN (match_ip_address_prefix_list
,
2066 match_ip_address_prefix_list_cmd
,
2067 "match ip address prefix-list WORD",
2070 "Match address of route\n"
2071 "Match entries of prefix-lists\n"
2072 "IP prefix-list name\n")
2075 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2077 if (rmap_match_set_hook
.match_ip_address_prefix_list
)
2078 return rmap_match_set_hook
.match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2079 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2084 DEFUN (no_match_ip_address_prefix_list
,
2085 no_match_ip_address_prefix_list_cmd
,
2086 "no match ip address prefix-list [WORD]",
2090 "Match address of route\n"
2091 "Match entries of prefix-lists\n"
2092 "IP prefix-list name\n")
2095 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2097 if (rmap_match_set_hook
.no_match_ip_address_prefix_list
)
2099 if (argc
<= idx_word
)
2100 return rmap_match_set_hook
.no_match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2101 NULL
, RMAP_EVENT_PLIST_DELETED
);
2102 return rmap_match_set_hook
.no_match_ip_address_prefix_list(vty
, index
, "ip address prefix-list",
2103 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2109 DEFUN (match_ip_next_hop
,
2110 match_ip_next_hop_cmd
,
2111 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
2114 "Match next-hop address of route\n"
2115 "IP access-list number\n"
2116 "IP access-list number (expanded range)\n"
2117 "IP Access-list name\n")
2120 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2122 if (rmap_match_set_hook
.match_ip_next_hop
)
2123 return rmap_match_set_hook
.match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_acl
]->arg
,
2124 RMAP_EVENT_FILTER_ADDED
);
2129 DEFUN (no_match_ip_next_hop
,
2130 no_match_ip_next_hop_cmd
,
2131 "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]",
2135 "Match next-hop address of route\n"
2136 "IP access-list number\n"
2137 "IP access-list number (expanded range)\n"
2138 "IP Access-list name\n")
2141 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2143 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2145 if (argc
<= idx_word
)
2146 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", NULL
,
2147 RMAP_EVENT_FILTER_DELETED
);
2148 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_word
]->arg
,
2149 RMAP_EVENT_FILTER_DELETED
);
2155 DEFUN (match_ip_next_hop_prefix_list
,
2156 match_ip_next_hop_prefix_list_cmd
,
2157 "match ip next-hop prefix-list WORD",
2160 "Match next-hop address of route\n"
2161 "Match entries of prefix-lists\n"
2162 "IP prefix-list name\n")
2165 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2167 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
)
2168 return rmap_match_set_hook
.match_ip_next_hop_prefix_list (vty
, index
, "ip next-hop prefix-list",
2169 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2173 DEFUN (no_match_ip_next_hop_prefix_list
,
2174 no_match_ip_next_hop_prefix_list_cmd
,
2175 "no match ip next-hop prefix-list [WORD]",
2179 "Match next-hop address of route\n"
2180 "Match entries of prefix-lists\n"
2181 "IP prefix-list name\n")
2184 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2186 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2188 if (argc
<= idx_word
)
2189 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2190 NULL
, RMAP_EVENT_PLIST_DELETED
);
2191 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2192 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2198 DEFUN (match_ipv6_address
,
2199 match_ipv6_address_cmd
,
2200 "match ipv6 address WORD",
2203 "Match IPv6 address of route\n"
2204 "IPv6 access-list name\n")
2207 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2209 if (rmap_match_set_hook
.match_ipv6_address
)
2210 return rmap_match_set_hook
.match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2211 RMAP_EVENT_FILTER_ADDED
);
2215 DEFUN (no_match_ipv6_address
,
2216 no_match_ipv6_address_cmd
,
2217 "no match ipv6 address WORD",
2221 "Match IPv6 address of route\n"
2222 "IPv6 access-list name\n")
2225 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2227 if (rmap_match_set_hook
.no_match_ipv6_address
)
2228 return rmap_match_set_hook
.no_match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2229 RMAP_EVENT_FILTER_DELETED
);
2234 DEFUN (match_ipv6_address_prefix_list
,
2235 match_ipv6_address_prefix_list_cmd
,
2236 "match ipv6 address prefix-list WORD",
2239 "Match address of route\n"
2240 "Match entries of prefix-lists\n"
2241 "IP prefix-list name\n")
2244 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2246 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
)
2247 return rmap_match_set_hook
.match_ipv6_address_prefix_list (vty
, index
, "ipv6 address prefix-list",
2248 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2252 DEFUN (no_match_ipv6_address_prefix_list
,
2253 no_match_ipv6_address_prefix_list_cmd
,
2254 "no match ipv6 address prefix-list WORD",
2258 "Match address of route\n"
2259 "Match entries of prefix-lists\n"
2260 "IP prefix-list name\n")
2263 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2265 if (rmap_match_set_hook
.no_match_ipv6_address_prefix_list
)
2266 return rmap_match_set_hook
.no_match_ipv6_address_prefix_list(vty
, index
, "ipv6 address prefix-list",
2267 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2272 DEFUN (match_metric
,
2274 "match metric (0-4294967295)",
2276 "Match metric of route\n"
2280 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2282 if (rmap_match_set_hook
.match_metric
)
2283 return rmap_match_set_hook
.match_metric(vty
, index
, "metric", argv
[idx_number
]->arg
,
2284 RMAP_EVENT_MATCH_ADDED
);
2289 DEFUN (no_match_metric
,
2290 no_match_metric_cmd
,
2291 "no match metric [(0-4294967295)]",
2294 "Match metric of route\n"
2298 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2300 if (rmap_match_set_hook
.no_match_metric
)
2302 if (argc
<= idx_number
)
2303 return rmap_match_set_hook
.no_match_metric (vty
, index
, "metric",
2304 NULL
, RMAP_EVENT_MATCH_DELETED
);
2305 return rmap_match_set_hook
.no_match_metric(vty
, index
, "metric",
2306 argv
[idx_number
]->arg
,
2307 RMAP_EVENT_MATCH_DELETED
);
2315 "match tag (1-4294967295)",
2317 "Match tag of route\n"
2321 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2323 if (rmap_match_set_hook
.match_tag
)
2324 return rmap_match_set_hook
.match_tag(vty
, index
, "tag", argv
[idx_number
]->arg
,
2325 RMAP_EVENT_MATCH_ADDED
);
2330 DEFUN (no_match_tag
,
2332 "no match tag [(1-4294967295)]",
2335 "Match tag of route\n"
2338 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2341 char *arg
= argv_find (argv
, argc
, "(1-4294967295)", &idx
) ?
2342 argv
[idx
]->arg
: NULL
;
2344 if (rmap_match_set_hook
.no_match_tag
)
2345 return rmap_match_set_hook
.no_match_tag (vty
, index
, "tag", arg
,
2346 RMAP_EVENT_MATCH_DELETED
);
2351 DEFUN (set_ip_nexthop
,
2353 "set ip next-hop A.B.C.D",
2356 "Next hop address\n"
2357 "IP address of next hop\n")
2362 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2364 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
2367 vty_out (vty
, "%% Malformed nexthop address%s", VTY_NEWLINE
);
2370 if (su
.sin
.sin_addr
.s_addr
== 0 ||
2371 IPV4_CLASS_DE(su
.sin
.sin_addr
.s_addr
))
2373 vty_out (vty
, "%% nexthop address cannot be 0.0.0.0, multicast "
2374 "or reserved%s", VTY_NEWLINE
);
2378 if (rmap_match_set_hook
.set_ip_nexthop
)
2379 return rmap_match_set_hook
.set_ip_nexthop(vty
, index
, "ip next-hop", argv
[idx_ipv4
]->arg
);
2384 DEFUN (no_set_ip_nexthop
,
2385 no_set_ip_nexthop_cmd
,
2386 "no set ip next-hop [<peer-address|A.B.C.D>]",
2390 "Next hop address\n"
2391 "Use peer address (for BGP only)\n"
2392 "IP address of next hop\n")
2395 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2397 if (rmap_match_set_hook
.no_set_ip_nexthop
)
2399 if (argc
<= idx_peer
)
2400 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", NULL
);
2401 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", argv
[idx_peer
]->arg
);
2407 DEFUN (set_ipv6_nexthop_local
,
2408 set_ipv6_nexthop_local_cmd
,
2409 "set ipv6 next-hop local X:X::X:X",
2412 "IPv6 next-hop address\n"
2413 "IPv6 local address\n"
2414 "IPv6 address of next hop\n")
2417 struct in6_addr addr
;
2419 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2421 ret
= inet_pton (AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
2424 vty_out (vty
, "%% Malformed nexthop address%s", VTY_NEWLINE
);
2427 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
2429 vty_out (vty
, "%% Invalid link-local nexthop address%s", VTY_NEWLINE
);
2433 if (rmap_match_set_hook
.set_ipv6_nexthop_local
)
2434 return rmap_match_set_hook
.set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[idx_ipv6
]->arg
);
2439 DEFUN (no_set_ipv6_nexthop_local
,
2440 no_set_ipv6_nexthop_local_cmd
,
2441 "no set ipv6 next-hop local [X:X::X:X]",
2445 "IPv6 next-hop address\n"
2446 "IPv6 local address\n"
2447 "IPv6 address of next hop\n")
2450 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2452 if (rmap_match_set_hook
.no_set_ipv6_nexthop_local
)
2454 if (argc
<= idx_ipv6
)
2455 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", NULL
);
2456 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[5]->arg
);
2463 "set metric <(0-4294967295)|rtt|+rtt|-rtt|+metric|-metric>",
2465 "Metric value for destination routing protocol\n"
2467 "Assign round trip time\n"
2468 "Add round trip time\n"
2469 "Subtract round trip time\n"
2471 "Subtract metric\n")
2474 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2476 if (rmap_match_set_hook
.set_metric
)
2477 return rmap_match_set_hook
.set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2482 DEFUN (no_set_metric
,
2484 "no set metric [(0-4294967295)]",
2487 "Metric value for destination routing protocol\n"
2491 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2493 if (rmap_match_set_hook
.no_set_metric
)
2495 if (argc
<= idx_number
)
2496 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", NULL
);
2497 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2505 "set tag (1-4294967295)",
2507 "Tag value for routing protocol\n"
2510 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2513 if (rmap_match_set_hook
.set_tag
)
2514 return rmap_match_set_hook
.set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2521 "no set tag [(1-4294967295)]",
2524 "Tag value for routing protocol\n"
2527 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2530 if (rmap_match_set_hook
.no_set_tag
)
2532 if (argc
<= idx_number
)
2533 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", NULL
);
2534 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2541 DEFUN_NOSH (route_map
,
2543 "route-map WORD <deny|permit> (1-65535)",
2544 "Create route-map or enter route-map command mode\n"
2546 "Route map denies set operations\n"
2547 "Route map permits set operations\n"
2548 "Sequence to insert to/delete from existing route-map entry\n")
2551 int idx_permit_deny
= 2;
2553 struct route_map
*map
;
2554 struct route_map_index
*index
;
2555 char *endptr
= NULL
;
2556 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2557 unsigned long pref
= strtoul (argv
[idx_number
]->arg
, &endptr
, 10);
2558 const char *mapname
= argv
[idx_word
]->arg
;
2560 /* Get route map. */
2561 map
= route_map_get (mapname
);
2562 index
= route_map_index_get (map
, permit
, pref
);
2564 VTY_PUSH_CONTEXT (RMAP_NODE
, index
);
2568 DEFUN (no_route_map_all
,
2569 no_route_map_all_cmd
,
2570 "no route-map WORD",
2572 "Create route-map or enter route-map command mode\n"
2576 const char *mapname
= argv
[idx_word
]->arg
;
2577 struct route_map
*map
;
2579 map
= route_map_lookup_by_name (mapname
);
2582 vty_out (vty
, "%% Could not find route-map %s%s", mapname
, VTY_NEWLINE
);
2586 route_map_delete (map
);
2591 DEFUN (no_route_map
,
2593 "no route-map WORD <deny|permit> (1-65535)",
2595 "Create route-map or enter route-map command mode\n"
2597 "Route map denies set operations\n"
2598 "Route map permits set operations\n"
2599 "Sequence to insert to/delete from existing route-map entry\n")
2602 int idx_permit_deny
= 3;
2604 struct route_map
*map
;
2605 struct route_map_index
*index
;
2606 char *endptr
= NULL
;
2607 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2608 const char *prefstr
= argv
[idx_number
]->arg
;
2609 const char *mapname
= argv
[idx_word
]->arg
;
2610 unsigned long pref
= strtoul (prefstr
, &endptr
, 10);
2612 /* Existence check. */
2613 map
= route_map_lookup_by_name (mapname
);
2616 vty_out (vty
, "%% Could not find route-map %s%s", mapname
, VTY_NEWLINE
);
2620 /* Lookup route map index. */
2621 index
= route_map_index_lookup (map
, permit
, pref
);
2624 vty_out (vty
, "%% Could not find route-map entry %s %s%s",
2625 mapname
, prefstr
, VTY_NEWLINE
);
2629 /* Delete index from route map. */
2630 route_map_index_delete (index
, 1);
2632 /* If this route rule is the last one, delete route map itself. */
2633 if (route_map_empty (map
))
2634 route_map_delete (map
);
2639 DEFUN (rmap_onmatch_next
,
2640 rmap_onmatch_next_cmd
,
2642 "Exit policy on matches\n"
2645 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2649 if (index
->type
== RMAP_DENY
)
2651 /* Under a deny clause, match means it's finished. No need to set next */
2652 vty_out (vty
, "on-match next not supported under route-map deny%s",
2656 index
->exitpolicy
= RMAP_NEXT
;
2661 DEFUN (no_rmap_onmatch_next
,
2662 no_rmap_onmatch_next_cmd
,
2665 "Exit policy on matches\n"
2668 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2671 index
->exitpolicy
= RMAP_EXIT
;
2676 DEFUN (rmap_onmatch_goto
,
2677 rmap_onmatch_goto_cmd
,
2678 "on-match goto (1-65535)",
2679 "Exit policy on matches\n"
2680 "Goto Clause number\n"
2684 char *num
= argv_find (argv
, argc
, "(1-65535)", &idx
) ? argv
[idx
]->arg
: NULL
;
2686 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2691 if (index
->type
== RMAP_DENY
)
2693 /* Under a deny clause, match means it's finished. No need to go anywhere */
2694 vty_out (vty
, "on-match goto not supported under route-map deny%s",
2700 VTY_GET_INTEGER_RANGE("route-map index", d
, num
, 1, 65535);
2702 d
= index
->pref
+ 1;
2704 if (d
<= index
->pref
)
2706 /* Can't allow you to do that, Dave */
2707 vty_out (vty
, "can't jump backwards in route-maps%s", VTY_NEWLINE
);
2712 index
->exitpolicy
= RMAP_GOTO
;
2713 index
->nextpref
= d
;
2719 DEFUN (no_rmap_onmatch_goto
,
2720 no_rmap_onmatch_goto_cmd
,
2723 "Exit policy on matches\n"
2724 "Goto Clause number\n")
2726 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2729 index
->exitpolicy
= RMAP_EXIT
;
2734 /* Cisco/GNU Zebra compatibility aliases */
2736 DEFUN (rmap_continue
,
2738 "continue (1-65535)",
2739 "Continue on a different entry within the route-map\n"
2740 "Route-map entry sequence number\n")
2742 return rmap_onmatch_goto (self
, vty
, argc
, argv
);
2746 DEFUN (no_rmap_continue
,
2747 no_rmap_continue_cmd
,
2748 "no continue [(1-65535)]",
2750 "Continue on a different entry within the route-map\n"
2751 "Route-map entry sequence number\n")
2753 return no_rmap_onmatch_goto (self
, vty
, argc
, argv
);
2757 DEFUN_NOSH (rmap_show_name
,
2759 "show route-map [WORD]",
2761 "route-map information\n"
2765 const char *name
= (argc
== 3) ? argv
[idx_word
]->arg
: NULL
;
2766 return vty_show_route_map (vty
, name
);
2772 "Jump to another Route-Map after match+set\n"
2773 "Target route-map name\n")
2776 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2777 const char *rmap
= argv
[idx_word
]->arg
;
2783 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2786 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2788 index
->nextrm
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
2790 /* Execute event hook. */
2791 route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED
,
2797 DEFUN (no_rmap_call
,
2801 "Jump to another Route-Map after match+set\n")
2803 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2807 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2810 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2811 index
->nextrm
= NULL
;
2817 DEFUN (rmap_description
,
2818 rmap_description_cmd
,
2819 "description LINE...",
2820 "Route-map comment\n"
2821 "Comment describing this route-map rule\n")
2824 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2828 if (index
->description
)
2829 XFREE (MTYPE_TMP
, index
->description
);
2830 index
->description
= argv_concat (argv
, argc
, idx_line
);
2835 DEFUN (no_rmap_description
,
2836 no_rmap_description_cmd
,
2839 "Route-map comment\n")
2841 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2845 if (index
->description
)
2846 XFREE (MTYPE_TMP
, index
->description
);
2847 index
->description
= NULL
;
2852 /* Configuration write function. */
2854 route_map_config_write (struct vty
*vty
)
2856 struct route_map
*map
;
2857 struct route_map_index
*index
;
2858 struct route_map_rule
*rule
;
2862 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2863 for (index
= map
->head
; index
; index
= index
->next
)
2866 vty_out (vty
, "!%s", VTY_NEWLINE
);
2870 vty_out (vty
, "route-map %s %s %d%s",
2872 route_map_type_str (index
->type
),
2873 index
->pref
, VTY_NEWLINE
);
2875 if (index
->description
)
2876 vty_out (vty
, " description %s%s", index
->description
, VTY_NEWLINE
);
2878 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
2879 vty_out (vty
, " match %s %s%s", rule
->cmd
->str
,
2880 rule
->rule_str
? rule
->rule_str
: "",
2883 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
2884 vty_out (vty
, " set %s %s%s", rule
->cmd
->str
,
2885 rule
->rule_str
? rule
->rule_str
: "",
2888 vty_out (vty
, " call %s%s", index
->nextrm
, VTY_NEWLINE
);
2889 if (index
->exitpolicy
== RMAP_GOTO
)
2890 vty_out (vty
, " on-match goto %d%s", index
->nextpref
, VTY_NEWLINE
);
2891 if (index
->exitpolicy
== RMAP_NEXT
)
2892 vty_out (vty
," on-match next%s", VTY_NEWLINE
);
2899 /* Route map node structure. */
2900 static struct cmd_node rmap_node
=
2903 "%s(config-route-map)# ",
2907 /* Common route map rules */
2910 route_map_rule_tag_compile (const char *arg
)
2912 unsigned long int tmp
;
2917 tmp
= strtoul(arg
, &endptr
, 0);
2918 if (arg
[0] == '\0' || *endptr
!= '\0' || errno
|| tmp
> ROUTE_TAG_MAX
)
2921 tag
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(*tag
));
2928 route_map_rule_tag_free (void *rule
)
2930 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
2934 route_map_finish (void)
2938 vector_free (route_match_vec
);
2939 route_match_vec
= NULL
;
2940 vector_free (route_set_vec
);
2941 route_set_vec
= NULL
;
2943 /* cleanup route_map */
2944 while (route_map_master
.head
)
2946 struct route_map
*map
= route_map_master
.head
;
2947 map
->to_be_processed
= 0;
2948 route_map_delete (map
);
2951 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2953 hash_free(route_map_dep_hash
[i
]);
2954 route_map_dep_hash
[i
] = NULL
;
2957 hash_free (route_map_master_hash
);
2958 route_map_master_hash
= NULL
;
2961 static void rmap_autocomplete(vector comps
, struct cmd_token
*token
)
2963 struct route_map
*map
;
2965 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2966 vector_set (comps
, XSTRDUP (MTYPE_COMPLETION
, map
->name
));
2969 static const struct cmd_variable_handler rmap_var_handlers
[] = {
2971 /* "route-map WORD" */
2972 .varname
= "route_map",
2973 .completions
= rmap_autocomplete
2975 .tokenname
= "ROUTEMAP_NAME",
2976 .completions
= rmap_autocomplete
2978 .tokenname
= "RMAP_NAME",
2979 .completions
= rmap_autocomplete
2985 /* Initialization of route map vector. */
2987 route_map_init (void)
2991 /* Make vector for match and set. */
2992 route_match_vec
= vector_init (1);
2993 route_set_vec
= vector_init (1);
2994 route_map_master_hash
= hash_create(route_map_hash_key_make
, route_map_hash_cmp
);
2996 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2997 route_map_dep_hash
[i
] = hash_create(route_map_dep_hash_make_key
,
2998 route_map_dep_hash_cmp
);
3000 cmd_variable_handler_register(rmap_var_handlers
);
3002 /* Install route map top node. */
3003 install_node (&rmap_node
, route_map_config_write
);
3005 /* Install route map commands. */
3006 install_default (RMAP_NODE
);
3007 install_element (CONFIG_NODE
, &route_map_cmd
);
3008 install_element (CONFIG_NODE
, &no_route_map_cmd
);
3009 install_element (CONFIG_NODE
, &no_route_map_all_cmd
);
3011 /* Install the on-match stuff */
3012 install_element (RMAP_NODE
, &route_map_cmd
);
3013 install_element (RMAP_NODE
, &rmap_onmatch_next_cmd
);
3014 install_element (RMAP_NODE
, &no_rmap_onmatch_next_cmd
);
3015 install_element (RMAP_NODE
, &rmap_onmatch_goto_cmd
);
3016 install_element (RMAP_NODE
, &no_rmap_onmatch_goto_cmd
);
3017 install_element (RMAP_NODE
, &rmap_continue_cmd
);
3018 install_element (RMAP_NODE
, &no_rmap_continue_cmd
);
3020 /* Install the continue stuff (ALIAS of on-match). */
3022 /* Install the call stuff. */
3023 install_element (RMAP_NODE
, &rmap_call_cmd
);
3024 install_element (RMAP_NODE
, &no_rmap_call_cmd
);
3026 /* Install description commands. */
3027 install_element (RMAP_NODE
, &rmap_description_cmd
);
3028 install_element (RMAP_NODE
, &no_rmap_description_cmd
);
3030 /* Install show command */
3031 install_element (ENABLE_NODE
, &rmap_show_name_cmd
);
3033 install_element (RMAP_NODE
, &match_interface_cmd
);
3034 install_element (RMAP_NODE
, &no_match_interface_cmd
);
3036 install_element (RMAP_NODE
, &match_ip_address_cmd
);
3037 install_element (RMAP_NODE
, &no_match_ip_address_cmd
);
3039 install_element (RMAP_NODE
, &match_ip_address_prefix_list_cmd
);
3040 install_element (RMAP_NODE
, &no_match_ip_address_prefix_list_cmd
);
3042 install_element (RMAP_NODE
, &match_ip_next_hop_cmd
);
3043 install_element (RMAP_NODE
, &no_match_ip_next_hop_cmd
);
3045 install_element (RMAP_NODE
, &match_ip_next_hop_prefix_list_cmd
);
3046 install_element (RMAP_NODE
, &no_match_ip_next_hop_prefix_list_cmd
);
3048 install_element (RMAP_NODE
, &match_ipv6_address_cmd
);
3049 install_element (RMAP_NODE
, &no_match_ipv6_address_cmd
);
3051 install_element (RMAP_NODE
, &match_ipv6_address_prefix_list_cmd
);
3052 install_element (RMAP_NODE
, &no_match_ipv6_address_prefix_list_cmd
);
3054 install_element (RMAP_NODE
, &match_metric_cmd
);
3055 install_element (RMAP_NODE
, &no_match_metric_cmd
);
3057 install_element (RMAP_NODE
, &match_tag_cmd
);
3058 install_element (RMAP_NODE
, &no_match_tag_cmd
);
3060 install_element (RMAP_NODE
, &set_ip_nexthop_cmd
);
3061 install_element (RMAP_NODE
, &no_set_ip_nexthop_cmd
);
3063 install_element (RMAP_NODE
, &set_ipv6_nexthop_local_cmd
);
3064 install_element (RMAP_NODE
, &no_set_ipv6_nexthop_local_cmd
);
3066 install_element (RMAP_NODE
, &set_metric_cmd
);
3067 install_element (RMAP_NODE
, &no_set_metric_cmd
);
3069 install_element (RMAP_NODE
, &set_tag_cmd
);
3070 install_element (RMAP_NODE
, &no_set_tag_cmd
);