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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
33 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP
, "Route map")
34 DEFINE_MTYPE( LIB
, ROUTE_MAP_NAME
, "Route map name")
35 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_INDEX
, "Route map index")
36 DEFINE_MTYPE( LIB
, ROUTE_MAP_RULE
, "Route map rule")
37 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_RULE_STR
, "Route map rule str")
38 DEFINE_MTYPE( LIB
, ROUTE_MAP_COMPILED
, "Route map compiled")
39 DEFINE_MTYPE_STATIC(LIB
, ROUTE_MAP_DEP
, "Route map dependency")
41 DEFINE_QOBJ_TYPE(route_map_index
)
42 DEFINE_QOBJ_TYPE(route_map
)
44 /* Vector for route match rules. */
45 static vector route_match_vec
;
47 /* Vector for route set rules. */
48 static vector route_set_vec
;
50 struct route_map_match_set_hooks
53 int (*match_interface
) (struct vty
*vty
,
54 struct route_map_index
*index
,
57 route_map_event_t type
);
59 /* no match interface */
60 int (*no_match_interface
) (struct vty
*vty
,
61 struct route_map_index
*index
,
64 route_map_event_t type
);
66 /* match ip address */
67 int (*match_ip_address
) (struct vty
*vty
,
68 struct route_map_index
*index
,
71 route_map_event_t type
);
73 /* no match ip address */
74 int (*no_match_ip_address
) (struct vty
*vty
,
75 struct route_map_index
*index
,
78 route_map_event_t type
);
80 /* match ip address prefix list */
81 int (*match_ip_address_prefix_list
) (struct vty
*vty
,
82 struct route_map_index
*index
,
85 route_map_event_t type
);
87 /* no match ip address prefix list */
88 int (*no_match_ip_address_prefix_list
) (struct vty
*vty
,
89 struct route_map_index
*index
,
92 route_map_event_t type
);
94 /* match ip next hop */
95 int (*match_ip_next_hop
) (struct vty
*vty
,
96 struct route_map_index
*index
,
99 route_map_event_t type
);
101 /* no match ip next hop */
102 int (*no_match_ip_next_hop
) (struct vty
*vty
,
103 struct route_map_index
*index
,
106 route_map_event_t type
);
108 /* match ip next hop prefix list */
109 int (*match_ip_next_hop_prefix_list
) (struct vty
*vty
,
110 struct route_map_index
*index
,
113 route_map_event_t type
);
115 /* no match ip next hop prefix list */
116 int (*no_match_ip_next_hop_prefix_list
) (struct vty
*vty
,
117 struct route_map_index
*index
,
120 route_map_event_t type
);
122 /* match ipv6 address */
123 int (*match_ipv6_address
) (struct vty
*vty
,
124 struct route_map_index
*index
,
127 route_map_event_t type
);
129 /* no match ipv6 address */
130 int (*no_match_ipv6_address
) (struct vty
*vty
,
131 struct route_map_index
*index
,
134 route_map_event_t type
);
137 /* match ipv6 address prefix list */
138 int (*match_ipv6_address_prefix_list
) (struct vty
*vty
,
139 struct route_map_index
*index
,
142 route_map_event_t type
);
144 /* no match ipv6 address prefix list */
145 int (*no_match_ipv6_address_prefix_list
) (struct vty
*vty
,
146 struct route_map_index
*index
,
149 route_map_event_t type
);
152 int (*match_metric
) (struct vty
*vty
,
153 struct route_map_index
*index
,
156 route_map_event_t type
);
158 /* no match metric */
159 int (*no_match_metric
) (struct vty
*vty
,
160 struct route_map_index
*index
,
163 route_map_event_t type
);
166 int (*match_tag
) (struct vty
*vty
,
167 struct route_map_index
*index
,
170 route_map_event_t type
);
173 int (*no_match_tag
) (struct vty
*vty
,
174 struct route_map_index
*index
,
177 route_map_event_t type
);
180 int (*set_ip_nexthop
) (struct vty
*vty
,
181 struct route_map_index
*index
,
185 /* no set ip nexthop */
186 int (*no_set_ip_nexthop
) (struct vty
*vty
,
187 struct route_map_index
*index
,
191 /* set ipv6 nexthop local */
192 int (*set_ipv6_nexthop_local
) (struct vty
*vty
,
193 struct route_map_index
*index
,
197 /* no set ipv6 nexthop local */
198 int (*no_set_ipv6_nexthop_local
) (struct vty
*vty
,
199 struct route_map_index
*index
,
204 int (*set_metric
) (struct vty
*vty
,
205 struct route_map_index
*index
,
210 int (*no_set_metric
) (struct vty
*vty
,
211 struct route_map_index
*index
,
216 int (*set_tag
) (struct vty
*vty
,
217 struct route_map_index
*index
,
222 int (*no_set_tag
) (struct vty
*vty
,
223 struct route_map_index
*index
,
229 struct route_map_match_set_hooks rmap_match_set_hook
;
231 /* match interface */
233 route_map_match_interface_hook (int (*func
) (struct vty
*vty
,
234 struct route_map_index
*index
,
237 route_map_event_t type
))
239 rmap_match_set_hook
.match_interface
= func
;
242 /* no match interface */
244 route_map_no_match_interface_hook (int (*func
) (struct vty
*vty
,
245 struct route_map_index
*index
,
248 route_map_event_t type
))
250 rmap_match_set_hook
.no_match_interface
= func
;
253 /* match ip address */
255 route_map_match_ip_address_hook (int (*func
) (struct vty
*vty
,
256 struct route_map_index
*index
,
259 route_map_event_t type
))
261 rmap_match_set_hook
.match_ip_address
= func
;
264 /* no match ip address */
266 route_map_no_match_ip_address_hook (int (*func
) (struct vty
*vty
,
267 struct route_map_index
*index
,
270 route_map_event_t type
))
272 rmap_match_set_hook
.no_match_ip_address
= func
;
275 /* match ip address prefix list */
277 route_map_match_ip_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
278 struct route_map_index
*index
,
281 route_map_event_t type
))
283 rmap_match_set_hook
.match_ip_address_prefix_list
= func
;
286 /* no match ip address prefix list */
288 route_map_no_match_ip_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
289 struct route_map_index
*index
,
292 route_map_event_t type
))
294 rmap_match_set_hook
.no_match_ip_address_prefix_list
= func
;
297 /* match ip next hop */
299 route_map_match_ip_next_hop_hook (int (*func
) (struct vty
*vty
,
300 struct route_map_index
*index
,
303 route_map_event_t type
))
305 rmap_match_set_hook
.match_ip_next_hop
= func
;
308 /* no match ip next hop */
310 route_map_no_match_ip_next_hop_hook (int (*func
) (struct vty
*vty
,
311 struct route_map_index
*index
,
314 route_map_event_t type
))
316 rmap_match_set_hook
.no_match_ip_next_hop
= func
;
319 /* match ip next hop prefix list */
321 route_map_match_ip_next_hop_prefix_list_hook (int (*func
) (struct vty
*vty
,
322 struct route_map_index
*index
,
325 route_map_event_t type
))
327 rmap_match_set_hook
.match_ip_next_hop_prefix_list
= func
;
330 /* no match ip next hop prefix list */
332 route_map_no_match_ip_next_hop_prefix_list_hook (int (*func
) (struct vty
*vty
,
333 struct route_map_index
*index
,
336 route_map_event_t type
))
338 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
= func
;
341 /* match ipv6 address */
343 route_map_match_ipv6_address_hook (int (*func
) (struct vty
*vty
,
344 struct route_map_index
*index
,
347 route_map_event_t type
))
349 rmap_match_set_hook
.match_ipv6_address
= func
;
352 /* no match ipv6 address */
354 route_map_no_match_ipv6_address_hook (int (*func
) (struct vty
*vty
,
355 struct route_map_index
*index
,
358 route_map_event_t type
))
360 rmap_match_set_hook
.no_match_ipv6_address
= func
;
364 /* match ipv6 address prefix list */
366 route_map_match_ipv6_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
367 struct route_map_index
*index
,
370 route_map_event_t type
))
372 rmap_match_set_hook
.match_ipv6_address_prefix_list
= func
;
375 /* no match ipv6 address prefix list */
377 route_map_no_match_ipv6_address_prefix_list_hook (int (*func
) (struct vty
*vty
,
378 struct route_map_index
*index
,
381 route_map_event_t type
))
383 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
= func
;
388 route_map_match_metric_hook (int (*func
) (struct vty
*vty
,
389 struct route_map_index
*index
,
392 route_map_event_t type
))
394 rmap_match_set_hook
.match_metric
= func
;
397 /* no match metric */
399 route_map_no_match_metric_hook (int (*func
) (struct vty
*vty
,
400 struct route_map_index
*index
,
403 route_map_event_t type
))
405 rmap_match_set_hook
.no_match_metric
= func
;
410 route_map_match_tag_hook (int (*func
) (struct vty
*vty
,
411 struct route_map_index
*index
,
414 route_map_event_t type
))
416 rmap_match_set_hook
.match_tag
= func
;
421 route_map_no_match_tag_hook (int (*func
) (struct vty
*vty
,
422 struct route_map_index
*index
,
425 route_map_event_t type
))
427 rmap_match_set_hook
.no_match_tag
= func
;
432 route_map_set_ip_nexthop_hook (int (*func
) (struct vty
*vty
,
433 struct route_map_index
*index
,
437 rmap_match_set_hook
.set_ip_nexthop
= func
;
440 /* no set ip nexthop */
442 route_map_no_set_ip_nexthop_hook (int (*func
) (struct vty
*vty
,
443 struct route_map_index
*index
,
447 rmap_match_set_hook
.no_set_ip_nexthop
= func
;
450 /* set ipv6 nexthop local */
452 route_map_set_ipv6_nexthop_local_hook (int (*func
) (struct vty
*vty
,
453 struct route_map_index
*index
,
457 rmap_match_set_hook
.set_ipv6_nexthop_local
= func
;
460 /* no set ipv6 nexthop local */
462 route_map_no_set_ipv6_nexthop_local_hook (int (*func
) (struct vty
*vty
,
463 struct route_map_index
*index
,
467 rmap_match_set_hook
.no_set_ipv6_nexthop_local
= func
;
472 route_map_set_metric_hook (int (*func
) (struct vty
*vty
,
473 struct route_map_index
*index
,
477 rmap_match_set_hook
.set_metric
= func
;
482 route_map_no_set_metric_hook (int (*func
) (struct vty
*vty
,
483 struct route_map_index
*index
,
487 rmap_match_set_hook
.no_set_metric
= func
;
492 route_map_set_tag_hook (int (*func
) (struct vty
*vty
,
493 struct route_map_index
*index
,
497 rmap_match_set_hook
.set_tag
= func
;
502 route_map_no_set_tag_hook (int (*func
) (struct vty
*vty
,
503 struct route_map_index
*index
,
507 rmap_match_set_hook
.no_set_tag
= func
;
511 generic_match_add (struct vty
*vty
, struct route_map_index
*index
,
512 const char *command
, const char *arg
,
513 route_map_event_t type
)
517 ret
= route_map_add_match (index
, command
, arg
);
522 case RMAP_RULE_MISSING
:
523 vty_out (vty
, "%% Can't find rule.%s", VTY_NEWLINE
);
525 case RMAP_COMPILE_ERROR
:
526 vty_out (vty
, "%% Argument is malformed.%s", VTY_NEWLINE
);
531 if (type
!= RMAP_EVENT_MATCH_ADDED
)
533 route_map_upd8_dependency (type
, arg
, index
->map
->name
);
539 generic_match_delete (struct vty
*vty
, struct route_map_index
*index
,
540 const char *command
, const char *arg
,
541 route_map_event_t type
)
544 char *dep_name
= NULL
;
546 char *rmap_name
= NULL
;
548 if (type
!= RMAP_EVENT_MATCH_DELETED
)
550 /* ignore the mundane, the types without any dependency */
553 if ((tmpstr
= route_map_get_match_arg(index
, command
)) != NULL
)
554 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
558 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
560 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
563 ret
= route_map_delete_match (index
, command
, dep_name
);
568 case RMAP_RULE_MISSING
:
569 vty_out (vty
, "%% BGP Can't find rule.%s", VTY_NEWLINE
);
571 case RMAP_COMPILE_ERROR
:
572 vty_out (vty
, "%% BGP Argument is malformed.%s", VTY_NEWLINE
);
576 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
578 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
582 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
583 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
586 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
588 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
594 generic_set_add (struct vty
*vty
, struct route_map_index
*index
,
595 const char *command
, const char *arg
)
599 ret
= route_map_add_set (index
, command
, arg
);
604 case RMAP_RULE_MISSING
:
605 vty_out (vty
, "%% Can't find rule.%s", VTY_NEWLINE
);
607 case RMAP_COMPILE_ERROR
:
608 vty_out (vty
, "%% Argument is malformed.%s", VTY_NEWLINE
);
616 generic_set_delete (struct vty
*vty
, struct route_map_index
*index
,
617 const char *command
, const char *arg
)
621 ret
= route_map_delete_set (index
, command
, arg
);
626 case RMAP_RULE_MISSING
:
627 vty_out (vty
, "%% Can't find rule.%s", VTY_NEWLINE
);
629 case RMAP_COMPILE_ERROR
:
630 vty_out (vty
, "%% Argument is malformed.%s", VTY_NEWLINE
);
638 /* Route map rule. This rule has both `match' rule and `set' rule. */
639 struct route_map_rule
642 struct route_map_rule_cmd
*cmd
;
644 /* For pretty printing. */
647 /* Pre-compiled match rule. */
651 struct route_map_rule
*next
;
652 struct route_map_rule
*prev
;
655 /* Making route map list. */
656 struct route_map_list
658 struct route_map
*head
;
659 struct route_map
*tail
;
661 void (*add_hook
) (const char *);
662 void (*delete_hook
) (const char *);
663 void (*event_hook
) (route_map_event_t
, const char *);
666 /* Master list of route map. */
667 static struct route_map_list route_map_master
= { NULL
, NULL
, NULL
, NULL
, NULL
};
668 struct hash
*route_map_master_hash
= NULL
;
671 route_map_hash_key_make (void *p
)
673 const struct route_map
*map
= p
;
674 return string_hash_make (map
->name
);
678 route_map_hash_cmp(const void *p1
, const void *p2
)
680 const struct route_map
*map1
= p1
;
681 const struct route_map
*map2
= p2
;
683 if (map1
->deleted
== map2
->deleted
)
685 if (map1
->name
&& map2
->name
)
687 if (!strcmp (map1
->name
, map2
->name
))
692 else if (!map1
->name
&& !map2
->name
)
701 enum route_map_upd8_type
707 /* all possible route-map dependency types */
708 enum route_map_dep_type
710 ROUTE_MAP_DEP_RMAP
= 1,
712 ROUTE_MAP_DEP_ECLIST
,
714 ROUTE_MAP_DEP_ASPATH
,
715 ROUTE_MAP_DEP_FILTER
,
722 struct hash
*dep_rmap_hash
;
723 struct hash
*this_hash
; /* ptr to the hash structure this is part of */
726 /* Hashes maintaining dependency between various sublists used by route maps */
727 struct hash
*route_map_dep_hash
[ROUTE_MAP_DEP_MAX
];
729 static unsigned int route_map_dep_hash_make_key (void *p
);
730 static int route_map_dep_hash_cmp (const void *p1
, const void *p2
);
731 static void route_map_clear_all_references (char *rmap_name
);
732 static void route_map_rule_delete (struct route_map_rule_list
*,
733 struct route_map_rule
*);
734 static int rmap_debug
= 0;
737 route_map_index_delete (struct route_map_index
*, int);
739 /* New route map allocation. Please note route map's name must be
741 static struct route_map
*
742 route_map_new (const char *name
)
744 struct route_map
*new;
746 new = XCALLOC (MTYPE_ROUTE_MAP
, sizeof (struct route_map
));
747 new->name
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, name
);
748 QOBJ_REG (new, route_map
);
752 /* Add new name to route_map. */
753 static struct route_map
*
754 route_map_add (const char *name
)
756 struct route_map
*map
;
757 struct route_map_list
*list
;
759 map
= route_map_new (name
);
760 list
= &route_map_master
;
762 /* Add map to the hash */
763 hash_get(route_map_master_hash
, map
, hash_alloc_intern
);
765 /* Add new entry to the head of the list to match how it is added in the
766 * hash table. This is to ensure that if the same route-map has been
767 * created more than once and then marked for deletion (which can happen
768 * if prior deletions haven't completed as BGP hasn't yet done the
769 * route-map processing), the order of the entities is the same in both
770 * the list and the hash table. Otherwise, since there is nothing to
771 * distinguish between the two entries, the wrong entry could get freed.
772 * TODO: This needs to be re-examined to handle it better - e.g., revive
773 * a deleted entry if the route-map is created again.
776 map
->next
= list
->head
;
778 list
->head
->prev
= map
;
784 if (route_map_master
.add_hook
)
786 (*route_map_master
.add_hook
) (name
);
787 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_ADDED
);
792 /* this is supposed to be called post processing by
793 * the delete hook function. Don't invoke delete_hook
794 * again in this routine.
797 route_map_free_map (struct route_map
*map
)
799 struct route_map_list
*list
;
800 struct route_map_index
*index
;
802 while ((index
= map
->head
) != NULL
)
803 route_map_index_delete (index
, 0);
805 list
= &route_map_master
;
812 map
->next
->prev
= map
->prev
;
814 list
->tail
= map
->prev
;
817 map
->prev
->next
= map
->next
;
819 list
->head
= map
->next
;
821 hash_release(route_map_master_hash
, map
);
822 XFREE (MTYPE_ROUTE_MAP_NAME
, map
->name
);
823 XFREE (MTYPE_ROUTE_MAP
, map
);
827 /* Route map delete from list. */
829 route_map_delete (struct route_map
*map
)
831 struct route_map_index
*index
;
834 while ((index
= map
->head
) != NULL
)
835 route_map_index_delete (index
, 0);
840 /* Clear all dependencies */
841 route_map_clear_all_references(name
);
843 /* Execute deletion hook. */
844 if (route_map_master
.delete_hook
)
846 (*route_map_master
.delete_hook
) (name
);
847 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_DELETED
);
850 if (!map
->to_be_processed
)
852 route_map_free_map (map
);
856 /* Lookup route map by route map name string. */
858 route_map_lookup_by_name (const char *name
)
860 struct route_map
*map
;
861 struct route_map tmp_map
;
866 // map.deleted is 0 via memset
867 memset(&tmp_map
, 0, sizeof(struct route_map
));
868 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
869 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
870 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
875 route_map_mark_updated (const char *name
, int del_later
)
877 struct route_map
*map
;
879 struct route_map tmp_map
;
884 map
= route_map_lookup_by_name(name
);
886 /* If we did not find the routemap with deleted=0 try again
891 memset(&tmp_map
, 0, sizeof(struct route_map
));
892 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
894 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
895 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
900 map
->to_be_processed
= 1;
908 route_map_clear_updated (struct route_map
*map
)
914 map
->to_be_processed
= 0;
916 route_map_free_map(map
);
922 /* Lookup route map. If there isn't route map create one and return
924 static struct route_map
*
925 route_map_get (const char *name
)
927 struct route_map
*map
;
929 map
= route_map_lookup_by_name (name
);
931 map
= route_map_add (name
);
937 route_map_walk_update_list (int (*route_map_update_fn
) (char *name
))
939 struct route_map
*node
;
940 struct route_map
*nnode
= NULL
;
942 for (node
= route_map_master
.head
; node
; node
= nnode
)
944 if (node
->to_be_processed
)
946 /* DD: Should we add any thread yield code here */
947 route_map_update_fn(node
->name
);
949 route_map_clear_updated(node
);
956 /* Return route map's type string. */
958 route_map_type_str (enum route_map_type type
)
975 route_map_empty (struct route_map
*map
)
977 if (map
->head
== NULL
&& map
->tail
== NULL
)
985 vty_show_route_map_entry (struct vty
*vty
, struct route_map
*map
)
987 struct route_map_index
*index
;
988 struct route_map_rule
*rule
;
990 /* Print the name of the protocol */
992 vty_out (vty
, "%s", zlog_proto_names
[zlog_default
->protocol
]);
993 if (zlog_default
->instance
)
994 vty_out (vty
, " %d", zlog_default
->instance
);
995 vty_out (vty
, ":%s", VTY_NEWLINE
);
997 for (index
= map
->head
; index
; index
= index
->next
)
999 vty_out (vty
, "route-map %s, %s, sequence %d%s",
1000 map
->name
, route_map_type_str (index
->type
),
1001 index
->pref
, VTY_NEWLINE
);
1004 if (index
->description
)
1005 vty_out (vty
, " Description:%s %s%s", VTY_NEWLINE
,
1006 index
->description
, VTY_NEWLINE
);
1009 vty_out (vty
, " Match clauses:%s", VTY_NEWLINE
);
1010 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1011 vty_out (vty
, " %s %s%s",
1012 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
1014 vty_out (vty
, " Set clauses:%s", VTY_NEWLINE
);
1015 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1016 vty_out (vty
, " %s %s%s",
1017 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
1020 vty_out (vty
, " Call clause:%s", VTY_NEWLINE
);
1022 vty_out (vty
, " Call %s%s", index
->nextrm
, VTY_NEWLINE
);
1025 vty_out (vty
, " Action:%s", VTY_NEWLINE
);
1026 if (index
->exitpolicy
== RMAP_GOTO
)
1027 vty_out (vty
, " Goto %d%s", index
->nextpref
, VTY_NEWLINE
);
1028 else if (index
->exitpolicy
== RMAP_NEXT
)
1029 vty_out (vty
, " Continue to next entry%s", VTY_NEWLINE
);
1030 else if (index
->exitpolicy
== RMAP_EXIT
)
1031 vty_out (vty
, " Exit routemap%s", VTY_NEWLINE
);
1036 vty_show_route_map (struct vty
*vty
, const char *name
)
1038 struct route_map
*map
;
1042 map
= route_map_lookup_by_name (name
);
1046 vty_show_route_map_entry (vty
, map
);
1052 vty_out (vty
, "%s", zlog_proto_names
[zlog_default
->protocol
]);
1053 if (zlog_default
->instance
)
1054 vty_out (vty
, " %d", zlog_default
->instance
);
1055 vty_out (vty
, ": 'route-map %s' not found%s", name
, VTY_NEWLINE
);
1061 for (map
= route_map_master
.head
; map
; map
= map
->next
)
1063 vty_show_route_map_entry (vty
, map
);
1069 /* New route map allocation. Please note route map's name must be
1071 static struct route_map_index
*
1072 route_map_index_new (void)
1074 struct route_map_index
*new;
1076 new = XCALLOC (MTYPE_ROUTE_MAP_INDEX
, sizeof (struct route_map_index
));
1077 new->exitpolicy
= RMAP_EXIT
; /* Default to Cisco-style */
1078 QOBJ_REG (new, route_map_index
);
1082 /* Free route map index. */
1084 route_map_index_delete (struct route_map_index
*index
, int notify
)
1086 struct route_map_rule
*rule
;
1090 /* Free route match. */
1091 while ((rule
= index
->match_list
.head
) != NULL
)
1092 route_map_rule_delete (&index
->match_list
, rule
);
1094 /* Free route set. */
1095 while ((rule
= index
->set_list
.head
) != NULL
)
1096 route_map_rule_delete (&index
->set_list
, rule
);
1098 /* Remove index from route map list. */
1100 index
->next
->prev
= index
->prev
;
1102 index
->map
->tail
= index
->prev
;
1105 index
->prev
->next
= index
->next
;
1107 index
->map
->head
= index
->next
;
1109 /* Free 'char *nextrm' if not NULL */
1111 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
1113 /* Execute event hook. */
1114 if (route_map_master
.event_hook
&& notify
)
1116 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_DELETED
,
1118 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1120 XFREE (MTYPE_ROUTE_MAP_INDEX
, index
);
1123 /* Lookup index from route map. */
1124 static struct route_map_index
*
1125 route_map_index_lookup (struct route_map
*map
, enum route_map_type type
,
1128 struct route_map_index
*index
;
1130 for (index
= map
->head
; index
; index
= index
->next
)
1131 if ((index
->type
== type
|| type
== RMAP_ANY
)
1132 && index
->pref
== pref
)
1137 /* Add new index to route map. */
1138 static struct route_map_index
*
1139 route_map_index_add (struct route_map
*map
, enum route_map_type type
,
1142 struct route_map_index
*index
;
1143 struct route_map_index
*point
;
1145 /* Allocate new route map inex. */
1146 index
= route_map_index_new ();
1151 /* Compare preference. */
1152 for (point
= map
->head
; point
; point
= point
->next
)
1153 if (point
->pref
>= pref
)
1156 if (map
->head
== NULL
)
1158 map
->head
= map
->tail
= index
;
1160 else if (point
== NULL
)
1162 index
->prev
= map
->tail
;
1163 map
->tail
->next
= index
;
1166 else if (point
== map
->head
)
1168 index
->next
= map
->head
;
1169 map
->head
->prev
= index
;
1174 index
->next
= point
;
1175 index
->prev
= point
->prev
;
1177 point
->prev
->next
= index
;
1178 point
->prev
= index
;
1181 /* Execute event hook. */
1182 if (route_map_master
.event_hook
)
1184 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_ADDED
,
1186 route_map_notify_dependencies (map
->name
, RMAP_EVENT_CALL_ADDED
);
1191 /* Get route map index. */
1192 static struct route_map_index
*
1193 route_map_index_get (struct route_map
*map
, enum route_map_type type
,
1196 struct route_map_index
*index
;
1198 index
= route_map_index_lookup (map
, RMAP_ANY
, pref
);
1199 if (index
&& index
->type
!= type
)
1201 /* Delete index from route map. */
1202 route_map_index_delete (index
, 1);
1206 index
= route_map_index_add (map
, type
, pref
);
1210 /* New route map rule */
1211 static struct route_map_rule
*
1212 route_map_rule_new (void)
1214 struct route_map_rule
*new;
1216 new = XCALLOC (MTYPE_ROUTE_MAP_RULE
, sizeof (struct route_map_rule
));
1220 /* Install rule command to the match list. */
1222 route_map_install_match (struct route_map_rule_cmd
*cmd
)
1224 vector_set (route_match_vec
, cmd
);
1227 /* Install rule command to the set list. */
1229 route_map_install_set (struct route_map_rule_cmd
*cmd
)
1231 vector_set (route_set_vec
, cmd
);
1234 /* Lookup rule command from match list. */
1235 static struct route_map_rule_cmd
*
1236 route_map_lookup_match (const char *name
)
1239 struct route_map_rule_cmd
*rule
;
1241 for (i
= 0; i
< vector_active (route_match_vec
); i
++)
1242 if ((rule
= vector_slot (route_match_vec
, i
)) != NULL
)
1243 if (strcmp (rule
->str
, name
) == 0)
1248 /* Lookup rule command from set list. */
1249 static struct route_map_rule_cmd
*
1250 route_map_lookup_set (const char *name
)
1253 struct route_map_rule_cmd
*rule
;
1255 for (i
= 0; i
< vector_active (route_set_vec
); i
++)
1256 if ((rule
= vector_slot (route_set_vec
, i
)) != NULL
)
1257 if (strcmp (rule
->str
, name
) == 0)
1262 /* Add match and set rule to rule list. */
1264 route_map_rule_add (struct route_map_rule_list
*list
,
1265 struct route_map_rule
*rule
)
1268 rule
->prev
= list
->tail
;
1270 list
->tail
->next
= rule
;
1276 /* Delete rule from rule list. */
1278 route_map_rule_delete (struct route_map_rule_list
*list
,
1279 struct route_map_rule
*rule
)
1281 if (rule
->cmd
->func_free
)
1282 (*rule
->cmd
->func_free
) (rule
->value
);
1285 XFREE (MTYPE_ROUTE_MAP_RULE_STR
, rule
->rule_str
);
1288 rule
->next
->prev
= rule
->prev
;
1290 list
->tail
= rule
->prev
;
1292 rule
->prev
->next
= rule
->next
;
1294 list
->head
= rule
->next
;
1296 XFREE (MTYPE_ROUTE_MAP_RULE
, rule
);
1299 /* strcmp wrapper function which don't crush even argument is NULL. */
1301 rulecmp (const char *dst
, const char *src
)
1315 return strcmp (dst
, src
);
1320 /* Use this to return the already specified argument for this match. This is
1321 * useful to get the specified argument with a route map match rule when the
1322 * rule is being deleted and the argument is not provided.
1325 route_map_get_match_arg(struct route_map_index
*index
, const char *match_name
)
1327 struct route_map_rule
*rule
;
1328 struct route_map_rule_cmd
*cmd
;
1330 /* First lookup rule for add match statement. */
1331 cmd
= route_map_lookup_match (match_name
);
1335 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1336 if (rule
->cmd
== cmd
&& rule
->rule_str
!= NULL
)
1337 return (rule
->rule_str
);
1342 /* Add match statement to route map. */
1344 route_map_add_match (struct route_map_index
*index
, const char *match_name
,
1345 const char *match_arg
)
1347 struct route_map_rule
*rule
;
1348 struct route_map_rule
*next
;
1349 struct route_map_rule_cmd
*cmd
;
1353 /* First lookup rule for add match statement. */
1354 cmd
= route_map_lookup_match (match_name
);
1356 return RMAP_RULE_MISSING
;
1358 /* Next call compile function for this match statement. */
1359 if (cmd
->func_compile
)
1361 compile
= (*cmd
->func_compile
)(match_arg
);
1362 if (compile
== NULL
)
1363 return RMAP_COMPILE_ERROR
;
1368 /* If argument is completely same ignore it. */
1369 for (rule
= index
->match_list
.head
; rule
; rule
= next
)
1372 if (rule
->cmd
== cmd
)
1374 route_map_rule_delete (&index
->match_list
, rule
);
1379 /* Add new route map match rule. */
1380 rule
= route_map_rule_new ();
1382 rule
->value
= compile
;
1384 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, match_arg
);
1386 rule
->rule_str
= NULL
;
1388 /* Add new route match rule to linked list. */
1389 route_map_rule_add (&index
->match_list
, rule
);
1391 /* Execute event hook. */
1392 if (route_map_master
.event_hook
)
1394 (*route_map_master
.event_hook
) (replaced
?
1395 RMAP_EVENT_MATCH_REPLACED
:
1396 RMAP_EVENT_MATCH_ADDED
,
1398 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1404 /* Delete specified route match rule. */
1406 route_map_delete_match (struct route_map_index
*index
, const char *match_name
,
1407 const char *match_arg
)
1409 struct route_map_rule
*rule
;
1410 struct route_map_rule_cmd
*cmd
;
1412 cmd
= route_map_lookup_match (match_name
);
1416 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1417 if (rule
->cmd
== cmd
&&
1418 (rulecmp (rule
->rule_str
, match_arg
) == 0 || match_arg
== NULL
))
1420 route_map_rule_delete (&index
->match_list
, rule
);
1421 /* Execute event hook. */
1422 if (route_map_master
.event_hook
)
1424 (*route_map_master
.event_hook
) (RMAP_EVENT_MATCH_DELETED
,
1426 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1430 /* Can't find matched rule. */
1434 /* Add route-map set statement to the route map. */
1436 route_map_add_set (struct route_map_index
*index
, const char *set_name
,
1437 const char *set_arg
)
1439 struct route_map_rule
*rule
;
1440 struct route_map_rule
*next
;
1441 struct route_map_rule_cmd
*cmd
;
1445 cmd
= route_map_lookup_set (set_name
);
1447 return RMAP_RULE_MISSING
;
1449 /* Next call compile function for this match statement. */
1450 if (cmd
->func_compile
)
1452 compile
= (*cmd
->func_compile
)(set_arg
);
1453 if (compile
== NULL
)
1454 return RMAP_COMPILE_ERROR
;
1459 /* Add by WJL. if old set command of same kind exist, delete it first
1460 to ensure only one set command of same kind exist under a
1462 for (rule
= index
->set_list
.head
; rule
; rule
= next
)
1465 if (rule
->cmd
== cmd
)
1467 route_map_rule_delete (&index
->set_list
, rule
);
1472 /* Add new route map match rule. */
1473 rule
= route_map_rule_new ();
1475 rule
->value
= compile
;
1477 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, set_arg
);
1479 rule
->rule_str
= NULL
;
1481 /* Add new route match rule to linked list. */
1482 route_map_rule_add (&index
->set_list
, rule
);
1484 /* Execute event hook. */
1485 if (route_map_master
.event_hook
)
1487 (*route_map_master
.event_hook
) (replaced
?
1488 RMAP_EVENT_SET_REPLACED
:
1489 RMAP_EVENT_SET_ADDED
,
1491 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1496 /* Delete route map set rule. */
1498 route_map_delete_set (struct route_map_index
*index
, const char *set_name
,
1499 const char *set_arg
)
1501 struct route_map_rule
*rule
;
1502 struct route_map_rule_cmd
*cmd
;
1504 cmd
= route_map_lookup_set (set_name
);
1508 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1509 if ((rule
->cmd
== cmd
) &&
1510 (rulecmp (rule
->rule_str
, set_arg
) == 0 || set_arg
== NULL
))
1512 route_map_rule_delete (&index
->set_list
, rule
);
1513 /* Execute event hook. */
1514 if (route_map_master
.event_hook
)
1516 (*route_map_master
.event_hook
) (RMAP_EVENT_SET_DELETED
,
1518 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1522 /* Can't find matched rule. */
1526 /* Apply route map's each index to the object.
1528 The matrix for a route-map looks like this:
1529 (note, this includes the description for the "NEXT"
1530 and "GOTO" frobs now
1534 permit action | cont
1536 ------------------+---------------
1542 -Apply Set statements, accept route
1543 -If Call statement is present jump to the specified route-map, if it
1544 denies the route we finish.
1545 -If NEXT is specified, goto NEXT statement
1546 -If GOTO is specified, goto the first clause where pref > nextpref
1547 -If nothing is specified, do as Cisco and finish
1549 -Route is denied by route-map.
1553 If we get no matches after we've processed all updates, then the route
1556 Some notes on the new "CALL", "NEXT" and "GOTO"
1557 call WORD - If this clause is matched, then the set statements
1558 are executed and then we jump to route-map 'WORD'. If
1559 this route-map denies the route, we finish, in other case we
1560 do whatever the exit policy (EXIT, NEXT or GOTO) tells.
1561 on-match next - If this clause is matched, then the set statements
1562 are executed and then we drop through to the next clause
1563 on-match goto n - If this clause is matched, then the set statments
1564 are executed and then we goto the nth clause, or the
1565 first clause greater than this. In order to ensure
1566 route-maps *always* exit, you cannot jump backwards.
1569 We need to make sure our route-map processing matches the above
1572 static route_map_result_t
1573 route_map_apply_match (struct route_map_rule_list
*match_list
,
1574 struct prefix
*prefix
, route_map_object_t type
,
1577 route_map_result_t ret
= RMAP_NOMATCH
;
1578 struct route_map_rule
*match
;
1581 /* Check all match rule and if there is no match rule, go to the
1583 if (!match_list
->head
)
1587 for (match
= match_list
->head
; match
; match
= match
->next
)
1589 /* Try each match statement in turn, If any do not return
1590 RMAP_MATCH, return, otherwise continue on to next match
1591 statement. All match statements must match for end-result
1593 ret
= (*match
->cmd
->func_apply
) (match
->value
, prefix
,
1595 if (ret
!= RMAP_MATCH
)
1602 /* Apply route map to the object. */
1604 route_map_apply (struct route_map
*map
, struct prefix
*prefix
,
1605 route_map_object_t type
, void *object
)
1607 static int recursion
= 0;
1609 struct route_map_index
*index
;
1610 struct route_map_rule
*set
;
1612 if (recursion
> RMAP_RECURSION_LIMIT
)
1614 zlog (NULL
, LOG_WARNING
,
1615 "route-map recursion limit (%d) reached, discarding route",
1616 RMAP_RECURSION_LIMIT
);
1618 return RMAP_DENYMATCH
;
1622 return RMAP_DENYMATCH
;
1624 for (index
= map
->head
; index
; index
= index
->next
)
1626 /* Apply this index. */
1627 ret
= route_map_apply_match (&index
->match_list
, prefix
, type
, object
);
1629 /* Now we apply the matrix from above */
1630 if (ret
== RMAP_NOMATCH
)
1631 /* 'cont' from matrix - continue to next route-map sequence */
1633 else if (ret
== RMAP_MATCH
)
1635 if (index
->type
== RMAP_PERMIT
)
1638 /* permit+match must execute sets */
1639 for (set
= index
->set_list
.head
; set
; set
= set
->next
)
1640 ret
= (*set
->cmd
->func_apply
) (set
->value
, prefix
,
1643 /* Call another route-map if available */
1646 struct route_map
*nextrm
=
1647 route_map_lookup_by_name (index
->nextrm
);
1649 if (nextrm
) /* Target route-map found, jump to it */
1652 ret
= route_map_apply (nextrm
, prefix
, type
, object
);
1656 /* If nextrm returned 'deny', finish. */
1657 if (ret
== RMAP_DENYMATCH
)
1661 switch (index
->exitpolicy
)
1669 /* Find the next clause to jump to */
1670 struct route_map_index
*next
= index
->next
;
1671 int nextpref
= index
->nextpref
;
1673 while (next
&& next
->pref
< nextpref
)
1680 /* No clauses match! */
1686 else if (index
->type
== RMAP_DENY
)
1689 return RMAP_DENYMATCH
;
1693 /* Finally route-map does not match at all. */
1694 return RMAP_DENYMATCH
;
1698 route_map_add_hook (void (*func
) (const char *))
1700 route_map_master
.add_hook
= func
;
1704 route_map_delete_hook (void (*func
) (const char *))
1706 route_map_master
.delete_hook
= func
;
1710 route_map_event_hook (void (*func
) (route_map_event_t
, const char *))
1712 route_map_master
.event_hook
= func
;
1715 /* Routines for route map dependency lists and dependency processing */
1717 route_map_rmap_hash_cmp (const void *p1
, const void *p2
)
1719 return (strcmp((const char *)p1
, (const char *)p2
) == 0);
1723 route_map_dep_hash_cmp (const void *p1
, const void *p2
)
1726 return (strcmp (((const struct route_map_dep
*)p1
)->dep_name
, (const char *)p2
) == 0);
1730 route_map_clear_reference(struct hash_backet
*backet
, void *arg
)
1732 struct route_map_dep
*dep
= (struct route_map_dep
*)backet
->data
;
1737 rmap_name
= (char *)hash_release(dep
->dep_rmap_hash
, (void *)arg
);
1740 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1742 if (!dep
->dep_rmap_hash
->count
)
1744 dep
= hash_release(dep
->this_hash
, (void *)dep
->dep_name
);
1745 hash_free(dep
->dep_rmap_hash
);
1746 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1747 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1753 route_map_clear_all_references (char *rmap_name
)
1757 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
1759 hash_iterate(route_map_dep_hash
[i
], route_map_clear_reference
,
1765 route_map_dep_hash_alloc(void *p
)
1767 char *dep_name
= (char *)p
;
1768 struct route_map_dep
*dep_entry
;
1770 dep_entry
= XCALLOC(MTYPE_ROUTE_MAP_DEP
, sizeof(struct route_map_dep
));
1771 dep_entry
->dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1772 dep_entry
->dep_rmap_hash
= hash_create(route_map_dep_hash_make_key
,
1773 route_map_rmap_hash_cmp
);
1774 dep_entry
->this_hash
= NULL
;
1776 return((void *)dep_entry
);
1780 route_map_name_hash_alloc(void *p
)
1782 return((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME
, (const char *)p
));
1786 route_map_dep_hash_make_key (void *p
)
1788 return (string_hash_make((char *)p
));
1792 route_map_print_dependency (struct hash_backet
*backet
, void *data
)
1794 char *rmap_name
= (char *)backet
->data
;
1795 char *dep_name
= (char *)data
;
1798 zlog_debug("%s: Dependency for %s: %s", __FUNCTION__
, dep_name
, rmap_name
);
1802 route_map_dep_update (struct hash
*dephash
, const char *dep_name
,
1803 const char *rmap_name
,
1804 route_map_event_t type
)
1806 struct route_map_dep
*dep
= NULL
;
1808 char *dname
, *rname
;
1811 dname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1812 rname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1816 case RMAP_EVENT_PLIST_ADDED
:
1817 case RMAP_EVENT_CLIST_ADDED
:
1818 case RMAP_EVENT_ECLIST_ADDED
:
1819 case RMAP_EVENT_ASLIST_ADDED
:
1820 case RMAP_EVENT_CALL_ADDED
:
1821 case RMAP_EVENT_FILTER_ADDED
:
1823 zlog_debug("%s: Adding dependency for %s in %s", __FUNCTION__
,
1824 dep_name
, rmap_name
);
1825 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
,
1826 route_map_dep_hash_alloc
);
1832 if (!dep
->this_hash
)
1833 dep
->this_hash
= dephash
;
1835 hash_get(dep
->dep_rmap_hash
, rname
, route_map_name_hash_alloc
);
1837 case RMAP_EVENT_PLIST_DELETED
:
1838 case RMAP_EVENT_CLIST_DELETED
:
1839 case RMAP_EVENT_ECLIST_DELETED
:
1840 case RMAP_EVENT_ASLIST_DELETED
:
1841 case RMAP_EVENT_CALL_DELETED
:
1842 case RMAP_EVENT_FILTER_DELETED
:
1844 zlog_debug("%s: Deleting dependency for %s in %s", __FUNCTION__
,
1845 dep_name
, rmap_name
);
1846 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
, NULL
);
1851 ret_map_name
= (char *)hash_release(dep
->dep_rmap_hash
, rname
);
1853 XFREE(MTYPE_ROUTE_MAP_NAME
, ret_map_name
);
1855 if (!dep
->dep_rmap_hash
->count
)
1857 dep
= hash_release(dephash
, dname
);
1858 hash_free(dep
->dep_rmap_hash
);
1859 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1860 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1871 hash_iterate (dep
->dep_rmap_hash
, route_map_print_dependency
, dname
);
1875 XFREE(MTYPE_ROUTE_MAP_NAME
, rname
);
1876 XFREE(MTYPE_ROUTE_MAP_NAME
, dname
);
1880 static struct hash
*
1881 route_map_get_dep_hash (route_map_event_t event
)
1883 struct hash
*upd8_hash
= NULL
;
1887 case RMAP_EVENT_PLIST_ADDED
:
1888 case RMAP_EVENT_PLIST_DELETED
:
1889 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_PLIST
];
1891 case RMAP_EVENT_CLIST_ADDED
:
1892 case RMAP_EVENT_CLIST_DELETED
:
1893 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_CLIST
];
1895 case RMAP_EVENT_ECLIST_ADDED
:
1896 case RMAP_EVENT_ECLIST_DELETED
:
1897 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ECLIST
];
1899 case RMAP_EVENT_ASLIST_ADDED
:
1900 case RMAP_EVENT_ASLIST_DELETED
:
1901 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ASPATH
];
1903 case RMAP_EVENT_CALL_ADDED
:
1904 case RMAP_EVENT_CALL_DELETED
:
1905 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_RMAP
];
1907 case RMAP_EVENT_FILTER_ADDED
:
1908 case RMAP_EVENT_FILTER_DELETED
:
1909 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_FILTER
];
1919 route_map_process_dependency (struct hash_backet
*backet
, void *data
)
1922 route_map_event_t type
= (route_map_event_t
)(ptrdiff_t)data
;
1924 rmap_name
= (char *)backet
->data
;
1929 zlog_debug("%s: Notifying %s of dependency", __FUNCTION__
,
1931 if (route_map_master
.event_hook
)
1932 (*route_map_master
.event_hook
) (type
, rmap_name
);
1937 route_map_upd8_dependency (route_map_event_t type
, const char *arg
,
1938 const char *rmap_name
)
1940 struct hash
*upd8_hash
= NULL
;
1942 if ((upd8_hash
= route_map_get_dep_hash(type
)))
1943 route_map_dep_update (upd8_hash
, arg
, rmap_name
, type
);
1947 route_map_notify_dependencies (const char *affected_name
, route_map_event_t event
)
1949 struct route_map_dep
*dep
;
1950 struct hash
*upd8_hash
;
1956 name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, affected_name
);
1958 if ((upd8_hash
= route_map_get_dep_hash(event
)) == NULL
)
1960 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1964 dep
= (struct route_map_dep
*)hash_get (upd8_hash
, name
,
1968 if (!dep
->this_hash
)
1969 dep
->this_hash
= upd8_hash
;
1971 hash_iterate (dep
->dep_rmap_hash
, route_map_process_dependency
, (void *)event
);
1974 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1978 /* VTY related functions. */
1979 DEFUN (match_interface
,
1980 match_interface_cmd
,
1981 "match interface WORD",
1983 "match first hop interface of route\n"
1987 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
1989 if (rmap_match_set_hook
.match_interface
)
1990 return rmap_match_set_hook
.match_interface (vty
, index
, "interface", argv
[idx_word
]->arg
, RMAP_EVENT_MATCH_ADDED
);
1994 DEFUN (no_match_interface
,
1995 no_match_interface_cmd
,
1996 "no match interface [INTERFACE]",
1999 "Match first hop interface of route\n"
2002 char *iface
= (argc
== 4) ? argv
[3]->arg
: NULL
;
2003 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2005 if (rmap_match_set_hook
.no_match_interface
)
2006 return rmap_match_set_hook
.no_match_interface (vty
, index
, "interface", iface
, RMAP_EVENT_MATCH_DELETED
);
2011 DEFUN (match_ip_address
,
2012 match_ip_address_cmd
,
2013 "match ip address <(1-199)|(1300-2699)|WORD>",
2016 "Match address of route\n"
2017 "IP access-list number\n"
2018 "IP access-list number (expanded range)\n"
2019 "IP Access-list name\n")
2022 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2024 if (rmap_match_set_hook
.match_ip_address
)
2025 return rmap_match_set_hook
.match_ip_address (vty
, index
, "ip address", argv
[idx_acl
]->arg
,
2026 RMAP_EVENT_FILTER_ADDED
);
2031 DEFUN (no_match_ip_address
,
2032 no_match_ip_address_cmd
,
2033 "no match ip address [<(1-199)|(1300-2699)|WORD>]",
2037 "Match address of route\n"
2038 "IP access-list number\n"
2039 "IP access-list number (expanded range)\n"
2040 "IP Access-list name\n")
2043 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2045 if (rmap_match_set_hook
.no_match_ip_address
)
2047 if (argc
<= idx_word
)
2048 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", NULL
,
2049 RMAP_EVENT_FILTER_DELETED
);
2050 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", argv
[idx_word
]->arg
,
2051 RMAP_EVENT_FILTER_DELETED
);
2057 DEFUN (match_ip_address_prefix_list
,
2058 match_ip_address_prefix_list_cmd
,
2059 "match ip address prefix-list WORD",
2062 "Match address of route\n"
2063 "Match entries of prefix-lists\n"
2064 "IP prefix-list name\n")
2067 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2069 if (rmap_match_set_hook
.match_ip_address_prefix_list
)
2070 return rmap_match_set_hook
.match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2071 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2076 DEFUN (no_match_ip_address_prefix_list
,
2077 no_match_ip_address_prefix_list_cmd
,
2078 "no match ip address prefix-list [WORD]",
2082 "Match address of route\n"
2083 "Match entries of prefix-lists\n"
2084 "IP prefix-list name\n")
2087 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2089 if (rmap_match_set_hook
.no_match_ip_address_prefix_list
)
2091 if (argc
<= idx_word
)
2092 return rmap_match_set_hook
.no_match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2093 NULL
, RMAP_EVENT_PLIST_DELETED
);
2094 return rmap_match_set_hook
.no_match_ip_address_prefix_list(vty
, index
, "ip address prefix-list",
2095 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2101 DEFUN (match_ip_next_hop
,
2102 match_ip_next_hop_cmd
,
2103 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
2106 "Match next-hop address of route\n"
2107 "IP access-list number\n"
2108 "IP access-list number (expanded range)\n"
2109 "IP Access-list name\n")
2112 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2114 if (rmap_match_set_hook
.match_ip_next_hop
)
2115 return rmap_match_set_hook
.match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_acl
]->arg
,
2116 RMAP_EVENT_FILTER_ADDED
);
2121 DEFUN (no_match_ip_next_hop
,
2122 no_match_ip_next_hop_cmd
,
2123 "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]",
2127 "Match next-hop address of route\n"
2128 "IP access-list number\n"
2129 "IP access-list number (expanded range)\n"
2130 "IP Access-list name\n")
2133 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2135 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2137 if (argc
<= idx_word
)
2138 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", NULL
,
2139 RMAP_EVENT_FILTER_DELETED
);
2140 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_word
]->arg
,
2141 RMAP_EVENT_FILTER_DELETED
);
2147 DEFUN (match_ip_next_hop_prefix_list
,
2148 match_ip_next_hop_prefix_list_cmd
,
2149 "match ip next-hop prefix-list WORD",
2152 "Match next-hop address of route\n"
2153 "Match entries of prefix-lists\n"
2154 "IP prefix-list name\n")
2157 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2159 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
)
2160 return rmap_match_set_hook
.match_ip_next_hop_prefix_list (vty
, index
, "ip next-hop prefix-list",
2161 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2165 DEFUN (no_match_ip_next_hop_prefix_list
,
2166 no_match_ip_next_hop_prefix_list_cmd
,
2167 "no match ip next-hop prefix-list [WORD]",
2171 "Match next-hop address of route\n"
2172 "Match entries of prefix-lists\n"
2173 "IP prefix-list name\n")
2176 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2178 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2180 if (argc
<= idx_word
)
2181 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2182 NULL
, RMAP_EVENT_PLIST_DELETED
);
2183 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2184 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2190 DEFUN (match_ipv6_address
,
2191 match_ipv6_address_cmd
,
2192 "match ipv6 address WORD",
2195 "Match IPv6 address of route\n"
2196 "IPv6 access-list name\n")
2199 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2201 if (rmap_match_set_hook
.match_ipv6_address
)
2202 return rmap_match_set_hook
.match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2203 RMAP_EVENT_FILTER_ADDED
);
2207 DEFUN (no_match_ipv6_address
,
2208 no_match_ipv6_address_cmd
,
2209 "no match ipv6 address WORD",
2213 "Match IPv6 address of route\n"
2214 "IPv6 access-list name\n")
2217 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2219 if (rmap_match_set_hook
.no_match_ipv6_address
)
2220 return rmap_match_set_hook
.no_match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2221 RMAP_EVENT_FILTER_DELETED
);
2226 DEFUN (match_ipv6_address_prefix_list
,
2227 match_ipv6_address_prefix_list_cmd
,
2228 "match ipv6 address prefix-list WORD",
2231 "Match address of route\n"
2232 "Match entries of prefix-lists\n"
2233 "IP prefix-list name\n")
2236 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2238 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
)
2239 return rmap_match_set_hook
.match_ipv6_address_prefix_list (vty
, index
, "ipv6 address prefix-list",
2240 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2244 DEFUN (no_match_ipv6_address_prefix_list
,
2245 no_match_ipv6_address_prefix_list_cmd
,
2246 "no match ipv6 address prefix-list WORD",
2250 "Match address of route\n"
2251 "Match entries of prefix-lists\n"
2252 "IP prefix-list name\n")
2255 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2257 if (rmap_match_set_hook
.no_match_ipv6_address_prefix_list
)
2258 return rmap_match_set_hook
.no_match_ipv6_address_prefix_list(vty
, index
, "ipv6 address prefix-list",
2259 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2264 DEFUN (match_metric
,
2266 "match metric (0-4294967295)",
2268 "Match metric of route\n"
2272 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2274 if (rmap_match_set_hook
.match_metric
)
2275 return rmap_match_set_hook
.match_metric(vty
, index
, "metric", argv
[idx_number
]->arg
,
2276 RMAP_EVENT_MATCH_ADDED
);
2281 DEFUN (no_match_metric
,
2282 no_match_metric_cmd
,
2283 "no match metric [(0-4294967295)]",
2286 "Match metric of route\n"
2290 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2292 if (rmap_match_set_hook
.no_match_metric
)
2294 if (argc
<= idx_number
)
2295 return rmap_match_set_hook
.no_match_metric (vty
, index
, "metric",
2296 NULL
, RMAP_EVENT_MATCH_DELETED
);
2297 return rmap_match_set_hook
.no_match_metric(vty
, index
, "metric",
2298 argv
[idx_number
]->arg
,
2299 RMAP_EVENT_MATCH_DELETED
);
2307 "match tag (1-4294967295)",
2309 "Match tag of route\n"
2313 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2315 if (rmap_match_set_hook
.match_tag
)
2316 return rmap_match_set_hook
.match_tag(vty
, index
, "tag", argv
[idx_number
]->arg
,
2317 RMAP_EVENT_MATCH_ADDED
);
2322 DEFUN (no_match_tag
,
2324 "no match tag [(1-4294967295)]",
2327 "Match tag of route\n"
2330 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2332 if (rmap_match_set_hook
.no_match_tag
)
2333 return rmap_match_set_hook
.no_match_tag (vty
, index
, "tag", argv
[3]->arg
,
2334 RMAP_EVENT_MATCH_DELETED
);
2339 DEFUN (set_ip_nexthop
,
2341 "set ip next-hop A.B.C.D",
2344 "Next hop address\n"
2345 "IP address of next hop\n")
2350 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2352 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
2355 vty_out (vty
, "%% Malformed nexthop address%s", VTY_NEWLINE
);
2358 if (su
.sin
.sin_addr
.s_addr
== 0 ||
2359 IPV4_CLASS_DE(su
.sin
.sin_addr
.s_addr
))
2361 vty_out (vty
, "%% nexthop address cannot be 0.0.0.0, multicast "
2362 "or reserved%s", VTY_NEWLINE
);
2366 if (rmap_match_set_hook
.set_ip_nexthop
)
2367 return rmap_match_set_hook
.set_ip_nexthop(vty
, index
, "ip next-hop", argv
[idx_ipv4
]->arg
);
2372 DEFUN (no_set_ip_nexthop
,
2373 no_set_ip_nexthop_cmd
,
2374 "no set ip next-hop [<peer-address|A.B.C.D>]",
2377 "Next hop address\n"
2378 "Use peer address (for BGP only)\n"
2379 "IP address of next hop\n")
2382 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2384 if (rmap_match_set_hook
.no_set_ip_nexthop
)
2386 if (argc
<= idx_peer
)
2387 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", NULL
);
2388 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", argv
[idx_peer
]->arg
);
2394 DEFUN (set_ipv6_nexthop_local
,
2395 set_ipv6_nexthop_local_cmd
,
2396 "set ipv6 next-hop local X:X::X:X",
2399 "IPv6 next-hop address\n"
2400 "IPv6 local address\n"
2401 "IPv6 address of next hop\n")
2404 struct in6_addr addr
;
2406 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2408 ret
= inet_pton (AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
2411 vty_out (vty
, "%% Malformed nexthop address%s", VTY_NEWLINE
);
2414 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
2416 vty_out (vty
, "%% Invalid link-local nexthop address%s", VTY_NEWLINE
);
2420 if (rmap_match_set_hook
.set_ipv6_nexthop_local
)
2421 return rmap_match_set_hook
.set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[idx_ipv6
]->arg
);
2426 DEFUN (no_set_ipv6_nexthop_local
,
2427 no_set_ipv6_nexthop_local_cmd
,
2428 "no set ipv6 next-hop local [X:X::X:X]",
2432 "IPv6 next-hop address\n"
2433 "IPv6 local address\n"
2434 "IPv6 address of next hop\n")
2437 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2439 if (rmap_match_set_hook
.no_set_ipv6_nexthop_local
)
2441 if (argc
<= idx_ipv6
)
2442 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", NULL
);
2443 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[5]->arg
);
2450 "set metric <(0-4294967295)|rtt|+rtt|-rtt|+metric|-metric>",
2452 "Metric value for destination routing protocol\n"
2454 "Assign round trip time\n"
2455 "Add round trip time\n"
2456 "Subtract round trip time\n"
2458 "Subtract metric\n")
2461 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2463 if (rmap_match_set_hook
.set_metric
)
2464 return rmap_match_set_hook
.set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2469 DEFUN (no_set_metric
,
2471 "no set metric [(0-4294967295)]",
2474 "Metric value for destination routing protocol\n"
2478 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2480 if (rmap_match_set_hook
.no_set_metric
)
2482 if (argc
<= idx_number
)
2483 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", NULL
);
2484 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2492 "set tag (1-4294967295)",
2494 "Tag value for routing protocol\n"
2497 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2500 if (rmap_match_set_hook
.set_tag
)
2501 return rmap_match_set_hook
.set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2508 "no set tag [(1-4294967295)]",
2511 "Tag value for routing protocol\n"
2514 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2517 if (rmap_match_set_hook
.no_set_tag
)
2519 if (argc
<= idx_number
)
2520 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", NULL
);
2521 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2530 "route-map WORD <deny|permit> (1-65535)",
2531 "Create route-map or enter route-map command mode\n"
2533 "Route map denies set operations\n"
2534 "Route map permits set operations\n"
2535 "Sequence to insert to/delete from existing route-map entry\n")
2538 int idx_permit_deny
= 2;
2540 struct route_map
*map
;
2541 struct route_map_index
*index
;
2542 char *endptr
= NULL
;
2543 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2544 unsigned long pref
= strtoul (argv
[idx_number
]->arg
, &endptr
, 10);
2545 const char *mapname
= argv
[idx_word
]->arg
;
2547 /* Get route map. */
2548 map
= route_map_get (mapname
);
2549 index
= route_map_index_get (map
, permit
, pref
);
2551 VTY_PUSH_CONTEXT_COMPAT (RMAP_NODE
, index
);
2555 DEFUN (no_route_map_all
,
2556 no_route_map_all_cmd
,
2557 "no route-map WORD",
2559 "Create route-map or enter route-map command mode\n"
2563 const char *mapname
= argv
[idx_word
]->arg
;
2564 struct route_map
*map
;
2566 map
= route_map_lookup_by_name (mapname
);
2569 vty_out (vty
, "%% Could not find route-map %s%s", mapname
, VTY_NEWLINE
);
2573 route_map_delete (map
);
2578 DEFUN (no_route_map
,
2580 "no route-map WORD <deny|permit> (1-65535)",
2582 "Create route-map or enter route-map command mode\n"
2584 "Route map denies set operations\n"
2585 "Route map permits set operations\n"
2586 "Sequence to insert to/delete from existing route-map entry\n")
2589 int idx_permit_deny
= 3;
2591 struct route_map
*map
;
2592 struct route_map_index
*index
;
2593 char *endptr
= NULL
;
2594 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2595 const char *prefstr
= argv
[idx_number
]->arg
;
2596 const char *mapname
= argv
[idx_word
]->arg
;
2597 unsigned long pref
= strtoul (prefstr
, &endptr
, 10);
2599 /* Existence check. */
2600 map
= route_map_lookup_by_name (mapname
);
2603 vty_out (vty
, "%% Could not find route-map %s%s", mapname
, VTY_NEWLINE
);
2607 /* Lookup route map index. */
2608 index
= route_map_index_lookup (map
, permit
, pref
);
2611 vty_out (vty
, "%% Could not find route-map entry %s %s%s",
2612 mapname
, prefstr
, VTY_NEWLINE
);
2616 /* Delete index from route map. */
2617 route_map_index_delete (index
, 1);
2619 /* If this route rule is the last one, delete route map itself. */
2620 if (route_map_empty (map
))
2621 route_map_delete (map
);
2626 DEFUN (rmap_onmatch_next
,
2627 rmap_onmatch_next_cmd
,
2629 "Exit policy on matches\n"
2632 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2636 if (index
->type
== RMAP_DENY
)
2638 /* Under a deny clause, match means it's finished. No need to set next */
2639 vty_out (vty
, "on-match next not supported under route-map deny%s",
2643 index
->exitpolicy
= RMAP_NEXT
;
2648 DEFUN (no_rmap_onmatch_next
,
2649 no_rmap_onmatch_next_cmd
,
2652 "Exit policy on matches\n"
2655 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2658 index
->exitpolicy
= RMAP_EXIT
;
2663 DEFUN (rmap_onmatch_goto
,
2664 rmap_onmatch_goto_cmd
,
2665 "on-match goto (1-65535)",
2666 "Exit policy on matches\n"
2667 "Goto Clause number\n"
2672 num
= argv
[idx_number
]->arg
;
2675 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2680 if (index
->type
== RMAP_DENY
)
2682 /* Under a deny clause, match means it's finished. No need to go anywhere */
2683 vty_out (vty
, "on-match goto not supported under route-map deny%s",
2689 VTY_GET_INTEGER_RANGE("route-map index", d
, num
, 1, 65535);
2691 d
= index
->pref
+ 1;
2693 if (d
<= index
->pref
)
2695 /* Can't allow you to do that, Dave */
2696 vty_out (vty
, "can't jump backwards in route-maps%s", VTY_NEWLINE
);
2701 index
->exitpolicy
= RMAP_GOTO
;
2702 index
->nextpref
= d
;
2708 DEFUN (no_rmap_onmatch_goto
,
2709 no_rmap_onmatch_goto_cmd
,
2712 "Exit policy on matches\n"
2713 "Goto Clause number\n")
2715 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2718 index
->exitpolicy
= RMAP_EXIT
;
2723 /* Cisco/GNU Zebra compatibility aliases */
2725 DEFUN (rmap_continue
,
2727 "continue (1-65535)",
2728 "Continue on a different entry within the route-map\n"
2729 "Route-map entry sequence number\n")
2731 return rmap_onmatch_goto (self
, vty
, argc
, argv
);
2735 DEFUN (no_rmap_continue
,
2736 no_rmap_continue_cmd
,
2737 "no continue [(1-65535)]",
2739 "Continue on a different entry within the route-map\n"
2740 "Route-map entry sequence number\n")
2742 return no_rmap_onmatch_goto (self
, vty
, argc
, argv
);
2746 DEFUN (rmap_show_name
,
2748 "show route-map [WORD]",
2750 "route-map information\n"
2754 const char *name
= (argc
== 3) ? argv
[idx_word
]->arg
: NULL
;
2755 return vty_show_route_map (vty
, name
);
2761 "Jump to another Route-Map after match+set\n"
2762 "Target route-map name\n")
2765 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2766 const char *rmap
= argv
[idx_word
]->arg
;
2772 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2775 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2777 index
->nextrm
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
2780 /* Execute event hook. */
2781 route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED
,
2787 DEFUN (no_rmap_call
,
2791 "Jump to another Route-Map after match+set\n")
2793 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2797 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2800 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2801 index
->nextrm
= NULL
;
2807 DEFUN (rmap_description
,
2808 rmap_description_cmd
,
2809 "description LINE...",
2810 "Route-map comment\n"
2811 "Comment describing this route-map rule\n")
2814 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2818 if (index
->description
)
2819 XFREE (MTYPE_TMP
, index
->description
);
2820 index
->description
= argv_concat (argv
, argc
, idx_line
);
2825 DEFUN (no_rmap_description
,
2826 no_rmap_description_cmd
,
2829 "Route-map comment\n")
2831 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2835 if (index
->description
)
2836 XFREE (MTYPE_TMP
, index
->description
);
2837 index
->description
= NULL
;
2842 /* Configuration write function. */
2844 route_map_config_write (struct vty
*vty
)
2846 struct route_map
*map
;
2847 struct route_map_index
*index
;
2848 struct route_map_rule
*rule
;
2852 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2853 for (index
= map
->head
; index
; index
= index
->next
)
2856 vty_out (vty
, "!%s", VTY_NEWLINE
);
2860 vty_out (vty
, "route-map %s %s %d%s",
2862 route_map_type_str (index
->type
),
2863 index
->pref
, VTY_NEWLINE
);
2865 if (index
->description
)
2866 vty_out (vty
, " description %s%s", index
->description
, VTY_NEWLINE
);
2868 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
2869 vty_out (vty
, " match %s %s%s", rule
->cmd
->str
,
2870 rule
->rule_str
? rule
->rule_str
: "",
2873 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
2874 vty_out (vty
, " set %s %s%s", rule
->cmd
->str
,
2875 rule
->rule_str
? rule
->rule_str
: "",
2878 vty_out (vty
, " call %s%s", index
->nextrm
, VTY_NEWLINE
);
2879 if (index
->exitpolicy
== RMAP_GOTO
)
2880 vty_out (vty
, " on-match goto %d%s", index
->nextpref
, VTY_NEWLINE
);
2881 if (index
->exitpolicy
== RMAP_NEXT
)
2882 vty_out (vty
," on-match next%s", VTY_NEWLINE
);
2889 /* Route map node structure. */
2890 static struct cmd_node rmap_node
=
2893 "%s(config-route-map)# ",
2897 /* Common route map rules */
2900 route_map_rule_tag_compile (const char *arg
)
2902 unsigned long int tmp
;
2907 tmp
= strtoul(arg
, &endptr
, 0);
2908 if (arg
[0] == '\0' || *endptr
!= '\0' || errno
|| tmp
> ROUTE_TAG_MAX
)
2911 tag
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(*tag
));
2918 route_map_rule_tag_free (void *rule
)
2920 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
2924 route_map_finish (void)
2928 vector_free (route_match_vec
);
2929 route_match_vec
= NULL
;
2930 vector_free (route_set_vec
);
2931 route_set_vec
= NULL
;
2933 /* cleanup route_map */
2934 while (route_map_master
.head
)
2936 struct route_map
*map
= route_map_master
.head
;
2937 map
->to_be_processed
= 0;
2938 route_map_delete (map
);
2941 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2942 hash_free(route_map_dep_hash
[i
]);
2944 hash_free (route_map_master_hash
);
2947 /* Initialization of route map vector. */
2949 route_map_init (void)
2953 /* Make vector for match and set. */
2954 route_match_vec
= vector_init (1);
2955 route_set_vec
= vector_init (1);
2956 route_map_master_hash
= hash_create(route_map_hash_key_make
, route_map_hash_cmp
);
2958 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2959 route_map_dep_hash
[i
] = hash_create(route_map_dep_hash_make_key
,
2960 route_map_dep_hash_cmp
);
2962 /* Install route map top node. */
2963 install_node (&rmap_node
, route_map_config_write
);
2965 /* Install route map commands. */
2966 install_default (RMAP_NODE
);
2967 install_element (CONFIG_NODE
, &route_map_cmd
);
2968 install_element (CONFIG_NODE
, &no_route_map_cmd
);
2969 install_element (CONFIG_NODE
, &no_route_map_all_cmd
);
2971 /* Install the on-match stuff */
2972 install_element (RMAP_NODE
, &route_map_cmd
);
2973 install_element (RMAP_NODE
, &rmap_onmatch_next_cmd
);
2974 install_element (RMAP_NODE
, &no_rmap_onmatch_next_cmd
);
2975 install_element (RMAP_NODE
, &rmap_onmatch_goto_cmd
);
2976 install_element (RMAP_NODE
, &no_rmap_onmatch_goto_cmd
);
2977 install_element (RMAP_NODE
, &rmap_continue_cmd
);
2978 install_element (RMAP_NODE
, &no_rmap_continue_cmd
);
2980 /* Install the continue stuff (ALIAS of on-match). */
2982 /* Install the call stuff. */
2983 install_element (RMAP_NODE
, &rmap_call_cmd
);
2984 install_element (RMAP_NODE
, &no_rmap_call_cmd
);
2986 /* Install description commands. */
2987 install_element (RMAP_NODE
, &rmap_description_cmd
);
2988 install_element (RMAP_NODE
, &no_rmap_description_cmd
);
2990 /* Install show command */
2991 install_element (ENABLE_NODE
, &rmap_show_name_cmd
);
2993 install_element (RMAP_NODE
, &match_interface_cmd
);
2994 install_element (RMAP_NODE
, &no_match_interface_cmd
);
2996 install_element (RMAP_NODE
, &match_ip_address_cmd
);
2997 install_element (RMAP_NODE
, &no_match_ip_address_cmd
);
2999 install_element (RMAP_NODE
, &match_ip_address_prefix_list_cmd
);
3000 install_element (RMAP_NODE
, &no_match_ip_address_prefix_list_cmd
);
3002 install_element (RMAP_NODE
, &match_ip_next_hop_cmd
);
3003 install_element (RMAP_NODE
, &no_match_ip_next_hop_cmd
);
3005 install_element (RMAP_NODE
, &match_ip_next_hop_prefix_list_cmd
);
3006 install_element (RMAP_NODE
, &no_match_ip_next_hop_prefix_list_cmd
);
3008 install_element (RMAP_NODE
, &match_ipv6_address_cmd
);
3009 install_element (RMAP_NODE
, &no_match_ipv6_address_cmd
);
3011 install_element (RMAP_NODE
, &match_ipv6_address_prefix_list_cmd
);
3012 install_element (RMAP_NODE
, &no_match_ipv6_address_prefix_list_cmd
);
3014 install_element (RMAP_NODE
, &match_metric_cmd
);
3015 install_element (RMAP_NODE
, &no_match_metric_cmd
);
3017 install_element (RMAP_NODE
, &match_tag_cmd
);
3018 install_element (RMAP_NODE
, &no_match_tag_cmd
);
3020 install_element (RMAP_NODE
, &set_ip_nexthop_cmd
);
3021 install_element (RMAP_NODE
, &no_set_ip_nexthop_cmd
);
3023 install_element (RMAP_NODE
, &set_ipv6_nexthop_local_cmd
);
3024 install_element (RMAP_NODE
, &no_set_ipv6_nexthop_local_cmd
);
3026 install_element (RMAP_NODE
, &set_metric_cmd
);
3027 install_element (RMAP_NODE
, &no_set_metric_cmd
);
3029 install_element (RMAP_NODE
, &set_tag_cmd
);
3030 install_element (RMAP_NODE
, &no_set_tag_cmd
);