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
);
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 route_map_result_t
route_match_tag(void *rule
,
140 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 route_map_result_t
route_match_interface(void *rule
,
166 const struct prefix
*prefix
,
167 route_map_object_t type
,
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"
708 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
713 if (strcasecmp(proto
, "any") == 0)
714 rtype
= ZEBRA_ROUTE_MAX
;
716 rtype
= proto_name2num(proto
);
718 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
719 return CMD_WARNING_CONFIG_FAILED
;
722 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
727 DEFPY (no_ip_protocol
,
729 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
730 " $proto [route-map ROUTE-MAP$rmap]",
733 "Stop filtering routing info between zebra and protocol\n"
734 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
735 "Specify route-map\n"
740 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
745 if (strcasecmp(proto
, "any") == 0)
746 rtype
= ZEBRA_ROUTE_MAX
;
748 rtype
= proto_name2num(proto
);
750 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
751 return CMD_WARNING_CONFIG_FAILED
;
754 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
759 DEFPY (show_ip_protocol
,
760 show_ip_protocol_cmd
,
761 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
764 "IP protocol filtering status\n"
765 VRF_FULL_CMD_HELP_STR
)
767 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
772 DEFPY (ipv6_protocol
,
774 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
775 " $proto route-map ROUTE-MAP$rmap",
777 "Filter IPv6 routing info exchanged between zebra and protocol\n"
778 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
779 "Specify route-map\n"
784 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
789 if (strcasecmp(proto
, "any") == 0)
790 rtype
= ZEBRA_ROUTE_MAX
;
792 rtype
= proto_name2num(proto
);
794 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
795 return CMD_WARNING_CONFIG_FAILED
;
798 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
803 DEFPY (no_ipv6_protocol
,
804 no_ipv6_protocol_cmd
,
805 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
806 " $proto [route-map ROUTE-MAP$rmap]",
809 "Stop filtering IPv6 routing info between zebra and protocol\n"
810 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
811 "Specify route-map\n"
816 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
821 if (strcasecmp(proto
, "any") == 0)
822 rtype
= ZEBRA_ROUTE_MAX
;
824 rtype
= proto_name2num(proto
);
826 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
827 return CMD_WARNING_CONFIG_FAILED
;
830 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
835 DEFPY (show_ipv6_protocol
,
836 show_ipv6_protocol_cmd
,
837 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
840 "IPv6 protocol filtering status\n"
841 VRF_FULL_CMD_HELP_STR
)
843 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
848 DEFPY (ip_protocol_nht_rmap
,
849 ip_protocol_nht_rmap_cmd
,
850 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
851 " $proto route-map ROUTE-MAP$rmap",
853 "Filter Next Hop tracking route resolution\n"
854 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
855 "Specify route map\n"
861 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
866 if (strcasecmp(proto
, "any") == 0)
867 rtype
= ZEBRA_ROUTE_MAX
;
869 rtype
= proto_name2num(proto
);
871 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
872 return CMD_WARNING_CONFIG_FAILED
;
875 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
880 DEFPY (no_ip_protocol_nht_rmap
,
881 no_ip_protocol_nht_rmap_cmd
,
882 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
883 " $proto route-map [ROUTE-MAP$rmap]",
886 "Filter Next Hop tracking route resolution\n"
887 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
888 "Specify route map\n"
893 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
898 if (strcasecmp(proto
, "any") == 0)
899 rtype
= ZEBRA_ROUTE_MAX
;
901 rtype
= proto_name2num(proto
);
903 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
904 return CMD_WARNING_CONFIG_FAILED
;
907 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
912 DEFPY (show_ip_protocol_nht
,
913 show_ip_protocol_nht_cmd
,
914 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
917 "IP nexthop tracking table\n"
918 "IP Next Hop tracking filtering status\n"
919 VRF_FULL_CMD_HELP_STR
)
921 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
926 DEFPY (ipv6_protocol_nht_rmap
,
927 ipv6_protocol_nht_rmap_cmd
,
928 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
929 " $proto route-map ROUTE-MAP$rmap",
931 "Filter Next Hop tracking route resolution\n"
932 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
933 "Specify route map\n"
938 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
943 if (strcasecmp(proto
, "any") == 0)
944 rtype
= ZEBRA_ROUTE_MAX
;
946 rtype
= proto_name2num(proto
);
948 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
949 return CMD_WARNING_CONFIG_FAILED
;
952 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
957 DEFPY (no_ipv6_protocol_nht_rmap
,
958 no_ipv6_protocol_nht_rmap_cmd
,
959 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
960 " $proto [route-map ROUTE-MAP$rmap]",
963 "Filter Next Hop tracking route resolution\n"
964 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
965 "Specify route map\n"
970 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
975 if (strcasecmp(proto
, "any") == 0)
976 rtype
= ZEBRA_ROUTE_MAX
;
978 rtype
= proto_name2num(proto
);
980 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
981 return CMD_WARNING_CONFIG_FAILED
;
984 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
989 DEFPY (show_ipv6_protocol_nht
,
990 show_ipv6_protocol_nht_cmd
,
991 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
994 "Next Hop filtering status\n"
996 VRF_FULL_CMD_HELP_STR
)
998 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
1003 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1005 /* `match ip next-hop IP_ACCESS_LIST' */
1007 /* Match function return 1 if match is success else return zero. */
1008 static route_map_result_t
route_match_ip_next_hop(void *rule
,
1009 const struct prefix
*prefix
,
1010 route_map_object_t type
,
1013 struct access_list
*alist
;
1014 struct nh_rmap_obj
*nh_data
;
1015 struct prefix_ipv4 p
;
1017 if (type
== RMAP_ZEBRA
) {
1020 return RMAP_DENYMATCH
;
1022 switch (nh_data
->nexthop
->type
) {
1023 case NEXTHOP_TYPE_IFINDEX
:
1024 /* Interface routes can't match ip next-hop */
1025 return RMAP_NOMATCH
;
1026 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1027 case NEXTHOP_TYPE_IPV4
:
1029 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1030 p
.prefixlen
= IPV4_MAX_BITLEN
;
1033 return RMAP_NOMATCH
;
1035 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1037 return RMAP_NOMATCH
;
1039 return (access_list_apply(alist
, &p
) == FILTER_DENY
1043 return RMAP_NOMATCH
;
1046 /* Route map `ip next-hop' match statement. `arg' should be
1047 access-list name. */
1048 static void *route_match_ip_next_hop_compile(const char *arg
)
1050 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1053 /* Free route map's compiled `. */
1054 static void route_match_ip_next_hop_free(void *rule
)
1056 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1059 /* Route map commands for ip next-hop matching. */
1060 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1061 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
1062 route_match_ip_next_hop_free
};
1064 /* `match ip next-hop prefix-list PREFIX_LIST' */
1066 static route_map_result_t
1067 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1068 route_map_object_t type
, void *object
)
1070 struct prefix_list
*plist
;
1071 struct nh_rmap_obj
*nh_data
;
1072 struct prefix_ipv4 p
;
1074 if (type
== RMAP_ZEBRA
) {
1075 nh_data
= (struct nh_rmap_obj
*)object
;
1077 return RMAP_DENYMATCH
;
1079 switch (nh_data
->nexthop
->type
) {
1080 case NEXTHOP_TYPE_IFINDEX
:
1081 /* Interface routes can't match ip next-hop */
1082 return RMAP_NOMATCH
;
1083 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1084 case NEXTHOP_TYPE_IPV4
:
1086 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1087 p
.prefixlen
= IPV4_MAX_BITLEN
;
1090 return RMAP_NOMATCH
;
1092 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1094 return RMAP_NOMATCH
;
1096 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
1100 return RMAP_NOMATCH
;
1103 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1105 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1108 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1110 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1113 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
1114 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
1115 route_match_ip_next_hop_prefix_list_compile
,
1116 route_match_ip_next_hop_prefix_list_free
};
1118 /* `match ip address IP_ACCESS_LIST' */
1120 /* Match function should return 1 if match is success else return
1122 static route_map_result_t
route_match_address(afi_t afi
, void *rule
,
1123 const struct prefix
*prefix
,
1124 route_map_object_t type
,
1127 struct access_list
*alist
;
1129 if (type
== RMAP_ZEBRA
) {
1130 alist
= access_list_lookup(afi
, (char *)rule
);
1132 return RMAP_NOMATCH
;
1134 return (access_list_apply(alist
, prefix
) == FILTER_DENY
1138 return RMAP_NOMATCH
;
1141 static route_map_result_t
route_match_ip_address(void *rule
,
1142 const struct prefix
*prefix
,
1143 route_map_object_t type
,
1146 return route_match_address(AFI_IP
, rule
, prefix
, type
, object
);
1149 static route_map_result_t
route_match_ipv6_address(void *rule
,
1150 const struct prefix
*prefix
,
1151 route_map_object_t type
,
1155 return route_match_address(AFI_IP6
, rule
, prefix
, type
, object
);
1158 /* Route map `ip address' match statement. `arg' should be
1159 access-list name. */
1160 static void *route_match_address_compile(const char *arg
)
1162 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1165 /* Free route map's compiled `ip address' value. */
1166 static void route_match_address_free(void *rule
)
1168 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1171 /* Route map commands for ip address matching. */
1172 static struct route_map_rule_cmd route_match_ip_address_cmd
= {
1173 "ip address", route_match_ip_address
, route_match_address_compile
,
1174 route_match_address_free
};
1176 /* Route map commands for ipv6 address matching. */
1177 static struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1178 "ipv6 address", route_match_ipv6_address
, route_match_address_compile
,
1179 route_match_address_free
};
1181 /* `match ip address prefix-list PREFIX_LIST' */
1183 static route_map_result_t
1184 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1185 route_map_object_t type
, void *object
, afi_t afi
)
1187 struct prefix_list
*plist
;
1189 if (type
== RMAP_ZEBRA
) {
1190 plist
= prefix_list_lookup(afi
, (char *)rule
);
1192 return RMAP_NOMATCH
;
1194 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
1198 return RMAP_NOMATCH
;
1201 static route_map_result_t
1202 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1203 route_map_object_t type
, void *object
)
1205 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1209 static void *route_match_address_prefix_list_compile(const char *arg
)
1211 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1214 static void route_match_address_prefix_list_free(void *rule
)
1216 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1219 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
1220 "ip address prefix-list", route_match_ip_address_prefix_list
,
1221 route_match_address_prefix_list_compile
,
1222 route_match_address_prefix_list_free
};
1224 static route_map_result_t
1225 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1226 route_map_object_t type
, void *object
)
1228 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1232 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
1233 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
1234 route_match_address_prefix_list_compile
,
1235 route_match_address_prefix_list_free
};
1237 /* `match ipv6 next-hop type <TYPE>' */
1239 static route_map_result_t
1240 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1241 route_map_object_t type
, void *object
)
1243 struct nh_rmap_obj
*nh_data
;
1245 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET6
) {
1246 nh_data
= (struct nh_rmap_obj
*)object
;
1248 return RMAP_DENYMATCH
;
1250 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1253 return RMAP_NOMATCH
;
1256 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1258 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1261 static void route_match_ipv6_next_hop_type_free(void *rule
)
1263 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1266 struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd
= {
1267 "ipv6 next-hop type", route_match_ipv6_next_hop_type
,
1268 route_match_ipv6_next_hop_type_compile
,
1269 route_match_ipv6_next_hop_type_free
};
1271 /* `match ip address prefix-len PREFIXLEN' */
1273 static route_map_result_t
1274 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1275 route_map_object_t type
, void *object
)
1277 uint32_t *prefixlen
= (uint32_t *)rule
;
1279 if (type
== RMAP_ZEBRA
) {
1280 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
1283 return RMAP_NOMATCH
;
1286 static void *route_match_address_prefix_len_compile(const char *arg
)
1288 uint32_t *prefix_len
;
1289 char *endptr
= NULL
;
1290 unsigned long tmpval
;
1292 /* prefix len value shoud be integer. */
1293 if (!all_digit(arg
))
1297 tmpval
= strtoul(arg
, &endptr
, 10);
1298 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1301 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1303 *prefix_len
= tmpval
;
1307 static void route_match_address_prefix_len_free(void *rule
)
1309 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1312 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
= {
1313 "ip address prefix-len", route_match_address_prefix_len
,
1314 route_match_address_prefix_len_compile
,
1315 route_match_address_prefix_len_free
};
1317 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd
= {
1318 "ipv6 address prefix-len", route_match_address_prefix_len
,
1319 route_match_address_prefix_len_compile
,
1320 route_match_address_prefix_len_free
};
1322 /* `match ip nexthop prefix-len PREFIXLEN' */
1324 static route_map_result_t
1325 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1326 route_map_object_t type
, void *object
)
1328 uint32_t *prefixlen
= (uint32_t *)rule
;
1329 struct nh_rmap_obj
*nh_data
;
1330 struct prefix_ipv4 p
;
1332 if (type
== RMAP_ZEBRA
) {
1333 nh_data
= (struct nh_rmap_obj
*)object
;
1334 if (!nh_data
|| !nh_data
->nexthop
)
1335 return RMAP_DENYMATCH
;
1337 switch (nh_data
->nexthop
->type
) {
1338 case NEXTHOP_TYPE_IFINDEX
:
1339 /* Interface routes can't match ip next-hop */
1340 return RMAP_NOMATCH
;
1341 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1342 case NEXTHOP_TYPE_IPV4
:
1344 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1345 p
.prefixlen
= IPV4_MAX_BITLEN
;
1348 return RMAP_NOMATCH
;
1350 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
1353 return RMAP_NOMATCH
;
1356 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
= {
1357 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len
,
1358 route_match_address_prefix_len_compile
, /* reuse */
1359 route_match_address_prefix_len_free
/* reuse */
1362 /* `match ip next-hop type <blackhole>' */
1364 static route_map_result_t
1365 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1366 route_map_object_t type
, void *object
)
1368 struct nh_rmap_obj
*nh_data
;
1370 if (type
== RMAP_ZEBRA
&& prefix
->family
== AF_INET
) {
1371 nh_data
= (struct nh_rmap_obj
*)object
;
1373 return RMAP_DENYMATCH
;
1375 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1378 return RMAP_NOMATCH
;
1381 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1383 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1386 static void route_match_ip_next_hop_type_free(void *rule
)
1388 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1391 static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd
= {
1392 "ip next-hop type", route_match_ip_next_hop_type
,
1393 route_match_ip_next_hop_type_compile
,
1394 route_match_ip_next_hop_type_free
};
1396 /* `match source-protocol PROTOCOL' */
1398 static route_map_result_t
route_match_source_protocol(void *rule
,
1399 const struct prefix
*p
,
1400 route_map_object_t type
,
1403 uint32_t *rib_type
= (uint32_t *)rule
;
1404 struct nh_rmap_obj
*nh_data
;
1406 if (type
== RMAP_ZEBRA
) {
1407 nh_data
= (struct nh_rmap_obj
*)object
;
1409 return RMAP_DENYMATCH
;
1411 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1414 return RMAP_NOMATCH
;
1417 static void *route_match_source_protocol_compile(const char *arg
)
1422 i
= proto_name2num(arg
);
1423 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1430 static void route_match_source_protocol_free(void *rule
)
1432 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1435 static struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1436 "source-protocol", route_match_source_protocol
,
1437 route_match_source_protocol_compile
, route_match_source_protocol_free
};
1439 /* `source-instance` */
1440 static route_map_result_t
route_match_source_instance(void *rule
,
1441 const struct prefix
*p
,
1442 route_map_object_t type
,
1445 uint8_t *instance
= (uint8_t *)rule
;
1446 struct nh_rmap_obj
*nh_data
;
1448 if (type
!= RMAP_ZEBRA
)
1449 return RMAP_NOMATCH
;
1451 nh_data
= (struct nh_rmap_obj
*)object
;
1453 return RMAP_DENYMATCH
;
1455 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1458 static void *route_match_source_instance_compile(const char *arg
)
1464 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1471 static void route_match_source_instance_free(void *rule
)
1473 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1476 static struct route_map_rule_cmd route_match_source_instance_cmd
= {
1477 "source-instance", route_match_source_instance
,
1478 route_match_source_instance_compile
, route_match_source_instance_free
};
1480 /* `set src A.B.C.D' */
1483 static route_map_result_t
route_set_src(void *rule
, const struct prefix
*prefix
,
1484 route_map_object_t type
, void *object
)
1486 struct nh_rmap_obj
*nh_data
;
1488 if (type
== RMAP_ZEBRA
) {
1489 nh_data
= (struct nh_rmap_obj
*)object
;
1490 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1495 /* set src compilation. */
1496 static void *route_set_src_compile(const char *arg
)
1498 union g_addr src
, *psrc
;
1500 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1501 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1502 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1509 /* Free route map's compiled `set src' value. */
1510 static void route_set_src_free(void *rule
)
1512 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1515 /* Set src rule structure. */
1516 static struct route_map_rule_cmd route_set_src_cmd
= {
1517 "src", route_set_src
, route_set_src_compile
, route_set_src_free
,
1520 /* The function checks if the changed routemap specified by parameter rmap
1521 * matches the configured protocol routemaps in proto_rm table. If there is
1522 * a match then rib_update_table() to process the routes.
1524 static void zebra_rib_table_rm_update(const char *rmap
)
1527 struct route_table
*table
;
1528 struct vrf
*vrf
= NULL
;
1529 struct zebra_vrf
*zvrf
= NULL
;
1533 struct route_map
*old
= NULL
;
1535 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1539 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1540 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1541 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1542 if (IS_ZEBRA_DEBUG_EVENT
)
1544 "%s : AFI_IP rmap %s, route type %s",
1546 zebra_route_string(i
));
1548 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1550 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1551 route_map_lookup_by_name(rmap_name
);
1552 /* old is NULL. i.e Route map creation event.
1553 * So update applied_counter.
1554 * If Old is not NULL, i.e It may be routemap
1555 * updation or deletion.
1556 * So no need to update the counter.
1559 route_map_counter_increment(
1560 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1561 /* There is single rib table for all protocols
1564 table
= zvrf
->table
[AFI_IP
]
1571 RIB_UPDATE_RMAP_CHANGE
);
1575 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1576 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1577 if (IS_ZEBRA_DEBUG_EVENT
)
1579 "%s : AFI_IP6 rmap %s, route type %s",
1581 zebra_route_string(i
));
1583 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1585 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1586 route_map_lookup_by_name(rmap_name
);
1588 route_map_counter_increment(
1589 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1590 /* There is single rib table for all protocols
1592 if (afi_ipv6
== 0) {
1593 table
= zvrf
->table
[AFI_IP6
]
1600 RIB_UPDATE_RMAP_CHANGE
);
1608 /* The function checks if the changed routemap specified by parameter rmap
1609 * matches the configured protocol routemaps in nht_rm table. If there is
1610 * a match then zebra_evaluate_rnh() to process the nexthops.
1612 static void zebra_nht_rm_update(const char *rmap
)
1615 struct route_table
*table
;
1616 struct vrf
*vrf
= NULL
;
1617 struct zebra_vrf
*zvrf
= NULL
;
1621 struct route_map
*old
= NULL
;
1623 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1627 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1628 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1629 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1630 if (IS_ZEBRA_DEBUG_EVENT
)
1632 "%s : AFI_IP rmap %s, route type %s",
1634 zebra_route_string(i
));
1636 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1638 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1639 route_map_lookup_by_name(rmap_name
);
1641 route_map_counter_increment(
1642 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1643 /* There is single rib table for all protocols
1646 table
= zvrf
->table
[AFI_IP
]
1654 RNH_NEXTHOP_TYPE
, NULL
);
1659 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1660 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1661 if (IS_ZEBRA_DEBUG_EVENT
)
1663 "%s : AFI_IP6 rmap %s, route type %s",
1665 zebra_route_string(i
));
1667 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1669 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1670 route_map_lookup_by_name(rmap_name
);
1672 route_map_counter_increment(
1673 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1674 /* There is single rib table for all protocols
1676 if (afi_ipv6
== 0) {
1677 table
= zvrf
->table
[AFI_IP6
]
1685 RNH_NEXTHOP_TYPE
, NULL
);
1693 static void zebra_route_map_process_update_cb(char *rmap_name
)
1695 if (IS_ZEBRA_DEBUG_EVENT
)
1696 zlog_debug("Event handler for route-map: %s",
1698 zebra_import_table_rm_update(rmap_name
);
1699 zebra_rib_table_rm_update(rmap_name
);
1700 zebra_nht_rm_update(rmap_name
);
1703 static int zebra_route_map_update_timer(struct thread
*thread
)
1705 zebra_t_rmap_update
= NULL
;
1707 if (IS_ZEBRA_DEBUG_EVENT
)
1708 zlog_debug("Event driven route-map update triggered");
1710 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1712 "%u: Routemap update-timer fired, scheduling RIB processing",
1715 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1718 * This code needs to be updated to be:
1719 * 1) VRF Aware <sigh>
1720 * 2) Route-map aware
1725 static void zebra_route_map_set_delay_timer(uint32_t value
)
1727 zebra_rmap_update_timer
= value
;
1728 if (!value
&& zebra_t_rmap_update
) {
1729 /* Event driven route map updates is being disabled */
1730 /* But there's a pending timer. Fire it off now */
1731 thread_cancel(zebra_t_rmap_update
);
1732 zebra_route_map_update_timer(zebra_t_rmap_update
);
1736 void zebra_route_map_write_delay_timer(struct vty
*vty
)
1738 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1739 vty_out(vty
, "zebra route-map delay-timer %d\n",
1740 zebra_rmap_update_timer
);
1745 zebra_route_map_check(int family
, int rib_type
, uint8_t instance
,
1746 const struct prefix
*p
, struct nexthop
*nexthop
,
1747 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1749 struct route_map
*rmap
= NULL
;
1750 route_map_result_t ret
= RMAP_MATCH
;
1751 struct nh_rmap_obj nh_obj
;
1753 nh_obj
.nexthop
= nexthop
;
1754 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1755 nh_obj
.source_protocol
= rib_type
;
1756 nh_obj
.instance
= instance
;
1760 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1761 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1762 if (!rmap
&& PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
))
1763 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1765 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1771 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1773 return zebra_import_table_routemap
[afi
][table
];
1776 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1779 zebra_import_table_routemap
[afi
][table
] =
1780 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1783 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1785 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1789 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1790 const struct prefix
*p
,
1791 struct nexthop
*nexthop
,
1792 vrf_id_t vrf_id
, route_tag_t tag
,
1793 const char *rmap_name
)
1795 struct route_map
*rmap
= NULL
;
1796 route_map_result_t ret
= RMAP_DENYMATCH
;
1797 struct nh_rmap_obj nh_obj
;
1799 nh_obj
.nexthop
= nexthop
;
1800 nh_obj
.vrf_id
= vrf_id
;
1801 nh_obj
.source_protocol
= re_type
;
1802 nh_obj
.instance
= instance
;
1806 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1807 rmap
= route_map_lookup_by_name(rmap_name
);
1809 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1815 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1816 const struct prefix
*p
,
1817 struct zebra_vrf
*zvrf
,
1818 struct route_entry
*re
,
1819 struct nexthop
*nexthop
)
1821 struct route_map
*rmap
= NULL
;
1822 route_map_result_t ret
= RMAP_MATCH
;
1823 struct nh_rmap_obj nh_obj
;
1825 nh_obj
.nexthop
= nexthop
;
1826 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1827 nh_obj
.source_protocol
= re
->type
;
1828 nh_obj
.instance
= re
->instance
;
1829 nh_obj
.metric
= re
->metric
;
1830 nh_obj
.tag
= re
->tag
;
1832 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1833 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1834 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1835 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1837 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1842 static void zebra_route_map_mark_update(const char *rmap_name
)
1844 /* rmap_update_timer of 0 means don't do route updates */
1845 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1846 zebra_t_rmap_update
= NULL
;
1847 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1848 NULL
, zebra_rmap_update_timer
,
1849 &zebra_t_rmap_update
);
1853 static void zebra_route_map_add(const char *rmap_name
)
1855 if (route_map_mark_updated(rmap_name
) == 0)
1856 zebra_route_map_mark_update(rmap_name
);
1858 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1861 static void zebra_route_map_delete(const char *rmap_name
)
1863 if (route_map_mark_updated(rmap_name
) == 0)
1864 zebra_route_map_mark_update(rmap_name
);
1866 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1869 static void zebra_route_map_event(route_map_event_t event
,
1870 const char *rmap_name
)
1872 if (route_map_mark_updated(rmap_name
) == 0)
1873 zebra_route_map_mark_update(rmap_name
);
1875 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1878 /* ip protocol configuration write function */
1879 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1880 struct zebra_vrf
*zvrf
)
1885 memset(space
, 0, sizeof(space
));
1887 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1888 sprintf(space
, "%s", " ");
1890 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1891 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1892 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1893 zebra_route_string(i
),
1894 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1896 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1897 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1898 zebra_route_string(i
),
1899 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1901 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1902 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1903 zebra_route_string(i
),
1904 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1906 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1907 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1908 zebra_route_string(i
),
1909 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1912 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1913 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1914 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1916 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1917 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1918 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1920 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1921 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1922 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1924 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1925 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1926 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1928 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1929 vty_out(vty
, "zebra route-map delay-timer %d\n",
1930 zebra_rmap_update_timer
);
1933 void zebra_route_map_init(void)
1935 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1936 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1937 install_element(VRF_NODE
, &ip_protocol_cmd
);
1938 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1939 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1940 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1941 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1942 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1943 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1944 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1945 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1946 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1947 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1948 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1949 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1950 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1951 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1952 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1953 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1954 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1955 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1956 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1960 route_map_add_hook(zebra_route_map_add
);
1961 route_map_delete_hook(zebra_route_map_delete
);
1962 route_map_event_hook(zebra_route_map_event
);
1964 route_map_match_interface_hook(generic_match_add
);
1965 route_map_no_match_interface_hook(generic_match_delete
);
1967 route_map_match_ip_address_hook(generic_match_add
);
1968 route_map_no_match_ip_address_hook(generic_match_delete
);
1970 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1971 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1973 route_map_match_ip_next_hop_hook(generic_match_add
);
1974 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1976 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1977 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1979 route_map_match_ip_next_hop_type_hook(generic_match_add
);
1980 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
1982 route_map_match_tag_hook(generic_match_add
);
1983 route_map_no_match_tag_hook(generic_match_delete
);
1985 route_map_match_ipv6_address_hook(generic_match_add
);
1986 route_map_no_match_ipv6_address_hook(generic_match_delete
);
1988 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
1989 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
1991 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
1992 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
1994 route_map_install_match(&route_match_tag_cmd
);
1995 route_map_install_match(&route_match_interface_cmd
);
1996 route_map_install_match(&route_match_ip_next_hop_cmd
);
1997 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
1998 route_map_install_match(&route_match_ip_address_cmd
);
1999 route_map_install_match(&route_match_ipv6_address_cmd
);
2000 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
2001 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
2002 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
2003 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
2004 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
2005 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
2006 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
2007 route_map_install_match(&route_match_source_protocol_cmd
);
2008 route_map_install_match(&route_match_source_instance_cmd
);
2011 route_map_install_set(&route_set_src_cmd
);
2013 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
2014 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
2015 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
2016 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
2017 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
2018 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
2019 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
2020 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
2021 install_element(RMAP_NODE
, &match_source_instance_cmd
);
2022 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
2025 install_element(RMAP_NODE
, &set_src_cmd
);
2026 install_element(RMAP_NODE
, &no_set_src_cmd
);