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/zserv.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
);
131 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
133 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
139 * Match function return 1 if match is success else return 0
141 static route_map_result_t
route_match_tag(void *rule
,
142 const struct prefix
*prefix
,
143 route_map_object_t type
, void *object
)
146 struct nh_rmap_obj
*nh_data
;
148 if (type
== RMAP_ZEBRA
) {
152 if (nh_data
->tag
== *tag
)
158 /* Route map commands for tag matching */
159 static struct route_map_rule_cmd route_match_tag_cmd
= {
160 "tag", route_match_tag
, route_map_rule_tag_compile
,
161 route_map_rule_tag_free
,
165 /* `match interface IFNAME' */
166 /* Match function return 1 if match is success else return zero. */
167 static route_map_result_t
route_match_interface(void *rule
,
168 const struct prefix
*prefix
,
169 route_map_object_t type
,
172 struct nh_rmap_obj
*nh_data
;
176 if (type
== RMAP_ZEBRA
) {
177 if (strcasecmp(ifname
, "any") == 0)
180 if (!nh_data
|| !nh_data
->nexthop
)
182 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
185 if (nh_data
->nexthop
->ifindex
== ifindex
)
191 /* Route map `match interface' match statement. `arg' is IFNAME value */
192 static void *route_match_interface_compile(const char *arg
)
194 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
197 /* Free route map's compiled `match interface' value. */
198 static void route_match_interface_free(void *rule
)
200 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
203 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
208 vty_out(vty
, "Protocol : route-map\n");
209 vty_out(vty
, "------------------------\n");
211 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
212 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
213 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
214 PROTO_RM_NAME(zvrf
, af_type
, i
));
216 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
219 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
220 vty_out(vty
, "%-10s : %-10s\n", "any",
221 PROTO_RM_NAME(zvrf
, af_type
, i
));
223 vty_out(vty
, "%-10s : none\n", "any");
226 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
231 vty_out(vty
, "Protocol : route-map\n");
232 vty_out(vty
, "------------------------\n");
234 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
235 if (NHT_RM_NAME(zvrf
, af_type
, i
))
236 vty_out(vty
, "%-10s : %-10s\n", zebra_route_string(i
),
237 NHT_RM_NAME(zvrf
, af_type
, i
));
239 vty_out(vty
, "%-10s : none\n", zebra_route_string(i
));
242 if (NHT_RM_NAME(zvrf
, af_type
, i
))
243 vty_out(vty
, "%-10s : %-10s\n", "any",
244 NHT_RM_NAME(zvrf
, af_type
, i
));
246 vty_out(vty
, "%-10s : none\n", "any");
249 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
250 const char *vrf_name
)
252 struct zebra_vrf
*zvrf
;
257 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
258 zvrf
= (struct zebra_vrf
*)vrf
->info
;
261 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
262 show_vrf_proto_rm(vty
, zvrf
, af_type
);
265 vrf_id_t vrf_id
= VRF_DEFAULT
;
268 VRF_GET_ID(vrf_id
, vrf_name
, false);
270 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
274 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
275 show_vrf_proto_rm(vty
, zvrf
, af_type
);
281 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
282 const char *vrf_name
)
284 struct zebra_vrf
*zvrf
;
289 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
290 zvrf
= (struct zebra_vrf
*)vrf
->info
;
294 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
295 show_vrf_nht_rm(vty
, zvrf
, af_type
);
298 vrf_id_t vrf_id
= VRF_DEFAULT
;
301 VRF_GET_ID(vrf_id
, vrf_name
, false);
303 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
307 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
308 show_vrf_nht_rm(vty
, zvrf
, af_type
);
314 /* Route map commands for interface matching */
315 struct route_map_rule_cmd route_match_interface_cmd
= {
316 "interface", route_match_interface
, route_match_interface_compile
,
317 route_match_interface_free
};
319 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
320 int rtype
, afi_t afi
, safi_t safi
)
322 struct route_table
*table
;
324 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
325 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
328 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
331 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
332 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
333 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
335 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
337 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
339 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
340 zvrf
->vrf
->vrf_id
, rtype
);
341 /* Process routes of interested address-families. */
342 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
344 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
350 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
351 int rtype
, afi_t afi
, safi_t safi
)
353 struct route_table
*table
;
355 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
358 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
359 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
360 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
362 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
363 zvrf
->vrf
->vrf_id
, rtype
);
364 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
366 /* Process routes of interested address-families. */
367 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
369 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
);
371 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
376 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
380 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
381 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
384 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
387 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
388 NHT_RM_MAP(zvrf
, afi
, rtype
) =
389 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
391 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
392 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
, NULL
);
397 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
401 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
404 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
405 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
406 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
408 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
409 zvrf
->vrf
->vrf_id
, rtype
);
410 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
412 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, RNH_NEXTHOP_TYPE
,
415 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
420 DEFUN (match_ip_address_prefix_len
,
421 match_ip_address_prefix_len_cmd
,
422 "match ip address prefix-len (0-32)",
425 "Match prefix length of ip address\n"
426 "Match prefix length of ip address\n"
429 return zebra_route_match_add(vty
, "ip address prefix-len", argv
[4]->arg
,
430 RMAP_EVENT_MATCH_ADDED
);
433 DEFUN (no_match_ip_address_prefix_len
,
434 no_match_ip_address_prefix_len_cmd
,
435 "no match ip address prefix-len [(0-32)]",
439 "Match prefix length of ip address\n"
440 "Match prefix length of ip address\n"
443 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
444 return zebra_route_match_delete(vty
, "ip address prefix-len", plen
,
445 RMAP_EVENT_MATCH_DELETED
);
448 DEFUN (match_ipv6_address_prefix_len
,
449 match_ipv6_address_prefix_len_cmd
,
450 "match ipv6 address prefix-len (0-128)",
453 "Match prefix length of ipv6 address\n"
454 "Match prefix length of ipv6 address\n"
457 return zebra_route_match_add(vty
, "ipv6 address prefix-len",
458 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
461 DEFUN (no_match_ipv6_address_prefix_len
,
462 no_match_ipv6_address_prefix_len_cmd
,
463 "no match ipv6 address prefix-len [(0-128)]",
467 "Match prefix length of ip address\n"
468 "Match prefix length of ip address\n"
471 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
472 return zebra_route_match_delete(vty
, "ipv6 address prefix-len", plen
,
473 RMAP_EVENT_MATCH_DELETED
);
476 DEFUN (match_ip_nexthop_prefix_len
,
477 match_ip_nexthop_prefix_len_cmd
,
478 "match ip next-hop prefix-len (0-32)",
481 "Match prefixlen of nexthop ip address\n"
482 "Match prefixlen of given nexthop\n"
485 return zebra_route_match_add(vty
, "ip next-hop prefix-len",
486 argv
[4]->arg
, RMAP_EVENT_MATCH_ADDED
);
489 DEFUN (no_match_ip_nexthop_prefix_len
,
490 no_match_ip_nexthop_prefix_len_cmd
,
491 "no match ip next-hop prefix-len [(0-32)]",
495 "Match prefixlen of nexthop ip address\n"
496 "Match prefix length of nexthop\n"
499 char *plen
= (argc
== 6) ? argv
[5]->arg
: NULL
;
500 return zebra_route_match_delete(vty
, "ip next-hop prefix-len", plen
,
501 RMAP_EVENT_MATCH_DELETED
);
504 DEFUN (match_source_protocol
,
505 match_source_protocol_cmd
,
506 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
508 "Match protocol via which the route was learnt\n"
519 "Routes from directly connected peer\n"
520 "Routes from system configuration\n"
521 "Routes from kernel\n"
522 "Statically configured routes\n"
525 char *proto
= argv
[2]->text
;
528 i
= proto_name2num(proto
);
530 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
531 return CMD_WARNING_CONFIG_FAILED
;
533 return zebra_route_match_add(vty
, "source-protocol", proto
,
534 RMAP_EVENT_MATCH_ADDED
);
537 DEFUN (no_match_source_protocol
,
538 no_match_source_protocol_cmd
,
539 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
542 "No match protocol via which the route was learnt\n"
553 "Routes from directly connected peer\n"
554 "Routes from system configuration\n"
555 "Routes from kernel\n"
556 "Statically configured routes\n"
559 char *proto
= (argc
== 4) ? argv
[3]->text
: NULL
;
560 return zebra_route_match_delete(vty
, "source-protocol", proto
,
561 RMAP_EVENT_MATCH_DELETED
);
564 DEFUN (match_source_instance
,
565 match_source_instance_cmd
,
566 "match source-instance (0-255)",
568 "Match the protocol's instance number\n"
569 "The instance number\n")
571 char *instance
= argv
[2]->arg
;
573 return zebra_route_match_add(vty
, "source-instance", instance
,
574 RMAP_EVENT_MATCH_ADDED
);
577 DEFUN (no_match_source_instance
,
578 no_match_source_instance_cmd
,
579 "no match source-instance [(0-255)]",
581 "Match the protocol's instance number\n"
582 "The instance number\n")
584 char *instance
= (argc
== 4) ? argv
[3]->arg
: NULL
;
586 return zebra_route_match_delete(vty
, "source-instance", instance
,
587 RMAP_EVENT_MATCH_ADDED
);
594 "set src <A.B.C.D|X:X::X:X>",
596 "src address for route\n"
598 "IPv6 src address\n")
602 struct interface
*pif
= NULL
;
607 if (inet_pton(AF_INET
, argv
[idx_ip
]->arg
, &src
.ipv4
) != 1) {
608 if (inet_pton(AF_INET6
, argv
[idx_ip
]->arg
, &src
.ipv6
) != 1) {
609 vty_out(vty
, "%% not a valid IPv4/v6 address\n");
610 return CMD_WARNING_CONFIG_FAILED
;
613 p
.family
= family
= AF_INET6
;
614 p
.u
.prefix6
= src
.ipv6
;
615 p
.prefixlen
= IPV6_MAX_BITLEN
;
617 p
.family
= family
= AF_INET
;
618 p
.u
.prefix4
= src
.ipv4
;
619 p
.prefixlen
= IPV4_MAX_BITLEN
;
622 if (!zebra_check_addr(&p
)) {
623 vty_out(vty
, "%% not a valid source IPv4/v6 address\n");
624 return CMD_WARNING_CONFIG_FAILED
;
627 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
628 if (family
== AF_INET
)
629 pif
= if_lookup_exact_address((void *)&src
.ipv4
,
630 AF_INET
, vrf
->vrf_id
);
631 else if (family
== AF_INET6
)
632 pif
= if_lookup_exact_address((void *)&src
.ipv6
,
633 AF_INET6
, vrf
->vrf_id
);
640 vty_out(vty
, "%% not a local address\n");
641 return CMD_WARNING_CONFIG_FAILED
;
644 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
645 return generic_set_add(vty
, index
, "src", argv
[idx_ip
]->arg
);
650 "no set src [<A.B.C.D|X:X::X:X>]",
653 "Source address for route\n"
657 char *ip
= (argc
== 4) ? argv
[3]->arg
: NULL
;
658 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
659 return generic_set_delete(vty
, index
, "src", ip
);
662 DEFUN (zebra_route_map_timer
,
663 zebra_route_map_timer_cmd
,
664 "zebra route-map delay-timer (0-600)",
666 "Set route-map parameters\n"
667 "Time to wait before route-map updates are processed\n"
668 "0 means event-driven updates are disabled\n")
671 uint32_t rmap_delay_timer
;
673 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
674 zebra_route_map_set_delay_timer(rmap_delay_timer
);
676 return (CMD_SUCCESS
);
679 DEFUN (no_zebra_route_map_timer
,
680 no_zebra_route_map_timer_cmd
,
681 "no zebra route-map delay-timer [(0-600)]",
684 "Set route-map parameters\n"
685 "Reset delay-timer to default value, 30 secs\n"
686 "0 means event-driven updates are disabled\n")
688 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
690 return (CMD_SUCCESS
);
695 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
696 " $proto route-map ROUTE-MAP$rmap",
698 "Filter routing info exchanged between zebra and protocol\n"
699 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
700 "Specify route-map\n"
705 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
710 if (strcasecmp(proto
, "any") == 0)
711 rtype
= ZEBRA_ROUTE_MAX
;
713 rtype
= proto_name2num(proto
);
715 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
716 return CMD_WARNING_CONFIG_FAILED
;
719 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
724 DEFPY (no_ip_protocol
,
726 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
727 " $proto [route-map ROUTE-MAP$rmap]",
730 "Stop filtering routing info between zebra and protocol\n"
731 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
732 "Specify route-map\n"
737 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
742 if (strcasecmp(proto
, "any") == 0)
743 rtype
= ZEBRA_ROUTE_MAX
;
745 rtype
= proto_name2num(proto
);
747 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
748 return CMD_WARNING_CONFIG_FAILED
;
751 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
756 DEFPY (show_ip_protocol
,
757 show_ip_protocol_cmd
,
758 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
761 "IP protocol filtering status\n"
762 VRF_FULL_CMD_HELP_STR
)
764 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
769 DEFPY (ipv6_protocol
,
771 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
772 " $proto route-map ROUTE-MAP$rmap",
774 "Filter IPv6 routing info exchanged between zebra and protocol\n"
775 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
776 "Specify route-map\n"
781 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
786 if (strcasecmp(proto
, "any") == 0)
787 rtype
= ZEBRA_ROUTE_MAX
;
789 rtype
= proto_name2num(proto
);
791 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
792 return CMD_WARNING_CONFIG_FAILED
;
795 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
800 DEFPY (no_ipv6_protocol
,
801 no_ipv6_protocol_cmd
,
802 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
803 " $proto [route-map ROUTE-MAP$rmap]",
806 "Stop filtering IPv6 routing info between zebra and protocol\n"
807 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
808 "Specify route-map\n"
813 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
818 if (strcasecmp(proto
, "any") == 0)
819 rtype
= ZEBRA_ROUTE_MAX
;
821 rtype
= proto_name2num(proto
);
823 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
824 return CMD_WARNING_CONFIG_FAILED
;
827 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
832 DEFPY (show_ipv6_protocol
,
833 show_ipv6_protocol_cmd
,
834 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
837 "IPv6 protocol filtering status\n"
838 VRF_FULL_CMD_HELP_STR
)
840 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
845 DEFPY (ip_protocol_nht_rmap
,
846 ip_protocol_nht_rmap_cmd
,
847 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
848 " $proto route-map ROUTE-MAP$rmap",
850 "Filter Next Hop tracking route resolution\n"
851 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
852 "Specify route map\n"
858 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
863 if (strcasecmp(proto
, "any") == 0)
864 rtype
= ZEBRA_ROUTE_MAX
;
866 rtype
= proto_name2num(proto
);
868 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
869 return CMD_WARNING_CONFIG_FAILED
;
872 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
877 DEFPY (no_ip_protocol_nht_rmap
,
878 no_ip_protocol_nht_rmap_cmd
,
879 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
880 " $proto route-map [ROUTE-MAP$rmap]",
883 "Filter Next Hop tracking route resolution\n"
884 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
885 "Specify route map\n"
890 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
895 if (strcasecmp(proto
, "any") == 0)
896 rtype
= ZEBRA_ROUTE_MAX
;
898 rtype
= proto_name2num(proto
);
900 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
901 return CMD_WARNING_CONFIG_FAILED
;
904 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
909 DEFPY (show_ip_protocol_nht
,
910 show_ip_protocol_nht_cmd
,
911 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
914 "IP nexthop tracking table\n"
915 "IP Next Hop tracking filtering status\n"
916 VRF_FULL_CMD_HELP_STR
)
918 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
923 DEFPY (ipv6_protocol_nht_rmap
,
924 ipv6_protocol_nht_rmap_cmd
,
925 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
926 " $proto route-map ROUTE-MAP$rmap",
928 "Filter Next Hop tracking route resolution\n"
929 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
930 "Specify route map\n"
935 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
940 if (strcasecmp(proto
, "any") == 0)
941 rtype
= ZEBRA_ROUTE_MAX
;
943 rtype
= proto_name2num(proto
);
945 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
946 return CMD_WARNING_CONFIG_FAILED
;
949 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
954 DEFPY (no_ipv6_protocol_nht_rmap
,
955 no_ipv6_protocol_nht_rmap_cmd
,
956 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
957 " $proto [route-map ROUTE-MAP$rmap]",
960 "Filter Next Hop tracking route resolution\n"
961 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
962 "Specify route map\n"
967 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
972 if (strcasecmp(proto
, "any") == 0)
973 rtype
= ZEBRA_ROUTE_MAX
;
975 rtype
= proto_name2num(proto
);
977 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
978 return CMD_WARNING_CONFIG_FAILED
;
981 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
986 DEFPY (show_ipv6_protocol_nht
,
987 show_ipv6_protocol_nht_cmd
,
988 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
991 "Next Hop filtering status\n"
993 VRF_FULL_CMD_HELP_STR
)
995 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
1000 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1002 /* `match ip next-hop IP_ACCESS_LIST' */
1004 /* Match function return 1 if match is success else return zero. */
1005 static route_map_result_t
route_match_ip_next_hop(void *rule
,
1006 const struct prefix
*prefix
,
1007 route_map_object_t type
,
1010 struct access_list
*alist
;
1011 struct nh_rmap_obj
*nh_data
;
1012 struct prefix_ipv4 p
;
1014 if (type
== RMAP_ZEBRA
) {
1017 return RMAP_DENYMATCH
;
1019 switch (nh_data
->nexthop
->type
) {
1020 case NEXTHOP_TYPE_IFINDEX
:
1021 /* Interface routes can't match ip next-hop */
1022 return RMAP_NOMATCH
;
1023 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1024 case NEXTHOP_TYPE_IPV4
:
1026 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1027 p
.prefixlen
= IPV4_MAX_BITLEN
;
1030 return RMAP_NOMATCH
;
1032 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1034 return RMAP_NOMATCH
;
1036 return (access_list_apply(alist
, &p
) == FILTER_DENY
1040 return RMAP_NOMATCH
;
1043 /* Route map `ip next-hop' match statement. `arg' should be
1044 access-list name. */
1045 static void *route_match_ip_next_hop_compile(const char *arg
)
1047 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1050 /* Free route map's compiled `. */
1051 static void route_match_ip_next_hop_free(void *rule
)
1053 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1056 /* Route map commands for ip next-hop matching. */
1057 static struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1058 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
1059 route_match_ip_next_hop_free
};
1061 /* `match ip next-hop prefix-list PREFIX_LIST' */
1063 static route_map_result_t
1064 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1065 route_map_object_t type
, void *object
)
1067 struct prefix_list
*plist
;
1068 struct nh_rmap_obj
*nh_data
;
1069 struct prefix_ipv4 p
;
1071 if (type
== RMAP_ZEBRA
) {
1072 nh_data
= (struct nh_rmap_obj
*)object
;
1074 return RMAP_DENYMATCH
;
1076 switch (nh_data
->nexthop
->type
) {
1077 case NEXTHOP_TYPE_IFINDEX
:
1078 /* Interface routes can't match ip next-hop */
1079 return RMAP_NOMATCH
;
1080 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1081 case NEXTHOP_TYPE_IPV4
:
1083 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1084 p
.prefixlen
= IPV4_MAX_BITLEN
;
1087 return RMAP_NOMATCH
;
1089 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1091 return RMAP_NOMATCH
;
1093 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
1097 return RMAP_NOMATCH
;
1100 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1102 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1105 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1107 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1110 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
1111 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
1112 route_match_ip_next_hop_prefix_list_compile
,
1113 route_match_ip_next_hop_prefix_list_free
};
1115 /* `match ip address IP_ACCESS_LIST' */
1117 /* Match function should return 1 if match is success else return
1119 static route_map_result_t
route_match_address(afi_t afi
, void *rule
,
1120 const struct prefix
*prefix
,
1121 route_map_object_t type
,
1124 struct access_list
*alist
;
1126 if (type
== RMAP_ZEBRA
) {
1127 alist
= access_list_lookup(afi
, (char *)rule
);
1129 return RMAP_NOMATCH
;
1131 return (access_list_apply(alist
, prefix
) == FILTER_DENY
1135 return RMAP_NOMATCH
;
1138 static route_map_result_t
route_match_ip_address(void *rule
,
1139 const struct prefix
*prefix
,
1140 route_map_object_t type
,
1143 return route_match_address(AFI_IP
, rule
, prefix
, type
, object
);
1146 static route_map_result_t
route_match_ipv6_address(void *rule
,
1147 const struct prefix
*prefix
,
1148 route_map_object_t type
,
1152 return route_match_address(AFI_IP6
, rule
, prefix
, type
, object
);
1155 /* Route map `ip address' match statement. `arg' should be
1156 access-list name. */
1157 static void *route_match_address_compile(const char *arg
)
1159 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1162 /* Free route map's compiled `ip address' value. */
1163 static void route_match_address_free(void *rule
)
1165 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1168 /* Route map commands for ip address matching. */
1169 static struct route_map_rule_cmd route_match_ip_address_cmd
= {
1170 "ip address", route_match_ip_address
, route_match_address_compile
,
1171 route_match_address_free
};
1173 /* Route map commands for ipv6 address matching. */
1174 static struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1175 "ipv6 address", route_match_ipv6_address
, route_match_address_compile
,
1176 route_match_address_free
};
1178 /* `match ip address prefix-list PREFIX_LIST' */
1180 static route_map_result_t
1181 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1182 route_map_object_t type
, void *object
, afi_t afi
)
1184 struct prefix_list
*plist
;
1186 if (type
== RMAP_ZEBRA
) {
1187 plist
= prefix_list_lookup(afi
, (char *)rule
);
1189 return RMAP_NOMATCH
;
1191 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
1195 return RMAP_NOMATCH
;
1198 static route_map_result_t
1199 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1200 route_map_object_t type
, void *object
)
1202 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1206 static void *route_match_address_prefix_list_compile(const char *arg
)
1208 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1211 static void route_match_address_prefix_list_free(void *rule
)
1213 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1216 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
1217 "ip address prefix-list", route_match_ip_address_prefix_list
,
1218 route_match_address_prefix_list_compile
,
1219 route_match_address_prefix_list_free
};
1221 static route_map_result_t
1222 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1223 route_map_object_t type
, void *object
)
1225 return (route_match_address_prefix_list(rule
, prefix
, type
, object
,
1229 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
1230 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
1231 route_match_address_prefix_list_compile
,
1232 route_match_address_prefix_list_free
};
1234 /* `match ip address prefix-len PREFIXLEN' */
1236 static route_map_result_t
1237 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1238 route_map_object_t type
, void *object
)
1240 uint32_t *prefixlen
= (uint32_t *)rule
;
1242 if (type
== RMAP_ZEBRA
) {
1243 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
1246 return RMAP_NOMATCH
;
1249 static void *route_match_address_prefix_len_compile(const char *arg
)
1251 uint32_t *prefix_len
;
1252 char *endptr
= NULL
;
1253 unsigned long tmpval
;
1255 /* prefix len value shoud be integer. */
1256 if (!all_digit(arg
))
1260 tmpval
= strtoul(arg
, &endptr
, 10);
1261 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1264 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1266 *prefix_len
= tmpval
;
1270 static void route_match_address_prefix_len_free(void *rule
)
1272 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1275 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd
= {
1276 "ip address prefix-len", route_match_address_prefix_len
,
1277 route_match_address_prefix_len_compile
,
1278 route_match_address_prefix_len_free
};
1280 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd
= {
1281 "ipv6 address prefix-len", route_match_address_prefix_len
,
1282 route_match_address_prefix_len_compile
,
1283 route_match_address_prefix_len_free
};
1285 /* `match ip nexthop prefix-len PREFIXLEN' */
1287 static route_map_result_t
1288 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1289 route_map_object_t type
, void *object
)
1291 uint32_t *prefixlen
= (uint32_t *)rule
;
1292 struct nh_rmap_obj
*nh_data
;
1293 struct prefix_ipv4 p
;
1295 if (type
== RMAP_ZEBRA
) {
1296 nh_data
= (struct nh_rmap_obj
*)object
;
1297 if (!nh_data
|| !nh_data
->nexthop
)
1298 return RMAP_DENYMATCH
;
1300 switch (nh_data
->nexthop
->type
) {
1301 case NEXTHOP_TYPE_IFINDEX
:
1302 /* Interface routes can't match ip next-hop */
1303 return RMAP_NOMATCH
;
1304 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1305 case NEXTHOP_TYPE_IPV4
:
1307 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1308 p
.prefixlen
= IPV4_MAX_BITLEN
;
1311 return RMAP_NOMATCH
;
1313 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
1316 return RMAP_NOMATCH
;
1319 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd
= {
1320 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len
,
1321 route_match_address_prefix_len_compile
, /* reuse */
1322 route_match_address_prefix_len_free
/* reuse */
1325 /* `match source-protocol PROTOCOL' */
1327 static route_map_result_t
route_match_source_protocol(void *rule
,
1328 const struct prefix
*p
,
1329 route_map_object_t type
,
1332 uint32_t *rib_type
= (uint32_t *)rule
;
1333 struct nh_rmap_obj
*nh_data
;
1335 if (type
== RMAP_ZEBRA
) {
1336 nh_data
= (struct nh_rmap_obj
*)object
;
1338 return RMAP_DENYMATCH
;
1340 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1343 return RMAP_NOMATCH
;
1346 static void *route_match_source_protocol_compile(const char *arg
)
1351 i
= proto_name2num(arg
);
1352 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1359 static void route_match_source_protocol_free(void *rule
)
1361 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1364 static struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1365 "source-protocol", route_match_source_protocol
,
1366 route_match_source_protocol_compile
, route_match_source_protocol_free
};
1368 /* `source-instance` */
1369 static route_map_result_t
route_match_source_instance(void *rule
,
1370 const struct prefix
*p
,
1371 route_map_object_t type
,
1374 uint8_t *instance
= (uint8_t *)rule
;
1375 struct nh_rmap_obj
*nh_data
;
1377 if (type
!= RMAP_ZEBRA
)
1378 return RMAP_NOMATCH
;
1380 nh_data
= (struct nh_rmap_obj
*)object
;
1382 return RMAP_DENYMATCH
;
1384 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1387 static void *route_match_source_instance_compile(const char *arg
)
1393 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1400 static void route_match_source_instance_free(void *rule
)
1402 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1405 static struct route_map_rule_cmd route_match_source_instance_cmd
= {
1406 "source-instance", route_match_source_instance
,
1407 route_match_source_instance_compile
, route_match_source_instance_free
};
1409 /* `set src A.B.C.D' */
1412 static route_map_result_t
route_set_src(void *rule
, const struct prefix
*prefix
,
1413 route_map_object_t type
, void *object
)
1415 struct nh_rmap_obj
*nh_data
;
1417 if (type
== RMAP_ZEBRA
) {
1418 nh_data
= (struct nh_rmap_obj
*)object
;
1419 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1424 /* set src compilation. */
1425 static void *route_set_src_compile(const char *arg
)
1427 union g_addr src
, *psrc
;
1429 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1430 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1431 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1438 /* Free route map's compiled `set src' value. */
1439 static void route_set_src_free(void *rule
)
1441 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1444 /* Set src rule structure. */
1445 static struct route_map_rule_cmd route_set_src_cmd
= {
1446 "src", route_set_src
, route_set_src_compile
, route_set_src_free
,
1449 /* The function checks if the changed routemap specified by parameter rmap
1450 * matches the configured protocol routemaps in proto_rm table. If there is
1451 * a match then rib_update_table() to process the routes.
1453 static void zebra_rib_table_rm_update(const char *rmap
)
1456 struct route_table
*table
;
1457 struct vrf
*vrf
= NULL
;
1458 struct zebra_vrf
*zvrf
= NULL
;
1463 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1467 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1468 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1469 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1470 if (IS_ZEBRA_DEBUG_EVENT
)
1472 "%s : AFI_IP rmap %s, route type %s",
1474 zebra_route_string(i
));
1476 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1477 route_map_lookup_by_name(rmap_name
);
1478 /* There is single rib table for all protocols
1481 table
= zvrf
->table
[AFI_IP
]
1488 RIB_UPDATE_RMAP_CHANGE
);
1492 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1493 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1494 if (IS_ZEBRA_DEBUG_EVENT
)
1496 "%s : AFI_IP6 rmap %s, route type %s",
1498 zebra_route_string(i
));
1500 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1501 route_map_lookup_by_name(rmap_name
);
1502 /* There is single rib table for all protocols
1504 if (afi_ipv6
== 0) {
1505 table
= zvrf
->table
[AFI_IP6
]
1512 RIB_UPDATE_RMAP_CHANGE
);
1520 /* The function checks if the changed routemap specified by parameter rmap
1521 * matches the configured protocol routemaps in nht_rm table. If there is
1522 * a match then zebra_evaluate_rnh() to process the nexthops.
1524 static void zebra_nht_rm_update(const char *rmap
)
1527 struct route_table
*table
;
1528 struct vrf
*vrf
= NULL
;
1529 struct zebra_vrf
*zvrf
= NULL
;
1534 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1538 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1539 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1540 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1541 if (IS_ZEBRA_DEBUG_EVENT
)
1543 "%s : AFI_IP rmap %s, route type %s",
1545 zebra_route_string(i
));
1547 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1548 route_map_lookup_by_name(rmap_name
);
1549 /* There is single rib table for all protocols
1552 table
= zvrf
->table
[AFI_IP
]
1560 RNH_NEXTHOP_TYPE
, NULL
);
1565 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1566 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1567 if (IS_ZEBRA_DEBUG_EVENT
)
1569 "%s : AFI_IP6 rmap %s, route type %s",
1571 zebra_route_string(i
));
1573 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1574 route_map_lookup_by_name(rmap_name
);
1575 /* There is single rib table for all protocols
1577 if (afi_ipv6
== 0) {
1578 table
= zvrf
->table
[AFI_IP6
]
1586 RNH_NEXTHOP_TYPE
, NULL
);
1594 static void zebra_route_map_process_update_cb(char *rmap_name
)
1596 if (IS_ZEBRA_DEBUG_EVENT
)
1597 zlog_debug("Event handler for route-map: %s",
1599 zebra_import_table_rm_update(rmap_name
);
1600 zebra_rib_table_rm_update(rmap_name
);
1601 zebra_nht_rm_update(rmap_name
);
1604 static int zebra_route_map_update_timer(struct thread
*thread
)
1606 zebra_t_rmap_update
= NULL
;
1608 if (IS_ZEBRA_DEBUG_EVENT
)
1609 zlog_debug("Event driven route-map update triggered");
1611 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1613 "%u: Routemap update-timer fired, scheduling RIB processing",
1616 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1619 * This code needs to be updated to be:
1620 * 1) VRF Aware <sigh>
1621 * 2) Route-map aware
1626 static void zebra_route_map_set_delay_timer(uint32_t value
)
1628 zebra_rmap_update_timer
= value
;
1629 if (!value
&& zebra_t_rmap_update
) {
1630 /* Event driven route map updates is being disabled */
1631 /* But there's a pending timer. Fire it off now */
1632 thread_cancel(zebra_t_rmap_update
);
1633 zebra_route_map_update_timer(zebra_t_rmap_update
);
1637 void zebra_route_map_write_delay_timer(struct vty
*vty
)
1639 if (vty
&& (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
))
1640 vty_out(vty
, "zebra route-map delay-timer %d\n",
1641 zebra_rmap_update_timer
);
1646 zebra_route_map_check(int family
, int rib_type
, uint8_t instance
,
1647 const struct prefix
*p
, struct nexthop
*nexthop
,
1648 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1650 struct route_map
*rmap
= NULL
;
1651 route_map_result_t ret
= RMAP_MATCH
;
1652 struct nh_rmap_obj nh_obj
;
1654 nh_obj
.nexthop
= nexthop
;
1655 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1656 nh_obj
.source_protocol
= rib_type
;
1657 nh_obj
.instance
= instance
;
1661 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
)
1662 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1663 if (!rmap
&& PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
))
1664 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1666 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1672 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1674 return zebra_import_table_routemap
[afi
][table
];
1677 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1680 zebra_import_table_routemap
[afi
][table
] =
1681 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1684 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1686 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1690 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1691 const struct prefix
*p
,
1692 struct nexthop
*nexthop
,
1693 vrf_id_t vrf_id
, route_tag_t tag
,
1694 const char *rmap_name
)
1696 struct route_map
*rmap
= NULL
;
1697 route_map_result_t ret
= RMAP_DENYMATCH
;
1698 struct nh_rmap_obj nh_obj
;
1700 nh_obj
.nexthop
= nexthop
;
1701 nh_obj
.vrf_id
= vrf_id
;
1702 nh_obj
.source_protocol
= re_type
;
1703 nh_obj
.instance
= instance
;
1707 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1708 rmap
= route_map_lookup_by_name(rmap_name
);
1710 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1716 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1717 const struct prefix
*p
,
1718 struct zebra_vrf
*zvrf
,
1719 struct route_entry
*re
,
1720 struct nexthop
*nexthop
)
1722 struct route_map
*rmap
= NULL
;
1723 route_map_result_t ret
= RMAP_MATCH
;
1724 struct nh_rmap_obj nh_obj
;
1726 nh_obj
.nexthop
= nexthop
;
1727 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1728 nh_obj
.source_protocol
= re
->type
;
1729 nh_obj
.instance
= re
->instance
;
1730 nh_obj
.metric
= re
->metric
;
1731 nh_obj
.tag
= re
->tag
;
1733 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1734 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1735 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1736 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1738 ret
= route_map_apply(rmap
, p
, RMAP_ZEBRA
, &nh_obj
);
1743 static void zebra_route_map_mark_update(const char *rmap_name
)
1745 /* rmap_update_timer of 0 means don't do route updates */
1746 if (zebra_rmap_update_timer
&& !zebra_t_rmap_update
) {
1747 zebra_t_rmap_update
= NULL
;
1748 thread_add_timer(zebrad
.master
, zebra_route_map_update_timer
,
1749 NULL
, zebra_rmap_update_timer
,
1750 &zebra_t_rmap_update
);
1754 static void zebra_route_map_add(const char *rmap_name
)
1756 if (route_map_mark_updated(rmap_name
) == 0)
1757 zebra_route_map_mark_update(rmap_name
);
1759 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1762 static void zebra_route_map_delete(const char *rmap_name
)
1764 if (route_map_mark_updated(rmap_name
) == 0)
1765 zebra_route_map_mark_update(rmap_name
);
1767 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1770 static void zebra_route_map_event(route_map_event_t event
,
1771 const char *rmap_name
)
1773 if (route_map_mark_updated(rmap_name
) == 0)
1774 zebra_route_map_mark_update(rmap_name
);
1776 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1779 /* ip protocol configuration write function */
1780 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1781 struct zebra_vrf
*zvrf
)
1786 memset(space
, 0, sizeof(space
));
1788 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1789 sprintf(space
, "%s", " ");
1791 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1792 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1793 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1794 zebra_route_string(i
),
1795 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1797 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1798 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1799 zebra_route_string(i
),
1800 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1802 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1803 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1804 zebra_route_string(i
),
1805 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1807 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1808 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1809 zebra_route_string(i
),
1810 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1813 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1814 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1815 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1817 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1818 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1819 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1821 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1822 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1823 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1825 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1826 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1827 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1829 if (zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1830 vty_out(vty
, "zebra route-map delay-timer %d\n",
1831 zebra_rmap_update_timer
);
1834 void zebra_route_map_init(void)
1836 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1837 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1838 install_element(VRF_NODE
, &ip_protocol_cmd
);
1839 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1840 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1841 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1842 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1843 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1844 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1845 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1846 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1847 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1848 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1849 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1850 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1851 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1852 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1853 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1854 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1855 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1856 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1857 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1861 route_map_add_hook(zebra_route_map_add
);
1862 route_map_delete_hook(zebra_route_map_delete
);
1863 route_map_event_hook(zebra_route_map_event
);
1865 route_map_match_interface_hook(generic_match_add
);
1866 route_map_no_match_interface_hook(generic_match_delete
);
1868 route_map_match_ip_address_hook(generic_match_add
);
1869 route_map_no_match_ip_address_hook(generic_match_delete
);
1871 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1872 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1874 route_map_match_ip_next_hop_hook(generic_match_add
);
1875 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1877 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1878 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1880 route_map_match_tag_hook(generic_match_add
);
1881 route_map_no_match_tag_hook(generic_match_delete
);
1883 route_map_match_ipv6_address_hook(generic_match_add
);
1884 route_map_no_match_ipv6_address_hook(generic_match_delete
);
1886 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
1887 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
1889 route_map_install_match(&route_match_tag_cmd
);
1890 route_map_install_match(&route_match_interface_cmd
);
1891 route_map_install_match(&route_match_ip_next_hop_cmd
);
1892 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
1893 route_map_install_match(&route_match_ip_address_cmd
);
1894 route_map_install_match(&route_match_ipv6_address_cmd
);
1895 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
1896 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
1897 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
1898 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
1899 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
1900 route_map_install_match(&route_match_source_protocol_cmd
);
1901 route_map_install_match(&route_match_source_instance_cmd
);
1904 route_map_install_set(&route_set_src_cmd
);
1906 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
1907 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
1908 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
1909 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
1910 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
1911 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
1912 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
1913 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
1914 install_element(RMAP_NODE
, &match_source_instance_cmd
);
1915 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
1918 install_element(RMAP_NODE
, &set_src_cmd
);
1919 install_element(RMAP_NODE
, &no_set_src_cmd
);