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
);
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
);
90 /* Delete zebra route map rule. */
91 static int zebra_route_match_delete(struct vty
*vty
, const char *command
,
92 const char *arg
, route_map_event_t type
)
94 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
96 int retval
= CMD_SUCCESS
;
97 char *dep_name
= NULL
;
99 char *rmap_name
= NULL
;
101 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
102 /* ignore the mundane, the types without any dependency */
104 if ((tmpstr
= route_map_get_match_arg(index
, command
))
107 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
109 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
111 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
114 ret
= route_map_delete_match(index
, command
, arg
);
116 case RMAP_RULE_MISSING
:
117 vty_out(vty
, "%% Zebra Can't find rule.\n");
118 retval
= CMD_WARNING_CONFIG_FAILED
;
120 case RMAP_COMPILE_ERROR
:
121 vty_out(vty
, "%% Zebra Argument is malformed.\n");
122 retval
= CMD_WARNING_CONFIG_FAILED
;
124 case RMAP_COMPILE_SUCCESS
:
125 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
126 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
130 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
131 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
137 * Match function return 1 if match is success else return 0
139 static enum route_map_cmd_result_t
140 route_match_tag(void *rule
, const struct prefix
*prefix
,
141 route_map_object_t type
, void *object
)
144 struct nh_rmap_obj
*nh_data
;
146 if (type
== RMAP_ZEBRA
) {
150 if (nh_data
->tag
== *tag
)
156 /* Route map commands for tag matching */
157 static struct route_map_rule_cmd route_match_tag_cmd
= {
158 "tag", route_match_tag
, route_map_rule_tag_compile
,
159 route_map_rule_tag_free
,
163 /* `match interface IFNAME' */
164 /* Match function return 1 if match is success else return zero. */
165 static enum route_map_cmd_result_t
166 route_match_interface(void *rule
, const struct prefix
*prefix
,
167 route_map_object_t type
, void *object
)
169 struct nh_rmap_obj
*nh_data
;
173 if (type
== RMAP_ZEBRA
) {
174 if (strcasecmp(ifname
, "any") == 0)
177 if (!nh_data
|| !nh_data
->nexthop
)
179 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
182 if (nh_data
->nexthop
->ifindex
== ifindex
)
188 /* Route map `match interface' match statement. `arg' is IFNAME value */
189 static void *route_match_interface_compile(const char *arg
)
191 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
194 /* Free route map's compiled `match interface' value. */
195 static void route_match_interface_free(void *rule
)
197 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
200 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
205 vty_out(vty
, "Protocol : route-map\n");
206 vty_out(vty
, "------------------------\n");
208 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
209 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
210 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
211 PROTO_RM_NAME(zvrf
, af_type
, i
));
213 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
216 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
217 vty_out(vty
, "%-10s : %-10s\n", "any",
218 PROTO_RM_NAME(zvrf
, af_type
, i
));
220 vty_out(vty
, "%-10s : none\n", "any");
223 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
228 vty_out(vty
, "Protocol : route-map\n");
229 vty_out(vty
, "------------------------\n");
231 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
232 if (NHT_RM_NAME(zvrf
, af_type
, i
))
233 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
234 NHT_RM_NAME(zvrf
, af_type
, i
));
236 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
239 if (NHT_RM_NAME(zvrf
, af_type
, i
))
240 vty_out(vty
, "%-10s : %-10s\n", "any",
241 NHT_RM_NAME(zvrf
, af_type
, i
));
243 vty_out(vty
, "%-10s : none\n", "any");
246 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
247 const char *vrf_name
)
249 struct zebra_vrf
*zvrf
;
254 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
255 zvrf
= (struct zebra_vrf
*)vrf
->info
;
258 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
259 show_vrf_proto_rm(vty
, zvrf
, af_type
);
262 vrf_id_t vrf_id
= VRF_DEFAULT
;
265 VRF_GET_ID(vrf_id
, vrf_name
, false);
267 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
271 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
272 show_vrf_proto_rm(vty
, zvrf
, af_type
);
278 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
279 const char *vrf_name
)
281 struct zebra_vrf
*zvrf
;
286 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
287 zvrf
= (struct zebra_vrf
*)vrf
->info
;
291 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
292 show_vrf_nht_rm(vty
, zvrf
, af_type
);
295 vrf_id_t vrf_id
= VRF_DEFAULT
;
298 VRF_GET_ID(vrf_id
, vrf_name
, false);
300 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
304 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
305 show_vrf_nht_rm(vty
, zvrf
, af_type
);
311 /* Route map commands for interface matching */
312 struct route_map_rule_cmd route_match_interface_cmd
= {
313 "interface", route_match_interface
, route_match_interface_compile
,
314 route_match_interface_free
};
316 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
317 int rtype
, afi_t afi
, safi_t safi
)
319 struct route_table
*table
;
321 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
322 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
325 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
327 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
328 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
329 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
330 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
331 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
333 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
335 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
337 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
338 zvrf
->vrf
->vrf_id
, rtype
);
339 /* Process routes of interested address-families. */
340 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
342 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
348 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
349 int rtype
, afi_t afi
, safi_t safi
)
351 struct route_table
*table
;
353 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
356 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
358 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
359 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
360 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
362 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
363 zvrf
->vrf
->vrf_id
, rtype
);
364 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
366 /* Process routes of interested address-families. */
367 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
369 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
371 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
376 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
380 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
381 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
384 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
386 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
387 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
388 NHT_RM_MAP(zvrf
, afi
, rtype
) =
389 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
390 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
392 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
393 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
, NULL
);
398 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
402 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
405 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
406 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
407 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
408 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
410 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
411 zvrf
->vrf
->vrf_id
, rtype
);
412 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
414 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
,
417 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
422 DEFUN (match_ip_address_prefix_len
,
423 match_ip_address_prefix_len_cmd
,
424 "match ip address prefix-len (0-32)",
427 "Match prefix length of ip address\n"
428 "Match prefix length of ip address\n"
431 return zebra_route_match_add(vty
, "ip address prefix-len", argv
[4]->arg
,
432 RMAP_EVENT_MATCH_ADDED
);
435 DEFUN (no_match_ip_address_prefix_len
,
436 no_match_ip_address_prefix_len_cmd
,
437 "no match ip address prefix-len [(0-32)]",
441 "Match prefix length of ip address\n"
442 "Match prefix length of ip address\n"
445 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
446 return zebra_route_match_delete(vty
, "ip address prefix-len", plen
,
447 RMAP_EVENT_MATCH_DELETED
);
450 DEFUN (match_ipv6_address_prefix_len
,
451 match_ipv6_address_prefix_len_cmd
,
452 "match ipv6 address prefix-len (0-128)",
455 "Match prefix length of ipv6 address\n"
456 "Match prefix length of ipv6 address\n"
459 return zebra_route_match_add(vty
, "ipv6 address prefix-len",
460 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
463 DEFUN (no_match_ipv6_address_prefix_len
,
464 no_match_ipv6_address_prefix_len_cmd
,
465 "no match ipv6 address prefix-len [(0-128)]",
469 "Match prefix length of ip address\n"
470 "Match prefix length of ip address\n"
473 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
474 return zebra_route_match_delete(vty
, "ipv6 address prefix-len", plen
,
475 RMAP_EVENT_MATCH_DELETED
);
478 DEFUN (match_ip_nexthop_prefix_len
,
479 match_ip_nexthop_prefix_len_cmd
,
480 "match ip next-hop prefix-len (0-32)",
483 "Match prefixlen of nexthop ip address\n"
484 "Match prefixlen of given nexthop\n"
487 return zebra_route_match_add(vty
, "ip next-hop prefix-len",
488 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
491 DEFUN (no_match_ip_nexthop_prefix_len
,
492 no_match_ip_nexthop_prefix_len_cmd
,
493 "no match ip next-hop prefix-len [(0-32)]",
497 "Match prefixlen of nexthop ip address\n"
498 "Match prefix length of nexthop\n"
501 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
502 return zebra_route_match_delete(vty
, "ip next-hop prefix-len", plen
,
503 RMAP_EVENT_MATCH_DELETED
);
506 DEFUN (match_source_protocol
,
507 match_source_protocol_cmd
,
508 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
510 "Match protocol via which the route was learnt\n"
521 "Routes from directly connected peer\n"
522 "Routes from system configuration\n"
523 "Routes from kernel\n"
524 "Statically configured routes\n"
527 char *proto
= argv
[2]->text
;
530 i
= proto_name2num(proto
);
532 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
533 return CMD_WARNING_CONFIG_FAILED
;
535 return zebra_route_match_add(vty
, "source-protocol", proto
,
536 RMAP_EVENT_MATCH_ADDED
);
539 DEFUN (no_match_source_protocol
,
540 no_match_source_protocol_cmd
,
541 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
544 "No match protocol via which the route was learnt\n"
555 "Routes from directly connected peer\n"
556 "Routes from system configuration\n"
557 "Routes from kernel\n"
558 "Statically configured routes\n"
561 char *proto
= (argc
== 4) ? argv
[3]->text
: NULL
;
562 return zebra_route_match_delete(vty
, "source-protocol", proto
,
563 RMAP_EVENT_MATCH_DELETED
);
566 DEFUN (match_source_instance
,
567 match_source_instance_cmd
,
568 "match source-instance (0-255)",
570 "Match the protocol's instance number\n"
571 "The instance number\n")
573 char *instance
= argv
[2]->arg
;
575 return zebra_route_match_add(vty
, "source-instance", instance
,
576 RMAP_EVENT_MATCH_ADDED
);
579 DEFUN (no_match_source_instance
,
580 no_match_source_instance_cmd
,
581 "no match source-instance [(0-255)]",
583 "Match the protocol's instance number\n"
584 "The instance number\n")
586 char *instance
= (argc
== 4) ? argv
[3]->arg
: NULL
;
588 return zebra_route_match_delete(vty
, "source-instance", instance
,
589 RMAP_EVENT_MATCH_ADDED
);
596 "set src <A.B.C.D|X:X::X:X>",
598 "src address for route\n"
600 "IPv6 src address\n")
604 struct interface
*pif
= NULL
;
609 if (inet_pton(AF_INET
, argv
[idx_ip
]->arg
, &src
.ipv4
) != 1) {
610 if (inet_pton(AF_INET6
, argv
[idx_ip
]->arg
, &src
.ipv6
) != 1) {
611 vty_out(vty
, "%% not a valid IPv4/v6 address\n");
612 return CMD_WARNING_CONFIG_FAILED
;
615 p
.family
= family
= AF_INET6
;
616 p
.u
.prefix6
= src
.ipv6
;
617 p
.prefixlen
= IPV6_MAX_BITLEN
;
619 p
.family
= family
= AF_INET
;
620 p
.u
.prefix4
= src
.ipv4
;
621 p
.prefixlen
= IPV4_MAX_BITLEN
;
624 if (!zebra_check_addr(&p
)) {
625 vty_out(vty
, "%% not a valid source IPv4/v6 address\n");
626 return CMD_WARNING_CONFIG_FAILED
;
629 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
630 if (family
== AF_INET
)
631 pif
= if_lookup_exact_address((void *)&src
.ipv4
,
632 AF_INET
, vrf
->vrf_id
);
633 else if (family
== AF_INET6
)
634 pif
= if_lookup_exact_address((void *)&src
.ipv6
,
635 AF_INET6
, vrf
->vrf_id
);
642 vty_out(vty
, "%% not a local address\n");
643 return CMD_WARNING_CONFIG_FAILED
;
646 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
647 return generic_set_add(vty
, index
, "src", argv
[idx_ip
]->arg
);
652 "no set src [<A.B.C.D|X:X::X:X>]",
655 "Source address for route\n"
659 char *ip
= (argc
== 4) ? argv
[3]->arg
: NULL
;
660 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
661 return generic_set_delete(vty
, index
, "src", ip
);
664 DEFUN (zebra_route_map_timer
,
665 zebra_route_map_timer_cmd
,
666 "zebra route-map delay-timer (0-600)",
668 "Set route-map parameters\n"
669 "Time to wait before route-map updates are processed\n"
670 "0 means event-driven updates are disabled\n")
673 uint32_t rmap_delay_timer
;
675 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
676 zebra_route_map_set_delay_timer(rmap_delay_timer
);
678 return (CMD_SUCCESS
);
681 DEFUN (no_zebra_route_map_timer
,
682 no_zebra_route_map_timer_cmd
,
683 "no zebra route-map delay-timer [(0-600)]",
686 "Set route-map parameters\n"
687 "Reset delay-timer to default value, 30 secs\n"
688 "0 means event-driven updates are disabled\n")
690 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
692 return (CMD_SUCCESS
);
697 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
698 " $proto route-map ROUTE-MAP$rmap",
700 "Filter routing info exchanged between zebra and protocol\n"
701 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
702 "Specify route-map\n"
710 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
715 if (strcasecmp(proto
, "any") == 0)
716 rtype
= ZEBRA_ROUTE_MAX
;
718 rtype
= proto_name2num(proto
);
720 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
721 return CMD_WARNING_CONFIG_FAILED
;
724 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
729 DEFPY (no_ip_protocol
,
731 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
732 " $proto [route-map ROUTE-MAP$rmap]",
735 "Stop filtering routing info between zebra and protocol\n"
736 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
737 "Specify route-map\n"
744 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
749 if (strcasecmp(proto
, "any") == 0)
750 rtype
= ZEBRA_ROUTE_MAX
;
752 rtype
= proto_name2num(proto
);
754 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
755 return CMD_WARNING_CONFIG_FAILED
;
758 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
763 DEFPY (show_ip_protocol
,
764 show_ip_protocol_cmd
,
765 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
768 "IP protocol filtering status\n"
769 VRF_FULL_CMD_HELP_STR
)
771 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
776 DEFPY (ipv6_protocol
,
778 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
779 " $proto route-map ROUTE-MAP$rmap",
781 "Filter IPv6 routing info exchanged between zebra and protocol\n"
782 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
783 "Specify route-map\n"
791 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
796 if (strcasecmp(proto
, "any") == 0)
797 rtype
= ZEBRA_ROUTE_MAX
;
799 rtype
= proto_name2num(proto
);
801 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
802 return CMD_WARNING_CONFIG_FAILED
;
805 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
810 DEFPY (no_ipv6_protocol
,
811 no_ipv6_protocol_cmd
,
812 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
813 " $proto [route-map ROUTE-MAP$rmap]",
816 "Stop filtering IPv6 routing info between zebra and protocol\n"
817 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
818 "Specify route-map\n"
825 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
830 if (strcasecmp(proto
, "any") == 0)
831 rtype
= ZEBRA_ROUTE_MAX
;
833 rtype
= proto_name2num(proto
);
835 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
836 return CMD_WARNING_CONFIG_FAILED
;
839 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
844 DEFPY (show_ipv6_protocol
,
845 show_ipv6_protocol_cmd
,
846 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
849 "IPv6 protocol filtering status\n"
850 VRF_FULL_CMD_HELP_STR
)
852 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
857 DEFPY (ip_protocol_nht_rmap
,
858 ip_protocol_nht_rmap_cmd
,
859 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
860 " $proto route-map ROUTE-MAP$rmap",
862 "Filter Next Hop tracking route resolution\n"
863 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
864 "Specify route map\n"
873 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
878 if (strcasecmp(proto
, "any") == 0)
879 rtype
= ZEBRA_ROUTE_MAX
;
881 rtype
= proto_name2num(proto
);
883 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
884 return CMD_WARNING_CONFIG_FAILED
;
887 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
892 DEFPY (no_ip_protocol_nht_rmap
,
893 no_ip_protocol_nht_rmap_cmd
,
894 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
895 " $proto route-map [ROUTE-MAP$rmap]",
898 "Filter Next Hop tracking route resolution\n"
899 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
900 "Specify route map\n"
907 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
912 if (strcasecmp(proto
, "any") == 0)
913 rtype
= ZEBRA_ROUTE_MAX
;
915 rtype
= proto_name2num(proto
);
917 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
918 return CMD_WARNING_CONFIG_FAILED
;
921 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
926 DEFPY (show_ip_protocol_nht
,
927 show_ip_protocol_nht_cmd
,
928 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
931 "IP nexthop tracking table\n"
932 "IP Next Hop tracking filtering status\n"
933 VRF_FULL_CMD_HELP_STR
)
935 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
940 DEFPY (ipv6_protocol_nht_rmap
,
941 ipv6_protocol_nht_rmap_cmd
,
942 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
943 " $proto route-map ROUTE-MAP$rmap",
945 "Filter Next Hop tracking route resolution\n"
946 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
947 "Specify route map\n"
955 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
960 if (strcasecmp(proto
, "any") == 0)
961 rtype
= ZEBRA_ROUTE_MAX
;
963 rtype
= proto_name2num(proto
);
965 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
966 return CMD_WARNING_CONFIG_FAILED
;
969 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
974 DEFPY (no_ipv6_protocol_nht_rmap
,
975 no_ipv6_protocol_nht_rmap_cmd
,
976 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
977 " $proto [route-map ROUTE-MAP$rmap]",
980 "Filter Next Hop tracking route resolution\n"
981 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
982 "Specify route map\n"
989 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
994 if (strcasecmp(proto
, "any") == 0)
995 rtype
= ZEBRA_ROUTE_MAX
;
997 rtype
= proto_name2num(proto
);
999 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
1000 return CMD_WARNING_CONFIG_FAILED
;
1003 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
1008 DEFPY (show_ipv6_protocol_nht
,
1009 show_ipv6_protocol_nht_cmd
,
1010 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
1013 "Next Hop filtering status\n"
1015 VRF_FULL_CMD_HELP_STR
)
1017 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
1022 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1024 /* `match ip next-hop IP_ACCESS_LIST' */
1026 /* Match function return 1 if match is success else return zero. */
1027 static enum route_map_cmd_result_t
1028 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
,
1029 route_map_object_t type
, void *object
)
1031 struct access_list
*alist
;
1032 struct nh_rmap_obj
*nh_data
;
1033 struct prefix_ipv4 p
;
1035 if (type
== RMAP_ZEBRA
) {
1038 return RMAP_NOMATCH
;
1040 switch (nh_data
->nexthop
->type
) {
1041 case NEXTHOP_TYPE_IFINDEX
:
1042 /* Interface routes can't match ip next-hop */
1043 return RMAP_NOMATCH
;
1044 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1045 case NEXTHOP_TYPE_IPV4
:
1047 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1048 p
.prefixlen
= IPV4_MAX_BITLEN
;
1051 return RMAP_NOMATCH
;
1053 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1055 return RMAP_NOMATCH
;
1057 return (access_list_apply(alist
, &p
) == FILTER_DENY
1061 return RMAP_NOMATCH
;
1064 /* Route map `ip next-hop' match statement. `arg' should be
1065 access-list name. */
1066 static void *route_match_ip_next_hop_compile(const char *arg
)
1068 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1071 /* Free route map's compiled `. */
1072 static void route_match_ip_next_hop_free(void *rule
)
1074 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1077 /* Route map commands for ip next-hop matching. */
1078 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1079 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
1080 route_match_ip_next_hop_free
};
1082 /* `match ip next-hop prefix-list PREFIX_LIST' */
1084 static enum route_map_cmd_result_t
1085 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1086 route_map_object_t type
, void *object
)
1088 struct prefix_list
*plist
;
1089 struct nh_rmap_obj
*nh_data
;
1090 struct prefix_ipv4 p
;
1092 if (type
== RMAP_ZEBRA
) {
1093 nh_data
= (struct nh_rmap_obj
*)object
;
1095 return RMAP_NOMATCH
;
1097 switch (nh_data
->nexthop
->type
) {
1098 case NEXTHOP_TYPE_IFINDEX
:
1099 /* Interface routes can't match ip next-hop */
1100 return RMAP_NOMATCH
;
1101 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1102 case NEXTHOP_TYPE_IPV4
:
1104 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1105 p
.prefixlen
= IPV4_MAX_BITLEN
;
1108 return RMAP_NOMATCH
;
1110 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1112 return RMAP_NOMATCH
;
1114 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
1118 return RMAP_NOMATCH
;
1121 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1123 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1126 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1128 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1131 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
1132 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
1133 route_match_ip_next_hop_prefix_list_compile
,
1134 route_match_ip_next_hop_prefix_list_free
};
1136 /* `match ip address IP_ACCESS_LIST' */
1138 /* Match function should return 1 if match is success else return
1140 static enum route_map_cmd_result_t
1141 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1142 route_map_object_t type
, void *object
)
1144 struct access_list
*alist
;
1146 if (type
== RMAP_ZEBRA
) {
1147 alist
= access_list_lookup(afi
, (char *)rule
);
1149 return RMAP_NOMATCH
;
1151 return (access_list_apply(alist
, prefix
) == FILTER_DENY
1155 return RMAP_NOMATCH
;
1158 static enum route_map_cmd_result_t
1159 route_match_ip_address(void *rule
, const struct prefix
*prefix
,
1160 route_map_object_t type
, void *object
)
1162 return route_match_address(AFI_IP
, rule
, prefix
, type
, object
);
1165 static enum route_map_cmd_result_t
1166 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
,
1167 route_map_object_t type
, void *object
)
1169 return route_match_address(AFI_IP6
, rule
, prefix
, type
, object
);
1172 /* Route map `ip address' match statement. `arg' should be
1173 access-list name. */
1174 static void *route_match_address_compile(const char *arg
)
1176 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1179 /* Free route map's compiled `ip address' value. */
1180 static void route_match_address_free(void *rule
)
1182 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1185 /* Route map commands for ip address matching. */
1186 static struct route_map_rule_cmd route_match_ip_address_cmd
= {
1187 "ip address", route_match_ip_address
, route_match_address_compile
,
1188 route_match_address_free
};
1190 /* Route map commands for ipv6 address matching. */
1191 static struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1192 "ipv6 address", route_match_ipv6_address
, route_match_address_compile
,
1193 route_match_address_free
};
1195 /* `match ip address prefix-list PREFIX_LIST' */
1197 static enum route_map_cmd_result_t
1198 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1199 route_map_object_t type
, void *object
, afi_t afi
)
1201 struct prefix_list
*plist
;
1203 if (type
== RMAP_ZEBRA
) {
1204 plist
= prefix_list_lookup(afi
, (char *)rule
);
1206 return RMAP_NOMATCH
;
1208 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
1212 return RMAP_NOMATCH
;
1215 static enum route_map_cmd_result_t
1216 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1217 route_map_object_t type
, void *object
)
1219 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1223 static void *route_match_address_prefix_list_compile(const char *arg
)
1225 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1228 static void route_match_address_prefix_list_free(void *rule
)
1230 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1233 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
1234 "ip address prefix-list", route_match_ip_address_prefix_list
,
1235 route_match_address_prefix_list_compile
,
1236 route_match_address_prefix_list_free
};
1238 static enum route_map_cmd_result_t
1239 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1240 route_map_object_t type
, void *object
)
1242 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1246 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
1247 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
1248 route_match_address_prefix_list_compile
,
1249 route_match_address_prefix_list_free
};
1251 /* `match ipv6 next-hop type <TYPE>' */
1253 static enum route_map_cmd_result_t
1254 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1255 route_map_object_t type
, void *object
)
1257 struct nh_rmap_obj
*nh_data
;
1259 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET6
) {
1260 nh_data
= (struct nh_rmap_obj
*)object
;
1262 return RMAP_NOMATCH
;
1264 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1267 return RMAP_NOMATCH
;
1270 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1272 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1275 static void route_match_ipv6_next_hop_type_free(void *rule
)
1277 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1280 struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd
= {
1281 "ipv6 next-hop type", route_match_ipv6_next_hop_type
,
1282 route_match_ipv6_next_hop_type_compile
,
1283 route_match_ipv6_next_hop_type_free
};
1285 /* `match ip address prefix-len PREFIXLEN' */
1287 static enum route_map_cmd_result_t
1288 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1289 route_map_object_t type
, void *object
)
1291 uint32_t *prefixlen
= (uint32_t *)rule
;
1293 if (type
== RMAP_ZEBRA
) {
1294 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
1297 return RMAP_NOMATCH
;
1300 static void *route_match_address_prefix_len_compile(const char *arg
)
1302 uint32_t *prefix_len
;
1303 char *endptr
= NULL
;
1304 unsigned long tmpval
;
1306 /* prefix len value shoud be integer. */
1307 if (!all_digit(arg
))
1311 tmpval
= strtoul(arg
, &endptr
, 10);
1312 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1315 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1317 *prefix_len
= tmpval
;
1321 static void route_match_address_prefix_len_free(void *rule
)
1323 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1326 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
= {
1327 "ip address prefix-len", route_match_address_prefix_len
,
1328 route_match_address_prefix_len_compile
,
1329 route_match_address_prefix_len_free
};
1331 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd
= {
1332 "ipv6 address prefix-len", route_match_address_prefix_len
,
1333 route_match_address_prefix_len_compile
,
1334 route_match_address_prefix_len_free
};
1336 /* `match ip nexthop prefix-len PREFIXLEN' */
1338 static enum route_map_cmd_result_t
1339 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1340 route_map_object_t type
, void *object
)
1342 uint32_t *prefixlen
= (uint32_t *)rule
;
1343 struct nh_rmap_obj
*nh_data
;
1344 struct prefix_ipv4 p
;
1346 if (type
== RMAP_ZEBRA
) {
1347 nh_data
= (struct nh_rmap_obj
*)object
;
1348 if (!nh_data
|| !nh_data
->nexthop
)
1349 return RMAP_NOMATCH
;
1351 switch (nh_data
->nexthop
->type
) {
1352 case NEXTHOP_TYPE_IFINDEX
:
1353 /* Interface routes can't match ip next-hop */
1354 return RMAP_NOMATCH
;
1355 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1356 case NEXTHOP_TYPE_IPV4
:
1358 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1359 p
.prefixlen
= IPV4_MAX_BITLEN
;
1362 return RMAP_NOMATCH
;
1364 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
1367 return RMAP_NOMATCH
;
1370 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
= {
1371 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len
,
1372 route_match_address_prefix_len_compile
, /* reuse */
1373 route_match_address_prefix_len_free
/* reuse */
1376 /* `match ip next-hop type <blackhole>' */
1378 static enum route_map_cmd_result_t
1379 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1380 route_map_object_t type
, void *object
)
1382 struct nh_rmap_obj
*nh_data
;
1384 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET
) {
1385 nh_data
= (struct nh_rmap_obj
*)object
;
1387 return RMAP_NOMATCH
;
1389 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1392 return RMAP_NOMATCH
;
1395 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1397 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1400 static void route_match_ip_next_hop_type_free(void *rule
)
1402 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1405 static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd
= {
1406 "ip next-hop type", route_match_ip_next_hop_type
,
1407 route_match_ip_next_hop_type_compile
,
1408 route_match_ip_next_hop_type_free
};
1410 /* `match source-protocol PROTOCOL' */
1412 static enum route_map_cmd_result_t
1413 route_match_source_protocol(void *rule
, const struct prefix
*p
,
1414 route_map_object_t type
, void *object
)
1416 uint32_t *rib_type
= (uint32_t *)rule
;
1417 struct nh_rmap_obj
*nh_data
;
1419 if (type
== RMAP_ZEBRA
) {
1420 nh_data
= (struct nh_rmap_obj
*)object
;
1422 return RMAP_NOMATCH
;
1424 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1427 return RMAP_NOMATCH
;
1430 static void *route_match_source_protocol_compile(const char *arg
)
1435 i
= proto_name2num(arg
);
1436 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1443 static void route_match_source_protocol_free(void *rule
)
1445 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1448 static struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1449 "source-protocol", route_match_source_protocol
,
1450 route_match_source_protocol_compile
, route_match_source_protocol_free
};
1452 /* `source-instance` */
1453 static enum route_map_cmd_result_t
1454 route_match_source_instance(void *rule
, const struct prefix
*p
,
1455 route_map_object_t type
, void *object
)
1457 uint8_t *instance
= (uint8_t *)rule
;
1458 struct nh_rmap_obj
*nh_data
;
1460 if (type
!= RMAP_ZEBRA
)
1461 return RMAP_NOMATCH
;
1463 nh_data
= (struct nh_rmap_obj
*)object
;
1465 return RMAP_NOMATCH
;
1467 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1470 static void *route_match_source_instance_compile(const char *arg
)
1476 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1483 static void route_match_source_instance_free(void *rule
)
1485 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1488 static struct route_map_rule_cmd route_match_source_instance_cmd
= {
1489 "source-instance", route_match_source_instance
,
1490 route_match_source_instance_compile
, route_match_source_instance_free
};
1492 /* `set src A.B.C.D' */
1495 static enum route_map_cmd_result_t
1496 route_set_src(void *rule
, const struct prefix
*prefix
, route_map_object_t type
,
1499 struct nh_rmap_obj
*nh_data
;
1501 if (type
== RMAP_ZEBRA
) {
1502 nh_data
= (struct nh_rmap_obj
*)object
;
1503 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1508 /* set src compilation. */
1509 static void *route_set_src_compile(const char *arg
)
1511 union g_addr src
, *psrc
;
1513 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1514 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1515 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1522 /* Free route map's compiled `set src' value. */
1523 static void route_set_src_free(void *rule
)
1525 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1528 /* Set src rule structure. */
1529 static struct route_map_rule_cmd route_set_src_cmd
= {
1530 "src", route_set_src
, route_set_src_compile
, route_set_src_free
,
1533 /* The function checks if the changed routemap specified by parameter rmap
1534 * matches the configured protocol routemaps in proto_rm table. If there is
1535 * a match then rib_update_table() to process the routes.
1537 static void zebra_rib_table_rm_update(const char *rmap
)
1540 struct route_table
*table
;
1541 struct vrf
*vrf
= NULL
;
1542 struct zebra_vrf
*zvrf
= NULL
;
1546 struct route_map
*old
= NULL
;
1548 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1552 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1553 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1554 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1555 if (IS_ZEBRA_DEBUG_EVENT
)
1557 "%s : AFI_IP rmap %s, route type %s",
1559 zebra_route_string(i
));
1561 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1563 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1564 route_map_lookup_by_name(rmap_name
);
1565 /* old is NULL. i.e Route map creation event.
1566 * So update applied_counter.
1567 * If Old is not NULL, i.e It may be routemap
1568 * updation or deletion.
1569 * So no need to update the counter.
1572 route_map_counter_increment(
1573 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1574 /* There is single rib table for all protocols
1577 table
= zvrf
->table
[AFI_IP
]
1584 RIB_UPDATE_RMAP_CHANGE
);
1588 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1589 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1590 if (IS_ZEBRA_DEBUG_EVENT
)
1592 "%s : AFI_IP6 rmap %s, route type %s",
1594 zebra_route_string(i
));
1596 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1598 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1599 route_map_lookup_by_name(rmap_name
);
1601 route_map_counter_increment(
1602 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1603 /* There is single rib table for all protocols
1605 if (afi_ipv6
== 0) {
1606 table
= zvrf
->table
[AFI_IP6
]
1613 RIB_UPDATE_RMAP_CHANGE
);
1621 /* The function checks if the changed routemap specified by parameter rmap
1622 * matches the configured protocol routemaps in nht_rm table. If there is
1623 * a match then zebra_evaluate_rnh() to process the nexthops.
1625 static void zebra_nht_rm_update(const char *rmap
)
1628 struct route_table
*table
;
1629 struct vrf
*vrf
= NULL
;
1630 struct zebra_vrf
*zvrf
= NULL
;
1634 struct route_map
*old
= NULL
;
1636 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1640 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1641 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1642 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1643 if (IS_ZEBRA_DEBUG_EVENT
)
1645 "%s : AFI_IP rmap %s, route type %s",
1647 zebra_route_string(i
));
1649 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1651 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1652 route_map_lookup_by_name(rmap_name
);
1654 route_map_counter_increment(
1655 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1656 /* There is single rib table for all protocols
1659 table
= zvrf
->table
[AFI_IP
]
1667 RNH_NEXTHOP_TYPE
, NULL
);
1672 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1673 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1674 if (IS_ZEBRA_DEBUG_EVENT
)
1676 "%s : AFI_IP6 rmap %s, route type %s",
1678 zebra_route_string(i
));
1680 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1682 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1683 route_map_lookup_by_name(rmap_name
);
1685 route_map_counter_increment(
1686 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1687 /* There is single rib table for all protocols
1689 if (afi_ipv6
== 0) {
1690 table
= zvrf
->table
[AFI_IP6
]
1698 RNH_NEXTHOP_TYPE
, NULL
);
1706 static void zebra_route_map_process_update_cb(char *rmap_name
)
1708 if (IS_ZEBRA_DEBUG_EVENT
)
1709 zlog_debug("Event handler for route-map: %s",
1711 zebra_import_table_rm_update(rmap_name
);
1712 zebra_rib_table_rm_update(rmap_name
);
1713 zebra_nht_rm_update(rmap_name
);
1716 static int zebra_route_map_update_timer(struct thread
*thread
)
1718 zebra_t_rmap_update
= NULL
;
1720 if (IS_ZEBRA_DEBUG_EVENT
)
1721 zlog_debug("Event driven route-map update triggered");
1723 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1725 "%u: Routemap update-timer fired, scheduling RIB processing",
1728 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1731 * This code needs to be updated to be:
1732 * 1) VRF Aware <sigh>
1733 * 2) Route-map aware
1738 static void zebra_route_map_set_delay_timer(uint32_t value
)
1740 zebra_rmap_update_timer
= value
;
1741 if (!value
&& zebra_t_rmap_update
) {
1742 /* Event driven route map updates is being disabled */
1743 /* But there's a pending timer. Fire it off now */
1744 thread_cancel(zebra_t_rmap_update
);
1745 zebra_route_map_update_timer(zebra_t_rmap_update
);
1749 void zebra_route_map_write_delay_timer(struct vty
*vty
)
1751 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1752 vty_out(vty
, "zebra route-map delay-timer %d\n",
1753 zebra_rmap_update_timer
);
1758 zebra_route_map_check(int family
, int rib_type
, uint8_t instance
,
1759 const struct prefix
*p
, struct nexthop
*nexthop
,
1760 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1762 struct route_map
*rmap
= NULL
;
1763 route_map_result_t ret
= RMAP_PERMITMATCH
;
1764 struct nh_rmap_obj nh_obj
;
1766 nh_obj
.nexthop
= nexthop
;
1767 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1768 nh_obj
.source_protocol
= rib_type
;
1769 nh_obj
.instance
= instance
;
1773 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1774 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1775 if (!rmap
&& PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
))
1776 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1778 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1784 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1786 return zebra_import_table_routemap
[afi
][table
];
1789 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1792 zebra_import_table_routemap
[afi
][table
] =
1793 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1796 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1798 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1802 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1803 const struct prefix
*p
,
1804 struct nexthop
*nexthop
,
1805 vrf_id_t vrf_id
, route_tag_t tag
,
1806 const char *rmap_name
)
1808 struct route_map
*rmap
= NULL
;
1809 route_map_result_t ret
= RMAP_DENYMATCH
;
1810 struct nh_rmap_obj nh_obj
;
1812 nh_obj
.nexthop
= nexthop
;
1813 nh_obj
.vrf_id
= vrf_id
;
1814 nh_obj
.source_protocol
= re_type
;
1815 nh_obj
.instance
= instance
;
1819 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1820 rmap
= route_map_lookup_by_name(rmap_name
);
1822 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1828 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1829 const struct prefix
*p
,
1830 struct zebra_vrf
*zvrf
,
1831 struct route_entry
*re
,
1832 struct nexthop
*nexthop
)
1834 struct route_map
*rmap
= NULL
;
1835 route_map_result_t ret
= RMAP_PERMITMATCH
;
1836 struct nh_rmap_obj nh_obj
;
1838 nh_obj
.nexthop
= nexthop
;
1839 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1840 nh_obj
.source_protocol
= re
->type
;
1841 nh_obj
.instance
= re
->instance
;
1842 nh_obj
.metric
= re
->metric
;
1843 nh_obj
.tag
= re
->tag
;
1845 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1846 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1847 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1848 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1850 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1855 static void zebra_route_map_mark_update(const char *rmap_name
)
1857 /* rmap_update_timer of 0 means don't do route updates */
1858 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1859 zebra_t_rmap_update
= NULL
;
1860 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1861 NULL
, zebra_rmap_update_timer
,
1862 &zebra_t_rmap_update
);
1866 static void zebra_route_map_add(const char *rmap_name
)
1868 if (route_map_mark_updated(rmap_name
) == 0)
1869 zebra_route_map_mark_update(rmap_name
);
1871 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1874 static void zebra_route_map_delete(const char *rmap_name
)
1876 if (route_map_mark_updated(rmap_name
) == 0)
1877 zebra_route_map_mark_update(rmap_name
);
1879 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1882 static void zebra_route_map_event(const char *rmap_name
)
1884 if (route_map_mark_updated(rmap_name
) == 0)
1885 zebra_route_map_mark_update(rmap_name
);
1887 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1890 /* ip protocol configuration write function */
1891 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1892 struct zebra_vrf
*zvrf
)
1897 memset(space
, 0, sizeof(space
));
1899 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1900 sprintf(space
, "%s", " ");
1902 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1903 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1904 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1905 zebra_route_string(i
),
1906 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1908 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1909 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1910 zebra_route_string(i
),
1911 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1913 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1914 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1915 zebra_route_string(i
),
1916 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1918 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1919 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1920 zebra_route_string(i
),
1921 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1924 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1925 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1926 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1928 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1929 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1930 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1932 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1933 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1934 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1936 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1937 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1938 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1940 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1941 vty_out(vty
, "zebra route-map delay-timer %d\n",
1942 zebra_rmap_update_timer
);
1945 void zebra_route_map_init(void)
1947 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1948 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1949 install_element(VRF_NODE
, &ip_protocol_cmd
);
1950 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1951 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1952 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1953 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1954 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1955 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1956 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1957 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1958 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1959 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1960 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1961 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1962 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1963 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1964 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1965 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1966 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1967 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1968 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1972 route_map_add_hook(zebra_route_map_add
);
1973 route_map_delete_hook(zebra_route_map_delete
);
1974 route_map_event_hook(zebra_route_map_event
);
1976 route_map_match_interface_hook(generic_match_add
);
1977 route_map_no_match_interface_hook(generic_match_delete
);
1979 route_map_match_ip_address_hook(generic_match_add
);
1980 route_map_no_match_ip_address_hook(generic_match_delete
);
1982 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1983 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1985 route_map_match_ip_next_hop_hook(generic_match_add
);
1986 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1988 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1989 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1991 route_map_match_ip_next_hop_type_hook(generic_match_add
);
1992 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
1994 route_map_match_tag_hook(generic_match_add
);
1995 route_map_no_match_tag_hook(generic_match_delete
);
1997 route_map_match_ipv6_address_hook(generic_match_add
);
1998 route_map_no_match_ipv6_address_hook(generic_match_delete
);
2000 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
2001 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
2003 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
2004 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
2006 route_map_install_match(&route_match_tag_cmd
);
2007 route_map_install_match(&route_match_interface_cmd
);
2008 route_map_install_match(&route_match_ip_next_hop_cmd
);
2009 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
2010 route_map_install_match(&route_match_ip_address_cmd
);
2011 route_map_install_match(&route_match_ipv6_address_cmd
);
2012 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
2013 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
2014 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
2015 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
2016 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
2017 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
2018 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
2019 route_map_install_match(&route_match_source_protocol_cmd
);
2020 route_map_install_match(&route_match_source_instance_cmd
);
2023 route_map_install_set(&route_set_src_cmd
);
2025 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
2026 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
2027 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
2028 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
2029 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
2030 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
2031 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
2032 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
2033 install_element(RMAP_NODE
, &match_source_instance_cmd
);
2034 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
2037 install_element(RMAP_NODE
, &set_src_cmd
);
2038 install_element(RMAP_NODE
, &no_set_src_cmd
);