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
:
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
);
95 enum rmap_compile_rets ret
;
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
, type
);
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
:
131 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
132 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
138 * Match function return 1 if match is success else return 0
140 static enum route_map_cmd_result_t
141 route_match_tag(void *rule
, const struct prefix
*prefix
,
142 route_map_object_t type
, void *object
)
145 struct nh_rmap_obj
*nh_data
;
147 if (type
== RMAP_ZEBRA
) {
151 if (nh_data
->tag
== *tag
)
157 /* Route map commands for tag matching */
158 static struct route_map_rule_cmd route_match_tag_cmd
= {
159 "tag", route_match_tag
, route_map_rule_tag_compile
,
160 route_map_rule_tag_free
,
164 /* `match interface IFNAME' */
165 /* Match function return 1 if match is success else return zero. */
166 static enum route_map_cmd_result_t
167 route_match_interface(void *rule
, const struct prefix
*prefix
,
168 route_map_object_t type
, void *object
)
170 struct nh_rmap_obj
*nh_data
;
174 if (type
== RMAP_ZEBRA
) {
175 if (strcasecmp(ifname
, "any") == 0)
178 if (!nh_data
|| !nh_data
->nexthop
)
180 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
183 if (nh_data
->nexthop
->ifindex
== ifindex
)
189 /* Route map `match interface' match statement. `arg' is IFNAME value */
190 static void *route_match_interface_compile(const char *arg
)
192 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
195 /* Free route map's compiled `match interface' value. */
196 static void route_match_interface_free(void *rule
)
198 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
201 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
206 vty_out(vty
, "Protocol : route-map\n");
207 vty_out(vty
, "------------------------\n");
209 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
210 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
211 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
212 PROTO_RM_NAME(zvrf
, af_type
, i
));
214 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
217 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
218 vty_out(vty
, "%-10s : %-10s\n", "any",
219 PROTO_RM_NAME(zvrf
, af_type
, i
));
221 vty_out(vty
, "%-10s : none\n", "any");
224 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
229 vty_out(vty
, "Protocol : route-map\n");
230 vty_out(vty
, "------------------------\n");
232 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
233 if (NHT_RM_NAME(zvrf
, af_type
, i
))
234 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
235 NHT_RM_NAME(zvrf
, af_type
, i
));
237 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
240 if (NHT_RM_NAME(zvrf
, af_type
, i
))
241 vty_out(vty
, "%-10s : %-10s\n", "any",
242 NHT_RM_NAME(zvrf
, af_type
, i
));
244 vty_out(vty
, "%-10s : none\n", "any");
247 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
248 const char *vrf_name
)
250 struct zebra_vrf
*zvrf
;
255 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
256 zvrf
= (struct zebra_vrf
*)vrf
->info
;
259 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
260 show_vrf_proto_rm(vty
, zvrf
, af_type
);
263 vrf_id_t vrf_id
= VRF_DEFAULT
;
266 VRF_GET_ID(vrf_id
, vrf_name
, false);
268 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
272 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
273 show_vrf_proto_rm(vty
, zvrf
, af_type
);
279 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
280 const char *vrf_name
)
282 struct zebra_vrf
*zvrf
;
287 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
288 zvrf
= (struct zebra_vrf
*)vrf
->info
;
292 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
293 show_vrf_nht_rm(vty
, zvrf
, af_type
);
296 vrf_id_t vrf_id
= VRF_DEFAULT
;
299 VRF_GET_ID(vrf_id
, vrf_name
, false);
301 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
305 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
306 show_vrf_nht_rm(vty
, zvrf
, af_type
);
312 /* Route map commands for interface matching */
313 struct route_map_rule_cmd route_match_interface_cmd
= {
314 "interface", route_match_interface
, route_match_interface_compile
,
315 route_match_interface_free
};
317 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
318 int rtype
, afi_t afi
, safi_t safi
)
320 struct route_table
*table
;
322 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
323 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
326 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
328 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
329 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
330 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
331 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
332 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
334 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
336 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
338 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
339 zvrf
->vrf
->vrf_id
, rtype
);
340 /* Process routes of interested address-families. */
341 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
343 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
349 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
350 int rtype
, afi_t afi
, safi_t safi
)
352 struct route_table
*table
;
354 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
357 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
359 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
360 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
361 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
363 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
364 zvrf
->vrf
->vrf_id
, rtype
);
365 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
367 /* Process routes of interested address-families. */
368 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
370 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
372 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
377 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
381 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
382 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
385 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
387 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
388 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
389 NHT_RM_MAP(zvrf
, afi
, rtype
) =
390 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
391 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
393 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
394 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
, NULL
);
399 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
403 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
406 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
407 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
408 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
409 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
411 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
412 zvrf
->vrf
->vrf_id
, rtype
);
413 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
415 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
,
418 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
423 DEFUN (match_ip_address_prefix_len
,
424 match_ip_address_prefix_len_cmd
,
425 "match ip address prefix-len (0-32)",
428 "Match prefix length of ip address\n"
429 "Match prefix length of ip address\n"
432 return zebra_route_match_add(vty
, "ip address prefix-len", argv
[4]->arg
,
433 RMAP_EVENT_MATCH_ADDED
);
436 DEFUN (no_match_ip_address_prefix_len
,
437 no_match_ip_address_prefix_len_cmd
,
438 "no match ip address prefix-len [(0-32)]",
442 "Match prefix length of ip address\n"
443 "Match prefix length of ip address\n"
446 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
447 return zebra_route_match_delete(vty
, "ip address prefix-len", plen
,
448 RMAP_EVENT_MATCH_DELETED
);
451 DEFUN (match_ipv6_address_prefix_len
,
452 match_ipv6_address_prefix_len_cmd
,
453 "match ipv6 address prefix-len (0-128)",
456 "Match prefix length of ipv6 address\n"
457 "Match prefix length of ipv6 address\n"
460 return zebra_route_match_add(vty
, "ipv6 address prefix-len",
461 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
464 DEFUN (no_match_ipv6_address_prefix_len
,
465 no_match_ipv6_address_prefix_len_cmd
,
466 "no match ipv6 address prefix-len [(0-128)]",
470 "Match prefix length of ip address\n"
471 "Match prefix length of ip address\n"
474 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
475 return zebra_route_match_delete(vty
, "ipv6 address prefix-len", plen
,
476 RMAP_EVENT_MATCH_DELETED
);
479 DEFUN (match_ip_nexthop_prefix_len
,
480 match_ip_nexthop_prefix_len_cmd
,
481 "match ip next-hop prefix-len (0-32)",
484 "Match prefixlen of nexthop ip address\n"
485 "Match prefixlen of given nexthop\n"
488 return zebra_route_match_add(vty
, "ip next-hop prefix-len",
489 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
492 DEFUN (no_match_ip_nexthop_prefix_len
,
493 no_match_ip_nexthop_prefix_len_cmd
,
494 "no match ip next-hop prefix-len [(0-32)]",
498 "Match prefixlen of nexthop ip address\n"
499 "Match prefix length of nexthop\n"
502 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
503 return zebra_route_match_delete(vty
, "ip next-hop prefix-len", plen
,
504 RMAP_EVENT_MATCH_DELETED
);
507 DEFUN (match_source_protocol
,
508 match_source_protocol_cmd
,
509 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
511 "Match protocol via which the route was learnt\n"
522 "Routes from directly connected peer\n"
523 "Routes from system configuration\n"
524 "Routes from kernel\n"
525 "Statically configured routes\n"
528 char *proto
= argv
[2]->text
;
531 i
= proto_name2num(proto
);
533 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
534 return CMD_WARNING_CONFIG_FAILED
;
536 return zebra_route_match_add(vty
, "source-protocol", proto
,
537 RMAP_EVENT_MATCH_ADDED
);
540 DEFUN (no_match_source_protocol
,
541 no_match_source_protocol_cmd
,
542 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
545 "No match protocol via which the route was learnt\n"
556 "Routes from directly connected peer\n"
557 "Routes from system configuration\n"
558 "Routes from kernel\n"
559 "Statically configured routes\n"
562 char *proto
= (argc
== 4) ? argv
[3]->text
: NULL
;
563 return zebra_route_match_delete(vty
, "source-protocol", proto
,
564 RMAP_EVENT_MATCH_DELETED
);
567 DEFUN (match_source_instance
,
568 match_source_instance_cmd
,
569 "match source-instance (0-255)",
571 "Match the protocol's instance number\n"
572 "The instance number\n")
574 char *instance
= argv
[2]->arg
;
576 return zebra_route_match_add(vty
, "source-instance", instance
,
577 RMAP_EVENT_MATCH_ADDED
);
580 DEFUN (no_match_source_instance
,
581 no_match_source_instance_cmd
,
582 "no match source-instance [(0-255)]",
584 "Match the protocol's instance number\n"
585 "The instance number\n")
587 char *instance
= (argc
== 4) ? argv
[3]->arg
: NULL
;
589 return zebra_route_match_delete(vty
, "source-instance", instance
,
590 RMAP_EVENT_MATCH_ADDED
);
597 "set src <A.B.C.D|X:X::X:X>",
599 "src address for route\n"
601 "IPv6 src address\n")
605 struct interface
*pif
= NULL
;
610 if (inet_pton(AF_INET
, argv
[idx_ip
]->arg
, &src
.ipv4
) != 1) {
611 if (inet_pton(AF_INET6
, argv
[idx_ip
]->arg
, &src
.ipv6
) != 1) {
612 vty_out(vty
, "%% not a valid IPv4/v6 address\n");
613 return CMD_WARNING_CONFIG_FAILED
;
616 p
.family
= family
= AF_INET6
;
617 p
.u
.prefix6
= src
.ipv6
;
618 p
.prefixlen
= IPV6_MAX_BITLEN
;
620 p
.family
= family
= AF_INET
;
621 p
.u
.prefix4
= src
.ipv4
;
622 p
.prefixlen
= IPV4_MAX_BITLEN
;
625 if (!zebra_check_addr(&p
)) {
626 vty_out(vty
, "%% not a valid source IPv4/v6 address\n");
627 return CMD_WARNING_CONFIG_FAILED
;
630 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
631 if (family
== AF_INET
)
632 pif
= if_lookup_exact_address((void *)&src
.ipv4
,
633 AF_INET
, vrf
->vrf_id
);
634 else if (family
== AF_INET6
)
635 pif
= if_lookup_exact_address((void *)&src
.ipv6
,
636 AF_INET6
, vrf
->vrf_id
);
643 vty_out(vty
, "%% not a local address\n");
644 return CMD_WARNING_CONFIG_FAILED
;
647 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
648 return generic_set_add(vty
, index
, "src", argv
[idx_ip
]->arg
);
653 "no set src [<A.B.C.D|X:X::X:X>]",
656 "Source address for route\n"
660 char *ip
= (argc
== 4) ? argv
[3]->arg
: NULL
;
661 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
662 return generic_set_delete(vty
, index
, "src", ip
);
665 DEFUN (zebra_route_map_timer
,
666 zebra_route_map_timer_cmd
,
667 "zebra route-map delay-timer (0-600)",
669 "Set route-map parameters\n"
670 "Time to wait before route-map updates are processed\n"
671 "0 means event-driven updates are disabled\n")
674 uint32_t rmap_delay_timer
;
676 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
677 zebra_route_map_set_delay_timer(rmap_delay_timer
);
679 return (CMD_SUCCESS
);
682 DEFUN (no_zebra_route_map_timer
,
683 no_zebra_route_map_timer_cmd
,
684 "no zebra route-map delay-timer [(0-600)]",
687 "Set route-map parameters\n"
688 "Reset delay-timer to default value, 30 secs\n"
689 "0 means event-driven updates are disabled\n")
691 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
693 return (CMD_SUCCESS
);
698 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
699 " $proto route-map ROUTE-MAP$rmap",
701 "Filter routing info exchanged between zebra and protocol\n"
702 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
703 "Specify route-map\n"
711 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
716 if (strcasecmp(proto
, "any") == 0)
717 rtype
= ZEBRA_ROUTE_MAX
;
719 rtype
= proto_name2num(proto
);
721 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
722 return CMD_WARNING_CONFIG_FAILED
;
725 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
730 DEFPY (no_ip_protocol
,
732 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
733 " $proto [route-map ROUTE-MAP$rmap]",
736 "Stop filtering routing info between zebra and protocol\n"
737 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
738 "Specify route-map\n"
745 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
750 if (strcasecmp(proto
, "any") == 0)
751 rtype
= ZEBRA_ROUTE_MAX
;
753 rtype
= proto_name2num(proto
);
755 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
756 return CMD_WARNING_CONFIG_FAILED
;
759 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
764 DEFPY (show_ip_protocol
,
765 show_ip_protocol_cmd
,
766 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
769 "IP protocol filtering status\n"
770 VRF_FULL_CMD_HELP_STR
)
772 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
777 DEFPY (ipv6_protocol
,
779 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
780 " $proto route-map ROUTE-MAP$rmap",
782 "Filter IPv6 routing info exchanged between zebra and protocol\n"
783 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
784 "Specify route-map\n"
792 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
797 if (strcasecmp(proto
, "any") == 0)
798 rtype
= ZEBRA_ROUTE_MAX
;
800 rtype
= proto_name2num(proto
);
802 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
803 return CMD_WARNING_CONFIG_FAILED
;
806 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
811 DEFPY (no_ipv6_protocol
,
812 no_ipv6_protocol_cmd
,
813 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
814 " $proto [route-map ROUTE-MAP$rmap]",
817 "Stop filtering IPv6 routing info between zebra and protocol\n"
818 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
819 "Specify route-map\n"
826 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
831 if (strcasecmp(proto
, "any") == 0)
832 rtype
= ZEBRA_ROUTE_MAX
;
834 rtype
= proto_name2num(proto
);
836 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
837 return CMD_WARNING_CONFIG_FAILED
;
840 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
845 DEFPY (show_ipv6_protocol
,
846 show_ipv6_protocol_cmd
,
847 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
850 "IPv6 protocol filtering status\n"
851 VRF_FULL_CMD_HELP_STR
)
853 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
858 DEFPY (ip_protocol_nht_rmap
,
859 ip_protocol_nht_rmap_cmd
,
860 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
861 " $proto route-map ROUTE-MAP$rmap",
863 "Filter Next Hop tracking route resolution\n"
864 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
865 "Specify route map\n"
874 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
879 if (strcasecmp(proto
, "any") == 0)
880 rtype
= ZEBRA_ROUTE_MAX
;
882 rtype
= proto_name2num(proto
);
884 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
885 return CMD_WARNING_CONFIG_FAILED
;
888 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
893 DEFPY (no_ip_protocol_nht_rmap
,
894 no_ip_protocol_nht_rmap_cmd
,
895 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
896 " $proto route-map [ROUTE-MAP$rmap]",
899 "Filter Next Hop tracking route resolution\n"
900 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
901 "Specify route map\n"
908 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
913 if (strcasecmp(proto
, "any") == 0)
914 rtype
= ZEBRA_ROUTE_MAX
;
916 rtype
= proto_name2num(proto
);
918 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
919 return CMD_WARNING_CONFIG_FAILED
;
922 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
927 DEFPY (show_ip_protocol_nht
,
928 show_ip_protocol_nht_cmd
,
929 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
932 "IP nexthop tracking table\n"
933 "IP Next Hop tracking filtering status\n"
934 VRF_FULL_CMD_HELP_STR
)
936 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
941 DEFPY (ipv6_protocol_nht_rmap
,
942 ipv6_protocol_nht_rmap_cmd
,
943 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
944 " $proto route-map ROUTE-MAP$rmap",
946 "Filter Next Hop tracking route resolution\n"
947 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
948 "Specify route map\n"
956 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
961 if (strcasecmp(proto
, "any") == 0)
962 rtype
= ZEBRA_ROUTE_MAX
;
964 rtype
= proto_name2num(proto
);
966 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
967 return CMD_WARNING_CONFIG_FAILED
;
970 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
975 DEFPY (no_ipv6_protocol_nht_rmap
,
976 no_ipv6_protocol_nht_rmap_cmd
,
977 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
978 " $proto [route-map ROUTE-MAP$rmap]",
981 "Filter Next Hop tracking route resolution\n"
982 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
983 "Specify route map\n"
990 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
995 if (strcasecmp(proto
, "any") == 0)
996 rtype
= ZEBRA_ROUTE_MAX
;
998 rtype
= proto_name2num(proto
);
1000 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
1001 return CMD_WARNING_CONFIG_FAILED
;
1004 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
1009 DEFPY (show_ipv6_protocol_nht
,
1010 show_ipv6_protocol_nht_cmd
,
1011 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
1014 "Next Hop filtering status\n"
1016 VRF_FULL_CMD_HELP_STR
)
1018 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
1023 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1025 /* `match ip next-hop IP_ACCESS_LIST' */
1027 /* Match function return 1 if match is success else return zero. */
1028 static enum route_map_cmd_result_t
1029 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
,
1030 route_map_object_t type
, void *object
)
1032 struct access_list
*alist
;
1033 struct nh_rmap_obj
*nh_data
;
1034 struct prefix_ipv4 p
;
1036 if (type
== RMAP_ZEBRA
) {
1039 return RMAP_NOMATCH
;
1041 switch (nh_data
->nexthop
->type
) {
1042 case NEXTHOP_TYPE_IFINDEX
:
1043 /* Interface routes can't match ip next-hop */
1044 return RMAP_NOMATCH
;
1045 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1046 case NEXTHOP_TYPE_IPV4
:
1048 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1049 p
.prefixlen
= IPV4_MAX_BITLEN
;
1052 return RMAP_NOMATCH
;
1054 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1056 return RMAP_NOMATCH
;
1058 return (access_list_apply(alist
, &p
) == FILTER_DENY
1062 return RMAP_NOMATCH
;
1065 /* Route map `ip next-hop' match statement. `arg' should be
1066 access-list name. */
1067 static void *route_match_ip_next_hop_compile(const char *arg
)
1069 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1072 /* Free route map's compiled `. */
1073 static void route_match_ip_next_hop_free(void *rule
)
1075 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1078 /* Route map commands for ip next-hop matching. */
1079 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1080 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
1081 route_match_ip_next_hop_free
};
1083 /* `match ip next-hop prefix-list PREFIX_LIST' */
1085 static enum route_map_cmd_result_t
1086 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1087 route_map_object_t type
, void *object
)
1089 struct prefix_list
*plist
;
1090 struct nh_rmap_obj
*nh_data
;
1091 struct prefix_ipv4 p
;
1093 if (type
== RMAP_ZEBRA
) {
1094 nh_data
= (struct nh_rmap_obj
*)object
;
1096 return RMAP_NOMATCH
;
1098 switch (nh_data
->nexthop
->type
) {
1099 case NEXTHOP_TYPE_IFINDEX
:
1100 /* Interface routes can't match ip next-hop */
1101 return RMAP_NOMATCH
;
1102 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1103 case NEXTHOP_TYPE_IPV4
:
1105 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1106 p
.prefixlen
= IPV4_MAX_BITLEN
;
1109 return RMAP_NOMATCH
;
1111 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1113 return RMAP_NOMATCH
;
1115 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
1119 return RMAP_NOMATCH
;
1122 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1124 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1127 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1129 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1132 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
1133 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
1134 route_match_ip_next_hop_prefix_list_compile
,
1135 route_match_ip_next_hop_prefix_list_free
};
1137 /* `match ip address IP_ACCESS_LIST' */
1139 /* Match function should return 1 if match is success else return
1141 static enum route_map_cmd_result_t
1142 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1143 route_map_object_t type
, void *object
)
1145 struct access_list
*alist
;
1147 if (type
== RMAP_ZEBRA
) {
1148 alist
= access_list_lookup(afi
, (char *)rule
);
1150 return RMAP_NOMATCH
;
1152 return (access_list_apply(alist
, prefix
) == FILTER_DENY
1156 return RMAP_NOMATCH
;
1159 static enum route_map_cmd_result_t
1160 route_match_ip_address(void *rule
, const struct prefix
*prefix
,
1161 route_map_object_t type
, void *object
)
1163 return route_match_address(AFI_IP
, rule
, prefix
, type
, object
);
1166 static enum route_map_cmd_result_t
1167 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
,
1168 route_map_object_t type
, void *object
)
1170 return route_match_address(AFI_IP6
, rule
, prefix
, type
, object
);
1173 /* Route map `ip address' match statement. `arg' should be
1174 access-list name. */
1175 static void *route_match_address_compile(const char *arg
)
1177 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1180 /* Free route map's compiled `ip address' value. */
1181 static void route_match_address_free(void *rule
)
1183 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1186 /* Route map commands for ip address matching. */
1187 static struct route_map_rule_cmd route_match_ip_address_cmd
= {
1188 "ip address", route_match_ip_address
, route_match_address_compile
,
1189 route_match_address_free
};
1191 /* Route map commands for ipv6 address matching. */
1192 static struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1193 "ipv6 address", route_match_ipv6_address
, route_match_address_compile
,
1194 route_match_address_free
};
1196 /* `match ip address prefix-list PREFIX_LIST' */
1198 static enum route_map_cmd_result_t
1199 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1200 route_map_object_t type
, void *object
, afi_t afi
)
1202 struct prefix_list
*plist
;
1204 if (type
== RMAP_ZEBRA
) {
1205 plist
= prefix_list_lookup(afi
, (char *)rule
);
1207 return RMAP_NOMATCH
;
1209 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
1213 return RMAP_NOMATCH
;
1216 static enum route_map_cmd_result_t
1217 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1218 route_map_object_t type
, void *object
)
1220 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1224 static void *route_match_address_prefix_list_compile(const char *arg
)
1226 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1229 static void route_match_address_prefix_list_free(void *rule
)
1231 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1234 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
1235 "ip address prefix-list", route_match_ip_address_prefix_list
,
1236 route_match_address_prefix_list_compile
,
1237 route_match_address_prefix_list_free
};
1239 static enum route_map_cmd_result_t
1240 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1241 route_map_object_t type
, void *object
)
1243 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1247 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
1248 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
1249 route_match_address_prefix_list_compile
,
1250 route_match_address_prefix_list_free
};
1252 /* `match ipv6 next-hop type <TYPE>' */
1254 static enum route_map_cmd_result_t
1255 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1256 route_map_object_t type
, void *object
)
1258 struct nh_rmap_obj
*nh_data
;
1260 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET6
) {
1261 nh_data
= (struct nh_rmap_obj
*)object
;
1263 return RMAP_NOMATCH
;
1265 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1268 return RMAP_NOMATCH
;
1271 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1273 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1276 static void route_match_ipv6_next_hop_type_free(void *rule
)
1278 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1281 struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd
= {
1282 "ipv6 next-hop type", route_match_ipv6_next_hop_type
,
1283 route_match_ipv6_next_hop_type_compile
,
1284 route_match_ipv6_next_hop_type_free
};
1286 /* `match ip address prefix-len PREFIXLEN' */
1288 static enum route_map_cmd_result_t
1289 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1290 route_map_object_t type
, void *object
)
1292 uint32_t *prefixlen
= (uint32_t *)rule
;
1294 if (type
== RMAP_ZEBRA
) {
1295 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
1298 return RMAP_NOMATCH
;
1301 static void *route_match_address_prefix_len_compile(const char *arg
)
1303 uint32_t *prefix_len
;
1304 char *endptr
= NULL
;
1305 unsigned long tmpval
;
1307 /* prefix len value shoud be integer. */
1308 if (!all_digit(arg
))
1312 tmpval
= strtoul(arg
, &endptr
, 10);
1313 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1316 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1318 *prefix_len
= tmpval
;
1322 static void route_match_address_prefix_len_free(void *rule
)
1324 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1327 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
= {
1328 "ip address prefix-len", route_match_address_prefix_len
,
1329 route_match_address_prefix_len_compile
,
1330 route_match_address_prefix_len_free
};
1332 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd
= {
1333 "ipv6 address prefix-len", route_match_address_prefix_len
,
1334 route_match_address_prefix_len_compile
,
1335 route_match_address_prefix_len_free
};
1337 /* `match ip nexthop prefix-len PREFIXLEN' */
1339 static enum route_map_cmd_result_t
1340 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1341 route_map_object_t type
, void *object
)
1343 uint32_t *prefixlen
= (uint32_t *)rule
;
1344 struct nh_rmap_obj
*nh_data
;
1345 struct prefix_ipv4 p
;
1347 if (type
== RMAP_ZEBRA
) {
1348 nh_data
= (struct nh_rmap_obj
*)object
;
1349 if (!nh_data
|| !nh_data
->nexthop
)
1350 return RMAP_NOMATCH
;
1352 switch (nh_data
->nexthop
->type
) {
1353 case NEXTHOP_TYPE_IFINDEX
:
1354 /* Interface routes can't match ip next-hop */
1355 return RMAP_NOMATCH
;
1356 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1357 case NEXTHOP_TYPE_IPV4
:
1359 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1360 p
.prefixlen
= IPV4_MAX_BITLEN
;
1363 return RMAP_NOMATCH
;
1365 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
1368 return RMAP_NOMATCH
;
1371 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
= {
1372 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len
,
1373 route_match_address_prefix_len_compile
, /* reuse */
1374 route_match_address_prefix_len_free
/* reuse */
1377 /* `match ip next-hop type <blackhole>' */
1379 static enum route_map_cmd_result_t
1380 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1381 route_map_object_t type
, void *object
)
1383 struct nh_rmap_obj
*nh_data
;
1385 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET
) {
1386 nh_data
= (struct nh_rmap_obj
*)object
;
1388 return RMAP_NOMATCH
;
1390 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1393 return RMAP_NOMATCH
;
1396 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1398 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1401 static void route_match_ip_next_hop_type_free(void *rule
)
1403 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1406 static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd
= {
1407 "ip next-hop type", route_match_ip_next_hop_type
,
1408 route_match_ip_next_hop_type_compile
,
1409 route_match_ip_next_hop_type_free
};
1411 /* `match source-protocol PROTOCOL' */
1413 static enum route_map_cmd_result_t
1414 route_match_source_protocol(void *rule
, const struct prefix
*p
,
1415 route_map_object_t type
, void *object
)
1417 uint32_t *rib_type
= (uint32_t *)rule
;
1418 struct nh_rmap_obj
*nh_data
;
1420 if (type
== RMAP_ZEBRA
) {
1421 nh_data
= (struct nh_rmap_obj
*)object
;
1423 return RMAP_NOMATCH
;
1425 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1428 return RMAP_NOMATCH
;
1431 static void *route_match_source_protocol_compile(const char *arg
)
1436 i
= proto_name2num(arg
);
1437 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1444 static void route_match_source_protocol_free(void *rule
)
1446 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1449 static struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1450 "source-protocol", route_match_source_protocol
,
1451 route_match_source_protocol_compile
, route_match_source_protocol_free
};
1453 /* `source-instance` */
1454 static enum route_map_cmd_result_t
1455 route_match_source_instance(void *rule
, const struct prefix
*p
,
1456 route_map_object_t type
, void *object
)
1458 uint8_t *instance
= (uint8_t *)rule
;
1459 struct nh_rmap_obj
*nh_data
;
1461 if (type
!= RMAP_ZEBRA
)
1462 return RMAP_NOMATCH
;
1464 nh_data
= (struct nh_rmap_obj
*)object
;
1466 return RMAP_NOMATCH
;
1468 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1471 static void *route_match_source_instance_compile(const char *arg
)
1477 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1484 static void route_match_source_instance_free(void *rule
)
1486 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1489 static struct route_map_rule_cmd route_match_source_instance_cmd
= {
1490 "source-instance", route_match_source_instance
,
1491 route_match_source_instance_compile
, route_match_source_instance_free
};
1493 /* `set src A.B.C.D' */
1496 static enum route_map_cmd_result_t
1497 route_set_src(void *rule
, const struct prefix
*prefix
, route_map_object_t type
,
1500 struct nh_rmap_obj
*nh_data
;
1502 if (type
== RMAP_ZEBRA
) {
1503 nh_data
= (struct nh_rmap_obj
*)object
;
1504 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1509 /* set src compilation. */
1510 static void *route_set_src_compile(const char *arg
)
1512 union g_addr src
, *psrc
;
1514 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1515 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1516 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1523 /* Free route map's compiled `set src' value. */
1524 static void route_set_src_free(void *rule
)
1526 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1529 /* Set src rule structure. */
1530 static struct route_map_rule_cmd route_set_src_cmd
= {
1531 "src", route_set_src
, route_set_src_compile
, route_set_src_free
,
1534 /* The function checks if the changed routemap specified by parameter rmap
1535 * matches the configured protocol routemaps in proto_rm table. If there is
1536 * a match then rib_update_table() to process the routes.
1538 static void zebra_rib_table_rm_update(const char *rmap
)
1541 struct route_table
*table
;
1542 struct vrf
*vrf
= NULL
;
1543 struct zebra_vrf
*zvrf
= NULL
;
1547 struct route_map
*old
= NULL
;
1549 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1553 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1554 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1555 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1556 if (IS_ZEBRA_DEBUG_EVENT
)
1558 "%s : AFI_IP rmap %s, route type %s",
1560 zebra_route_string(i
));
1562 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1564 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1565 route_map_lookup_by_name(rmap_name
);
1566 /* old is NULL. i.e Route map creation event.
1567 * So update applied_counter.
1568 * If Old is not NULL, i.e It may be routemap
1569 * updation or deletion.
1570 * So no need to update the counter.
1573 route_map_counter_increment(
1574 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1575 /* There is single rib table for all protocols
1578 table
= zvrf
->table
[AFI_IP
]
1585 RIB_UPDATE_RMAP_CHANGE
);
1589 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1590 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1591 if (IS_ZEBRA_DEBUG_EVENT
)
1593 "%s : AFI_IP6 rmap %s, route type %s",
1595 zebra_route_string(i
));
1597 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1599 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1600 route_map_lookup_by_name(rmap_name
);
1602 route_map_counter_increment(
1603 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1604 /* There is single rib table for all protocols
1606 if (afi_ipv6
== 0) {
1607 table
= zvrf
->table
[AFI_IP6
]
1614 RIB_UPDATE_RMAP_CHANGE
);
1622 /* The function checks if the changed routemap specified by parameter rmap
1623 * matches the configured protocol routemaps in nht_rm table. If there is
1624 * a match then zebra_evaluate_rnh() to process the nexthops.
1626 static void zebra_nht_rm_update(const char *rmap
)
1629 struct route_table
*table
;
1630 struct vrf
*vrf
= NULL
;
1631 struct zebra_vrf
*zvrf
= NULL
;
1635 struct route_map
*old
= NULL
;
1637 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1641 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1642 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1643 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1644 if (IS_ZEBRA_DEBUG_EVENT
)
1646 "%s : AFI_IP rmap %s, route type %s",
1648 zebra_route_string(i
));
1650 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1652 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1653 route_map_lookup_by_name(rmap_name
);
1655 route_map_counter_increment(
1656 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1657 /* There is single rib table for all protocols
1660 table
= zvrf
->table
[AFI_IP
]
1668 RNH_NEXTHOP_TYPE
, NULL
);
1673 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1674 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1675 if (IS_ZEBRA_DEBUG_EVENT
)
1677 "%s : AFI_IP6 rmap %s, route type %s",
1679 zebra_route_string(i
));
1681 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1683 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1684 route_map_lookup_by_name(rmap_name
);
1686 route_map_counter_increment(
1687 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1688 /* There is single rib table for all protocols
1690 if (afi_ipv6
== 0) {
1691 table
= zvrf
->table
[AFI_IP6
]
1699 RNH_NEXTHOP_TYPE
, NULL
);
1707 static void zebra_route_map_process_update_cb(char *rmap_name
)
1709 if (IS_ZEBRA_DEBUG_EVENT
)
1710 zlog_debug("Event handler for route-map: %s",
1712 zebra_import_table_rm_update(rmap_name
);
1713 zebra_rib_table_rm_update(rmap_name
);
1714 zebra_nht_rm_update(rmap_name
);
1717 static int zebra_route_map_update_timer(struct thread
*thread
)
1719 zebra_t_rmap_update
= NULL
;
1721 if (IS_ZEBRA_DEBUG_EVENT
)
1722 zlog_debug("Event driven route-map update triggered");
1724 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1726 "%u: Routemap update-timer fired, scheduling RIB processing",
1729 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1732 * This code needs to be updated to be:
1733 * 1) VRF Aware <sigh>
1734 * 2) Route-map aware
1739 static void zebra_route_map_set_delay_timer(uint32_t value
)
1741 zebra_rmap_update_timer
= value
;
1742 if (!value
&& zebra_t_rmap_update
) {
1743 /* Event driven route map updates is being disabled */
1744 /* But there's a pending timer. Fire it off now */
1745 thread_cancel(zebra_t_rmap_update
);
1746 zebra_route_map_update_timer(zebra_t_rmap_update
);
1750 void zebra_route_map_write_delay_timer(struct vty
*vty
)
1752 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1753 vty_out(vty
, "zebra route-map delay-timer %d\n",
1754 zebra_rmap_update_timer
);
1759 zebra_route_map_check(int family
, int rib_type
, uint8_t instance
,
1760 const struct prefix
*p
, struct nexthop
*nexthop
,
1761 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1763 struct route_map
*rmap
= NULL
;
1764 route_map_result_t ret
= RMAP_PERMITMATCH
;
1765 struct nh_rmap_obj nh_obj
;
1767 nh_obj
.nexthop
= nexthop
;
1768 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1769 nh_obj
.source_protocol
= rib_type
;
1770 nh_obj
.instance
= instance
;
1774 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1775 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1776 if (!rmap
&& PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
))
1777 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1779 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1785 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1787 return zebra_import_table_routemap
[afi
][table
];
1790 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1793 zebra_import_table_routemap
[afi
][table
] =
1794 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1797 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1799 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1803 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1804 const struct prefix
*p
,
1805 struct nexthop
*nexthop
,
1806 vrf_id_t vrf_id
, route_tag_t tag
,
1807 const char *rmap_name
)
1809 struct route_map
*rmap
= NULL
;
1810 route_map_result_t ret
= RMAP_DENYMATCH
;
1811 struct nh_rmap_obj nh_obj
;
1813 nh_obj
.nexthop
= nexthop
;
1814 nh_obj
.vrf_id
= vrf_id
;
1815 nh_obj
.source_protocol
= re_type
;
1816 nh_obj
.instance
= instance
;
1820 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1821 rmap
= route_map_lookup_by_name(rmap_name
);
1823 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1829 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1830 const struct prefix
*p
,
1831 struct zebra_vrf
*zvrf
,
1832 struct route_entry
*re
,
1833 struct nexthop
*nexthop
)
1835 struct route_map
*rmap
= NULL
;
1836 route_map_result_t ret
= RMAP_PERMITMATCH
;
1837 struct nh_rmap_obj nh_obj
;
1839 nh_obj
.nexthop
= nexthop
;
1840 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1841 nh_obj
.source_protocol
= re
->type
;
1842 nh_obj
.instance
= re
->instance
;
1843 nh_obj
.metric
= re
->metric
;
1844 nh_obj
.tag
= re
->tag
;
1846 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1847 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1848 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1849 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1851 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1856 static void zebra_route_map_mark_update(const char *rmap_name
)
1858 /* rmap_update_timer of 0 means don't do route updates */
1859 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1860 zebra_t_rmap_update
= NULL
;
1861 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1862 NULL
, zebra_rmap_update_timer
,
1863 &zebra_t_rmap_update
);
1867 static void zebra_route_map_add(const char *rmap_name
)
1869 if (route_map_mark_updated(rmap_name
) == 0)
1870 zebra_route_map_mark_update(rmap_name
);
1872 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1875 static void zebra_route_map_delete(const char *rmap_name
)
1877 if (route_map_mark_updated(rmap_name
) == 0)
1878 zebra_route_map_mark_update(rmap_name
);
1880 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1883 static void zebra_route_map_event(const char *rmap_name
)
1885 if (route_map_mark_updated(rmap_name
) == 0)
1886 zebra_route_map_mark_update(rmap_name
);
1888 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1891 /* ip protocol configuration write function */
1892 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1893 struct zebra_vrf
*zvrf
)
1898 memset(space
, 0, sizeof(space
));
1900 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1901 sprintf(space
, "%s", " ");
1903 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1904 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1905 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1906 zebra_route_string(i
),
1907 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1909 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1910 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1911 zebra_route_string(i
),
1912 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1914 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1915 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1916 zebra_route_string(i
),
1917 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1919 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1920 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1921 zebra_route_string(i
),
1922 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1925 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1926 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1927 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1929 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1930 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1931 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1933 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1934 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1935 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1937 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1938 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1939 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1941 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1942 vty_out(vty
, "zebra route-map delay-timer %d\n",
1943 zebra_rmap_update_timer
);
1946 void zebra_route_map_init(void)
1948 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1949 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1950 install_element(VRF_NODE
, &ip_protocol_cmd
);
1951 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1952 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1953 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1954 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1955 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1956 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1957 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1958 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1959 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1960 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1961 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1962 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1963 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1964 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1965 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1966 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1967 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1968 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1969 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1973 route_map_add_hook(zebra_route_map_add
);
1974 route_map_delete_hook(zebra_route_map_delete
);
1975 route_map_event_hook(zebra_route_map_event
);
1977 route_map_match_interface_hook(generic_match_add
);
1978 route_map_no_match_interface_hook(generic_match_delete
);
1980 route_map_match_ip_address_hook(generic_match_add
);
1981 route_map_no_match_ip_address_hook(generic_match_delete
);
1983 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1984 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1986 route_map_match_ip_next_hop_hook(generic_match_add
);
1987 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1989 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1990 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1992 route_map_match_ip_next_hop_type_hook(generic_match_add
);
1993 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
1995 route_map_match_tag_hook(generic_match_add
);
1996 route_map_no_match_tag_hook(generic_match_delete
);
1998 route_map_match_ipv6_address_hook(generic_match_add
);
1999 route_map_no_match_ipv6_address_hook(generic_match_delete
);
2001 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
2002 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
2004 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
2005 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
2007 route_map_install_match(&route_match_tag_cmd
);
2008 route_map_install_match(&route_match_interface_cmd
);
2009 route_map_install_match(&route_match_ip_next_hop_cmd
);
2010 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
2011 route_map_install_match(&route_match_ip_address_cmd
);
2012 route_map_install_match(&route_match_ipv6_address_cmd
);
2013 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
2014 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
2015 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
2016 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
2017 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
2018 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
2019 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
2020 route_map_install_match(&route_match_source_protocol_cmd
);
2021 route_map_install_match(&route_match_source_instance_cmd
);
2024 route_map_install_set(&route_set_src_cmd
);
2026 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
2027 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
2028 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
2029 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
2030 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
2031 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
2032 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
2033 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
2034 install_element(RMAP_NODE
, &match_source_instance_cmd
);
2035 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
2038 install_element(RMAP_NODE
, &set_src_cmd
);
2039 install_element(RMAP_NODE
, &no_set_src_cmd
);