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
31 /* Vector for route match rules. */
32 static vector route_match_vec
;
34 /* Vector for route set rules. */
35 static vector route_set_vec
;
37 /* Route map rule. This rule has both `match' rule and `set' rule. */
41 struct route_map_rule_cmd
*cmd
;
43 /* For pretty printing. */
46 /* Pre-compiled match rule. */
50 struct route_map_rule
*next
;
51 struct route_map_rule
*prev
;
54 /* Making route map list. */
57 struct route_map
*head
;
58 struct route_map
*tail
;
60 void (*add_hook
) (const char *);
61 void (*delete_hook
) (const char *);
62 void (*event_hook
) (route_map_event_t
, const char *);
65 /* Master list of route map. */
66 static struct route_map_list route_map_master
= { NULL
, NULL
, NULL
, NULL
};
69 route_map_rule_delete (struct route_map_rule_list
*,
70 struct route_map_rule
*);
73 route_map_index_delete (struct route_map_index
*, int);
75 /* New route map allocation. Please note route map's name must be
77 static struct route_map
*
78 route_map_new (const char *name
)
80 struct route_map
*new;
82 new = XCALLOC (MTYPE_ROUTE_MAP
, sizeof (struct route_map
));
83 new->name
= XSTRDUP (MTYPE_ROUTE_MAP_NAME
, name
);
87 /* Add new name to route_map. */
88 static struct route_map
*
89 route_map_add (const char *name
)
91 struct route_map
*map
;
92 struct route_map_list
*list
;
94 map
= route_map_new (name
);
95 list
= &route_map_master
;
98 map
->prev
= list
->tail
;
100 list
->tail
->next
= map
;
106 if (route_map_master
.add_hook
)
107 (*route_map_master
.add_hook
) (name
);
112 /* Route map delete from list. */
114 route_map_delete (struct route_map
*map
)
116 struct route_map_list
*list
;
117 struct route_map_index
*index
;
120 while ((index
= map
->head
) != NULL
)
121 route_map_index_delete (index
, 0);
125 list
= &route_map_master
;
128 map
->next
->prev
= map
->prev
;
130 list
->tail
= map
->prev
;
133 map
->prev
->next
= map
->next
;
135 list
->head
= map
->next
;
137 XFREE (MTYPE_ROUTE_MAP
, map
);
139 /* Execute deletion hook. */
140 if (route_map_master
.delete_hook
)
141 (*route_map_master
.delete_hook
) (name
);
144 XFREE (MTYPE_ROUTE_MAP_NAME
, name
);
148 /* Lookup route map by route map name string. */
150 route_map_lookup_by_name (const char *name
)
152 struct route_map
*map
;
154 for (map
= route_map_master
.head
; map
; map
= map
->next
)
155 if (strcmp (map
->name
, name
) == 0)
160 /* Lookup route map. If there isn't route map create one and return
163 route_map_get (const char *name
)
165 struct route_map
*map
;
167 map
= route_map_lookup_by_name (name
);
169 map
= route_map_add (name
);
173 /* Return route map's type string. */
175 route_map_type_str (enum route_map_type type
)
192 route_map_empty (struct route_map
*map
)
194 if (map
->head
== NULL
&& map
->tail
== NULL
)
202 vty_show_route_map_entry (struct vty
*vty
, struct route_map
*map
)
204 struct route_map_index
*index
;
205 struct route_map_rule
*rule
;
207 for (index
= map
->head
; index
; index
= index
->next
)
209 vty_out (vty
, "route-map %s, %s, sequence %d%s",
210 map
->name
, route_map_type_str (index
->type
),
211 index
->pref
, VTY_NEWLINE
);
214 vty_out (vty
, " Match clauses:%s", VTY_NEWLINE
);
215 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
216 vty_out (vty
, " %s %s%s",
217 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
219 vty_out (vty
, " Set clauses:%s", VTY_NEWLINE
);
220 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
221 vty_out (vty
, " %s %s%s",
222 rule
->cmd
->str
, rule
->rule_str
, VTY_NEWLINE
);
224 vty_out (vty
, " Action:%s", VTY_NEWLINE
);
227 vty_out (vty
, " Call %s%s", index
->nextrm
, VTY_NEWLINE
);
228 else if (index
->exitpolicy
== RMAP_GOTO
)
229 vty_out (vty
, " Goto %d%s", index
->nextpref
, VTY_NEWLINE
);
230 else if (index
->exitpolicy
== RMAP_NEXT
)
232 vty_out (vty
, " Goto next, (entry ");
234 vty_out (vty
, " %d)%s", index
->next
->pref
, VTY_NEWLINE
);
236 vty_out (vty
, " undefined)%s", VTY_NEWLINE
);
238 else if (index
->exitpolicy
== RMAP_EXIT
)
239 vty_out (vty
, " Exit routemap%s", VTY_NEWLINE
);
244 vty_show_route_map (struct vty
*vty
, const char *name
)
246 struct route_map
*map
;
250 map
= route_map_lookup_by_name (name
);
254 vty_show_route_map_entry (vty
, map
);
259 vty_out (vty
, "%%route-map %s not found%s", name
, VTY_NEWLINE
);
267 /* New route map allocation. Please note route map's name must be
269 struct route_map_index
*
270 route_map_index_new ()
272 struct route_map_index
*new;
274 new = XCALLOC (MTYPE_ROUTE_MAP_INDEX
, sizeof (struct route_map_index
));
275 new->exitpolicy
= RMAP_EXIT
; /* Default to Cisco-style */
279 /* Free route map index. */
281 route_map_index_delete (struct route_map_index
*index
, int notify
)
283 struct route_map_rule
*rule
;
285 /* Free route match. */
286 while ((rule
= index
->match_list
.head
) != NULL
)
287 route_map_rule_delete (&index
->match_list
, rule
);
289 /* Free route set. */
290 while ((rule
= index
->set_list
.head
) != NULL
)
291 route_map_rule_delete (&index
->set_list
, rule
);
293 /* Remove index from route map list. */
295 index
->next
->prev
= index
->prev
;
297 index
->map
->tail
= index
->prev
;
300 index
->prev
->next
= index
->next
;
302 index
->map
->head
= index
->next
;
304 /* Free 'char *nextrm' if not NULL */
306 free (index
->nextrm
);
308 /* Execute event hook. */
309 if (route_map_master
.event_hook
&& notify
)
310 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_DELETED
,
313 XFREE (MTYPE_ROUTE_MAP_INDEX
, index
);
316 /* Lookup index from route map. */
317 struct route_map_index
*
318 route_map_index_lookup (struct route_map
*map
, enum route_map_type type
,
321 struct route_map_index
*index
;
323 for (index
= map
->head
; index
; index
= index
->next
)
324 if ((index
->type
== type
|| type
== RMAP_ANY
)
325 && index
->pref
== pref
)
330 /* Add new index to route map. */
331 struct route_map_index
*
332 route_map_index_add (struct route_map
*map
, enum route_map_type type
,
335 struct route_map_index
*index
;
336 struct route_map_index
*point
;
338 /* Allocate new route map inex. */
339 index
= route_map_index_new ();
344 /* Compare preference. */
345 for (point
= map
->head
; point
; point
= point
->next
)
346 if (point
->pref
>= pref
)
349 if (map
->head
== NULL
)
351 map
->head
= map
->tail
= index
;
353 else if (point
== NULL
)
355 index
->prev
= map
->tail
;
356 map
->tail
->next
= index
;
359 else if (point
== map
->head
)
361 index
->next
= map
->head
;
362 map
->head
->prev
= index
;
368 index
->prev
= point
->prev
;
370 point
->prev
->next
= index
;
374 /* Execute event hook. */
375 if (route_map_master
.event_hook
)
376 (*route_map_master
.event_hook
) (RMAP_EVENT_INDEX_ADDED
,
382 /* Get route map index. */
383 struct route_map_index
*
384 route_map_index_get (struct route_map
*map
, enum route_map_type type
,
387 struct route_map_index
*index
;
389 index
= route_map_index_lookup (map
, RMAP_ANY
, pref
);
390 if (index
&& index
->type
!= type
)
392 /* Delete index from route map. */
393 route_map_index_delete (index
, 1);
397 index
= route_map_index_add (map
, type
, pref
);
401 /* New route map rule */
402 struct route_map_rule
*
403 route_map_rule_new ()
405 struct route_map_rule
*new;
407 new = XCALLOC (MTYPE_ROUTE_MAP_RULE
, sizeof (struct route_map_rule
));
411 /* Install rule command to the match list. */
413 route_map_install_match (struct route_map_rule_cmd
*cmd
)
415 vector_set (route_match_vec
, cmd
);
418 /* Install rule command to the set list. */
420 route_map_install_set (struct route_map_rule_cmd
*cmd
)
422 vector_set (route_set_vec
, cmd
);
425 /* Lookup rule command from match list. */
426 struct route_map_rule_cmd
*
427 route_map_lookup_match (const char *name
)
430 struct route_map_rule_cmd
*rule
;
432 for (i
= 0; i
< vector_active (route_match_vec
); i
++)
433 if ((rule
= vector_slot (route_match_vec
, i
)) != NULL
)
434 if (strcmp (rule
->str
, name
) == 0)
439 /* Lookup rule command from set list. */
440 struct route_map_rule_cmd
*
441 route_map_lookup_set (const char *name
)
444 struct route_map_rule_cmd
*rule
;
446 for (i
= 0; i
< vector_active (route_set_vec
); i
++)
447 if ((rule
= vector_slot (route_set_vec
, i
)) != NULL
)
448 if (strcmp (rule
->str
, name
) == 0)
453 /* Add match and set rule to rule list. */
455 route_map_rule_add (struct route_map_rule_list
*list
,
456 struct route_map_rule
*rule
)
459 rule
->prev
= list
->tail
;
461 list
->tail
->next
= rule
;
467 /* Delete rule from rule list. */
469 route_map_rule_delete (struct route_map_rule_list
*list
,
470 struct route_map_rule
*rule
)
472 if (rule
->cmd
->func_free
)
473 (*rule
->cmd
->func_free
) (rule
->value
);
476 XFREE (MTYPE_ROUTE_MAP_RULE_STR
, rule
->rule_str
);
479 rule
->next
->prev
= rule
->prev
;
481 list
->tail
= rule
->prev
;
483 rule
->prev
->next
= rule
->next
;
485 list
->head
= rule
->next
;
487 XFREE (MTYPE_ROUTE_MAP_RULE
, rule
);
490 /* strcmp wrapper function which don't crush even argument is NULL. */
492 rulecmp (const char *dst
, const char *src
)
506 return strcmp (dst
, src
);
511 /* Add match statement to route map. */
513 route_map_add_match (struct route_map_index
*index
, const char *match_name
,
514 const char *match_arg
)
516 struct route_map_rule
*rule
;
517 struct route_map_rule
*next
;
518 struct route_map_rule_cmd
*cmd
;
522 /* First lookup rule for add match statement. */
523 cmd
= route_map_lookup_match (match_name
);
525 return RMAP_RULE_MISSING
;
527 /* Next call compile function for this match statement. */
528 if (cmd
->func_compile
)
530 compile
= (*cmd
->func_compile
)(match_arg
);
532 return RMAP_COMPILE_ERROR
;
537 /* If argument is completely same ignore it. */
538 for (rule
= index
->match_list
.head
; rule
; rule
= next
)
541 if (rule
->cmd
== cmd
)
543 route_map_rule_delete (&index
->match_list
, rule
);
548 /* Add new route map match rule. */
549 rule
= route_map_rule_new ();
551 rule
->value
= compile
;
553 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, match_arg
);
555 rule
->rule_str
= NULL
;
557 /* Add new route match rule to linked list. */
558 route_map_rule_add (&index
->match_list
, rule
);
560 /* Execute event hook. */
561 if (route_map_master
.event_hook
)
562 (*route_map_master
.event_hook
) (replaced
?
563 RMAP_EVENT_MATCH_REPLACED
:
564 RMAP_EVENT_MATCH_ADDED
,
570 /* Delete specified route match rule. */
572 route_map_delete_match (struct route_map_index
*index
, const char *match_name
,
573 const char *match_arg
)
575 struct route_map_rule
*rule
;
576 struct route_map_rule_cmd
*cmd
;
578 cmd
= route_map_lookup_match (match_name
);
582 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
583 if (rule
->cmd
== cmd
&&
584 (rulecmp (rule
->rule_str
, match_arg
) == 0 || match_arg
== NULL
))
586 route_map_rule_delete (&index
->match_list
, rule
);
587 /* Execute event hook. */
588 if (route_map_master
.event_hook
)
589 (*route_map_master
.event_hook
) (RMAP_EVENT_MATCH_DELETED
,
593 /* Can't find matched rule. */
597 /* Add route-map set statement to the route map. */
599 route_map_add_set (struct route_map_index
*index
, const char *set_name
,
602 struct route_map_rule
*rule
;
603 struct route_map_rule
*next
;
604 struct route_map_rule_cmd
*cmd
;
608 cmd
= route_map_lookup_set (set_name
);
610 return RMAP_RULE_MISSING
;
612 /* Next call compile function for this match statement. */
613 if (cmd
->func_compile
)
615 compile
= (*cmd
->func_compile
)(set_arg
);
617 return RMAP_COMPILE_ERROR
;
622 /* Add by WJL. if old set command of same kind exist, delete it first
623 to ensure only one set command of same kind exist under a
625 for (rule
= index
->set_list
.head
; rule
; rule
= next
)
628 if (rule
->cmd
== cmd
)
630 route_map_rule_delete (&index
->set_list
, rule
);
635 /* Add new route map match rule. */
636 rule
= route_map_rule_new ();
638 rule
->value
= compile
;
640 rule
->rule_str
= XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR
, set_arg
);
642 rule
->rule_str
= NULL
;
644 /* Add new route match rule to linked list. */
645 route_map_rule_add (&index
->set_list
, rule
);
647 /* Execute event hook. */
648 if (route_map_master
.event_hook
)
649 (*route_map_master
.event_hook
) (replaced
?
650 RMAP_EVENT_SET_REPLACED
:
651 RMAP_EVENT_SET_ADDED
,
656 /* Delete route map set rule. */
658 route_map_delete_set (struct route_map_index
*index
, const char *set_name
,
661 struct route_map_rule
*rule
;
662 struct route_map_rule_cmd
*cmd
;
664 cmd
= route_map_lookup_set (set_name
);
668 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
669 if ((rule
->cmd
== cmd
) &&
670 (rulecmp (rule
->rule_str
, set_arg
) == 0 || set_arg
== NULL
))
672 route_map_rule_delete (&index
->set_list
, rule
);
673 /* Execute event hook. */
674 if (route_map_master
.event_hook
)
675 (*route_map_master
.event_hook
) (RMAP_EVENT_SET_DELETED
,
679 /* Can't find matched rule. */
683 /* Apply route map's each index to the object.
685 The matrix for a route-map looks like this:
686 (note, this includes the description for the "NEXT"
693 ------------------+---------------
699 -Apply Set statements, accept route
700 -If Call statement is present jump to the specified route-map, if it
701 denies the route we finish.
702 -If NEXT is specified, goto NEXT statement
703 -If GOTO is specified, goto the first clause where pref > nextpref
704 -If nothing is specified, do as Cisco and finish
706 -Route is denied by route-map.
710 If we get no matches after we've processed all updates, then the route
713 Some notes on the new "CALL", "NEXT" and "GOTO"
714 call WORD - If this clause is matched, then the set statements
715 are executed and then we jump to route-map 'WORD'. If
716 this route-map denies the route, we finish, in other case we
717 do whatever the exit policy (EXIT, NEXT or GOTO) tells.
718 on-match next - If this clause is matched, then the set statements
719 are executed and then we drop through to the next clause
720 on-match goto n - If this clause is matched, then the set statments
721 are executed and then we goto the nth clause, or the
722 first clause greater than this. In order to ensure
723 route-maps *always* exit, you cannot jump backwards.
726 We need to make sure our route-map processing matches the above
730 route_map_apply_match (struct route_map_rule_list
*match_list
,
731 struct prefix
*prefix
, route_map_object_t type
,
734 route_map_result_t ret
= RMAP_NOMATCH
;
735 struct route_map_rule
*match
;
738 /* Check all match rule and if there is no match rule, go to the
740 if (!match_list
->head
)
744 for (match
= match_list
->head
; match
; match
= match
->next
)
746 /* Try each match statement in turn, If any do not return
747 RMAP_MATCH, return, otherwise continue on to next match
748 statement. All match statements must match for end-result
750 ret
= (*match
->cmd
->func_apply
) (match
->value
, prefix
,
752 if (ret
!= RMAP_MATCH
)
759 /* Apply route map to the object. */
761 route_map_apply (struct route_map
*map
, struct prefix
*prefix
,
762 route_map_object_t type
, void *object
)
764 static int recursion
= 0;
766 struct route_map_index
*index
;
767 struct route_map_rule
*set
;
769 if (recursion
> RMAP_RECURSION_LIMIT
)
771 zlog (NULL
, LOG_WARNING
,
772 "route-map recursion limit (%d) reached, discarding route",
773 RMAP_RECURSION_LIMIT
);
775 return RMAP_DENYMATCH
;
779 return RMAP_DENYMATCH
;
781 for (index
= map
->head
; index
; index
= index
->next
)
783 /* Apply this index. */
784 ret
= route_map_apply_match (&index
->match_list
, prefix
, type
, object
);
786 /* Now we apply the matrix from above */
787 if (ret
== RMAP_NOMATCH
)
788 /* 'cont' from matrix - continue to next route-map sequence */
790 else if (ret
== RMAP_MATCH
)
792 if (index
->type
== RMAP_PERMIT
)
795 /* permit+match must execute sets */
796 for (set
= index
->set_list
.head
; set
; set
= set
->next
)
797 ret
= (*set
->cmd
->func_apply
) (set
->value
, prefix
,
800 /* Call another route-map if available */
803 struct route_map
*nextrm
=
804 route_map_lookup_by_name (index
->nextrm
);
806 if (nextrm
) /* Target route-map found, jump to it */
809 ret
= route_map_apply (nextrm
, prefix
, type
, object
);
813 /* If nextrm returned 'deny', finish. */
814 if (ret
== RMAP_DENYMATCH
)
818 switch (index
->exitpolicy
)
826 /* Find the next clause to jump to */
827 struct route_map_index
*next
= index
->next
;
828 int nextpref
= index
->nextpref
;
830 while (next
&& next
->pref
< nextpref
)
837 /* No clauses match! */
843 else if (index
->type
== RMAP_DENY
)
846 return RMAP_DENYMATCH
;
850 /* Finally route-map does not match at all. */
851 return RMAP_DENYMATCH
;
855 route_map_add_hook (void (*func
) (const char *))
857 route_map_master
.add_hook
= func
;
861 route_map_delete_hook (void (*func
) (const char *))
863 route_map_master
.delete_hook
= func
;
867 route_map_event_hook (void (*func
) (route_map_event_t
, const char *))
869 route_map_master
.event_hook
= func
;
875 /* Make vector for match and set. */
876 route_match_vec
= vector_init (1);
877 route_set_vec
= vector_init (1);
880 /* VTY related functions. */
883 "route-map WORD (deny|permit) <1-65535>",
884 "Create route-map or enter route-map command mode\n"
886 "Route map denies set operations\n"
887 "Route map permits set operations\n"
888 "Sequence to insert to/delete from existing route-map entry\n")
892 struct route_map
*map
;
893 struct route_map_index
*index
;
897 if (strncmp (argv
[1], "permit", strlen (argv
[1])) == 0)
898 permit
= RMAP_PERMIT
;
899 else if (strncmp (argv
[1], "deny", strlen (argv
[1])) == 0)
903 vty_out (vty
, "the third field must be [permit|deny]%s", VTY_NEWLINE
);
907 /* Preference check. */
908 pref
= strtoul (argv
[2], &endptr
, 10);
909 if (pref
== ULONG_MAX
|| *endptr
!= '\0')
911 vty_out (vty
, "the fourth field must be positive integer%s",
915 if (pref
== 0 || pref
> 65535)
917 vty_out (vty
, "the fourth field must be <1-65535>%s", VTY_NEWLINE
);
922 map
= route_map_get (argv
[0]);
923 index
= route_map_index_get (map
, permit
, pref
);
926 vty
->node
= RMAP_NODE
;
930 DEFUN (no_route_map_all
,
931 no_route_map_all_cmd
,
934 "Create route-map or enter route-map command mode\n"
937 struct route_map
*map
;
939 map
= route_map_lookup_by_name (argv
[0]);
942 vty_out (vty
, "%% Could not find route-map %s%s",
943 argv
[0], VTY_NEWLINE
);
947 route_map_delete (map
);
954 "no route-map WORD (deny|permit) <1-65535>",
956 "Create route-map or enter route-map command mode\n"
958 "Route map denies set operations\n"
959 "Route map permits set operations\n"
960 "Sequence to insert to/delete from existing route-map entry\n")
964 struct route_map
*map
;
965 struct route_map_index
*index
;
969 if (strncmp (argv
[1], "permit", strlen (argv
[1])) == 0)
970 permit
= RMAP_PERMIT
;
971 else if (strncmp (argv
[1], "deny", strlen (argv
[1])) == 0)
975 vty_out (vty
, "the third field must be [permit|deny]%s", VTY_NEWLINE
);
980 pref
= strtoul (argv
[2], &endptr
, 10);
981 if (pref
== ULONG_MAX
|| *endptr
!= '\0')
983 vty_out (vty
, "the fourth field must be positive integer%s",
987 if (pref
== 0 || pref
> 65535)
989 vty_out (vty
, "the fourth field must be <1-65535>%s", VTY_NEWLINE
);
993 /* Existence check. */
994 map
= route_map_lookup_by_name (argv
[0]);
997 vty_out (vty
, "%% Could not find route-map %s%s",
998 argv
[0], VTY_NEWLINE
);
1002 /* Lookup route map index. */
1003 index
= route_map_index_lookup (map
, permit
, pref
);
1006 vty_out (vty
, "%% Could not find route-map entry %s %s%s",
1007 argv
[0], argv
[2], VTY_NEWLINE
);
1011 /* Delete index from route map. */
1012 route_map_index_delete (index
, 1);
1014 /* If this route rule is the last one, delete route map itself. */
1015 if (route_map_empty (map
))
1016 route_map_delete (map
);
1021 DEFUN (rmap_onmatch_next
,
1022 rmap_onmatch_next_cmd
,
1024 "Exit policy on matches\n"
1027 struct route_map_index
*index
;
1032 index
->exitpolicy
= RMAP_NEXT
;
1037 DEFUN (no_rmap_onmatch_next
,
1038 no_rmap_onmatch_next_cmd
,
1041 "Exit policy on matches\n"
1044 struct route_map_index
*index
;
1049 index
->exitpolicy
= RMAP_EXIT
;
1054 DEFUN (rmap_onmatch_goto
,
1055 rmap_onmatch_goto_cmd
,
1056 "on-match goto <1-65535>",
1057 "Exit policy on matches\n"
1058 "Goto Clause number\n"
1061 struct route_map_index
*index
;
1070 if (d
<= index
->pref
)
1072 /* Can't allow you to do that, Dave */
1073 vty_out (vty
, "can't jump backwards in route-maps%s",
1079 index
->exitpolicy
= RMAP_GOTO
;
1080 index
->nextpref
= d
;
1086 DEFUN (no_rmap_onmatch_goto
,
1087 no_rmap_onmatch_goto_cmd
,
1090 "Exit policy on matches\n"
1091 "Goto Clause number\n")
1093 struct route_map_index
*index
;
1098 index
->exitpolicy
= RMAP_EXIT
;
1103 /* Cisco/GNU Zebra compatible ALIASes for on-match next */
1104 ALIAS (rmap_onmatch_goto
,
1107 "Continue on a different entry within the route-map\n")
1109 ALIAS (no_rmap_onmatch_goto
,
1110 no_rmap_continue_cmd
,
1113 "Continue on a different entry within the route-map\n")
1115 /* GNU Zebra compatible */
1116 ALIAS (rmap_onmatch_goto
,
1117 rmap_continue_seq_cmd
,
1118 "continue <1-65535>",
1119 "Continue on a different entry within the route-map\n"
1120 "Route-map entry sequence number\n")
1122 ALIAS (no_rmap_onmatch_goto
,
1123 no_rmap_continue_seq
,
1124 "no continue <1-65535>",
1126 "Continue on a different entry within the route-map\n"
1127 "Route-map entry sequence number\n")
1133 "route-map information\n")
1135 return vty_show_route_map (vty
, NULL
);
1138 DEFUN (rmap_show_name
,
1140 "show route-map WORD",
1142 "route-map information\n"
1145 return vty_show_route_map (vty
, argv
[0]);
1148 ALIAS (rmap_onmatch_goto
,
1149 rmap_continue_index_cmd
,
1150 "continue <1-65536>",
1151 "Exit policy on matches\n"
1152 "Goto Clause number\n")
1157 "Jump to another Route-Map after match+set\n"
1158 "Target route-map name\n")
1160 struct route_map_index
*index
;
1166 free (index
->nextrm
);
1167 index
->nextrm
= strdup (argv
[0]);
1172 DEFUN (no_rmap_call
,
1176 "Jump to another Route-Map after match+set\n")
1178 struct route_map_index
*index
;
1184 free (index
->nextrm
);
1185 index
->nextrm
= NULL
;
1191 DEFUN (rmap_description
,
1192 rmap_description_cmd
,
1193 "description .LINE",
1194 "Route-map comment\n"
1195 "Comment describing this route-map rule\n")
1197 struct route_map_index
*index
;
1202 if (index
->description
)
1203 XFREE (MTYPE_TMP
, index
->description
);
1204 index
->description
= argv_concat (argv
, argc
, 0);
1209 DEFUN (no_rmap_description
,
1210 no_rmap_description_cmd
,
1213 "Route-map comment\n")
1215 struct route_map_index
*index
;
1220 if (index
->description
)
1221 XFREE (MTYPE_TMP
, index
->description
);
1222 index
->description
= NULL
;
1227 /* Configuration write function. */
1229 route_map_config_write (struct vty
*vty
)
1231 struct route_map
*map
;
1232 struct route_map_index
*index
;
1233 struct route_map_rule
*rule
;
1237 for (map
= route_map_master
.head
; map
; map
= map
->next
)
1238 for (index
= map
->head
; index
; index
= index
->next
)
1241 vty_out (vty
, "!%s", VTY_NEWLINE
);
1245 vty_out (vty
, "route-map %s %s %d%s",
1247 route_map_type_str (index
->type
),
1248 index
->pref
, VTY_NEWLINE
);
1250 if (index
->description
)
1251 vty_out (vty
, " description %s%s", index
->description
, VTY_NEWLINE
);
1253 for (rule
= index
->match_list
.head
; rule
; rule
= rule
->next
)
1254 vty_out (vty
, " match %s %s%s", rule
->cmd
->str
,
1255 rule
->rule_str
? rule
->rule_str
: "",
1258 for (rule
= index
->set_list
.head
; rule
; rule
= rule
->next
)
1259 vty_out (vty
, " set %s %s%s", rule
->cmd
->str
,
1260 rule
->rule_str
? rule
->rule_str
: "",
1263 vty_out (vty
, " call %s%s", index
->nextrm
, VTY_NEWLINE
);
1264 if (index
->exitpolicy
== RMAP_GOTO
)
1265 vty_out (vty
, " on-match goto %d%s", index
->nextpref
, VTY_NEWLINE
);
1266 if (index
->exitpolicy
== RMAP_NEXT
)
1267 vty_out (vty
," on-match next%s", VTY_NEWLINE
);
1274 /* Route map node structure. */
1275 struct cmd_node rmap_node
=
1278 "%s(config-route-map)# ",
1282 /* Initialization of route map vector. */
1284 route_map_init_vty ()
1286 /* Install route map top node. */
1287 install_node (&rmap_node
, route_map_config_write
);
1289 /* Install route map commands. */
1290 install_default (RMAP_NODE
);
1291 install_element (CONFIG_NODE
, &route_map_cmd
);
1292 install_element (CONFIG_NODE
, &no_route_map_cmd
);
1293 install_element (CONFIG_NODE
, &no_route_map_all_cmd
);
1295 /* Install the on-match stuff */
1296 install_element (RMAP_NODE
, &route_map_cmd
);
1297 install_element (RMAP_NODE
, &rmap_onmatch_next_cmd
);
1298 install_element (RMAP_NODE
, &no_rmap_onmatch_next_cmd
);
1299 install_element (RMAP_NODE
, &rmap_onmatch_goto_cmd
);
1300 install_element (RMAP_NODE
, &no_rmap_onmatch_goto_cmd
);
1302 /* Install the continue stuff (ALIAS of on-match). */
1303 install_element (RMAP_NODE
, &rmap_continue_cmd
);
1304 install_element (RMAP_NODE
, &no_rmap_continue_cmd
);
1305 install_element (RMAP_NODE
, &rmap_continue_index_cmd
);
1307 /* Install the call stuff. */
1308 install_element (RMAP_NODE
, &rmap_call_cmd
);
1309 install_element (RMAP_NODE
, &no_rmap_call_cmd
);
1311 /* Install description commands. */
1312 install_element (RMAP_NODE
, &rmap_description_cmd
);
1313 install_element (RMAP_NODE
, &no_rmap_description_cmd
);
1315 /* Install show command */
1316 install_element (ENABLE_NODE
, &rmap_show_cmd
);
1317 install_element (ENABLE_NODE
, &rmap_show_name_cmd
);