2 * Copyright (C) 2006 IBM Corporation
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
24 #include "zebra_memory.h"
35 #include "zebra/zserv.h"
36 #include "zebra/redistribute.h"
37 #include "zebra/debug.h"
38 #include "zebra/zebra_rnh.h"
39 #include "zebra/zebra_routemap.h"
41 static u_int32_t zebra_rmap_update_timer
= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
;
42 static struct thread
*zebra_t_rmap_update
= NULL
;
43 char *proto_rm
[AFI_MAX
][ZEBRA_ROUTE_MAX
+ 1]; /* "any" == ZEBRA_ROUTE_MAX */
44 /* NH Tracking route map */
45 char *nht_rm
[AFI_MAX
][ZEBRA_ROUTE_MAX
+ 1]; /* "any" == ZEBRA_ROUTE_MAX */
46 char *zebra_import_table_routemap
[AFI_MAX
][ZEBRA_KERNEL_TABLE_MAX
];
49 struct nexthop
*nexthop
;
51 u_int32_t source_protocol
;
56 static void zebra_route_map_set_delay_timer(u_int32_t value
);
59 /* Add zebra route map rule */
60 static int zebra_route_match_add(struct vty
*vty
, const char *command
,
61 const char *arg
, route_map_event_t type
)
63 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
66 ret
= route_map_add_match(index
, command
, arg
);
69 case RMAP_RULE_MISSING
:
70 vty_out(vty
, "%% Zebra Can't find rule.\n");
71 return CMD_WARNING_CONFIG_FAILED
;
72 case RMAP_COMPILE_ERROR
:
73 vty_out(vty
, "%% Zebra Argument is malformed.\n");
74 return CMD_WARNING_CONFIG_FAILED
;
78 if (type
!= RMAP_EVENT_MATCH_ADDED
) {
79 route_map_upd8_dependency(type
, arg
, index
->map
->name
);
84 /* Delete zebra route map rule. */
85 static int zebra_route_match_delete(struct vty
*vty
, const char *command
,
86 const char *arg
, route_map_event_t type
)
88 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
90 char *dep_name
= NULL
;
92 char *rmap_name
= NULL
;
94 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
95 /* ignore the mundane, the types without any dependency */
97 if ((tmpstr
= route_map_get_match_arg(index
, command
))
100 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
102 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
104 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
107 ret
= route_map_delete_match(index
, command
, arg
);
110 case RMAP_RULE_MISSING
:
111 vty_out(vty
, "%% Zebra Can't find rule.\n");
112 return CMD_WARNING_CONFIG_FAILED
;
113 case RMAP_COMPILE_ERROR
:
114 vty_out(vty
, "%% Zebra Argument is malformed.\n");
115 return CMD_WARNING_CONFIG_FAILED
;
119 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
120 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
123 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
125 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
131 * Match function return 1 if match is success else return 0
133 static route_map_result_t
route_match_tag(void *rule
, struct prefix
*prefix
,
134 route_map_object_t type
, void *object
)
137 struct nh_rmap_obj
*nh_data
;
139 if (type
== RMAP_ZEBRA
) {
143 if (nh_data
->tag
== *tag
)
149 /* Route map commands for tag matching */
150 static struct route_map_rule_cmd route_match_tag_cmd
= {
153 route_map_rule_tag_compile
,
154 route_map_rule_tag_free
,
158 /* `match interface IFNAME' */
159 /* Match function return 1 if match is success else return zero. */
160 static route_map_result_t
route_match_interface(void *rule
,
161 struct prefix
*prefix
,
162 route_map_object_t type
,
165 struct nh_rmap_obj
*nh_data
;
169 if (type
== RMAP_ZEBRA
) {
170 if (strcasecmp(ifname
, "any") == 0)
173 if (!nh_data
|| !nh_data
->nexthop
)
175 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
178 if (nh_data
->nexthop
->ifindex
== ifindex
)
184 /* Route map `match interface' match statement. `arg' is IFNAME value */
185 static void *route_match_interface_compile(const char *arg
)
187 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
190 /* Free route map's compiled `match interface' value. */
191 static void route_match_interface_free(void *rule
)
193 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
196 /* Route map commands for interface matching */
197 struct route_map_rule_cmd route_match_interface_cmd
= {
198 "interface", route_match_interface
, route_match_interface_compile
,
199 route_match_interface_free
};
201 DEFUN (match_ip_address_prefix_len
,
202 match_ip_address_prefix_len_cmd
,
203 "match ip address prefix-len (0-32)",
206 "Match prefix length of ip address\n"
207 "Match prefix length of ip address\n"
210 return zebra_route_match_add(vty
, "ip address prefix-len", argv
[4]->arg
,
211 RMAP_EVENT_MATCH_ADDED
);
214 DEFUN (no_match_ip_address_prefix_len
,
215 no_match_ip_address_prefix_len_cmd
,
216 "no match ip address prefix-len [(0-32)]",
220 "Match prefix length of ip address\n"
221 "Match prefix length of ip address\n"
224 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
225 return zebra_route_match_delete(vty
, "ip address prefix-len", plen
,
226 RMAP_EVENT_MATCH_DELETED
);
230 DEFUN (match_ip_nexthop_prefix_len
,
231 match_ip_nexthop_prefix_len_cmd
,
232 "match ip next-hop prefix-len (0-32)",
235 "Match prefixlen of nexthop ip address\n"
236 "Match prefixlen of given nexthop\n"
239 return zebra_route_match_add(vty
, "ip next-hop prefix-len",
240 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
243 DEFUN (no_match_ip_nexthop_prefix_len
,
244 no_match_ip_nexthop_prefix_len_cmd
,
245 "no match ip next-hop prefix-len [(0-32)]",
249 "Match prefixlen of nexthop ip address\n"
250 "Match prefix length of nexthop\n"
253 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
254 return zebra_route_match_delete(vty
, "ip next-hop prefix-len", plen
,
255 RMAP_EVENT_MATCH_DELETED
);
259 DEFUN (match_source_protocol
,
260 match_source_protocol_cmd
,
261 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>",
263 "Match protocol via which the route was learnt\n"
270 "Routes from directly connected peer\n"
271 "Routes from system configuration\n"
272 "Routes from kernel\n"
273 "Statically configured routes\n")
275 char *proto
= argv
[2]->text
;
278 i
= proto_name2num(proto
);
280 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
281 return CMD_WARNING_CONFIG_FAILED
;
283 return zebra_route_match_add(vty
, "source-protocol", proto
,
284 RMAP_EVENT_MATCH_ADDED
);
287 DEFUN (no_match_source_protocol
,
288 no_match_source_protocol_cmd
,
289 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>]",
292 "No match protocol via which the route was learnt\n"
299 "Routes from directly connected peer\n"
300 "Routes from system configuration\n"
301 "Routes from kernel\n"
302 "Statically configured routes\n")
304 char *proto
= (argc
== 4) ? argv
[3]->text
: NULL
;
305 return zebra_route_match_delete(vty
, "source-protocol", proto
,
306 RMAP_EVENT_MATCH_DELETED
);
313 "set src <A.B.C.D|X:X::X:X>",
315 "src address for route\n"
317 "IPv6 src address\n")
321 struct interface
*pif
= NULL
;
326 if (inet_pton(AF_INET
, argv
[idx_ip
]->arg
, &src
.ipv4
) != 1) {
327 if (inet_pton(AF_INET6
, argv
[idx_ip
]->arg
, &src
.ipv6
) != 1) {
328 vty_out(vty
, "%% not a valid IPv4/v6 address\n");
329 return CMD_WARNING_CONFIG_FAILED
;
332 p
.family
= family
= AF_INET6
;
333 p
.u
.prefix6
= src
.ipv6
;
334 p
.prefixlen
= IPV6_MAX_BITLEN
;
336 p
.family
= family
= AF_INET
;
337 p
.u
.prefix4
= src
.ipv4
;
338 p
.prefixlen
= IPV4_MAX_BITLEN
;
341 if (!zebra_check_addr(&p
)) {
342 vty_out(vty
, "%% not a valid source IPv4/v6 address\n");
343 return CMD_WARNING_CONFIG_FAILED
;
346 RB_FOREACH(vrf
, vrf_id_head
, &vrfs_by_id
)
348 if (family
== AF_INET
)
349 pif
= if_lookup_exact_address((void *)&src
.ipv4
,
350 AF_INET
, vrf
->vrf_id
);
351 else if (family
== AF_INET6
)
352 pif
= if_lookup_exact_address((void *)&src
.ipv6
,
353 AF_INET6
, vrf
->vrf_id
);
360 vty_out(vty
, "%% not a local address\n");
361 return CMD_WARNING_CONFIG_FAILED
;
364 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
365 return generic_set_add(vty
, index
, "src", argv
[idx_ip
]->arg
);
370 "no set src [<A.B.C.D|X:X::X:X>]",
373 "Source address for route\n"
377 char *ip
= (argc
== 4) ? argv
[3]->arg
: NULL
;
378 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
379 return generic_set_delete(vty
, index
, "src", ip
);
382 DEFUN (zebra_route_map_timer
,
383 zebra_route_map_timer_cmd
,
384 "zebra route-map delay-timer (0-600)",
385 "Zebra information\n"
386 "Set route-map parameters\n"
387 "Time to wait before route-map updates are processed\n"
388 "0 means event-driven updates are disabled\n")
391 u_int32_t rmap_delay_timer
;
393 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
394 zebra_route_map_set_delay_timer(rmap_delay_timer
);
396 return (CMD_SUCCESS
);
399 DEFUN (no_zebra_route_map_timer
,
400 no_zebra_route_map_timer_cmd
,
401 "no zebra route-map delay-timer [(0-600)]",
403 "Zebra information\n"
404 "Set route-map parameters\n"
405 "Reset delay-timer to default value, 30 secs\n"
406 "0 means event-driven updates are disabled\n")
408 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
410 return (CMD_SUCCESS
);
416 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
418 "Filter routing info exchanged between zebra and protocol\n"
419 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
420 "Specify route-map\n"
423 char *proto
= argv
[2]->text
;
424 char *rmap
= argv
[4]->arg
;
427 if (strcasecmp(proto
, "any") == 0)
430 i
= proto_name2num(proto
);
432 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
433 return CMD_WARNING_CONFIG_FAILED
;
435 if (proto_rm
[AFI_IP
][i
]) {
436 if (strcmp(proto_rm
[AFI_IP
][i
], rmap
) == 0)
439 XFREE(MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP
][i
]);
441 proto_rm
[AFI_IP
][i
] = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
443 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
445 "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
448 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
452 DEFUN (no_ip_protocol
,
454 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
457 "Stop filtering routing info between zebra and protocol\n"
458 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
459 "Specify route map\n"
462 char *proto
= argv
[3]->text
;
463 char *rmap
= (argc
== 6) ? argv
[5]->arg
: NULL
;
466 if (strcasecmp(proto
, "any") == 0)
469 i
= proto_name2num(proto
);
472 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
473 return CMD_WARNING_CONFIG_FAILED
;
476 if (!proto_rm
[AFI_IP
][i
])
479 if (!rmap
|| strcmp(rmap
, proto_rm
[AFI_IP
][i
]) == 0) {
480 XFREE(MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP
][i
]);
481 proto_rm
[AFI_IP
][i
] = NULL
;
483 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
485 "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
487 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
492 DEFUN (show_ip_protocol
,
493 show_ip_protocol_cmd
,
497 "IP protocol filtering status\n")
501 vty_out(vty
, "Protocol : route-map \n");
502 vty_out(vty
, "------------------------\n");
503 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
504 if (proto_rm
[AFI_IP
][i
])
505 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
506 proto_rm
[AFI_IP
][i
]);
508 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
510 if (proto_rm
[AFI_IP
][i
])
511 vty_out(vty
, "%-10s : %-10s\n", "any", proto_rm
[AFI_IP
][i
]);
513 vty_out(vty
, "%-10s : none\n", "any");
518 DEFUN (ipv6_protocol
,
520 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
522 "Filter IPv6 routing info exchanged between zebra and protocol\n"
523 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
524 "Specify route map\n"
527 char *proto
= argv
[2]->text
;
528 char *rmap
= argv
[4]->arg
;
531 if (strcasecmp(proto
, "any") == 0)
534 i
= proto_name2num(proto
);
536 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
537 return CMD_WARNING_CONFIG_FAILED
;
539 if (proto_rm
[AFI_IP6
][i
]) {
540 if (strcmp(proto_rm
[AFI_IP6
][i
], rmap
) == 0)
543 XFREE(MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP6
][i
]);
545 proto_rm
[AFI_IP6
][i
] = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
547 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
549 "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
552 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
556 DEFUN (no_ipv6_protocol
,
557 no_ipv6_protocol_cmd
,
558 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
561 "Stop filtering IPv6 routing info between zebra and protocol\n"
562 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
563 "Specify route map\n"
566 const char *proto
= argv
[3]->text
;
567 const char *rmap
= (argc
== 6) ? argv
[5]->arg
: NULL
;
570 if (strcasecmp(proto
, "any") == 0)
573 i
= proto_name2num(proto
);
575 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
576 return CMD_WARNING_CONFIG_FAILED
;
578 if (!proto_rm
[AFI_IP6
][i
])
581 if (!rmap
|| strcmp(rmap
, proto_rm
[AFI_IP6
][i
]) == 0) {
582 XFREE(MTYPE_ROUTE_MAP_NAME
, proto_rm
[AFI_IP6
][i
]);
583 proto_rm
[AFI_IP6
][i
] = NULL
;
585 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
587 "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
590 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
595 DEFUN (show_ipv6_protocol
,
596 show_ipv6_protocol_cmd
,
597 "show ipv6 protocol",
600 "IPv6 protocol filtering status\n")
604 vty_out(vty
, "Protocol : route-map \n");
605 vty_out(vty
, "------------------------\n");
606 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
607 if (proto_rm
[AFI_IP6
][i
])
608 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
609 proto_rm
[AFI_IP6
][i
]);
611 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
613 if (proto_rm
[AFI_IP6
][i
])
614 vty_out(vty
, "%-10s : %-10s\n", "any", proto_rm
[AFI_IP6
][i
]);
616 vty_out(vty
, "%-10s : none\n", "any");
621 DEFUN (ip_protocol_nht_rmap
,
622 ip_protocol_nht_rmap_cmd
,
623 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
625 "Filter Next Hop tracking route resolution\n"
626 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
627 "Specify route map\n"
630 char *proto
= argv
[2]->text
;
631 char *rmap
= argv
[4]->arg
;
634 if (strcasecmp(proto
, "any") == 0)
637 i
= proto_name2num(proto
);
639 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
640 return CMD_WARNING_CONFIG_FAILED
;
642 if (nht_rm
[AFI_IP
][i
]) {
643 if (strcmp(nht_rm
[AFI_IP
][i
], rmap
) == 0)
646 XFREE(MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP
][i
]);
649 nht_rm
[AFI_IP
][i
] = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
650 zebra_evaluate_rnh(0, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
655 DEFUN (no_ip_protocol_nht_rmap
,
656 no_ip_protocol_nht_rmap_cmd
,
657 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
660 "Filter Next Hop tracking route resolution\n"
661 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
662 "Specify route map\n"
666 char *proto
= argv
[3]->text
;
667 char *rmap
= argv_find(argv
, argc
, "ROUTE-MAP", &idx
) ? argv
[idx
]->arg
670 int i
= strmatch(proto
, "any") ? ZEBRA_ROUTE_MAX
671 : proto_name2num(proto
);
674 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
675 return CMD_WARNING_CONFIG_FAILED
;
678 if (!nht_rm
[AFI_IP
][i
])
681 if (!rmap
|| strcmp(rmap
, nht_rm
[AFI_IP
][i
]) == 0) {
682 XFREE(MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP
][i
]);
683 nht_rm
[AFI_IP
][i
] = NULL
;
684 zebra_evaluate_rnh(0, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
689 DEFUN (show_ip_protocol_nht
,
690 show_ip_protocol_nht_cmd
,
691 "show ip nht route-map",
694 "IP nexthop tracking table\n"
695 "IP Next Hop tracking filtering status\n")
699 vty_out(vty
, "Protocol : route-map \n");
700 vty_out(vty
, "------------------------\n");
701 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
702 if (nht_rm
[AFI_IP
][i
])
703 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
706 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
708 if (nht_rm
[AFI_IP
][i
])
709 vty_out(vty
, "%-10s : %-10s\n", "any", nht_rm
[AFI_IP
][i
]);
711 vty_out(vty
, "%-10s : none\n", "any");
716 DEFUN (ipv6_protocol_nht_rmap
,
717 ipv6_protocol_nht_rmap_cmd
,
718 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" route-map ROUTE-MAP",
720 "Filter Next Hop tracking route resolution\n"
721 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
722 "Specify route map\n"
725 char *proto
= argv
[2]->text
;
726 char *rmap
= argv
[4]->arg
;
729 if (strcasecmp(proto
, "any") == 0)
732 i
= proto_name2num(proto
);
734 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
735 return CMD_WARNING_CONFIG_FAILED
;
737 if (nht_rm
[AFI_IP6
][i
])
738 XFREE(MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP6
][i
]);
739 nht_rm
[AFI_IP6
][i
] = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
740 zebra_evaluate_rnh(0, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
745 DEFUN (no_ipv6_protocol_nht_rmap
,
746 no_ipv6_protocol_nht_rmap_cmd
,
747 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
" [route-map ROUTE-MAP]",
750 "Filter Next Hop tracking route resolution\n"
751 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
752 "Specify route map\n"
755 char *proto
= argv
[3]->text
;
756 char *rmap
= (argc
== 6) ? argv
[5]->arg
: NULL
;
759 if (strcasecmp(proto
, "any") == 0)
762 i
= proto_name2num(proto
);
764 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
765 return CMD_WARNING_CONFIG_FAILED
;
768 if (nht_rm
[AFI_IP6
][i
] && rmap
&& strcmp(rmap
, nht_rm
[AFI_IP6
][i
])) {
769 vty_out(vty
, "invalid route-map \"%s\"\n", rmap
);
770 return CMD_WARNING_CONFIG_FAILED
;
773 if (nht_rm
[AFI_IP6
][i
]) {
774 XFREE(MTYPE_ROUTE_MAP_NAME
, nht_rm
[AFI_IP6
][i
]);
775 nht_rm
[AFI_IP6
][i
] = NULL
;
778 zebra_evaluate_rnh(0, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
783 DEFUN (show_ipv6_protocol_nht
,
784 show_ipv6_protocol_nht_cmd
,
785 "show ipv6 nht route-map",
788 "Next Hop filtering status\n"
793 vty_out(vty
, "Protocol : route-map \n");
794 vty_out(vty
, "------------------------\n");
795 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
796 if (nht_rm
[AFI_IP6
][i
])
797 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
800 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
802 if (nht_rm
[AFI_IP
][i
])
803 vty_out(vty
, "%-10s : %-10s\n", "any", nht_rm
[AFI_IP6
][i
]);
805 vty_out(vty
, "%-10s : none\n", "any");
810 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
812 /* `match ip next-hop IP_ACCESS_LIST' */
814 /* Match function return 1 if match is success else return zero. */
815 static route_map_result_t
route_match_ip_next_hop(void *rule
,
816 struct prefix
*prefix
,
817 route_map_object_t type
,
820 struct access_list
*alist
;
821 struct nh_rmap_obj
*nh_data
;
822 struct prefix_ipv4 p
;
824 if (type
== RMAP_ZEBRA
) {
827 return RMAP_DENYMATCH
;
829 switch (nh_data
->nexthop
->type
) {
830 case NEXTHOP_TYPE_IFINDEX
:
831 /* Interface routes can't match ip next-hop */
833 case NEXTHOP_TYPE_IPV4_IFINDEX
:
834 case NEXTHOP_TYPE_IPV4
:
836 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
837 p
.prefixlen
= IPV4_MAX_BITLEN
;
842 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
846 return (access_list_apply(alist
, &p
) == FILTER_DENY
853 /* Route map `ip next-hop' match statement. `arg' should be
855 static void *route_match_ip_next_hop_compile(const char *arg
)
857 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
860 /* Free route map's compiled `. */
861 static void route_match_ip_next_hop_free(void *rule
)
863 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
866 /* Route map commands for ip next-hop matching. */
867 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
868 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
869 route_match_ip_next_hop_free
};
871 /* `match ip next-hop prefix-list PREFIX_LIST' */
873 static route_map_result_t
874 route_match_ip_next_hop_prefix_list(void *rule
, struct prefix
*prefix
,
875 route_map_object_t type
, void *object
)
877 struct prefix_list
*plist
;
878 struct nh_rmap_obj
*nh_data
;
879 struct prefix_ipv4 p
;
881 if (type
== RMAP_ZEBRA
) {
882 nh_data
= (struct nh_rmap_obj
*)object
;
884 return RMAP_DENYMATCH
;
886 switch (nh_data
->nexthop
->type
) {
887 case NEXTHOP_TYPE_IFINDEX
:
888 /* Interface routes can't match ip next-hop */
890 case NEXTHOP_TYPE_IPV4_IFINDEX
:
891 case NEXTHOP_TYPE_IPV4
:
893 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
894 p
.prefixlen
= IPV4_MAX_BITLEN
;
899 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
903 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
910 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
912 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
915 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
917 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
920 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
921 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
922 route_match_ip_next_hop_prefix_list_compile
,
923 route_match_ip_next_hop_prefix_list_free
};
925 /* `match ip address IP_ACCESS_LIST' */
927 /* Match function should return 1 if match is success else return
929 static route_map_result_t
route_match_ip_address(void *rule
,
930 struct prefix
*prefix
,
931 route_map_object_t type
,
934 struct access_list
*alist
;
936 if (type
== RMAP_ZEBRA
) {
937 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
941 return (access_list_apply(alist
, prefix
) == FILTER_DENY
948 /* Route map `ip address' match statement. `arg' should be
950 static void *route_match_ip_address_compile(const char *arg
)
952 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
955 /* Free route map's compiled `ip address' value. */
956 static void route_match_ip_address_free(void *rule
)
958 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
961 /* Route map commands for ip address matching. */
962 static struct route_map_rule_cmd route_match_ip_address_cmd
= {
963 "ip address", route_match_ip_address
, route_match_ip_address_compile
,
964 route_match_ip_address_free
};
966 /* `match ip address prefix-list PREFIX_LIST' */
968 static route_map_result_t
969 route_match_ip_address_prefix_list(void *rule
, struct prefix
*prefix
,
970 route_map_object_t type
, void *object
)
972 struct prefix_list
*plist
;
974 if (type
== RMAP_ZEBRA
) {
975 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
979 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
986 static void *route_match_ip_address_prefix_list_compile(const char *arg
)
988 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
991 static void route_match_ip_address_prefix_list_free(void *rule
)
993 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
996 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
997 "ip address prefix-list", route_match_ip_address_prefix_list
,
998 route_match_ip_address_prefix_list_compile
,
999 route_match_ip_address_prefix_list_free
};
1002 /* `match ip address prefix-len PREFIXLEN' */
1004 static route_map_result_t
1005 route_match_ip_address_prefix_len(void *rule
, struct prefix
*prefix
,
1006 route_map_object_t type
, void *object
)
1008 u_int32_t
*prefixlen
= (u_int32_t
*)rule
;
1010 if (type
== RMAP_ZEBRA
) {
1011 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
1014 return RMAP_NOMATCH
;
1017 static void *route_match_ip_address_prefix_len_compile(const char *arg
)
1019 u_int32_t
*prefix_len
;
1020 char *endptr
= NULL
;
1021 unsigned long tmpval
;
1023 /* prefix len value shoud be integer. */
1024 if (!all_digit(arg
))
1028 tmpval
= strtoul(arg
, &endptr
, 10);
1029 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1032 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(u_int32_t
));
1037 *prefix_len
= tmpval
;
1041 static void route_match_ip_address_prefix_len_free(void *rule
)
1043 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1046 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
= {
1047 "ip address prefix-len", route_match_ip_address_prefix_len
,
1048 route_match_ip_address_prefix_len_compile
,
1049 route_match_ip_address_prefix_len_free
};
1052 /* `match ip nexthop prefix-len PREFIXLEN' */
1054 static route_map_result_t
1055 route_match_ip_nexthop_prefix_len(void *rule
, struct prefix
*prefix
,
1056 route_map_object_t type
, void *object
)
1058 u_int32_t
*prefixlen
= (u_int32_t
*)rule
;
1059 struct nh_rmap_obj
*nh_data
;
1060 struct prefix_ipv4 p
;
1062 if (type
== RMAP_ZEBRA
) {
1063 nh_data
= (struct nh_rmap_obj
*)object
;
1064 if (!nh_data
|| !nh_data
->nexthop
)
1065 return RMAP_DENYMATCH
;
1067 switch (nh_data
->nexthop
->type
) {
1068 case NEXTHOP_TYPE_IFINDEX
:
1069 /* Interface routes can't match ip next-hop */
1070 return RMAP_NOMATCH
;
1071 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1072 case NEXTHOP_TYPE_IPV4
:
1074 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1075 p
.prefixlen
= IPV4_MAX_BITLEN
;
1078 return RMAP_NOMATCH
;
1080 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
1083 return RMAP_NOMATCH
;
1086 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
= {
1087 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len
,
1088 route_match_ip_address_prefix_len_compile
, /* reuse */
1089 route_match_ip_address_prefix_len_free
/* reuse */
1092 /* `match source-protocol PROTOCOL' */
1094 static route_map_result_t
route_match_source_protocol(void *rule
,
1095 struct prefix
*prefix
,
1096 route_map_object_t type
,
1099 u_int32_t
*rib_type
= (u_int32_t
*)rule
;
1100 struct nh_rmap_obj
*nh_data
;
1102 if (type
== RMAP_ZEBRA
) {
1103 nh_data
= (struct nh_rmap_obj
*)object
;
1105 return RMAP_DENYMATCH
;
1107 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1110 return RMAP_NOMATCH
;
1113 static void *route_match_source_protocol_compile(const char *arg
)
1115 u_int32_t
*rib_type
;
1118 i
= proto_name2num(arg
);
1119 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(u_int32_t
));
1126 static void route_match_source_protocol_free(void *rule
)
1128 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1131 static struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1132 "source-protocol", route_match_source_protocol
,
1133 route_match_source_protocol_compile
, route_match_source_protocol_free
};
1135 /* `set src A.B.C.D' */
1138 static route_map_result_t
route_set_src(void *rule
, struct prefix
*prefix
,
1139 route_map_object_t type
, void *object
)
1141 struct nh_rmap_obj
*nh_data
;
1143 if (type
== RMAP_ZEBRA
) {
1144 nh_data
= (struct nh_rmap_obj
*)object
;
1145 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1150 /* set src compilation. */
1151 static void *route_set_src_compile(const char *arg
)
1153 union g_addr src
, *psrc
;
1155 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1156 || (src
.ipv4
.s_addr
&& (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1))) {
1157 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1164 /* Free route map's compiled `set src' value. */
1165 static void route_set_src_free(void *rule
)
1167 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1170 /* Set src rule structure. */
1171 static struct route_map_rule_cmd route_set_src_cmd
= {
1174 route_set_src_compile
,
1178 static int zebra_route_map_update_timer(struct thread
*thread
)
1180 zebra_t_rmap_update
= NULL
;
1182 if (IS_ZEBRA_DEBUG_EVENT
)
1183 zlog_debug("Event driven route-map update triggered");
1185 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1187 "%u: Routemap update-timer fired, scheduling RIB processing",
1190 zebra_import_table_rm_update();
1191 rib_update(VRF_DEFAULT
, RIB_UPDATE_RMAP_CHANGE
);
1192 zebra_evaluate_rnh(0, AF_INET
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1193 zebra_evaluate_rnh(0, AF_INET6
, 1, RNH_NEXTHOP_TYPE
, NULL
);
1198 static void zebra_route_map_set_delay_timer(u_int32_t value
)
1200 zebra_rmap_update_timer
= value
;
1201 if (!value
&& zebra_t_rmap_update
) {
1202 /* Event driven route map updates is being disabled */
1203 /* But there's a pending timer. Fire it off now */
1204 thread_cancel(zebra_t_rmap_update
);
1205 zebra_route_map_update_timer(zebra_t_rmap_update
);
1209 void zebra_route_map_write_delay_timer(struct vty
*vty
)
1211 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1212 vty_out(vty
, "zebra route-map delay-timer %d\n",
1213 zebra_rmap_update_timer
);
1217 route_map_result_t
zebra_route_map_check(int family
, int rib_type
,
1219 struct nexthop
*nexthop
,
1220 vrf_id_t vrf_id
, route_tag_t tag
)
1222 struct route_map
*rmap
= NULL
;
1223 route_map_result_t ret
= RMAP_MATCH
;
1224 struct nh_rmap_obj nh_obj
;
1226 nh_obj
.nexthop
= nexthop
;
1227 nh_obj
.vrf_id
= vrf_id
;
1228 nh_obj
.source_protocol
= rib_type
;
1232 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1233 rmap
= route_map_lookup_by_name(proto_rm
[family
][rib_type
]);
1234 if (!rmap
&& proto_rm
[family
][ZEBRA_ROUTE_MAX
])
1235 rmap
= route_map_lookup_by_name(
1236 proto_rm
[family
][ZEBRA_ROUTE_MAX
]);
1238 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1244 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1246 return zebra_import_table_routemap
[afi
][table
];
1249 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1252 zebra_import_table_routemap
[afi
][table
] =
1253 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1256 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1258 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1262 zebra_import_table_route_map_check(int family
, int re_type
, struct prefix
*p
,
1263 struct nexthop
*nexthop
, vrf_id_t vrf_id
,
1264 route_tag_t tag
, const char *rmap_name
)
1266 struct route_map
*rmap
= NULL
;
1267 route_map_result_t ret
= RMAP_DENYMATCH
;
1268 struct nh_rmap_obj nh_obj
;
1270 nh_obj
.nexthop
= nexthop
;
1271 nh_obj
.vrf_id
= vrf_id
;
1272 nh_obj
.source_protocol
= re_type
;
1276 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1277 rmap
= route_map_lookup_by_name(rmap_name
);
1279 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1285 route_map_result_t
zebra_nht_route_map_check(int family
, int client_proto
,
1287 struct route_entry
*re
,
1288 struct nexthop
*nexthop
)
1290 struct route_map
*rmap
= NULL
;
1291 route_map_result_t ret
= RMAP_MATCH
;
1292 struct nh_rmap_obj nh_obj
;
1294 nh_obj
.nexthop
= nexthop
;
1295 nh_obj
.vrf_id
= re
->vrf_id
;
1296 nh_obj
.source_protocol
= re
->type
;
1297 nh_obj
.metric
= re
->metric
;
1298 nh_obj
.tag
= re
->tag
;
1300 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1301 rmap
= route_map_lookup_by_name(nht_rm
[family
][client_proto
]);
1302 if (!rmap
&& nht_rm
[family
][ZEBRA_ROUTE_MAX
])
1303 rmap
= route_map_lookup_by_name(
1304 nht_rm
[family
][ZEBRA_ROUTE_MAX
]);
1306 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1312 static void zebra_route_map_mark_update(const char *rmap_name
)
1314 /* rmap_update_timer of 0 means don't do route updates */
1315 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1316 zebra_t_rmap_update
= NULL
;
1317 thread_add_timer(zebrad
.master
, zebra_route_map_update_timer
,
1318 NULL
, zebra_rmap_update_timer
,
1319 &zebra_t_rmap_update
);
1323 static void zebra_route_map_add(const char *rmap_name
)
1325 zebra_route_map_mark_update(rmap_name
);
1326 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1329 static void zebra_route_map_delete(const char *rmap_name
)
1331 zebra_route_map_mark_update(rmap_name
);
1332 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1335 static void zebra_route_map_event(route_map_event_t event
,
1336 const char *rmap_name
)
1338 zebra_route_map_mark_update(rmap_name
);
1339 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1342 /* ip protocol configuration write function */
1343 void zebra_routemap_config_write_protocol(struct vty
*vty
)
1347 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1348 if (proto_rm
[AFI_IP
][i
])
1349 vty_out(vty
, "ip protocol %s route-map %s\n",
1350 zebra_route_string(i
), proto_rm
[AFI_IP
][i
]);
1352 if (proto_rm
[AFI_IP6
][i
])
1353 vty_out(vty
, "ipv6 protocol %s route-map %s\n",
1354 zebra_route_string(i
), proto_rm
[AFI_IP6
][i
]);
1356 if (nht_rm
[AFI_IP
][i
])
1357 vty_out(vty
, "ip nht %s route-map %s\n",
1358 zebra_route_string(i
), nht_rm
[AFI_IP
][i
]);
1360 if (nht_rm
[AFI_IP6
][i
])
1361 vty_out(vty
, "ipv6 nht %s route-map %s\n",
1362 zebra_route_string(i
), nht_rm
[AFI_IP6
][i
]);
1365 if (proto_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
])
1366 vty_out(vty
, "ip protocol %s route-map %s\n", "any",
1367 proto_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
]);
1369 if (proto_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
])
1370 vty_out(vty
, "ipv6 protocol %s route-map %s\n", "any",
1371 proto_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
]);
1373 if (nht_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
])
1374 vty_out(vty
, "ip nht %s route-map %s\n", "any",
1375 nht_rm
[AFI_IP
][ZEBRA_ROUTE_MAX
]);
1377 if (nht_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
])
1378 vty_out(vty
, "ipv6 nht %s route-map %s\n", "any",
1379 nht_rm
[AFI_IP6
][ZEBRA_ROUTE_MAX
]);
1381 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1382 vty_out(vty
, "zebra route-map delay-timer %d\n",
1383 zebra_rmap_update_timer
);
1386 void zebra_route_map_init()
1388 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1389 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1390 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1391 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1392 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1393 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1394 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1395 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1396 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1397 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1398 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1399 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1400 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1401 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1405 route_map_add_hook(zebra_route_map_add
);
1406 route_map_delete_hook(zebra_route_map_delete
);
1407 route_map_event_hook(zebra_route_map_event
);
1409 route_map_match_interface_hook(generic_match_add
);
1410 route_map_no_match_interface_hook(generic_match_delete
);
1412 route_map_match_ip_address_hook(generic_match_add
);
1413 route_map_no_match_ip_address_hook(generic_match_delete
);
1415 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1416 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1418 route_map_match_ip_next_hop_hook(generic_match_add
);
1419 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1421 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1422 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1424 route_map_match_tag_hook(generic_match_add
);
1425 route_map_no_match_tag_hook(generic_match_delete
);
1427 route_map_install_match(&route_match_tag_cmd
);
1428 route_map_install_match(&route_match_interface_cmd
);
1429 route_map_install_match(&route_match_ip_next_hop_cmd
);
1430 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
1431 route_map_install_match(&route_match_ip_address_cmd
);
1432 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
1433 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
1434 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
1435 route_map_install_match(&route_match_source_protocol_cmd
);
1437 route_map_install_set(&route_set_src_cmd
);
1439 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
1440 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
1441 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
1442 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
1443 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
1444 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
1446 install_element(RMAP_NODE
, &set_src_cmd
);
1447 install_element(RMAP_NODE
, &no_set_src_cmd
);