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_outln (vty
, "%% [%s] Can't find rule.", frr_protonameinst
);
526 case RMAP_COMPILE_ERROR
:
527 vty_outln (vty
, "%% [%s] Argument form is unsupported or malformed.",
533 if (type
!= RMAP_EVENT_MATCH_ADDED
)
535 route_map_upd8_dependency (type
, arg
, index
->map
->name
);
541 generic_match_delete (struct vty
*vty
, struct route_map_index
*index
,
542 const char *command
, const char *arg
,
543 route_map_event_t type
)
546 char *dep_name
= NULL
;
548 char *rmap_name
= NULL
;
550 if (type
!= RMAP_EVENT_MATCH_DELETED
)
552 /* ignore the mundane, the types without any dependency */
555 if ((tmpstr
= route_map_get_match_arg(index
, command
)) != NULL
)
556 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
560 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
562 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
565 ret
= route_map_delete_match (index
, command
, dep_name
);
570 case RMAP_RULE_MISSING
:
571 vty_outln (vty
, "%% [%s] Can't find rule.", frr_protonameinst
);
573 case RMAP_COMPILE_ERROR
:
574 vty_outln (vty
, "%% [%s] Argument form is unsupported or malformed.",
579 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
581 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
585 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
586 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
589 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
591 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
597 generic_set_add (struct vty
*vty
, struct route_map_index
*index
,
598 const char *command
, const char *arg
)
602 ret
= route_map_add_set (index
, command
, arg
);
607 case RMAP_RULE_MISSING
:
608 vty_outln (vty
, "%% [%s] Can't find rule.", frr_protonameinst
);
610 case RMAP_COMPILE_ERROR
:
611 vty_outln (vty
, "%% [%s] Argument form is unsupported or malformed.",
620 generic_set_delete (struct vty
*vty
, struct route_map_index
*index
,
621 const char *command
, const char *arg
)
625 ret
= route_map_delete_set (index
, command
, arg
);
630 case RMAP_RULE_MISSING
:
631 vty_outln (vty
, "%% [%s] Can't find rule.", frr_protonameinst
);
633 case RMAP_COMPILE_ERROR
:
634 vty_outln (vty
, "%% [%s] Argument form is unsupported or malformed.",
643 /* Route map rule. This rule has both `match' rule and `set' rule. */
644 struct route_map_rule
647 struct route_map_rule_cmd
*cmd
;
649 /* For pretty printing. */
652 /* Pre-compiled match rule. */
656 struct route_map_rule
*next
;
657 struct route_map_rule
*prev
;
660 /* Making route map list. */
661 struct route_map_list
663 struct route_map
*head
;
664 struct route_map
*tail
;
666 void (*add_hook
) (const char *);
667 void (*delete_hook
) (const char *);
668 void (*event_hook
) (route_map_event_t
, const char *);
671 /* Master list of route map. */
672 static struct route_map_list route_map_master
= { NULL
, NULL
, NULL
, NULL
, NULL
};
673 struct hash
*route_map_master_hash
= NULL
;
676 route_map_hash_key_make (void *p
)
678 const struct route_map
*map
= p
;
679 return string_hash_make (map
->name
);
683 route_map_hash_cmp(const void *p1
, const void *p2
)
685 const struct route_map
*map1
= p1
;
686 const struct route_map
*map2
= p2
;
688 if (map1
->deleted
== map2
->deleted
)
690 if (map1
->name
&& map2
->name
)
692 if (!strcmp (map1
->name
, map2
->name
))
697 else if (!map1
->name
&& !map2
->name
)
706 enum route_map_upd8_type
712 /* all possible route-map dependency types */
713 enum route_map_dep_type
715 ROUTE_MAP_DEP_RMAP
= 1,
717 ROUTE_MAP_DEP_ECLIST
,
718 ROUTE_MAP_DEP_LCLIST
,
720 ROUTE_MAP_DEP_ASPATH
,
721 ROUTE_MAP_DEP_FILTER
,
728 struct hash
*dep_rmap_hash
;
729 struct hash
*this_hash
; /* ptr to the hash structure this is part of */
732 /* Hashes maintaining dependency between various sublists used by route maps */
733 struct hash
*route_map_dep_hash
[ROUTE_MAP_DEP_MAX
];
735 static unsigned int route_map_dep_hash_make_key (void *p
);
736 static int route_map_dep_hash_cmp (const void *p1
, const void *p2
);
737 static void route_map_clear_all_references (char *rmap_name
);
738 static void route_map_rule_delete (struct route_map_rule_list
*,
739 struct route_map_rule
*);
740 static int rmap_debug
= 0;
743 route_map_index_delete (struct route_map_index
*, int);
745 /* New route map allocation. Please note route map's name must be
747 static struct route_map
*
748 route_map_new (const char *name
)
750 struct route_map
*new;
752 new = XCALLOC (MTYPE_ROUTE_MAP
, sizeof (struct route_map
));
753 new->name
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, name
);
754 QOBJ_REG (new, route_map
);
758 /* Add new name to route_map. */
759 static struct route_map
*
760 route_map_add (const char *name
)
762 struct route_map
*map
;
763 struct route_map_list
*list
;
765 map
= route_map_new (name
);
766 list
= &route_map_master
;
768 /* Add map to the hash */
769 hash_get(route_map_master_hash
, map
, hash_alloc_intern
);
771 /* Add new entry to the head of the list to match how it is added in the
772 * hash table. This is to ensure that if the same route-map has been
773 * created more than once and then marked for deletion (which can happen
774 * if prior deletions haven't completed as BGP hasn't yet done the
775 * route-map processing), the order of the entities is the same in both
776 * the list and the hash table. Otherwise, since there is nothing to
777 * distinguish between the two entries, the wrong entry could get freed.
778 * TODO: This needs to be re-examined to handle it better - e.g., revive
779 * a deleted entry if the route-map is created again.
782 map
->next
= list
->head
;
784 list
->head
->prev
= map
;
790 if (route_map_master
.add_hook
)
792 (*route_map_master
.add_hook
) (name
);
793 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_ADDED
);
798 /* this is supposed to be called post processing by
799 * the delete hook function. Don't invoke delete_hook
800 * again in this routine.
803 route_map_free_map (struct route_map
*map
)
805 struct route_map_list
*list
;
806 struct route_map_index
*index
;
811 while ((index
= map
->head
) != NULL
)
812 route_map_index_delete (index
, 0);
814 list
= &route_map_master
;
819 map
->next
->prev
= map
->prev
;
821 list
->tail
= map
->prev
;
824 map
->prev
->next
= map
->next
;
826 list
->head
= map
->next
;
828 hash_release(route_map_master_hash
, map
);
829 XFREE (MTYPE_ROUTE_MAP_NAME
, map
->name
);
830 XFREE (MTYPE_ROUTE_MAP
, map
);
833 /* Route map delete from list. */
835 route_map_delete (struct route_map
*map
)
837 struct route_map_index
*index
;
840 while ((index
= map
->head
) != NULL
)
841 route_map_index_delete (index
, 0);
846 /* Clear all dependencies */
847 route_map_clear_all_references(name
);
849 /* Execute deletion hook. */
850 if (route_map_master
.delete_hook
)
852 (*route_map_master
.delete_hook
) (name
);
853 route_map_notify_dependencies(name
, RMAP_EVENT_CALL_DELETED
);
856 if (!map
->to_be_processed
)
858 route_map_free_map (map
);
862 /* Lookup route map by route map name string. */
864 route_map_lookup_by_name (const char *name
)
866 struct route_map
*map
;
867 struct route_map tmp_map
;
872 // map.deleted is 0 via memset
873 memset(&tmp_map
, 0, sizeof(struct route_map
));
874 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
875 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
876 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
881 route_map_mark_updated (const char *name
, int del_later
)
883 struct route_map
*map
;
885 struct route_map tmp_map
;
890 map
= route_map_lookup_by_name(name
);
892 /* If we did not find the routemap with deleted=0 try again
897 memset(&tmp_map
, 0, sizeof(struct route_map
));
898 tmp_map
.name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, name
);
900 map
= hash_lookup(route_map_master_hash
, &tmp_map
);
901 XFREE(MTYPE_ROUTE_MAP_NAME
, tmp_map
.name
);
906 map
->to_be_processed
= 1;
914 route_map_clear_updated (struct route_map
*map
)
920 map
->to_be_processed
= 0;
922 route_map_free_map(map
);
928 /* Lookup route map. If there isn't route map create one and return
930 static struct route_map
*
931 route_map_get (const char *name
)
933 struct route_map
*map
;
935 map
= route_map_lookup_by_name (name
);
937 map
= route_map_add (name
);
943 route_map_walk_update_list (int (*route_map_update_fn
) (char *name
))
945 struct route_map
*node
;
946 struct route_map
*nnode
= NULL
;
948 for (node
= route_map_master
.head
; node
; node
= nnode
)
950 if (node
->to_be_processed
)
952 /* DD: Should we add any thread yield code here */
953 route_map_update_fn(node
->name
);
955 route_map_clear_updated(node
);
962 /* Return route map's type string. */
964 route_map_type_str (enum route_map_type type
)
981 route_map_empty (struct route_map
*map
)
983 if (map
->head
== NULL
&& map
->tail
== NULL
)
991 vty_show_route_map_entry (struct vty
*vty
, struct route_map
*map
)
993 struct route_map_index
*index
;
994 struct route_map_rule
*rule
;
996 vty_outln (vty
, "%s:", frr_protonameinst
);
998 for (index
= map
->head
; index
; index
= index
->next
)
1000 vty_outln (vty
, "route-map %s, %s, sequence %d",
1001 map
->name
, route_map_type_str (index
->type
),
1005 if (index
->description
)
1006 vty_outln (vty
, " Description:%s %s", VTYNL
,
1007 index
->description
);
1010 vty_outln (vty
, " Match clauses:");
1011 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1012 vty_outln (vty
, " %s %s",
1013 rule
->cmd
->str
, rule
->rule_str
);
1015 vty_outln (vty
, " Set clauses:");
1016 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1017 vty_outln (vty
, " %s %s",
1018 rule
->cmd
->str
, rule
->rule_str
);
1021 vty_outln (vty
, " Call clause:");
1023 vty_outln (vty
, " Call %s", index
->nextrm
);
1026 vty_outln (vty
, " Action:");
1027 if (index
->exitpolicy
== RMAP_GOTO
)
1028 vty_outln (vty
, " Goto %d", index
->nextpref
);
1029 else if (index
->exitpolicy
== RMAP_NEXT
)
1030 vty_outln (vty
, " Continue to next entry");
1031 else if (index
->exitpolicy
== RMAP_EXIT
)
1032 vty_outln (vty
, " Exit routemap");
1037 vty_show_route_map (struct vty
*vty
, const char *name
)
1039 struct route_map
*map
;
1043 map
= route_map_lookup_by_name (name
);
1047 vty_show_route_map_entry (vty
, map
);
1052 vty_outln (vty
, "%s: 'route-map %s' not found", frr_protonameinst
,
1059 for (map
= route_map_master
.head
; map
; map
= map
->next
)
1061 vty_show_route_map_entry (vty
, map
);
1067 /* New route map allocation. Please note route map's name must be
1069 static struct route_map_index
*
1070 route_map_index_new (void)
1072 struct route_map_index
*new;
1074 new = XCALLOC (MTYPE_ROUTE_MAP_INDEX
, sizeof (struct route_map_index
));
1075 new->exitpolicy
= RMAP_EXIT
; /* Default to Cisco-style */
1076 QOBJ_REG (new, route_map_index
);
1080 /* Free route map index. */
1082 route_map_index_delete (struct route_map_index
*index
, int notify
)
1084 struct route_map_rule
*rule
;
1088 /* Free route match. */
1089 while ((rule
= index
->match_list
.head
) != NULL
)
1090 route_map_rule_delete (&index
->match_list
, rule
);
1092 /* Free route set. */
1093 while ((rule
= index
->set_list
.head
) != NULL
)
1094 route_map_rule_delete (&index
->set_list
, rule
);
1096 /* Remove index from route map list. */
1098 index
->next
->prev
= index
->prev
;
1100 index
->map
->tail
= index
->prev
;
1103 index
->prev
->next
= index
->next
;
1105 index
->map
->head
= index
->next
;
1107 /* Free 'char *nextrm' if not NULL */
1109 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
1111 /* Execute event hook. */
1112 if (route_map_master
.event_hook
&& notify
)
1114 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_DELETED
,
1116 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1118 XFREE (MTYPE_ROUTE_MAP_INDEX
, index
);
1121 /* Lookup index from route map. */
1122 static struct route_map_index
*
1123 route_map_index_lookup (struct route_map
*map
, enum route_map_type type
,
1126 struct route_map_index
*index
;
1128 for (index
= map
->head
; index
; index
= index
->next
)
1129 if ((index
->type
== type
|| type
== RMAP_ANY
)
1130 && index
->pref
== pref
)
1135 /* Add new index to route map. */
1136 static struct route_map_index
*
1137 route_map_index_add (struct route_map
*map
, enum route_map_type type
,
1140 struct route_map_index
*index
;
1141 struct route_map_index
*point
;
1143 /* Allocate new route map inex. */
1144 index
= route_map_index_new ();
1149 /* Compare preference. */
1150 for (point
= map
->head
; point
; point
= point
->next
)
1151 if (point
->pref
>= pref
)
1154 if (map
->head
== NULL
)
1156 map
->head
= map
->tail
= index
;
1158 else if (point
== NULL
)
1160 index
->prev
= map
->tail
;
1161 map
->tail
->next
= index
;
1164 else if (point
== map
->head
)
1166 index
->next
= map
->head
;
1167 map
->head
->prev
= index
;
1172 index
->next
= point
;
1173 index
->prev
= point
->prev
;
1175 point
->prev
->next
= index
;
1176 point
->prev
= index
;
1179 /* Execute event hook. */
1180 if (route_map_master
.event_hook
)
1182 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_ADDED
,
1184 route_map_notify_dependencies (map
->name
, RMAP_EVENT_CALL_ADDED
);
1189 /* Get route map index. */
1190 static struct route_map_index
*
1191 route_map_index_get (struct route_map
*map
, enum route_map_type type
,
1194 struct route_map_index
*index
;
1196 index
= route_map_index_lookup (map
, RMAP_ANY
, pref
);
1197 if (index
&& index
->type
!= type
)
1199 /* Delete index from route map. */
1200 route_map_index_delete (index
, 1);
1204 index
= route_map_index_add (map
, type
, pref
);
1208 /* New route map rule */
1209 static struct route_map_rule
*
1210 route_map_rule_new (void)
1212 struct route_map_rule
*new;
1214 new = XCALLOC (MTYPE_ROUTE_MAP_RULE
, sizeof (struct route_map_rule
));
1218 /* Install rule command to the match list. */
1220 route_map_install_match (struct route_map_rule_cmd
*cmd
)
1222 vector_set (route_match_vec
, cmd
);
1225 /* Install rule command to the set list. */
1227 route_map_install_set (struct route_map_rule_cmd
*cmd
)
1229 vector_set (route_set_vec
, cmd
);
1232 /* Lookup rule command from match list. */
1233 static struct route_map_rule_cmd
*
1234 route_map_lookup_match (const char *name
)
1237 struct route_map_rule_cmd
*rule
;
1239 for (i
= 0; i
< vector_active (route_match_vec
); i
++)
1240 if ((rule
= vector_slot (route_match_vec
, i
)) != NULL
)
1241 if (strcmp (rule
->str
, name
) == 0)
1246 /* Lookup rule command from set list. */
1247 static struct route_map_rule_cmd
*
1248 route_map_lookup_set (const char *name
)
1251 struct route_map_rule_cmd
*rule
;
1253 for (i
= 0; i
< vector_active (route_set_vec
); i
++)
1254 if ((rule
= vector_slot (route_set_vec
, i
)) != NULL
)
1255 if (strcmp (rule
->str
, name
) == 0)
1260 /* Add match and set rule to rule list. */
1262 route_map_rule_add (struct route_map_rule_list
*list
,
1263 struct route_map_rule
*rule
)
1266 rule
->prev
= list
->tail
;
1268 list
->tail
->next
= rule
;
1274 /* Delete rule from rule list. */
1276 route_map_rule_delete (struct route_map_rule_list
*list
,
1277 struct route_map_rule
*rule
)
1279 if (rule
->cmd
->func_free
)
1280 (*rule
->cmd
->func_free
) (rule
->value
);
1283 XFREE (MTYPE_ROUTE_MAP_RULE_STR
, rule
->rule_str
);
1286 rule
->next
->prev
= rule
->prev
;
1288 list
->tail
= rule
->prev
;
1290 rule
->prev
->next
= rule
->next
;
1292 list
->head
= rule
->next
;
1294 XFREE (MTYPE_ROUTE_MAP_RULE
, rule
);
1297 /* strcmp wrapper function which don't crush even argument is NULL. */
1299 rulecmp (const char *dst
, const char *src
)
1313 return strcmp (dst
, src
);
1318 /* Use this to return the already specified argument for this match. This is
1319 * useful to get the specified argument with a route map match rule when the
1320 * rule is being deleted and the argument is not provided.
1323 route_map_get_match_arg(struct route_map_index
*index
, const char *match_name
)
1325 struct route_map_rule
*rule
;
1326 struct route_map_rule_cmd
*cmd
;
1328 /* First lookup rule for add match statement. */
1329 cmd
= route_map_lookup_match (match_name
);
1333 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1334 if (rule
->cmd
== cmd
&& rule
->rule_str
!= NULL
)
1335 return (rule
->rule_str
);
1340 /* Add match statement to route map. */
1342 route_map_add_match (struct route_map_index
*index
, const char *match_name
,
1343 const char *match_arg
)
1345 struct route_map_rule
*rule
;
1346 struct route_map_rule
*next
;
1347 struct route_map_rule_cmd
*cmd
;
1351 /* First lookup rule for add match statement. */
1352 cmd
= route_map_lookup_match (match_name
);
1354 return RMAP_RULE_MISSING
;
1356 /* Next call compile function for this match statement. */
1357 if (cmd
->func_compile
)
1359 compile
= (*cmd
->func_compile
)(match_arg
);
1360 if (compile
== NULL
)
1361 return RMAP_COMPILE_ERROR
;
1366 /* If argument is completely same ignore it. */
1367 for (rule
= index
->match_list
.head
; rule
; rule
= next
)
1370 if (rule
->cmd
== cmd
)
1372 route_map_rule_delete (&index
->match_list
, rule
);
1377 /* Add new route map match rule. */
1378 rule
= route_map_rule_new ();
1380 rule
->value
= compile
;
1382 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, match_arg
);
1384 rule
->rule_str
= NULL
;
1386 /* Add new route match rule to linked list. */
1387 route_map_rule_add (&index
->match_list
, rule
);
1389 /* Execute event hook. */
1390 if (route_map_master
.event_hook
)
1392 (*route_map_master
.event_hook
) (replaced
?
1393 RMAP_EVENT_MATCH_REPLACED
:
1394 RMAP_EVENT_MATCH_ADDED
,
1396 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1402 /* Delete specified route match rule. */
1404 route_map_delete_match (struct route_map_index
*index
, const char *match_name
,
1405 const char *match_arg
)
1407 struct route_map_rule
*rule
;
1408 struct route_map_rule_cmd
*cmd
;
1410 cmd
= route_map_lookup_match (match_name
);
1414 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1415 if (rule
->cmd
== cmd
&&
1416 (rulecmp (rule
->rule_str
, match_arg
) == 0 || match_arg
== NULL
))
1418 route_map_rule_delete (&index
->match_list
, rule
);
1419 /* Execute event hook. */
1420 if (route_map_master
.event_hook
)
1422 (*route_map_master
.event_hook
) (RMAP_EVENT_MATCH_DELETED
,
1424 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1428 /* Can't find matched rule. */
1432 /* Add route-map set statement to the route map. */
1434 route_map_add_set (struct route_map_index
*index
, const char *set_name
,
1435 const char *set_arg
)
1437 struct route_map_rule
*rule
;
1438 struct route_map_rule
*next
;
1439 struct route_map_rule_cmd
*cmd
;
1443 cmd
= route_map_lookup_set (set_name
);
1445 return RMAP_RULE_MISSING
;
1447 /* Next call compile function for this match statement. */
1448 if (cmd
->func_compile
)
1450 compile
= (*cmd
->func_compile
)(set_arg
);
1451 if (compile
== NULL
)
1452 return RMAP_COMPILE_ERROR
;
1457 /* Add by WJL. if old set command of same kind exist, delete it first
1458 to ensure only one set command of same kind exist under a
1460 for (rule
= index
->set_list
.head
; rule
; rule
= next
)
1463 if (rule
->cmd
== cmd
)
1465 route_map_rule_delete (&index
->set_list
, rule
);
1470 /* Add new route map match rule. */
1471 rule
= route_map_rule_new ();
1473 rule
->value
= compile
;
1475 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, set_arg
);
1477 rule
->rule_str
= NULL
;
1479 /* Add new route match rule to linked list. */
1480 route_map_rule_add (&index
->set_list
, rule
);
1482 /* Execute event hook. */
1483 if (route_map_master
.event_hook
)
1485 (*route_map_master
.event_hook
) (replaced
?
1486 RMAP_EVENT_SET_REPLACED
:
1487 RMAP_EVENT_SET_ADDED
,
1489 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1494 /* Delete route map set rule. */
1496 route_map_delete_set (struct route_map_index
*index
, const char *set_name
,
1497 const char *set_arg
)
1499 struct route_map_rule
*rule
;
1500 struct route_map_rule_cmd
*cmd
;
1502 cmd
= route_map_lookup_set (set_name
);
1506 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1507 if ((rule
->cmd
== cmd
) &&
1508 (rulecmp (rule
->rule_str
, set_arg
) == 0 || set_arg
== NULL
))
1510 route_map_rule_delete (&index
->set_list
, rule
);
1511 /* Execute event hook. */
1512 if (route_map_master
.event_hook
)
1514 (*route_map_master
.event_hook
) (RMAP_EVENT_SET_DELETED
,
1516 route_map_notify_dependencies(index
->map
->name
, RMAP_EVENT_CALL_ADDED
);
1520 /* Can't find matched rule. */
1524 /* Apply route map's each index to the object.
1526 The matrix for a route-map looks like this:
1527 (note, this includes the description for the "NEXT"
1528 and "GOTO" frobs now
1532 permit action | cont
1534 ------------------+---------------
1540 -Apply Set statements, accept route
1541 -If Call statement is present jump to the specified route-map, if it
1542 denies the route we finish.
1543 -If NEXT is specified, goto NEXT statement
1544 -If GOTO is specified, goto the first clause where pref > nextpref
1545 -If nothing is specified, do as Cisco and finish
1547 -Route is denied by route-map.
1551 If we get no matches after we've processed all updates, then the route
1554 Some notes on the new "CALL", "NEXT" and "GOTO"
1555 call WORD - If this clause is matched, then the set statements
1556 are executed and then we jump to route-map 'WORD'. If
1557 this route-map denies the route, we finish, in other case we
1558 do whatever the exit policy (EXIT, NEXT or GOTO) tells.
1559 on-match next - If this clause is matched, then the set statements
1560 are executed and then we drop through to the next clause
1561 on-match goto n - If this clause is matched, then the set statments
1562 are executed and then we goto the nth clause, or the
1563 first clause greater than this. In order to ensure
1564 route-maps *always* exit, you cannot jump backwards.
1567 We need to make sure our route-map processing matches the above
1570 static route_map_result_t
1571 route_map_apply_match (struct route_map_rule_list
*match_list
,
1572 struct prefix
*prefix
, route_map_object_t type
,
1575 route_map_result_t ret
= RMAP_NOMATCH
;
1576 struct route_map_rule
*match
;
1579 /* Check all match rule and if there is no match rule, go to the
1581 if (!match_list
->head
)
1585 for (match
= match_list
->head
; match
; match
= match
->next
)
1587 /* Try each match statement in turn, If any do not return
1588 RMAP_MATCH, return, otherwise continue on to next match
1589 statement. All match statements must match for end-result
1591 ret
= (*match
->cmd
->func_apply
) (match
->value
, prefix
,
1593 if (ret
!= RMAP_MATCH
)
1600 /* Apply route map to the object. */
1602 route_map_apply (struct route_map
*map
, struct prefix
*prefix
,
1603 route_map_object_t type
, void *object
)
1605 static int recursion
= 0;
1607 struct route_map_index
*index
;
1608 struct route_map_rule
*set
;
1610 if (recursion
> RMAP_RECURSION_LIMIT
)
1612 zlog_warn("route-map recursion limit (%d) reached, discarding route",
1613 RMAP_RECURSION_LIMIT
);
1615 return RMAP_DENYMATCH
;
1619 return RMAP_DENYMATCH
;
1621 for (index
= map
->head
; index
; index
= index
->next
)
1623 /* Apply this index. */
1624 ret
= route_map_apply_match (&index
->match_list
, prefix
, type
, object
);
1626 /* Now we apply the matrix from above */
1627 if (ret
== RMAP_NOMATCH
)
1628 /* 'cont' from matrix - continue to next route-map sequence */
1630 else if (ret
== RMAP_MATCH
)
1632 if (index
->type
== RMAP_PERMIT
)
1635 /* permit+match must execute sets */
1636 for (set
= index
->set_list
.head
; set
; set
= set
->next
)
1637 ret
= (*set
->cmd
->func_apply
) (set
->value
, prefix
,
1640 /* Call another route-map if available */
1643 struct route_map
*nextrm
=
1644 route_map_lookup_by_name (index
->nextrm
);
1646 if (nextrm
) /* Target route-map found, jump to it */
1649 ret
= route_map_apply (nextrm
, prefix
, type
, object
);
1653 /* If nextrm returned 'deny', finish. */
1654 if (ret
== RMAP_DENYMATCH
)
1658 switch (index
->exitpolicy
)
1666 /* Find the next clause to jump to */
1667 struct route_map_index
*next
= index
->next
;
1668 int nextpref
= index
->nextpref
;
1670 while (next
&& next
->pref
< nextpref
)
1677 /* No clauses match! */
1683 else if (index
->type
== RMAP_DENY
)
1686 return RMAP_DENYMATCH
;
1690 /* Finally route-map does not match at all. */
1691 return RMAP_DENYMATCH
;
1695 route_map_add_hook (void (*func
) (const char *))
1697 route_map_master
.add_hook
= func
;
1701 route_map_delete_hook (void (*func
) (const char *))
1703 route_map_master
.delete_hook
= func
;
1707 route_map_event_hook (void (*func
) (route_map_event_t
, const char *))
1709 route_map_master
.event_hook
= func
;
1712 /* Routines for route map dependency lists and dependency processing */
1714 route_map_rmap_hash_cmp (const void *p1
, const void *p2
)
1716 return (strcmp((const char *)p1
, (const char *)p2
) == 0);
1720 route_map_dep_hash_cmp (const void *p1
, const void *p2
)
1723 return (strcmp (((const struct route_map_dep
*)p1
)->dep_name
, (const char *)p2
) == 0);
1727 route_map_clear_reference(struct hash_backet
*backet
, void *arg
)
1729 struct route_map_dep
*dep
= (struct route_map_dep
*)backet
->data
;
1734 rmap_name
= (char *)hash_release(dep
->dep_rmap_hash
, (void *)arg
);
1737 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1739 if (!dep
->dep_rmap_hash
->count
)
1741 dep
= hash_release(dep
->this_hash
, (void *)dep
->dep_name
);
1742 hash_free(dep
->dep_rmap_hash
);
1743 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1744 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1750 route_map_clear_all_references (char *rmap_name
)
1754 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
1756 hash_iterate(route_map_dep_hash
[i
], route_map_clear_reference
,
1762 route_map_dep_hash_alloc(void *p
)
1764 char *dep_name
= (char *)p
;
1765 struct route_map_dep
*dep_entry
;
1767 dep_entry
= XCALLOC(MTYPE_ROUTE_MAP_DEP
, sizeof(struct route_map_dep
));
1768 dep_entry
->dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1769 dep_entry
->dep_rmap_hash
= hash_create(route_map_dep_hash_make_key
,
1770 route_map_rmap_hash_cmp
, NULL
);
1771 dep_entry
->this_hash
= NULL
;
1773 return((void *)dep_entry
);
1777 route_map_name_hash_alloc(void *p
)
1779 return((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME
, (const char *)p
));
1783 route_map_dep_hash_make_key (void *p
)
1785 return (string_hash_make((char *)p
));
1789 route_map_print_dependency (struct hash_backet
*backet
, void *data
)
1791 char *rmap_name
= (char *)backet
->data
;
1792 char *dep_name
= (char *)data
;
1795 zlog_debug("%s: Dependency for %s: %s", __FUNCTION__
, dep_name
, rmap_name
);
1799 route_map_dep_update (struct hash
*dephash
, const char *dep_name
,
1800 const char *rmap_name
,
1801 route_map_event_t type
)
1803 struct route_map_dep
*dep
= NULL
;
1805 char *dname
, *rname
;
1808 dname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, dep_name
);
1809 rname
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1813 case RMAP_EVENT_PLIST_ADDED
:
1814 case RMAP_EVENT_CLIST_ADDED
:
1815 case RMAP_EVENT_ECLIST_ADDED
:
1816 case RMAP_EVENT_ASLIST_ADDED
:
1817 case RMAP_EVENT_LLIST_ADDED
:
1818 case RMAP_EVENT_CALL_ADDED
:
1819 case RMAP_EVENT_FILTER_ADDED
:
1821 zlog_debug("%s: Adding dependency for %s in %s", __FUNCTION__
,
1822 dep_name
, rmap_name
);
1823 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
,
1824 route_map_dep_hash_alloc
);
1830 if (!dep
->this_hash
)
1831 dep
->this_hash
= dephash
;
1833 hash_get(dep
->dep_rmap_hash
, rname
, route_map_name_hash_alloc
);
1835 case RMAP_EVENT_PLIST_DELETED
:
1836 case RMAP_EVENT_CLIST_DELETED
:
1837 case RMAP_EVENT_ECLIST_DELETED
:
1838 case RMAP_EVENT_ASLIST_DELETED
:
1839 case RMAP_EVENT_LLIST_DELETED
:
1840 case RMAP_EVENT_CALL_DELETED
:
1841 case RMAP_EVENT_FILTER_DELETED
:
1843 zlog_debug("%s: Deleting dependency for %s in %s", __FUNCTION__
,
1844 dep_name
, rmap_name
);
1845 dep
= (struct route_map_dep
*) hash_get (dephash
, dname
, NULL
);
1850 ret_map_name
= (char *)hash_release(dep
->dep_rmap_hash
, rname
);
1852 XFREE(MTYPE_ROUTE_MAP_NAME
, ret_map_name
);
1854 if (!dep
->dep_rmap_hash
->count
)
1856 dep
= hash_release(dephash
, dname
);
1857 hash_free(dep
->dep_rmap_hash
);
1858 XFREE(MTYPE_ROUTE_MAP_NAME
, dep
->dep_name
);
1859 XFREE(MTYPE_ROUTE_MAP_DEP
, dep
);
1870 hash_iterate (dep
->dep_rmap_hash
, route_map_print_dependency
, dname
);
1874 XFREE(MTYPE_ROUTE_MAP_NAME
, rname
);
1875 XFREE(MTYPE_ROUTE_MAP_NAME
, dname
);
1879 static struct hash
*
1880 route_map_get_dep_hash (route_map_event_t event
)
1882 struct hash
*upd8_hash
= NULL
;
1886 case RMAP_EVENT_PLIST_ADDED
:
1887 case RMAP_EVENT_PLIST_DELETED
:
1888 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_PLIST
];
1890 case RMAP_EVENT_CLIST_ADDED
:
1891 case RMAP_EVENT_CLIST_DELETED
:
1892 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_CLIST
];
1894 case RMAP_EVENT_ECLIST_ADDED
:
1895 case RMAP_EVENT_ECLIST_DELETED
:
1896 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ECLIST
];
1898 case RMAP_EVENT_ASLIST_ADDED
:
1899 case RMAP_EVENT_ASLIST_DELETED
:
1900 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_ASPATH
];
1902 case RMAP_EVENT_LLIST_ADDED
:
1903 case RMAP_EVENT_LLIST_DELETED
:
1904 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_LCLIST
];
1906 case RMAP_EVENT_CALL_ADDED
:
1907 case RMAP_EVENT_CALL_DELETED
:
1908 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_RMAP
];
1910 case RMAP_EVENT_FILTER_ADDED
:
1911 case RMAP_EVENT_FILTER_DELETED
:
1912 upd8_hash
= route_map_dep_hash
[ROUTE_MAP_DEP_FILTER
];
1922 route_map_process_dependency (struct hash_backet
*backet
, void *data
)
1925 route_map_event_t type
= (route_map_event_t
)(ptrdiff_t)data
;
1927 rmap_name
= (char *)backet
->data
;
1932 zlog_debug("%s: Notifying %s of dependency", __FUNCTION__
,
1934 if (route_map_master
.event_hook
)
1935 (*route_map_master
.event_hook
) (type
, rmap_name
);
1940 route_map_upd8_dependency (route_map_event_t type
, const char *arg
,
1941 const char *rmap_name
)
1943 struct hash
*upd8_hash
= NULL
;
1945 if ((upd8_hash
= route_map_get_dep_hash(type
)))
1946 route_map_dep_update (upd8_hash
, arg
, rmap_name
, type
);
1950 route_map_notify_dependencies (const char *affected_name
, route_map_event_t event
)
1952 struct route_map_dep
*dep
;
1953 struct hash
*upd8_hash
;
1959 name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, affected_name
);
1961 if ((upd8_hash
= route_map_get_dep_hash(event
)) == NULL
)
1963 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1967 dep
= (struct route_map_dep
*)hash_get (upd8_hash
, name
,
1971 if (!dep
->this_hash
)
1972 dep
->this_hash
= upd8_hash
;
1974 hash_iterate (dep
->dep_rmap_hash
, route_map_process_dependency
, (void *)event
);
1977 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
1981 /* VTY related functions. */
1982 DEFUN (match_interface
,
1983 match_interface_cmd
,
1984 "match interface WORD",
1986 "match first hop interface of route\n"
1990 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
1992 if (rmap_match_set_hook
.match_interface
)
1993 return rmap_match_set_hook
.match_interface (vty
, index
, "interface", argv
[idx_word
]->arg
, RMAP_EVENT_MATCH_ADDED
);
1997 DEFUN (no_match_interface
,
1998 no_match_interface_cmd
,
1999 "no match interface [WORD]",
2002 "Match first hop interface of route\n"
2005 char *iface
= (argc
== 4) ? argv
[3]->arg
: NULL
;
2006 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2008 if (rmap_match_set_hook
.no_match_interface
)
2009 return rmap_match_set_hook
.no_match_interface (vty
, index
, "interface", iface
, RMAP_EVENT_MATCH_DELETED
);
2014 DEFUN (match_ip_address
,
2015 match_ip_address_cmd
,
2016 "match ip address <(1-199)|(1300-2699)|WORD>",
2019 "Match address of route\n"
2020 "IP access-list number\n"
2021 "IP access-list number (expanded range)\n"
2022 "IP Access-list name\n")
2025 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2027 if (rmap_match_set_hook
.match_ip_address
)
2028 return rmap_match_set_hook
.match_ip_address (vty
, index
, "ip address", argv
[idx_acl
]->arg
,
2029 RMAP_EVENT_FILTER_ADDED
);
2034 DEFUN (no_match_ip_address
,
2035 no_match_ip_address_cmd
,
2036 "no match ip address [<(1-199)|(1300-2699)|WORD>]",
2040 "Match address of route\n"
2041 "IP access-list number\n"
2042 "IP access-list number (expanded range)\n"
2043 "IP Access-list name\n")
2046 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2048 if (rmap_match_set_hook
.no_match_ip_address
)
2050 if (argc
<= idx_word
)
2051 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", NULL
,
2052 RMAP_EVENT_FILTER_DELETED
);
2053 return rmap_match_set_hook
.no_match_ip_address (vty
, index
, "ip address", argv
[idx_word
]->arg
,
2054 RMAP_EVENT_FILTER_DELETED
);
2060 DEFUN (match_ip_address_prefix_list
,
2061 match_ip_address_prefix_list_cmd
,
2062 "match ip address prefix-list WORD",
2065 "Match address of route\n"
2066 "Match entries of prefix-lists\n"
2067 "IP prefix-list name\n")
2070 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2072 if (rmap_match_set_hook
.match_ip_address_prefix_list
)
2073 return rmap_match_set_hook
.match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2074 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2079 DEFUN (no_match_ip_address_prefix_list
,
2080 no_match_ip_address_prefix_list_cmd
,
2081 "no match ip address prefix-list [WORD]",
2085 "Match address of route\n"
2086 "Match entries of prefix-lists\n"
2087 "IP prefix-list name\n")
2090 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2092 if (rmap_match_set_hook
.no_match_ip_address_prefix_list
)
2094 if (argc
<= idx_word
)
2095 return rmap_match_set_hook
.no_match_ip_address_prefix_list (vty
, index
, "ip address prefix-list",
2096 NULL
, RMAP_EVENT_PLIST_DELETED
);
2097 return rmap_match_set_hook
.no_match_ip_address_prefix_list(vty
, index
, "ip address prefix-list",
2098 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2104 DEFUN (match_ip_next_hop
,
2105 match_ip_next_hop_cmd
,
2106 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
2109 "Match next-hop address of route\n"
2110 "IP access-list number\n"
2111 "IP access-list number (expanded range)\n"
2112 "IP Access-list name\n")
2115 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2117 if (rmap_match_set_hook
.match_ip_next_hop
)
2118 return rmap_match_set_hook
.match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_acl
]->arg
,
2119 RMAP_EVENT_FILTER_ADDED
);
2124 DEFUN (no_match_ip_next_hop
,
2125 no_match_ip_next_hop_cmd
,
2126 "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]",
2130 "Match next-hop address of route\n"
2131 "IP access-list number\n"
2132 "IP access-list number (expanded range)\n"
2133 "IP Access-list name\n")
2136 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2138 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2140 if (argc
<= idx_word
)
2141 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", NULL
,
2142 RMAP_EVENT_FILTER_DELETED
);
2143 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop", argv
[idx_word
]->arg
,
2144 RMAP_EVENT_FILTER_DELETED
);
2150 DEFUN (match_ip_next_hop_prefix_list
,
2151 match_ip_next_hop_prefix_list_cmd
,
2152 "match ip next-hop prefix-list WORD",
2155 "Match next-hop address of route\n"
2156 "Match entries of prefix-lists\n"
2157 "IP prefix-list name\n")
2160 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2162 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
)
2163 return rmap_match_set_hook
.match_ip_next_hop_prefix_list (vty
, index
, "ip next-hop prefix-list",
2164 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2168 DEFUN (no_match_ip_next_hop_prefix_list
,
2169 no_match_ip_next_hop_prefix_list_cmd
,
2170 "no match ip next-hop prefix-list [WORD]",
2174 "Match next-hop address of route\n"
2175 "Match entries of prefix-lists\n"
2176 "IP prefix-list name\n")
2179 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2181 if (rmap_match_set_hook
.no_match_ip_next_hop
)
2183 if (argc
<= idx_word
)
2184 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2185 NULL
, RMAP_EVENT_PLIST_DELETED
);
2186 return rmap_match_set_hook
.no_match_ip_next_hop (vty
, index
, "ip next-hop prefix-list",
2187 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2193 DEFUN (match_ipv6_address
,
2194 match_ipv6_address_cmd
,
2195 "match ipv6 address WORD",
2198 "Match IPv6 address of route\n"
2199 "IPv6 access-list name\n")
2202 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2204 if (rmap_match_set_hook
.match_ipv6_address
)
2205 return rmap_match_set_hook
.match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2206 RMAP_EVENT_FILTER_ADDED
);
2210 DEFUN (no_match_ipv6_address
,
2211 no_match_ipv6_address_cmd
,
2212 "no match ipv6 address WORD",
2216 "Match IPv6 address of route\n"
2217 "IPv6 access-list name\n")
2220 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2222 if (rmap_match_set_hook
.no_match_ipv6_address
)
2223 return rmap_match_set_hook
.no_match_ipv6_address (vty
, index
, "ipv6 address", argv
[idx_word
]->arg
,
2224 RMAP_EVENT_FILTER_DELETED
);
2229 DEFUN (match_ipv6_address_prefix_list
,
2230 match_ipv6_address_prefix_list_cmd
,
2231 "match ipv6 address prefix-list WORD",
2234 "Match address of route\n"
2235 "Match entries of prefix-lists\n"
2236 "IP prefix-list name\n")
2239 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2241 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
)
2242 return rmap_match_set_hook
.match_ipv6_address_prefix_list (vty
, index
, "ipv6 address prefix-list",
2243 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
2247 DEFUN (no_match_ipv6_address_prefix_list
,
2248 no_match_ipv6_address_prefix_list_cmd
,
2249 "no match ipv6 address prefix-list WORD",
2253 "Match address of route\n"
2254 "Match entries of prefix-lists\n"
2255 "IP prefix-list name\n")
2258 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2260 if (rmap_match_set_hook
.no_match_ipv6_address_prefix_list
)
2261 return rmap_match_set_hook
.no_match_ipv6_address_prefix_list(vty
, index
, "ipv6 address prefix-list",
2262 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_DELETED
);
2267 DEFUN (match_metric
,
2269 "match metric (0-4294967295)",
2271 "Match metric of route\n"
2275 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2277 if (rmap_match_set_hook
.match_metric
)
2278 return rmap_match_set_hook
.match_metric(vty
, index
, "metric", argv
[idx_number
]->arg
,
2279 RMAP_EVENT_MATCH_ADDED
);
2284 DEFUN (no_match_metric
,
2285 no_match_metric_cmd
,
2286 "no match metric [(0-4294967295)]",
2289 "Match metric of route\n"
2293 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2295 if (rmap_match_set_hook
.no_match_metric
)
2297 if (argc
<= idx_number
)
2298 return rmap_match_set_hook
.no_match_metric (vty
, index
, "metric",
2299 NULL
, RMAP_EVENT_MATCH_DELETED
);
2300 return rmap_match_set_hook
.no_match_metric(vty
, index
, "metric",
2301 argv
[idx_number
]->arg
,
2302 RMAP_EVENT_MATCH_DELETED
);
2310 "match tag (1-4294967295)",
2312 "Match tag of route\n"
2316 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2318 if (rmap_match_set_hook
.match_tag
)
2319 return rmap_match_set_hook
.match_tag(vty
, index
, "tag", argv
[idx_number
]->arg
,
2320 RMAP_EVENT_MATCH_ADDED
);
2325 DEFUN (no_match_tag
,
2327 "no match tag [(1-4294967295)]",
2330 "Match tag of route\n"
2333 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2336 char *arg
= argv_find (argv
, argc
, "(1-4294967295)", &idx
) ?
2337 argv
[idx
]->arg
: NULL
;
2339 if (rmap_match_set_hook
.no_match_tag
)
2340 return rmap_match_set_hook
.no_match_tag (vty
, index
, "tag", arg
,
2341 RMAP_EVENT_MATCH_DELETED
);
2346 DEFUN (set_ip_nexthop
,
2348 "set ip next-hop A.B.C.D",
2351 "Next hop address\n"
2352 "IP address of next hop\n")
2357 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2359 ret
= str2sockunion (argv
[idx_ipv4
]->arg
, &su
);
2362 vty_outln (vty
, "%% Malformed nexthop address");
2365 if (su
.sin
.sin_addr
.s_addr
== 0 ||
2366 IPV4_CLASS_DE(su
.sin
.sin_addr
.s_addr
))
2369 "%% nexthop address cannot be 0.0.0.0, multicast " "or reserved");
2373 if (rmap_match_set_hook
.set_ip_nexthop
)
2374 return rmap_match_set_hook
.set_ip_nexthop(vty
, index
, "ip next-hop", argv
[idx_ipv4
]->arg
);
2379 DEFUN (no_set_ip_nexthop
,
2380 no_set_ip_nexthop_cmd
,
2381 "no set ip next-hop [<peer-address|A.B.C.D>]",
2385 "Next hop address\n"
2386 "Use peer address (for BGP only)\n"
2387 "IP address of next hop\n")
2390 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2392 if (rmap_match_set_hook
.no_set_ip_nexthop
)
2394 if (argc
<= idx_peer
)
2395 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", NULL
);
2396 return rmap_match_set_hook
.no_set_ip_nexthop (vty
, index
, "ip next-hop", argv
[idx_peer
]->arg
);
2402 DEFUN (set_ipv6_nexthop_local
,
2403 set_ipv6_nexthop_local_cmd
,
2404 "set ipv6 next-hop local X:X::X:X",
2407 "IPv6 next-hop address\n"
2408 "IPv6 local address\n"
2409 "IPv6 address of next hop\n")
2412 struct in6_addr addr
;
2414 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2416 ret
= inet_pton (AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
2419 vty_outln (vty
, "%% Malformed nexthop address");
2422 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
2424 vty_outln (vty
, "%% Invalid link-local nexthop address");
2428 if (rmap_match_set_hook
.set_ipv6_nexthop_local
)
2429 return rmap_match_set_hook
.set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[idx_ipv6
]->arg
);
2434 DEFUN (no_set_ipv6_nexthop_local
,
2435 no_set_ipv6_nexthop_local_cmd
,
2436 "no set ipv6 next-hop local [X:X::X:X]",
2440 "IPv6 next-hop address\n"
2441 "IPv6 local address\n"
2442 "IPv6 address of next hop\n")
2445 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2447 if (rmap_match_set_hook
.no_set_ipv6_nexthop_local
)
2449 if (argc
<= idx_ipv6
)
2450 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", NULL
);
2451 return rmap_match_set_hook
.no_set_ipv6_nexthop_local (vty
, index
, "ipv6 next-hop local", argv
[5]->arg
);
2458 "set metric <(0-4294967295)|rtt|+rtt|-rtt|+metric|-metric>",
2460 "Metric value for destination routing protocol\n"
2462 "Assign round trip time\n"
2463 "Add round trip time\n"
2464 "Subtract round trip time\n"
2466 "Subtract metric\n")
2469 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2471 const char *pass
= (argv
[idx_number
]->type
== RANGE_TKN
) ?
2472 argv
[idx_number
]->arg
: argv
[idx_number
]->text
;
2474 if (rmap_match_set_hook
.set_metric
)
2475 return rmap_match_set_hook
.set_metric (vty
, index
, "metric", pass
);
2480 DEFUN (no_set_metric
,
2482 "no set metric [(0-4294967295)]",
2485 "Metric value for destination routing protocol\n"
2489 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2491 if (rmap_match_set_hook
.no_set_metric
)
2493 if (argc
<= idx_number
)
2494 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", NULL
);
2495 return rmap_match_set_hook
.no_set_metric (vty
, index
, "metric", argv
[idx_number
]->arg
);
2503 "set tag (1-4294967295)",
2505 "Tag value for routing protocol\n"
2508 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2511 if (rmap_match_set_hook
.set_tag
)
2512 return rmap_match_set_hook
.set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2519 "no set tag [(1-4294967295)]",
2522 "Tag value for routing protocol\n"
2525 VTY_DECLVAR_CONTEXT (route_map_index
, index
);
2528 if (rmap_match_set_hook
.no_set_tag
)
2530 if (argc
<= idx_number
)
2531 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", NULL
);
2532 return rmap_match_set_hook
.no_set_tag (vty
, index
, "tag", argv
[idx_number
]->arg
);
2539 DEFUN_NOSH (route_map
,
2541 "route-map WORD <deny|permit> (1-65535)",
2542 "Create route-map or enter route-map command mode\n"
2544 "Route map denies set operations\n"
2545 "Route map permits set operations\n"
2546 "Sequence to insert to/delete from existing route-map entry\n")
2549 int idx_permit_deny
= 2;
2551 struct route_map
*map
;
2552 struct route_map_index
*index
;
2553 char *endptr
= NULL
;
2554 int permit
= argv
[idx_permit_deny
]->arg
[0] == 'p' ? RMAP_PERMIT
: RMAP_DENY
;
2555 unsigned long pref
= strtoul (argv
[idx_number
]->arg
, &endptr
, 10);
2556 const char *mapname
= argv
[idx_word
]->arg
;
2558 /* Get route map. */
2559 map
= route_map_get (mapname
);
2560 index
= route_map_index_get (map
, permit
, pref
);
2562 VTY_PUSH_CONTEXT (RMAP_NODE
, index
);
2566 DEFUN (no_route_map_all
,
2567 no_route_map_all_cmd
,
2568 "no route-map WORD",
2570 "Create route-map or enter route-map command mode\n"
2574 const char *mapname
= argv
[idx_word
]->arg
;
2575 struct route_map
*map
;
2577 map
= route_map_lookup_by_name (mapname
);
2580 vty_outln (vty
, "%% Could not find route-map %s", mapname
);
2584 route_map_delete (map
);
2589 DEFUN (no_route_map
,
2591 "no route-map WORD <deny|permit> (1-65535)",
2593 "Create route-map or enter route-map command mode\n"
2595 "Route map denies set operations\n"
2596 "Route map permits set operations\n"
2597 "Sequence to insert to/delete from existing route-map entry\n")
2600 int idx_permit_deny
= 3;
2602 struct route_map
*map
;
2603 struct route_map_index
*index
;
2604 char *endptr
= NULL
;
2605 int permit
= strmatch (argv
[idx_permit_deny
]->text
, "permit") ?
2606 RMAP_PERMIT
: RMAP_DENY
;
2607 const char *prefstr
= argv
[idx_number
]->arg
;
2608 const char *mapname
= argv
[idx_word
]->arg
;
2609 unsigned long pref
= strtoul (prefstr
, &endptr
, 10);
2611 /* Existence check. */
2612 map
= route_map_lookup_by_name (mapname
);
2615 vty_outln (vty
, "%% Could not find route-map %s", mapname
);
2619 /* Lookup route map index. */
2620 index
= route_map_index_lookup (map
, permit
, pref
);
2623 vty_outln (vty
, "%% Could not find route-map entry %s %s",
2628 /* Delete index from route map. */
2629 route_map_index_delete (index
, 1);
2631 /* If this route rule is the last one, delete route map itself. */
2632 if (route_map_empty (map
))
2633 route_map_delete (map
);
2638 DEFUN (rmap_onmatch_next
,
2639 rmap_onmatch_next_cmd
,
2641 "Exit policy on matches\n"
2644 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2648 if (index
->type
== RMAP_DENY
)
2650 /* Under a deny clause, match means it's finished. No need to set next */
2651 vty_outln (vty
,"on-match next not supported under route-map deny");
2654 index
->exitpolicy
= RMAP_NEXT
;
2659 DEFUN (no_rmap_onmatch_next
,
2660 no_rmap_onmatch_next_cmd
,
2663 "Exit policy on matches\n"
2666 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2669 index
->exitpolicy
= RMAP_EXIT
;
2674 DEFUN (rmap_onmatch_goto
,
2675 rmap_onmatch_goto_cmd
,
2676 "on-match goto (1-65535)",
2677 "Exit policy on matches\n"
2678 "Goto Clause number\n"
2682 char *num
= argv_find (argv
, argc
, "(1-65535)", &idx
) ? argv
[idx
]->arg
: NULL
;
2684 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2689 if (index
->type
== RMAP_DENY
)
2691 /* Under a deny clause, match means it's finished. No need to go anywhere */
2692 vty_outln (vty
,"on-match goto not supported under route-map deny");
2697 d
= strtoul(num
, NULL
, 10);
2699 d
= index
->pref
+ 1;
2701 if (d
<= index
->pref
)
2703 /* Can't allow you to do that, Dave */
2704 vty_outln (vty
, "can't jump backwards in route-maps");
2709 index
->exitpolicy
= RMAP_GOTO
;
2710 index
->nextpref
= d
;
2716 DEFUN (no_rmap_onmatch_goto
,
2717 no_rmap_onmatch_goto_cmd
,
2720 "Exit policy on matches\n"
2721 "Goto Clause number\n")
2723 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2726 index
->exitpolicy
= RMAP_EXIT
;
2731 /* Cisco/GNU Zebra compatibility aliases */
2733 DEFUN (rmap_continue
,
2735 "continue (1-65535)",
2736 "Continue on a different entry within the route-map\n"
2737 "Route-map entry sequence number\n")
2739 return rmap_onmatch_goto (self
, vty
, argc
, argv
);
2743 DEFUN (no_rmap_continue
,
2744 no_rmap_continue_cmd
,
2745 "no continue [(1-65535)]",
2747 "Continue on a different entry within the route-map\n"
2748 "Route-map entry sequence number\n")
2750 return no_rmap_onmatch_goto (self
, vty
, argc
, argv
);
2754 DEFUN (rmap_show_name
,
2756 "show route-map [WORD]",
2758 "route-map information\n"
2762 const char *name
= (argc
== 3) ? argv
[idx_word
]->arg
: NULL
;
2763 return vty_show_route_map (vty
, name
);
2769 "Jump to another Route-Map after match+set\n"
2770 "Target route-map name\n")
2773 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2774 const char *rmap
= argv
[idx_word
]->arg
;
2780 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2783 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2785 index
->nextrm
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, rmap
);
2787 /* Execute event hook. */
2788 route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED
,
2794 DEFUN (no_rmap_call
,
2798 "Jump to another Route-Map after match+set\n")
2800 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2804 route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED
,
2807 XFREE (MTYPE_ROUTE_MAP_NAME
, index
->nextrm
);
2808 index
->nextrm
= NULL
;
2814 DEFUN (rmap_description
,
2815 rmap_description_cmd
,
2816 "description LINE...",
2817 "Route-map comment\n"
2818 "Comment describing this route-map rule\n")
2821 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2825 if (index
->description
)
2826 XFREE (MTYPE_TMP
, index
->description
);
2827 index
->description
= argv_concat (argv
, argc
, idx_line
);
2832 DEFUN (no_rmap_description
,
2833 no_rmap_description_cmd
,
2836 "Route-map comment\n")
2838 struct route_map_index
*index
= VTY_GET_CONTEXT (route_map_index
);
2842 if (index
->description
)
2843 XFREE (MTYPE_TMP
, index
->description
);
2844 index
->description
= NULL
;
2849 /* Configuration write function. */
2851 route_map_config_write (struct vty
*vty
)
2853 struct route_map
*map
;
2854 struct route_map_index
*index
;
2855 struct route_map_rule
*rule
;
2859 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2860 for (index
= map
->head
; index
; index
= index
->next
)
2863 vty_outln (vty
, "!");
2867 vty_outln (vty
, "route-map %s %s %d",
2869 route_map_type_str (index
->type
),
2872 if (index
->description
)
2873 vty_outln (vty
, " description %s", index
->description
);
2875 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
2876 vty_outln (vty
, " match %s %s", rule
->cmd
->str
,
2877 rule
->rule_str
? rule
->rule_str
: "");
2879 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
2880 vty_outln (vty
, " set %s %s", rule
->cmd
->str
,
2881 rule
->rule_str
? rule
->rule_str
: "");
2883 vty_outln (vty
, " call %s", index
->nextrm
);
2884 if (index
->exitpolicy
== RMAP_GOTO
)
2885 vty_outln (vty
, " on-match goto %d", index
->nextpref
);
2886 if (index
->exitpolicy
== RMAP_NEXT
)
2887 vty_outln (vty
," on-match next");
2894 /* Route map node structure. */
2895 static struct cmd_node rmap_node
=
2898 "%s(config-route-map)# ",
2902 /* Common route map rules */
2905 route_map_rule_tag_compile (const char *arg
)
2907 unsigned long int tmp
;
2912 tmp
= strtoul(arg
, &endptr
, 0);
2913 if (arg
[0] == '\0' || *endptr
!= '\0' || errno
|| tmp
> ROUTE_TAG_MAX
)
2916 tag
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(*tag
));
2923 route_map_rule_tag_free (void *rule
)
2925 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
2929 route_map_finish (void)
2933 vector_free (route_match_vec
);
2934 route_match_vec
= NULL
;
2935 vector_free (route_set_vec
);
2936 route_set_vec
= NULL
;
2938 /* cleanup route_map */
2939 while (route_map_master
.head
)
2941 struct route_map
*map
= route_map_master
.head
;
2942 map
->to_be_processed
= 0;
2943 route_map_delete (map
);
2946 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2948 hash_free(route_map_dep_hash
[i
]);
2949 route_map_dep_hash
[i
] = NULL
;
2952 hash_free (route_map_master_hash
);
2953 route_map_master_hash
= NULL
;
2956 static void rmap_autocomplete(vector comps
, struct cmd_token
*token
)
2958 struct route_map
*map
;
2960 for (map
= route_map_master
.head
; map
; map
= map
->next
)
2961 vector_set (comps
, XSTRDUP (MTYPE_COMPLETION
, map
->name
));
2964 static const struct cmd_variable_handler rmap_var_handlers
[] = {
2966 /* "route-map WORD" */
2967 .varname
= "route_map",
2968 .completions
= rmap_autocomplete
2970 .tokenname
= "ROUTEMAP_NAME",
2971 .completions
= rmap_autocomplete
2973 .tokenname
= "RMAP_NAME",
2974 .completions
= rmap_autocomplete
2980 /* Initialization of route map vector. */
2982 route_map_init (void)
2986 /* Make vector for match and set. */
2987 route_match_vec
= vector_init (1);
2988 route_set_vec
= vector_init (1);
2989 route_map_master_hash
= hash_create(route_map_hash_key_make
, route_map_hash_cmp
, NULL
);
2991 for (i
= 1; i
< ROUTE_MAP_DEP_MAX
; i
++)
2992 route_map_dep_hash
[i
] = hash_create(route_map_dep_hash_make_key
,
2993 route_map_dep_hash_cmp
, NULL
);
2995 cmd_variable_handler_register(rmap_var_handlers
);
2997 /* Install route map top node. */
2998 install_node (&rmap_node
, route_map_config_write
);
3000 /* Install route map commands. */
3001 install_default (RMAP_NODE
);
3002 install_element (CONFIG_NODE
, &route_map_cmd
);
3003 install_element (CONFIG_NODE
, &no_route_map_cmd
);
3004 install_element (CONFIG_NODE
, &no_route_map_all_cmd
);
3006 /* Install the on-match stuff */
3007 install_element (RMAP_NODE
, &route_map_cmd
);
3008 install_element (RMAP_NODE
, &rmap_onmatch_next_cmd
);
3009 install_element (RMAP_NODE
, &no_rmap_onmatch_next_cmd
);
3010 install_element (RMAP_NODE
, &rmap_onmatch_goto_cmd
);
3011 install_element (RMAP_NODE
, &no_rmap_onmatch_goto_cmd
);
3012 install_element (RMAP_NODE
, &rmap_continue_cmd
);
3013 install_element (RMAP_NODE
, &no_rmap_continue_cmd
);
3015 /* Install the continue stuff (ALIAS of on-match). */
3017 /* Install the call stuff. */
3018 install_element (RMAP_NODE
, &rmap_call_cmd
);
3019 install_element (RMAP_NODE
, &no_rmap_call_cmd
);
3021 /* Install description commands. */
3022 install_element (RMAP_NODE
, &rmap_description_cmd
);
3023 install_element (RMAP_NODE
, &no_rmap_description_cmd
);
3025 /* Install show command */
3026 install_element (ENABLE_NODE
, &rmap_show_name_cmd
);
3028 install_element (RMAP_NODE
, &match_interface_cmd
);
3029 install_element (RMAP_NODE
, &no_match_interface_cmd
);
3031 install_element (RMAP_NODE
, &match_ip_address_cmd
);
3032 install_element (RMAP_NODE
, &no_match_ip_address_cmd
);
3034 install_element (RMAP_NODE
, &match_ip_address_prefix_list_cmd
);
3035 install_element (RMAP_NODE
, &no_match_ip_address_prefix_list_cmd
);
3037 install_element (RMAP_NODE
, &match_ip_next_hop_cmd
);
3038 install_element (RMAP_NODE
, &no_match_ip_next_hop_cmd
);
3040 install_element (RMAP_NODE
, &match_ip_next_hop_prefix_list_cmd
);
3041 install_element (RMAP_NODE
, &no_match_ip_next_hop_prefix_list_cmd
);
3043 install_element (RMAP_NODE
, &match_ipv6_address_cmd
);
3044 install_element (RMAP_NODE
, &no_match_ipv6_address_cmd
);
3046 install_element (RMAP_NODE
, &match_ipv6_address_prefix_list_cmd
);
3047 install_element (RMAP_NODE
, &no_match_ipv6_address_prefix_list_cmd
);
3049 install_element (RMAP_NODE
, &match_metric_cmd
);
3050 install_element (RMAP_NODE
, &no_match_metric_cmd
);
3052 install_element (RMAP_NODE
, &match_tag_cmd
);
3053 install_element (RMAP_NODE
, &no_match_tag_cmd
);
3055 install_element (RMAP_NODE
, &set_ip_nexthop_cmd
);
3056 install_element (RMAP_NODE
, &no_set_ip_nexthop_cmd
);
3058 install_element (RMAP_NODE
, &set_ipv6_nexthop_local_cmd
);
3059 install_element (RMAP_NODE
, &no_set_ipv6_nexthop_local_cmd
);
3061 install_element (RMAP_NODE
, &set_metric_cmd
);
3062 install_element (RMAP_NODE
, &no_set_metric_cmd
);
3064 install_element (RMAP_NODE
, &set_tag_cmd
);
3065 install_element (RMAP_NODE
, &no_set_tag_cmd
);