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"
36 #include "zebra/zebra_router.h"
37 #include "zebra/redistribute.h"
38 #include "zebra/debug.h"
39 #include "zebra/zebra_rnh.h"
40 #include "zebra/zebra_routemap.h"
42 #ifndef VTYSH_EXTRACT_PL
43 #include "zebra/zebra_routemap_clippy.c"
46 static uint32_t zebra_rmap_update_timer
= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
;
47 static struct thread
*zebra_t_rmap_update
= NULL
;
48 char *zebra_import_table_routemap
[AFI_MAX
][ZEBRA_KERNEL_TABLE_MAX
];
51 struct nexthop
*nexthop
;
53 uint32_t source_protocol
;
59 static void zebra_route_map_set_delay_timer(uint32_t value
);
62 /* Add zebra route map rule */
63 static int zebra_route_match_add(struct vty
*vty
, const char *command
,
64 const char *arg
, route_map_event_t type
)
66 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
67 enum rmap_compile_rets ret
;
68 int retval
= CMD_SUCCESS
;
70 ret
= route_map_add_match(index
, command
, arg
, type
);
72 case RMAP_RULE_MISSING
:
73 vty_out(vty
, "%% Zebra Can't find rule.\n");
74 retval
= CMD_WARNING_CONFIG_FAILED
;
76 case RMAP_COMPILE_ERROR
:
77 vty_out(vty
, "%% Zebra Argument is malformed.\n");
78 retval
= CMD_WARNING_CONFIG_FAILED
;
80 case RMAP_COMPILE_SUCCESS
:
81 if (type
!= RMAP_EVENT_MATCH_ADDED
) {
82 route_map_upd8_dependency(type
, arg
, index
->map
->name
);
85 case RMAP_DUPLICATE_RULE
:
95 /* Delete zebra route map rule. */
96 static int zebra_route_match_delete(struct vty
*vty
, const char *command
,
97 const char *arg
, route_map_event_t type
)
99 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
100 enum rmap_compile_rets ret
;
101 int retval
= CMD_SUCCESS
;
102 char *dep_name
= NULL
;
104 char *rmap_name
= NULL
;
106 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
107 /* ignore the mundane, the types without any dependency */
109 if ((tmpstr
= route_map_get_match_arg(index
, command
))
112 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
114 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
116 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
119 ret
= route_map_delete_match(index
, command
, arg
);
121 case RMAP_RULE_MISSING
:
122 vty_out(vty
, "%% Zebra Can't find rule.\n");
123 retval
= CMD_WARNING_CONFIG_FAILED
;
125 case RMAP_COMPILE_ERROR
:
126 vty_out(vty
, "%% Zebra Argument is malformed.\n");
127 retval
= CMD_WARNING_CONFIG_FAILED
;
129 case RMAP_COMPILE_SUCCESS
:
130 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
131 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
133 case RMAP_DUPLICATE_RULE
:
140 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
141 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
147 * Match function return 1 if match is success else return 0
149 static enum route_map_cmd_result_t
150 route_match_tag(void *rule
, const struct prefix
*prefix
,
151 route_map_object_t type
, void *object
)
154 struct nh_rmap_obj
*nh_data
;
156 if (type
== RMAP_ZEBRA
) {
160 if (nh_data
->tag
== *tag
)
166 /* Route map commands for tag matching */
167 static struct route_map_rule_cmd route_match_tag_cmd
= {
168 "tag", route_match_tag
, route_map_rule_tag_compile
,
169 route_map_rule_tag_free
,
173 /* `match interface IFNAME' */
174 /* Match function return 1 if match is success else return zero. */
175 static enum route_map_cmd_result_t
176 route_match_interface(void *rule
, const struct prefix
*prefix
,
177 route_map_object_t type
, void *object
)
179 struct nh_rmap_obj
*nh_data
;
183 if (type
== RMAP_ZEBRA
) {
184 if (strcasecmp(ifname
, "any") == 0)
187 if (!nh_data
|| !nh_data
->nexthop
)
189 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
192 if (nh_data
->nexthop
->ifindex
== ifindex
)
198 /* Route map `match interface' match statement. `arg' is IFNAME value */
199 static void *route_match_interface_compile(const char *arg
)
201 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
204 /* Free route map's compiled `match interface' value. */
205 static void route_match_interface_free(void *rule
)
207 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
210 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
215 vty_out(vty
, "Protocol : route-map\n");
216 vty_out(vty
, "------------------------\n");
218 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
219 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
220 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
221 PROTO_RM_NAME(zvrf
, af_type
, i
));
223 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
226 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
227 vty_out(vty
, "%-10s : %-10s\n", "any",
228 PROTO_RM_NAME(zvrf
, af_type
, i
));
230 vty_out(vty
, "%-10s : none\n", "any");
233 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
238 vty_out(vty
, "Protocol : route-map\n");
239 vty_out(vty
, "------------------------\n");
241 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
242 if (NHT_RM_NAME(zvrf
, af_type
, i
))
243 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
244 NHT_RM_NAME(zvrf
, af_type
, i
));
246 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
249 if (NHT_RM_NAME(zvrf
, af_type
, i
))
250 vty_out(vty
, "%-10s : %-10s\n", "any",
251 NHT_RM_NAME(zvrf
, af_type
, i
));
253 vty_out(vty
, "%-10s : none\n", "any");
256 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
257 const char *vrf_name
)
259 struct zebra_vrf
*zvrf
;
264 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
265 zvrf
= (struct zebra_vrf
*)vrf
->info
;
268 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
269 show_vrf_proto_rm(vty
, zvrf
, af_type
);
272 vrf_id_t vrf_id
= VRF_DEFAULT
;
275 VRF_GET_ID(vrf_id
, vrf_name
, false);
277 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
281 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
282 show_vrf_proto_rm(vty
, zvrf
, af_type
);
288 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
289 const char *vrf_name
)
291 struct zebra_vrf
*zvrf
;
296 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
297 zvrf
= (struct zebra_vrf
*)vrf
->info
;
301 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
302 show_vrf_nht_rm(vty
, zvrf
, af_type
);
305 vrf_id_t vrf_id
= VRF_DEFAULT
;
308 VRF_GET_ID(vrf_id
, vrf_name
, false);
310 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
314 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
315 show_vrf_nht_rm(vty
, zvrf
, af_type
);
321 /* Route map commands for interface matching */
322 struct route_map_rule_cmd route_match_interface_cmd
= {
323 "interface", route_match_interface
, route_match_interface_compile
,
324 route_match_interface_free
};
326 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
327 int rtype
, afi_t afi
, safi_t safi
)
329 struct route_table
*table
;
331 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
332 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
335 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
337 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
338 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
339 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
340 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
341 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
343 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
345 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
347 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
348 zvrf
->vrf
->vrf_id
, rtype
);
349 /* Process routes of interested address-families. */
350 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
352 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
358 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
359 int rtype
, afi_t afi
, safi_t safi
)
361 struct route_table
*table
;
363 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
366 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
368 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
369 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
370 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
372 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
373 zvrf
->vrf
->vrf_id
, rtype
);
374 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
376 /* Process routes of interested address-families. */
377 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
379 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
381 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
386 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
390 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
391 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
394 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
396 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
397 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
398 NHT_RM_MAP(zvrf
, afi
, rtype
) =
399 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
400 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
402 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
403 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
, NULL
);
408 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
412 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
415 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
416 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
417 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
418 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
420 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
421 zvrf
->vrf
->vrf_id
, rtype
);
422 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
424 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
,
427 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
432 DEFUN (match_ip_address_prefix_len
,
433 match_ip_address_prefix_len_cmd
,
434 "match ip address prefix-len (0-32)",
437 "Match prefix length of ip address\n"
438 "Match prefix length of ip address\n"
441 return zebra_route_match_add(vty
, "ip address prefix-len", argv
[4]->arg
,
442 RMAP_EVENT_MATCH_ADDED
);
445 DEFUN (no_match_ip_address_prefix_len
,
446 no_match_ip_address_prefix_len_cmd
,
447 "no match ip address prefix-len [(0-32)]",
451 "Match prefix length of ip address\n"
452 "Match prefix length of ip address\n"
455 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
456 return zebra_route_match_delete(vty
, "ip address prefix-len", plen
,
457 RMAP_EVENT_MATCH_DELETED
);
460 DEFUN (match_ipv6_address_prefix_len
,
461 match_ipv6_address_prefix_len_cmd
,
462 "match ipv6 address prefix-len (0-128)",
465 "Match prefix length of ipv6 address\n"
466 "Match prefix length of ipv6 address\n"
469 return zebra_route_match_add(vty
, "ipv6 address prefix-len",
470 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
473 DEFUN (no_match_ipv6_address_prefix_len
,
474 no_match_ipv6_address_prefix_len_cmd
,
475 "no match ipv6 address prefix-len [(0-128)]",
479 "Match prefix length of ip address\n"
480 "Match prefix length of ip address\n"
483 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
484 return zebra_route_match_delete(vty
, "ipv6 address prefix-len", plen
,
485 RMAP_EVENT_MATCH_DELETED
);
488 DEFUN (match_ip_nexthop_prefix_len
,
489 match_ip_nexthop_prefix_len_cmd
,
490 "match ip next-hop prefix-len (0-32)",
493 "Match prefixlen of nexthop ip address\n"
494 "Match prefixlen of given nexthop\n"
497 return zebra_route_match_add(vty
, "ip next-hop prefix-len",
498 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
501 DEFUN (no_match_ip_nexthop_prefix_len
,
502 no_match_ip_nexthop_prefix_len_cmd
,
503 "no match ip next-hop prefix-len [(0-32)]",
507 "Match prefixlen of nexthop ip address\n"
508 "Match prefix length of nexthop\n"
511 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
512 return zebra_route_match_delete(vty
, "ip next-hop prefix-len", plen
,
513 RMAP_EVENT_MATCH_DELETED
);
516 DEFUN (match_source_protocol
,
517 match_source_protocol_cmd
,
518 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
520 "Match protocol via which the route was learnt\n"
531 "Routes from directly connected peer\n"
532 "Routes from system configuration\n"
533 "Routes from kernel\n"
534 "Statically configured routes\n"
537 char *proto
= argv
[2]->text
;
540 i
= proto_name2num(proto
);
542 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
543 return CMD_WARNING_CONFIG_FAILED
;
545 return zebra_route_match_add(vty
, "source-protocol", proto
,
546 RMAP_EVENT_MATCH_ADDED
);
549 DEFUN (no_match_source_protocol
,
550 no_match_source_protocol_cmd
,
551 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
554 "No match protocol via which the route was learnt\n"
565 "Routes from directly connected peer\n"
566 "Routes from system configuration\n"
567 "Routes from kernel\n"
568 "Statically configured routes\n"
571 char *proto
= (argc
== 4) ? argv
[3]->text
: NULL
;
572 return zebra_route_match_delete(vty
, "source-protocol", proto
,
573 RMAP_EVENT_MATCH_DELETED
);
576 DEFUN (match_source_instance
,
577 match_source_instance_cmd
,
578 "match source-instance (0-255)",
580 "Match the protocol's instance number\n"
581 "The instance number\n")
583 char *instance
= argv
[2]->arg
;
585 return zebra_route_match_add(vty
, "source-instance", instance
,
586 RMAP_EVENT_MATCH_ADDED
);
589 DEFUN (no_match_source_instance
,
590 no_match_source_instance_cmd
,
591 "no match source-instance [(0-255)]",
593 "Match the protocol's instance number\n"
594 "The instance number\n")
596 char *instance
= (argc
== 4) ? argv
[3]->arg
: NULL
;
598 return zebra_route_match_delete(vty
, "source-instance", instance
,
599 RMAP_EVENT_MATCH_ADDED
);
606 "set src <A.B.C.D|X:X::X:X>",
608 "src address for route\n"
610 "IPv6 src address\n")
614 struct interface
*pif
= NULL
;
619 if (inet_pton(AF_INET
, argv
[idx_ip
]->arg
, &src
.ipv4
) != 1) {
620 if (inet_pton(AF_INET6
, argv
[idx_ip
]->arg
, &src
.ipv6
) != 1) {
621 vty_out(vty
, "%% not a valid IPv4/v6 address\n");
622 return CMD_WARNING_CONFIG_FAILED
;
625 p
.family
= family
= AF_INET6
;
626 p
.u
.prefix6
= src
.ipv6
;
627 p
.prefixlen
= IPV6_MAX_BITLEN
;
629 p
.family
= family
= AF_INET
;
630 p
.u
.prefix4
= src
.ipv4
;
631 p
.prefixlen
= IPV4_MAX_BITLEN
;
634 if (!zebra_check_addr(&p
)) {
635 vty_out(vty
, "%% not a valid source IPv4/v6 address\n");
636 return CMD_WARNING_CONFIG_FAILED
;
639 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
640 if (family
== AF_INET
)
641 pif
= if_lookup_exact_address((void *)&src
.ipv4
,
642 AF_INET
, vrf
->vrf_id
);
643 else if (family
== AF_INET6
)
644 pif
= if_lookup_exact_address((void *)&src
.ipv6
,
645 AF_INET6
, vrf
->vrf_id
);
652 vty_out(vty
, "%% not a local address\n");
653 return CMD_WARNING_CONFIG_FAILED
;
656 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
657 return generic_set_add(vty
, index
, "src", argv
[idx_ip
]->arg
);
662 "no set src [<A.B.C.D|X:X::X:X>]",
665 "Source address for route\n"
669 char *ip
= (argc
== 4) ? argv
[3]->arg
: NULL
;
670 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
671 return generic_set_delete(vty
, index
, "src", ip
);
674 DEFUN (zebra_route_map_timer
,
675 zebra_route_map_timer_cmd
,
676 "zebra route-map delay-timer (0-600)",
678 "Set route-map parameters\n"
679 "Time to wait before route-map updates are processed\n"
680 "0 means event-driven updates are disabled\n")
683 uint32_t rmap_delay_timer
;
685 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
686 zebra_route_map_set_delay_timer(rmap_delay_timer
);
688 return (CMD_SUCCESS
);
691 DEFUN (no_zebra_route_map_timer
,
692 no_zebra_route_map_timer_cmd
,
693 "no zebra route-map delay-timer [(0-600)]",
696 "Set route-map parameters\n"
697 "Reset delay-timer to default value, 30 secs\n"
698 "0 means event-driven updates are disabled\n")
700 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
702 return (CMD_SUCCESS
);
707 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
708 " $proto route-map ROUTE-MAP$rmap",
710 "Filter routing info exchanged between zebra and protocol\n"
711 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
712 "Specify route-map\n"
720 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
725 if (strcasecmp(proto
, "any") == 0)
726 rtype
= ZEBRA_ROUTE_MAX
;
728 rtype
= proto_name2num(proto
);
730 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
731 return CMD_WARNING_CONFIG_FAILED
;
734 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
739 DEFPY (no_ip_protocol
,
741 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
742 " $proto [route-map ROUTE-MAP$rmap]",
745 "Stop filtering routing info between zebra and protocol\n"
746 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
747 "Specify route-map\n"
754 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
759 if (strcasecmp(proto
, "any") == 0)
760 rtype
= ZEBRA_ROUTE_MAX
;
762 rtype
= proto_name2num(proto
);
764 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
765 return CMD_WARNING_CONFIG_FAILED
;
768 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
773 DEFPY (show_ip_protocol
,
774 show_ip_protocol_cmd
,
775 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
778 "IP protocol filtering status\n"
779 VRF_FULL_CMD_HELP_STR
)
781 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
786 DEFPY (ipv6_protocol
,
788 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
789 " $proto route-map ROUTE-MAP$rmap",
791 "Filter IPv6 routing info exchanged between zebra and protocol\n"
792 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
793 "Specify route-map\n"
801 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
806 if (strcasecmp(proto
, "any") == 0)
807 rtype
= ZEBRA_ROUTE_MAX
;
809 rtype
= proto_name2num(proto
);
811 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
812 return CMD_WARNING_CONFIG_FAILED
;
815 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
820 DEFPY (no_ipv6_protocol
,
821 no_ipv6_protocol_cmd
,
822 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
823 " $proto [route-map ROUTE-MAP$rmap]",
826 "Stop filtering IPv6 routing info between zebra and protocol\n"
827 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
828 "Specify route-map\n"
835 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
840 if (strcasecmp(proto
, "any") == 0)
841 rtype
= ZEBRA_ROUTE_MAX
;
843 rtype
= proto_name2num(proto
);
845 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
846 return CMD_WARNING_CONFIG_FAILED
;
849 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
854 DEFPY (show_ipv6_protocol
,
855 show_ipv6_protocol_cmd
,
856 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
859 "IPv6 protocol filtering status\n"
860 VRF_FULL_CMD_HELP_STR
)
862 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
867 DEFPY (ip_protocol_nht_rmap
,
868 ip_protocol_nht_rmap_cmd
,
869 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
870 " $proto route-map ROUTE-MAP$rmap",
872 "Filter Next Hop tracking route resolution\n"
873 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
874 "Specify route map\n"
883 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
888 if (strcasecmp(proto
, "any") == 0)
889 rtype
= ZEBRA_ROUTE_MAX
;
891 rtype
= proto_name2num(proto
);
893 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
894 return CMD_WARNING_CONFIG_FAILED
;
897 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
902 DEFPY (no_ip_protocol_nht_rmap
,
903 no_ip_protocol_nht_rmap_cmd
,
904 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
905 " $proto route-map [ROUTE-MAP$rmap]",
908 "Filter Next Hop tracking route resolution\n"
909 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
910 "Specify route map\n"
917 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
922 if (strcasecmp(proto
, "any") == 0)
923 rtype
= ZEBRA_ROUTE_MAX
;
925 rtype
= proto_name2num(proto
);
927 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
928 return CMD_WARNING_CONFIG_FAILED
;
931 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
936 DEFPY (show_ip_protocol_nht
,
937 show_ip_protocol_nht_cmd
,
938 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
941 "IP nexthop tracking table\n"
942 "IP Next Hop tracking filtering status\n"
943 VRF_FULL_CMD_HELP_STR
)
945 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
950 DEFPY (ipv6_protocol_nht_rmap
,
951 ipv6_protocol_nht_rmap_cmd
,
952 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
953 " $proto route-map ROUTE-MAP$rmap",
955 "Filter Next Hop tracking route resolution\n"
956 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
957 "Specify route map\n"
965 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
970 if (strcasecmp(proto
, "any") == 0)
971 rtype
= ZEBRA_ROUTE_MAX
;
973 rtype
= proto_name2num(proto
);
975 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
976 return CMD_WARNING_CONFIG_FAILED
;
979 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
984 DEFPY (no_ipv6_protocol_nht_rmap
,
985 no_ipv6_protocol_nht_rmap_cmd
,
986 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
987 " $proto [route-map ROUTE-MAP$rmap]",
990 "Filter Next Hop tracking route resolution\n"
991 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
992 "Specify route map\n"
999 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
1004 if (strcasecmp(proto
, "any") == 0)
1005 rtype
= ZEBRA_ROUTE_MAX
;
1007 rtype
= proto_name2num(proto
);
1009 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
1010 return CMD_WARNING_CONFIG_FAILED
;
1013 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
1018 DEFPY (show_ipv6_protocol_nht
,
1019 show_ipv6_protocol_nht_cmd
,
1020 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
1023 "Next Hop filtering status\n"
1025 VRF_FULL_CMD_HELP_STR
)
1027 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
1032 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1034 /* `match ip next-hop IP_ACCESS_LIST' */
1036 /* Match function return 1 if match is success else return zero. */
1037 static enum route_map_cmd_result_t
1038 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
,
1039 route_map_object_t type
, void *object
)
1041 struct access_list
*alist
;
1042 struct nh_rmap_obj
*nh_data
;
1043 struct prefix_ipv4 p
;
1045 if (type
== RMAP_ZEBRA
) {
1048 return RMAP_NOMATCH
;
1050 switch (nh_data
->nexthop
->type
) {
1051 case NEXTHOP_TYPE_IFINDEX
:
1052 /* Interface routes can't match ip next-hop */
1053 return RMAP_NOMATCH
;
1054 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1055 case NEXTHOP_TYPE_IPV4
:
1057 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1058 p
.prefixlen
= IPV4_MAX_BITLEN
;
1061 return RMAP_NOMATCH
;
1063 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1065 return RMAP_NOMATCH
;
1067 return (access_list_apply(alist
, &p
) == FILTER_DENY
1071 return RMAP_NOMATCH
;
1074 /* Route map `ip next-hop' match statement. `arg' should be
1075 access-list name. */
1076 static void *route_match_ip_next_hop_compile(const char *arg
)
1078 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1081 /* Free route map's compiled `. */
1082 static void route_match_ip_next_hop_free(void *rule
)
1084 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1087 /* Route map commands for ip next-hop matching. */
1088 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1089 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
1090 route_match_ip_next_hop_free
};
1092 /* `match ip next-hop prefix-list PREFIX_LIST' */
1094 static enum route_map_cmd_result_t
1095 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1096 route_map_object_t type
, void *object
)
1098 struct prefix_list
*plist
;
1099 struct nh_rmap_obj
*nh_data
;
1100 struct prefix_ipv4 p
;
1102 if (type
== RMAP_ZEBRA
) {
1103 nh_data
= (struct nh_rmap_obj
*)object
;
1105 return RMAP_NOMATCH
;
1107 switch (nh_data
->nexthop
->type
) {
1108 case NEXTHOP_TYPE_IFINDEX
:
1109 /* Interface routes can't match ip next-hop */
1110 return RMAP_NOMATCH
;
1111 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1112 case NEXTHOP_TYPE_IPV4
:
1114 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1115 p
.prefixlen
= IPV4_MAX_BITLEN
;
1118 return RMAP_NOMATCH
;
1120 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1122 return RMAP_NOMATCH
;
1124 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
1128 return RMAP_NOMATCH
;
1131 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1133 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1136 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1138 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1141 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
1142 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
1143 route_match_ip_next_hop_prefix_list_compile
,
1144 route_match_ip_next_hop_prefix_list_free
};
1146 /* `match ip address IP_ACCESS_LIST' */
1148 /* Match function should return 1 if match is success else return
1150 static enum route_map_cmd_result_t
1151 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1152 route_map_object_t type
, void *object
)
1154 struct access_list
*alist
;
1156 if (type
== RMAP_ZEBRA
) {
1157 alist
= access_list_lookup(afi
, (char *)rule
);
1159 return RMAP_NOMATCH
;
1161 return (access_list_apply(alist
, prefix
) == FILTER_DENY
1165 return RMAP_NOMATCH
;
1168 static enum route_map_cmd_result_t
1169 route_match_ip_address(void *rule
, const struct prefix
*prefix
,
1170 route_map_object_t type
, void *object
)
1172 return route_match_address(AFI_IP
, rule
, prefix
, type
, object
);
1175 static enum route_map_cmd_result_t
1176 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
,
1177 route_map_object_t type
, void *object
)
1179 return route_match_address(AFI_IP6
, rule
, prefix
, type
, object
);
1182 /* Route map `ip address' match statement. `arg' should be
1183 access-list name. */
1184 static void *route_match_address_compile(const char *arg
)
1186 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1189 /* Free route map's compiled `ip address' value. */
1190 static void route_match_address_free(void *rule
)
1192 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1195 /* Route map commands for ip address matching. */
1196 static struct route_map_rule_cmd route_match_ip_address_cmd
= {
1197 "ip address", route_match_ip_address
, route_match_address_compile
,
1198 route_match_address_free
};
1200 /* Route map commands for ipv6 address matching. */
1201 static struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1202 "ipv6 address", route_match_ipv6_address
, route_match_address_compile
,
1203 route_match_address_free
};
1205 /* `match ip address prefix-list PREFIX_LIST' */
1207 static enum route_map_cmd_result_t
1208 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1209 route_map_object_t type
, void *object
, afi_t afi
)
1211 struct prefix_list
*plist
;
1213 if (type
== RMAP_ZEBRA
) {
1214 plist
= prefix_list_lookup(afi
, (char *)rule
);
1216 return RMAP_NOMATCH
;
1218 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
1222 return RMAP_NOMATCH
;
1225 static enum route_map_cmd_result_t
1226 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1227 route_map_object_t type
, void *object
)
1229 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1233 static void *route_match_address_prefix_list_compile(const char *arg
)
1235 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1238 static void route_match_address_prefix_list_free(void *rule
)
1240 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1243 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
1244 "ip address prefix-list", route_match_ip_address_prefix_list
,
1245 route_match_address_prefix_list_compile
,
1246 route_match_address_prefix_list_free
};
1248 static enum route_map_cmd_result_t
1249 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1250 route_map_object_t type
, void *object
)
1252 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1256 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
1257 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
1258 route_match_address_prefix_list_compile
,
1259 route_match_address_prefix_list_free
};
1261 /* `match ipv6 next-hop type <TYPE>' */
1263 static enum route_map_cmd_result_t
1264 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1265 route_map_object_t type
, void *object
)
1267 struct nh_rmap_obj
*nh_data
;
1269 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET6
) {
1270 nh_data
= (struct nh_rmap_obj
*)object
;
1272 return RMAP_NOMATCH
;
1274 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1277 return RMAP_NOMATCH
;
1280 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1282 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1285 static void route_match_ipv6_next_hop_type_free(void *rule
)
1287 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1290 struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd
= {
1291 "ipv6 next-hop type", route_match_ipv6_next_hop_type
,
1292 route_match_ipv6_next_hop_type_compile
,
1293 route_match_ipv6_next_hop_type_free
};
1295 /* `match ip address prefix-len PREFIXLEN' */
1297 static enum route_map_cmd_result_t
1298 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1299 route_map_object_t type
, void *object
)
1301 uint32_t *prefixlen
= (uint32_t *)rule
;
1303 if (type
== RMAP_ZEBRA
) {
1304 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
1307 return RMAP_NOMATCH
;
1310 static void *route_match_address_prefix_len_compile(const char *arg
)
1312 uint32_t *prefix_len
;
1313 char *endptr
= NULL
;
1314 unsigned long tmpval
;
1316 /* prefix len value shoud be integer. */
1317 if (!all_digit(arg
))
1321 tmpval
= strtoul(arg
, &endptr
, 10);
1322 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1325 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1327 *prefix_len
= tmpval
;
1331 static void route_match_address_prefix_len_free(void *rule
)
1333 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1336 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
= {
1337 "ip address prefix-len", route_match_address_prefix_len
,
1338 route_match_address_prefix_len_compile
,
1339 route_match_address_prefix_len_free
};
1341 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd
= {
1342 "ipv6 address prefix-len", route_match_address_prefix_len
,
1343 route_match_address_prefix_len_compile
,
1344 route_match_address_prefix_len_free
};
1346 /* `match ip nexthop prefix-len PREFIXLEN' */
1348 static enum route_map_cmd_result_t
1349 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1350 route_map_object_t type
, void *object
)
1352 uint32_t *prefixlen
= (uint32_t *)rule
;
1353 struct nh_rmap_obj
*nh_data
;
1354 struct prefix_ipv4 p
;
1356 if (type
== RMAP_ZEBRA
) {
1357 nh_data
= (struct nh_rmap_obj
*)object
;
1358 if (!nh_data
|| !nh_data
->nexthop
)
1359 return RMAP_NOMATCH
;
1361 switch (nh_data
->nexthop
->type
) {
1362 case NEXTHOP_TYPE_IFINDEX
:
1363 /* Interface routes can't match ip next-hop */
1364 return RMAP_NOMATCH
;
1365 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1366 case NEXTHOP_TYPE_IPV4
:
1368 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1369 p
.prefixlen
= IPV4_MAX_BITLEN
;
1372 return RMAP_NOMATCH
;
1374 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
1377 return RMAP_NOMATCH
;
1380 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
= {
1381 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len
,
1382 route_match_address_prefix_len_compile
, /* reuse */
1383 route_match_address_prefix_len_free
/* reuse */
1386 /* `match ip next-hop type <blackhole>' */
1388 static enum route_map_cmd_result_t
1389 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1390 route_map_object_t type
, void *object
)
1392 struct nh_rmap_obj
*nh_data
;
1394 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET
) {
1395 nh_data
= (struct nh_rmap_obj
*)object
;
1397 return RMAP_NOMATCH
;
1399 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1402 return RMAP_NOMATCH
;
1405 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1407 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1410 static void route_match_ip_next_hop_type_free(void *rule
)
1412 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1415 static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd
= {
1416 "ip next-hop type", route_match_ip_next_hop_type
,
1417 route_match_ip_next_hop_type_compile
,
1418 route_match_ip_next_hop_type_free
};
1420 /* `match source-protocol PROTOCOL' */
1422 static enum route_map_cmd_result_t
1423 route_match_source_protocol(void *rule
, const struct prefix
*p
,
1424 route_map_object_t type
, void *object
)
1426 uint32_t *rib_type
= (uint32_t *)rule
;
1427 struct nh_rmap_obj
*nh_data
;
1429 if (type
== RMAP_ZEBRA
) {
1430 nh_data
= (struct nh_rmap_obj
*)object
;
1432 return RMAP_NOMATCH
;
1434 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1437 return RMAP_NOMATCH
;
1440 static void *route_match_source_protocol_compile(const char *arg
)
1445 i
= proto_name2num(arg
);
1446 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1453 static void route_match_source_protocol_free(void *rule
)
1455 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1458 static struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1459 "source-protocol", route_match_source_protocol
,
1460 route_match_source_protocol_compile
, route_match_source_protocol_free
};
1462 /* `source-instance` */
1463 static enum route_map_cmd_result_t
1464 route_match_source_instance(void *rule
, const struct prefix
*p
,
1465 route_map_object_t type
, void *object
)
1467 uint8_t *instance
= (uint8_t *)rule
;
1468 struct nh_rmap_obj
*nh_data
;
1470 if (type
!= RMAP_ZEBRA
)
1471 return RMAP_NOMATCH
;
1473 nh_data
= (struct nh_rmap_obj
*)object
;
1475 return RMAP_NOMATCH
;
1477 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1480 static void *route_match_source_instance_compile(const char *arg
)
1486 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1493 static void route_match_source_instance_free(void *rule
)
1495 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1498 static struct route_map_rule_cmd route_match_source_instance_cmd
= {
1499 "source-instance", route_match_source_instance
,
1500 route_match_source_instance_compile
, route_match_source_instance_free
};
1502 /* `set src A.B.C.D' */
1505 static enum route_map_cmd_result_t
1506 route_set_src(void *rule
, const struct prefix
*prefix
, route_map_object_t type
,
1509 struct nh_rmap_obj
*nh_data
;
1511 if (type
== RMAP_ZEBRA
) {
1512 nh_data
= (struct nh_rmap_obj
*)object
;
1513 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1518 /* set src compilation. */
1519 static void *route_set_src_compile(const char *arg
)
1521 union g_addr src
, *psrc
;
1523 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1524 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1525 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1532 /* Free route map's compiled `set src' value. */
1533 static void route_set_src_free(void *rule
)
1535 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1538 /* Set src rule structure. */
1539 static struct route_map_rule_cmd route_set_src_cmd
= {
1540 "src", route_set_src
, route_set_src_compile
, route_set_src_free
,
1543 /* The function checks if the changed routemap specified by parameter rmap
1544 * matches the configured protocol routemaps in proto_rm table. If there is
1545 * a match then rib_update_table() to process the routes.
1547 static void zebra_rib_table_rm_update(const char *rmap
)
1550 struct route_table
*table
;
1551 struct vrf
*vrf
= NULL
;
1552 struct zebra_vrf
*zvrf
= NULL
;
1556 struct route_map
*old
= NULL
;
1558 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1562 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1563 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1564 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1565 if (IS_ZEBRA_DEBUG_EVENT
)
1567 "%s : AFI_IP rmap %s, route type %s",
1569 zebra_route_string(i
));
1571 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1573 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1574 route_map_lookup_by_name(rmap_name
);
1575 /* old is NULL. i.e Route map creation event.
1576 * So update applied_counter.
1577 * If Old is not NULL, i.e It may be routemap
1578 * updation or deletion.
1579 * So no need to update the counter.
1582 route_map_counter_increment(
1583 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1584 /* There is single rib table for all protocols
1587 table
= zvrf
->table
[AFI_IP
]
1594 RIB_UPDATE_RMAP_CHANGE
);
1598 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1599 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1600 if (IS_ZEBRA_DEBUG_EVENT
)
1602 "%s : AFI_IP6 rmap %s, route type %s",
1604 zebra_route_string(i
));
1606 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1608 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1609 route_map_lookup_by_name(rmap_name
);
1611 route_map_counter_increment(
1612 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1613 /* There is single rib table for all protocols
1615 if (afi_ipv6
== 0) {
1616 table
= zvrf
->table
[AFI_IP6
]
1623 RIB_UPDATE_RMAP_CHANGE
);
1631 /* The function checks if the changed routemap specified by parameter rmap
1632 * matches the configured protocol routemaps in nht_rm table. If there is
1633 * a match then zebra_evaluate_rnh() to process the nexthops.
1635 static void zebra_nht_rm_update(const char *rmap
)
1638 struct route_table
*table
;
1639 struct vrf
*vrf
= NULL
;
1640 struct zebra_vrf
*zvrf
= NULL
;
1644 struct route_map
*old
= NULL
;
1646 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1650 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1651 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1652 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1653 if (IS_ZEBRA_DEBUG_EVENT
)
1655 "%s : AFI_IP rmap %s, route type %s",
1657 zebra_route_string(i
));
1659 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1661 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1662 route_map_lookup_by_name(rmap_name
);
1664 route_map_counter_increment(
1665 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1666 /* There is single rib table for all protocols
1669 table
= zvrf
->table
[AFI_IP
]
1677 RNH_NEXTHOP_TYPE
, NULL
);
1682 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1683 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1684 if (IS_ZEBRA_DEBUG_EVENT
)
1686 "%s : AFI_IP6 rmap %s, route type %s",
1688 zebra_route_string(i
));
1690 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1692 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1693 route_map_lookup_by_name(rmap_name
);
1695 route_map_counter_increment(
1696 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1697 /* There is single rib table for all protocols
1699 if (afi_ipv6
== 0) {
1700 table
= zvrf
->table
[AFI_IP6
]
1708 RNH_NEXTHOP_TYPE
, NULL
);
1716 static void zebra_route_map_process_update_cb(char *rmap_name
)
1718 if (IS_ZEBRA_DEBUG_EVENT
)
1719 zlog_debug("Event handler for route-map: %s",
1721 zebra_import_table_rm_update(rmap_name
);
1722 zebra_rib_table_rm_update(rmap_name
);
1723 zebra_nht_rm_update(rmap_name
);
1726 static int zebra_route_map_update_timer(struct thread
*thread
)
1728 zebra_t_rmap_update
= NULL
;
1730 if (IS_ZEBRA_DEBUG_EVENT
)
1731 zlog_debug("Event driven route-map update triggered");
1733 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1735 "%u: Routemap update-timer fired, scheduling RIB processing",
1738 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1741 * This code needs to be updated to be:
1742 * 1) VRF Aware <sigh>
1743 * 2) Route-map aware
1748 static void zebra_route_map_set_delay_timer(uint32_t value
)
1750 zebra_rmap_update_timer
= value
;
1751 if (!value
&& zebra_t_rmap_update
) {
1752 /* Event driven route map updates is being disabled */
1753 /* But there's a pending timer. Fire it off now */
1754 thread_cancel(zebra_t_rmap_update
);
1755 zebra_route_map_update_timer(zebra_t_rmap_update
);
1759 void zebra_route_map_write_delay_timer(struct vty
*vty
)
1761 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1762 vty_out(vty
, "zebra route-map delay-timer %d\n",
1763 zebra_rmap_update_timer
);
1768 zebra_route_map_check(int family
, int rib_type
, uint8_t instance
,
1769 const struct prefix
*p
, struct nexthop
*nexthop
,
1770 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1772 struct route_map
*rmap
= NULL
;
1773 route_map_result_t ret
= RMAP_PERMITMATCH
;
1774 struct nh_rmap_obj nh_obj
;
1776 nh_obj
.nexthop
= nexthop
;
1777 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1778 nh_obj
.source_protocol
= rib_type
;
1779 nh_obj
.instance
= instance
;
1783 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1784 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1785 if (!rmap
&& PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
))
1786 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1788 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1794 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1796 return zebra_import_table_routemap
[afi
][table
];
1799 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1802 zebra_import_table_routemap
[afi
][table
] =
1803 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1806 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1808 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1812 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1813 const struct prefix
*p
,
1814 struct nexthop
*nexthop
,
1815 vrf_id_t vrf_id
, route_tag_t tag
,
1816 const char *rmap_name
)
1818 struct route_map
*rmap
= NULL
;
1819 route_map_result_t ret
= RMAP_DENYMATCH
;
1820 struct nh_rmap_obj nh_obj
;
1822 nh_obj
.nexthop
= nexthop
;
1823 nh_obj
.vrf_id
= vrf_id
;
1824 nh_obj
.source_protocol
= re_type
;
1825 nh_obj
.instance
= instance
;
1829 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1830 rmap
= route_map_lookup_by_name(rmap_name
);
1832 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1838 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1839 const struct prefix
*p
,
1840 struct zebra_vrf
*zvrf
,
1841 struct route_entry
*re
,
1842 struct nexthop
*nexthop
)
1844 struct route_map
*rmap
= NULL
;
1845 route_map_result_t ret
= RMAP_PERMITMATCH
;
1846 struct nh_rmap_obj nh_obj
;
1848 nh_obj
.nexthop
= nexthop
;
1849 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1850 nh_obj
.source_protocol
= re
->type
;
1851 nh_obj
.instance
= re
->instance
;
1852 nh_obj
.metric
= re
->metric
;
1853 nh_obj
.tag
= re
->tag
;
1855 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1856 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1857 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1858 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1860 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1865 static void zebra_route_map_mark_update(const char *rmap_name
)
1867 /* rmap_update_timer of 0 means don't do route updates */
1868 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1869 zebra_t_rmap_update
= NULL
;
1870 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1871 NULL
, zebra_rmap_update_timer
,
1872 &zebra_t_rmap_update
);
1876 static void zebra_route_map_add(const char *rmap_name
)
1878 if (route_map_mark_updated(rmap_name
) == 0)
1879 zebra_route_map_mark_update(rmap_name
);
1881 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1884 static void zebra_route_map_delete(const char *rmap_name
)
1886 if (route_map_mark_updated(rmap_name
) == 0)
1887 zebra_route_map_mark_update(rmap_name
);
1889 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1892 static void zebra_route_map_event(const char *rmap_name
)
1894 if (route_map_mark_updated(rmap_name
) == 0)
1895 zebra_route_map_mark_update(rmap_name
);
1897 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1900 /* ip protocol configuration write function */
1901 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1902 struct zebra_vrf
*zvrf
)
1907 memset(space
, 0, sizeof(space
));
1909 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1910 sprintf(space
, "%s", " ");
1912 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1913 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1914 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1915 zebra_route_string(i
),
1916 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1918 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1919 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1920 zebra_route_string(i
),
1921 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1923 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1924 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1925 zebra_route_string(i
),
1926 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1928 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1929 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1930 zebra_route_string(i
),
1931 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1934 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1935 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1936 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1938 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1939 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1940 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1942 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1943 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1944 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1946 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1947 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1948 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1950 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1951 vty_out(vty
, "zebra route-map delay-timer %d\n",
1952 zebra_rmap_update_timer
);
1955 void zebra_route_map_init(void)
1957 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1958 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1959 install_element(VRF_NODE
, &ip_protocol_cmd
);
1960 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1961 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1962 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1963 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1964 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1965 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1966 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1967 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1968 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1969 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1970 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1971 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1972 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1973 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1974 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1975 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1976 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1977 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1978 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1982 route_map_add_hook(zebra_route_map_add
);
1983 route_map_delete_hook(zebra_route_map_delete
);
1984 route_map_event_hook(zebra_route_map_event
);
1986 route_map_match_interface_hook(generic_match_add
);
1987 route_map_no_match_interface_hook(generic_match_delete
);
1989 route_map_match_ip_address_hook(generic_match_add
);
1990 route_map_no_match_ip_address_hook(generic_match_delete
);
1992 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1993 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1995 route_map_match_ip_next_hop_hook(generic_match_add
);
1996 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1998 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1999 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
2001 route_map_match_ip_next_hop_type_hook(generic_match_add
);
2002 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
2004 route_map_match_tag_hook(generic_match_add
);
2005 route_map_no_match_tag_hook(generic_match_delete
);
2007 route_map_match_ipv6_address_hook(generic_match_add
);
2008 route_map_no_match_ipv6_address_hook(generic_match_delete
);
2010 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
2011 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
2013 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
2014 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
2016 route_map_install_match(&route_match_tag_cmd
);
2017 route_map_install_match(&route_match_interface_cmd
);
2018 route_map_install_match(&route_match_ip_next_hop_cmd
);
2019 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
2020 route_map_install_match(&route_match_ip_address_cmd
);
2021 route_map_install_match(&route_match_ipv6_address_cmd
);
2022 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
2023 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
2024 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
2025 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
2026 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
2027 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
2028 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
2029 route_map_install_match(&route_match_source_protocol_cmd
);
2030 route_map_install_match(&route_match_source_instance_cmd
);
2033 route_map_install_set(&route_set_src_cmd
);
2035 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
2036 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
2037 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
2038 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
2039 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
2040 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
2041 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
2042 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
2043 install_element(RMAP_NODE
, &match_source_instance_cmd
);
2044 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
2047 install_element(RMAP_NODE
, &set_src_cmd
);
2048 install_element(RMAP_NODE
, &no_set_src_cmd
);