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
32 #include "northbound_cli.h"
33 #include "lib/route_types.h"
37 #include "zebra/zebra_router.h"
38 #include "zebra/redistribute.h"
39 #include "zebra/debug.h"
40 #include "zebra/zebra_rnh.h"
41 #include "zebra/zebra_routemap.h"
43 #ifndef VTYSH_EXTRACT_PL
44 #include "zebra/zebra_routemap_clippy.c"
47 static uint32_t zebra_rmap_update_timer
= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
;
48 static struct thread
*zebra_t_rmap_update
= NULL
;
49 char *zebra_import_table_routemap
[AFI_MAX
][ZEBRA_KERNEL_TABLE_MAX
];
52 struct nexthop
*nexthop
;
54 uint32_t source_protocol
;
60 static void zebra_route_map_set_delay_timer(uint32_t value
);
63 * Match function return 1 if match is success else return 0
65 static enum route_map_cmd_result_t
66 route_match_tag(void *rule
, const struct prefix
*prefix
, void *object
)
69 struct nh_rmap_obj
*nh_data
;
74 if (nh_data
->tag
== *tag
)
80 /* Route map commands for tag matching */
81 static const struct route_map_rule_cmd route_match_tag_cmd
= {
84 route_map_rule_tag_compile
,
85 route_map_rule_tag_free
,
89 /* `match interface IFNAME' */
90 /* Match function return 1 if match is success else return zero. */
91 static enum route_map_cmd_result_t
92 route_match_interface(void *rule
, const struct prefix
*prefix
, void *object
)
94 struct nh_rmap_obj
*nh_data
;
98 if (strcasecmp(ifname
, "any") == 0)
101 if (!nh_data
|| !nh_data
->nexthop
)
103 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
106 if (nh_data
->nexthop
->ifindex
== ifindex
)
112 /* Route map `match interface' match statement. `arg' is IFNAME value */
113 static void *route_match_interface_compile(const char *arg
)
115 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
118 /* Free route map's compiled `match interface' value. */
119 static void route_match_interface_free(void *rule
)
121 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
124 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
129 vty_out(vty
, "Protocol : route-map\n");
130 vty_out(vty
, "-------------------------------------\n");
132 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
133 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
134 vty_out(vty
, "%-24s : %-10s\n", zebra_route_string(i
),
135 PROTO_RM_NAME(zvrf
, af_type
, i
));
137 vty_out(vty
, "%-24s : none\n", zebra_route_string(i
));
140 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
141 vty_out(vty
, "%-24s : %-10s\n", "any",
142 PROTO_RM_NAME(zvrf
, af_type
, i
));
144 vty_out(vty
, "%-24s : none\n", "any");
147 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
152 vty_out(vty
, "Protocol : route-map\n");
153 vty_out(vty
, "-------------------------------------\n");
155 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
156 if (NHT_RM_NAME(zvrf
, af_type
, i
))
157 vty_out(vty
, "%-24s : %-10s\n", zebra_route_string(i
),
158 NHT_RM_NAME(zvrf
, af_type
, i
));
160 vty_out(vty
, "%-24s : none\n", zebra_route_string(i
));
163 if (NHT_RM_NAME(zvrf
, af_type
, i
))
164 vty_out(vty
, "%-24s : %-10s\n", "any",
165 NHT_RM_NAME(zvrf
, af_type
, i
));
167 vty_out(vty
, "%-24s : none\n", "any");
170 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
171 const char *vrf_name
)
173 struct zebra_vrf
*zvrf
;
178 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
179 zvrf
= (struct zebra_vrf
*)vrf
->info
;
182 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
183 show_vrf_proto_rm(vty
, zvrf
, af_type
);
186 vrf_id_t vrf_id
= VRF_DEFAULT
;
189 VRF_GET_ID(vrf_id
, vrf_name
, false);
191 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
195 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
196 show_vrf_proto_rm(vty
, zvrf
, af_type
);
202 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
203 const char *vrf_name
)
205 struct zebra_vrf
*zvrf
;
210 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
211 zvrf
= (struct zebra_vrf
*)vrf
->info
;
215 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
216 show_vrf_nht_rm(vty
, zvrf
, af_type
);
219 vrf_id_t vrf_id
= VRF_DEFAULT
;
222 VRF_GET_ID(vrf_id
, vrf_name
, false);
224 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
228 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
229 show_vrf_nht_rm(vty
, zvrf
, af_type
);
235 /* Route map commands for interface matching */
236 static const struct route_map_rule_cmd route_match_interface_cmd
= {
238 route_match_interface
,
239 route_match_interface_compile
,
240 route_match_interface_free
243 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
244 int rtype
, afi_t afi
, safi_t safi
)
246 struct route_table
*table
;
248 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
249 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
252 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
254 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
255 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
256 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
257 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
258 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
260 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
262 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
264 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
265 zvrf
->vrf
->vrf_id
, rtype
);
266 /* Process routes of interested address-families. */
267 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
269 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
276 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
277 int rtype
, afi_t afi
, safi_t safi
)
279 struct route_table
*table
;
281 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
284 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
286 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
287 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
288 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
290 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
291 zvrf
->vrf
->vrf_id
, rtype
);
292 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
294 /* Process routes of interested address-families. */
295 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
297 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
300 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
305 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
309 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
310 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
313 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
315 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
316 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
317 NHT_RM_MAP(zvrf
, afi
, rtype
) =
318 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
319 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
321 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
322 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
327 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
331 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
334 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
335 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
336 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
337 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
339 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
340 zvrf
->vrf
->vrf_id
, rtype
);
341 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
343 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
345 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
351 match_ip_address_prefix_len
, match_ip_address_prefix_len_cmd
,
352 "match ip address prefix-len (0-32)$length",
355 "Match prefix length of IP address\n"
356 "Match prefix length of IP address\n"
360 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
361 char xpath_value
[XPATH_MAXLEN
];
363 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
365 xpath_value
, sizeof(xpath_value
),
366 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
368 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
370 return nb_cli_apply_changes(vty
, NULL
);
374 no_match_ip_address_prefix_len
, no_match_ip_address_prefix_len_cmd
,
375 "no match ip address prefix-len [(0-32)]",
379 "Match prefix length of IP address\n"
380 "Match prefix length of IP address\n"
384 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
386 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
388 return nb_cli_apply_changes(vty
, NULL
);
392 match_ipv6_address_prefix_len
, match_ipv6_address_prefix_len_cmd
,
393 "match ipv6 address prefix-len (0-128)$length",
396 "Match prefix length of IPv6 address\n"
397 "Match prefix length of IPv6 address\n"
401 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
402 char xpath_value
[XPATH_MAXLEN
];
404 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
406 xpath_value
, sizeof(xpath_value
),
407 "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
409 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
411 return nb_cli_apply_changes(vty
, NULL
);
415 no_match_ipv6_address_prefix_len
, no_match_ipv6_address_prefix_len_cmd
,
416 "no match ipv6 address prefix-len [(0-128)]",
420 "Match prefix length of IPv6 address\n"
421 "Match prefix length of IPv6 address\n"
425 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
427 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
429 return nb_cli_apply_changes(vty
, NULL
);
433 match_ip_nexthop_prefix_len
, match_ip_nexthop_prefix_len_cmd
,
434 "match ip next-hop prefix-len (0-32)$length",
437 "Match prefixlen of nexthop IP address\n"
438 "Match prefixlen of given nexthop\n"
442 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
443 char xpath_value
[XPATH_MAXLEN
];
445 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
447 xpath_value
, sizeof(xpath_value
),
448 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
450 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
452 return nb_cli_apply_changes(vty
, NULL
);
456 no_match_ip_nexthop_prefix_len
, no_match_ip_nexthop_prefix_len_cmd
,
457 "no match ip next-hop prefix-len [(0-32)]",
461 "Match prefixlen of nexthop IP address\n"
462 "Match prefix length of nexthop\n"
466 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
468 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
470 return nb_cli_apply_changes(vty
, NULL
);
474 match_source_protocol
, match_source_protocol_cmd
,
475 "match source-protocol " FRR_REDIST_STR_ZEBRA
"$proto",
477 "Match protocol via which the route was learnt\n"
478 FRR_REDIST_HELP_STR_ZEBRA
)
481 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
482 char xpath_value
[XPATH_MAXLEN
];
484 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
485 snprintf(xpath_value
, sizeof(xpath_value
),
486 "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
488 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, proto
);
490 return nb_cli_apply_changes(vty
, NULL
);
494 no_match_source_protocol
, no_match_source_protocol_cmd
,
495 "no match source-protocol [" FRR_REDIST_STR_ZEBRA
"]",
498 "Match protocol via which the route was learnt\n"
499 FRR_REDIST_HELP_STR_ZEBRA
)
502 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
504 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
506 return nb_cli_apply_changes(vty
, NULL
);
510 match_source_instance
, match_source_instance_cmd
,
511 "match source-instance (0-255)$instance",
513 "Match the protocol's instance number\n"
514 "The instance number\n")
517 "./match-condition[condition='frr-zebra-route-map:source-instance']";
518 char xpath_value
[XPATH_MAXLEN
];
520 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
521 snprintf(xpath_value
, sizeof(xpath_value
),
522 "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
524 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, instance_str
);
526 return nb_cli_apply_changes(vty
, NULL
);
530 no_match_source_instance
, no_match_source_instance_cmd
,
531 "no match source-instance [(0-255)]",
533 "Match the protocol's instance number\n"
534 "The instance number\n")
537 "./match-condition[condition='frr-zebra-route-map:source-instance']";
539 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
541 return nb_cli_apply_changes(vty
, NULL
);
547 set_src
, set_src_cmd
,
548 "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
550 "src address for route\n"
552 "IPv6 src address\n")
555 "./set-action[action='frr-zebra-route-map:src-address']";
556 char xpath_value
[XPATH_MAXLEN
];
558 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
561 xpath_value
, sizeof(xpath_value
),
562 "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
564 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
568 xpath_value
, sizeof(xpath_value
),
569 "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
571 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
575 return nb_cli_apply_changes(vty
, NULL
);
579 no_set_src
, no_set_src_cmd
,
580 "no set src [<A.B.C.D|X:X::X:X>]",
583 "Source address for route\n"
588 "./set-action[action='frr-zebra-route-map:src-address']";
590 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
592 return nb_cli_apply_changes(vty
, NULL
);
595 DEFUN_YANG (zebra_route_map_timer
,
596 zebra_route_map_timer_cmd
,
597 "zebra route-map delay-timer (0-600)",
599 "Set route-map parameters\n"
600 "Time to wait before route-map updates are processed\n"
601 "0 means route-map changes are run immediately instead of delaying\n")
604 uint32_t rmap_delay_timer
;
606 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
607 zebra_route_map_set_delay_timer(rmap_delay_timer
);
609 return (CMD_SUCCESS
);
612 DEFUN_YANG (no_zebra_route_map_timer
,
613 no_zebra_route_map_timer_cmd
,
614 "no zebra route-map delay-timer [(0-600)]",
617 "Set route-map parameters\n"
618 "Reset delay-timer to default value, 30 secs\n"
619 "0 means route-map changes are run immediately instead of delaying\n")
621 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
623 return (CMD_SUCCESS
);
626 DEFPY_YANG (ip_protocol
,
628 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
629 " $proto route-map ROUTE-MAP$rmap",
631 "Filter routing info exchanged between zebra and protocol\n"
632 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
633 "Specify route-map\n"
641 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
646 if (strcasecmp(proto
, "any") == 0)
647 rtype
= ZEBRA_ROUTE_MAX
;
649 rtype
= proto_name2num(proto
);
651 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
652 return CMD_WARNING_CONFIG_FAILED
;
655 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
660 DEFPY_YANG (no_ip_protocol
,
662 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
663 " $proto [route-map ROUTE-MAP$rmap]",
666 "Stop filtering routing info between zebra and protocol\n"
667 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
668 "Specify route-map\n"
675 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
680 if (strcasecmp(proto
, "any") == 0)
681 rtype
= ZEBRA_ROUTE_MAX
;
683 rtype
= proto_name2num(proto
);
685 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
686 return CMD_WARNING_CONFIG_FAILED
;
689 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
694 DEFPY_YANG (show_ip_protocol
,
695 show_ip_protocol_cmd
,
696 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
699 "IP protocol filtering status\n"
700 VRF_FULL_CMD_HELP_STR
)
702 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
707 DEFPY_YANG (ipv6_protocol
,
709 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
710 " $proto route-map ROUTE-MAP$rmap",
712 "Filter IPv6 routing info exchanged between zebra and protocol\n"
713 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
714 "Specify route-map\n"
722 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
727 if (strcasecmp(proto
, "any") == 0)
728 rtype
= ZEBRA_ROUTE_MAX
;
730 rtype
= proto_name2num(proto
);
732 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
733 return CMD_WARNING_CONFIG_FAILED
;
736 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
741 DEFPY_YANG (no_ipv6_protocol
,
742 no_ipv6_protocol_cmd
,
743 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
744 " $proto [route-map ROUTE-MAP$rmap]",
747 "Stop filtering IPv6 routing info between zebra and protocol\n"
748 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
749 "Specify route-map\n"
756 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
761 if (strcasecmp(proto
, "any") == 0)
762 rtype
= ZEBRA_ROUTE_MAX
;
764 rtype
= proto_name2num(proto
);
766 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
767 return CMD_WARNING_CONFIG_FAILED
;
770 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
775 DEFPY_YANG (show_ipv6_protocol
,
776 show_ipv6_protocol_cmd
,
777 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
780 "IPv6 protocol filtering status\n"
781 VRF_FULL_CMD_HELP_STR
)
783 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
788 DEFPY_YANG (ip_protocol_nht_rmap
,
789 ip_protocol_nht_rmap_cmd
,
790 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
791 " $proto route-map ROUTE-MAP$rmap",
793 "Filter Next Hop tracking route resolution\n"
794 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
795 "Specify route map\n"
804 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
809 if (strcasecmp(proto
, "any") == 0)
810 rtype
= ZEBRA_ROUTE_MAX
;
812 rtype
= proto_name2num(proto
);
814 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
815 return CMD_WARNING_CONFIG_FAILED
;
818 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
823 DEFPY_YANG (no_ip_protocol_nht_rmap
,
824 no_ip_protocol_nht_rmap_cmd
,
825 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
826 " $proto route-map [ROUTE-MAP$rmap]",
829 "Filter Next Hop tracking route resolution\n"
830 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
831 "Specify route map\n"
838 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
843 if (strcasecmp(proto
, "any") == 0)
844 rtype
= ZEBRA_ROUTE_MAX
;
846 rtype
= proto_name2num(proto
);
848 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
849 return CMD_WARNING_CONFIG_FAILED
;
852 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
857 DEFPY_YANG (show_ip_protocol_nht
,
858 show_ip_protocol_nht_cmd
,
859 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
862 "IP nexthop tracking table\n"
863 "IP Next Hop tracking filtering status\n"
864 VRF_FULL_CMD_HELP_STR
)
866 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
871 DEFPY_YANG (ipv6_protocol_nht_rmap
,
872 ipv6_protocol_nht_rmap_cmd
,
873 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
874 " $proto route-map ROUTE-MAP$rmap",
876 "Filter Next Hop tracking route resolution\n"
877 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
878 "Specify route map\n"
886 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
891 if (strcasecmp(proto
, "any") == 0)
892 rtype
= ZEBRA_ROUTE_MAX
;
894 rtype
= proto_name2num(proto
);
896 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
897 return CMD_WARNING_CONFIG_FAILED
;
900 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
905 DEFPY_YANG (no_ipv6_protocol_nht_rmap
,
906 no_ipv6_protocol_nht_rmap_cmd
,
907 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
908 " $proto [route-map ROUTE-MAP$rmap]",
911 "Filter Next Hop tracking route resolution\n"
912 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
913 "Specify route map\n"
920 ZEBRA_DECLVAR_CONTEXT(vrf
, zvrf
);
925 if (strcasecmp(proto
, "any") == 0)
926 rtype
= ZEBRA_ROUTE_MAX
;
928 rtype
= proto_name2num(proto
);
930 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
931 return CMD_WARNING_CONFIG_FAILED
;
934 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
939 DEFPY_YANG (show_ipv6_protocol_nht
,
940 show_ipv6_protocol_nht_cmd
,
941 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
944 "Next Hop filtering status\n"
946 VRF_FULL_CMD_HELP_STR
)
948 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
953 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
955 /* `match ip next-hop IP_ACCESS_LIST' */
957 /* Match function return 1 if match is success else return zero. */
958 static enum route_map_cmd_result_t
959 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
, void *object
)
961 struct access_list
*alist
;
962 struct nh_rmap_obj
*nh_data
;
963 struct prefix_ipv4 p
;
969 switch (nh_data
->nexthop
->type
) {
970 case NEXTHOP_TYPE_IFINDEX
:
971 /* Interface routes can't match ip next-hop */
973 case NEXTHOP_TYPE_IPV4_IFINDEX
:
974 case NEXTHOP_TYPE_IPV4
:
976 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
977 p
.prefixlen
= IPV4_MAX_BITLEN
;
982 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
986 return (access_list_apply(alist
, &p
) == FILTER_DENY
? RMAP_NOMATCH
990 /* Route map `ip next-hop' match statement. `arg' should be
992 static void *route_match_ip_next_hop_compile(const char *arg
)
994 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
997 /* Free route map's compiled `. */
998 static void route_match_ip_next_hop_free(void *rule
)
1000 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1003 /* Route map commands for ip next-hop matching. */
1004 static const struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1006 route_match_ip_next_hop
,
1007 route_match_ip_next_hop_compile
,
1008 route_match_ip_next_hop_free
1011 /* `match ip next-hop prefix-list PREFIX_LIST' */
1013 static enum route_map_cmd_result_t
1014 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1017 struct prefix_list
*plist
;
1018 struct nh_rmap_obj
*nh_data
;
1019 struct prefix_ipv4 p
;
1021 nh_data
= (struct nh_rmap_obj
*)object
;
1023 return RMAP_NOMATCH
;
1025 switch (nh_data
->nexthop
->type
) {
1026 case NEXTHOP_TYPE_IFINDEX
:
1027 /* Interface routes can't match ip next-hop */
1028 return RMAP_NOMATCH
;
1029 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1030 case NEXTHOP_TYPE_IPV4
:
1032 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1033 p
.prefixlen
= IPV4_MAX_BITLEN
;
1036 return RMAP_NOMATCH
;
1038 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1040 return RMAP_NOMATCH
;
1042 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
? RMAP_NOMATCH
1046 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1048 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1051 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1053 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1056 static const struct route_map_rule_cmd
1057 route_match_ip_next_hop_prefix_list_cmd
= {
1058 "ip next-hop prefix-list",
1059 route_match_ip_next_hop_prefix_list
,
1060 route_match_ip_next_hop_prefix_list_compile
,
1061 route_match_ip_next_hop_prefix_list_free
1064 /* `match ip address IP_ACCESS_LIST' */
1066 /* Match function should return 1 if match is success else return
1068 static enum route_map_cmd_result_t
1069 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1072 struct access_list
*alist
;
1074 alist
= access_list_lookup(afi
, (char *)rule
);
1076 return RMAP_NOMATCH
;
1078 return (access_list_apply(alist
, prefix
) == FILTER_DENY
? RMAP_NOMATCH
1082 static enum route_map_cmd_result_t
1083 route_match_ip_address(void *rule
, const struct prefix
*prefix
, void *object
)
1085 return route_match_address(AFI_IP
, rule
, prefix
, object
);
1088 static enum route_map_cmd_result_t
1089 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
, void *object
)
1091 return route_match_address(AFI_IP6
, rule
, prefix
, object
);
1094 /* Route map `ip address' match statement. `arg' should be
1095 access-list name. */
1096 static void *route_match_address_compile(const char *arg
)
1098 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1101 /* Free route map's compiled `ip address' value. */
1102 static void route_match_address_free(void *rule
)
1104 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1107 /* Route map commands for ip address matching. */
1108 static const struct route_map_rule_cmd route_match_ip_address_cmd
= {
1110 route_match_ip_address
,
1111 route_match_address_compile
,
1112 route_match_address_free
1115 /* Route map commands for ipv6 address matching. */
1116 static const struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1118 route_match_ipv6_address
,
1119 route_match_address_compile
,
1120 route_match_address_free
1123 /* `match ip address prefix-list PREFIX_LIST' */
1125 static enum route_map_cmd_result_t
1126 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1127 void *object
, afi_t afi
)
1129 struct prefix_list
*plist
;
1131 plist
= prefix_list_lookup(afi
, (char *)rule
);
1133 return RMAP_NOMATCH
;
1135 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
1139 static enum route_map_cmd_result_t
1140 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1143 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP
));
1146 static void *route_match_address_prefix_list_compile(const char *arg
)
1148 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1151 static void route_match_address_prefix_list_free(void *rule
)
1153 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1156 static const struct route_map_rule_cmd
1157 route_match_ip_address_prefix_list_cmd
= {
1158 "ip address prefix-list",
1159 route_match_ip_address_prefix_list
,
1160 route_match_address_prefix_list_compile
,
1161 route_match_address_prefix_list_free
1164 static enum route_map_cmd_result_t
1165 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1168 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP6
));
1171 static const struct route_map_rule_cmd
1172 route_match_ipv6_address_prefix_list_cmd
= {
1173 "ipv6 address prefix-list",
1174 route_match_ipv6_address_prefix_list
,
1175 route_match_address_prefix_list_compile
,
1176 route_match_address_prefix_list_free
1179 /* `match ipv6 next-hop type <TYPE>' */
1181 static enum route_map_cmd_result_t
1182 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1185 struct nh_rmap_obj
*nh_data
;
1187 if (prefix
->family
== AF_INET6
) {
1188 nh_data
= (struct nh_rmap_obj
*)object
;
1190 return RMAP_NOMATCH
;
1192 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1196 return RMAP_NOMATCH
;
1199 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1201 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1204 static void route_match_ipv6_next_hop_type_free(void *rule
)
1206 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1209 static const struct route_map_rule_cmd
1210 route_match_ipv6_next_hop_type_cmd
= {
1211 "ipv6 next-hop type",
1212 route_match_ipv6_next_hop_type
,
1213 route_match_ipv6_next_hop_type_compile
,
1214 route_match_ipv6_next_hop_type_free
1217 /* `match ip address prefix-len PREFIXLEN' */
1219 static enum route_map_cmd_result_t
1220 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1223 uint32_t *prefixlen
= (uint32_t *)rule
;
1225 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1228 static void *route_match_address_prefix_len_compile(const char *arg
)
1230 uint32_t *prefix_len
;
1231 char *endptr
= NULL
;
1232 unsigned long tmpval
;
1234 /* prefix len value shoud be integer. */
1235 if (!all_digit(arg
))
1239 tmpval
= strtoul(arg
, &endptr
, 10);
1240 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1243 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1245 *prefix_len
= tmpval
;
1249 static void route_match_address_prefix_len_free(void *rule
)
1251 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1254 static const struct route_map_rule_cmd
1255 route_match_ip_address_prefix_len_cmd
= {
1256 "ip address prefix-len",
1257 route_match_address_prefix_len
,
1258 route_match_address_prefix_len_compile
,
1259 route_match_address_prefix_len_free
1262 static const struct route_map_rule_cmd
1263 route_match_ipv6_address_prefix_len_cmd
= {
1264 "ipv6 address prefix-len",
1265 route_match_address_prefix_len
,
1266 route_match_address_prefix_len_compile
,
1267 route_match_address_prefix_len_free
1270 /* `match ip nexthop prefix-len PREFIXLEN' */
1272 static enum route_map_cmd_result_t
1273 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1276 uint32_t *prefixlen
= (uint32_t *)rule
;
1277 struct nh_rmap_obj
*nh_data
;
1278 struct prefix_ipv4 p
;
1280 nh_data
= (struct nh_rmap_obj
*)object
;
1281 if (!nh_data
|| !nh_data
->nexthop
)
1282 return RMAP_NOMATCH
;
1284 switch (nh_data
->nexthop
->type
) {
1285 case NEXTHOP_TYPE_IFINDEX
:
1286 /* Interface routes can't match ip next-hop */
1287 return RMAP_NOMATCH
;
1288 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1289 case NEXTHOP_TYPE_IPV4
:
1291 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1292 p
.prefixlen
= IPV4_MAX_BITLEN
;
1295 return RMAP_NOMATCH
;
1297 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1300 static const struct route_map_rule_cmd
1301 route_match_ip_nexthop_prefix_len_cmd
= {
1302 "ip next-hop prefix-len",
1303 route_match_ip_nexthop_prefix_len
,
1304 route_match_address_prefix_len_compile
, /* reuse */
1305 route_match_address_prefix_len_free
/* reuse */
1308 /* `match ip next-hop type <blackhole>' */
1310 static enum route_map_cmd_result_t
1311 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1314 struct nh_rmap_obj
*nh_data
;
1316 if (prefix
->family
== AF_INET
) {
1317 nh_data
= (struct nh_rmap_obj
*)object
;
1319 return RMAP_NOMATCH
;
1321 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1325 return RMAP_NOMATCH
;
1328 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1330 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1333 static void route_match_ip_next_hop_type_free(void *rule
)
1335 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1338 static const struct route_map_rule_cmd
1339 route_match_ip_next_hop_type_cmd
= {
1341 route_match_ip_next_hop_type
,
1342 route_match_ip_next_hop_type_compile
,
1343 route_match_ip_next_hop_type_free
1346 /* `match source-protocol PROTOCOL' */
1348 static enum route_map_cmd_result_t
1349 route_match_source_protocol(void *rule
, const struct prefix
*p
, void *object
)
1351 uint32_t *rib_type
= (uint32_t *)rule
;
1352 struct nh_rmap_obj
*nh_data
;
1354 nh_data
= (struct nh_rmap_obj
*)object
;
1356 return RMAP_NOMATCH
;
1358 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1362 static void *route_match_source_protocol_compile(const char *arg
)
1367 i
= proto_name2num(arg
);
1368 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1375 static void route_match_source_protocol_free(void *rule
)
1377 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1380 static const struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1382 route_match_source_protocol
,
1383 route_match_source_protocol_compile
,
1384 route_match_source_protocol_free
1387 /* `source-instance` */
1388 static enum route_map_cmd_result_t
1389 route_match_source_instance(void *rule
, const struct prefix
*p
, void *object
)
1391 uint8_t *instance
= (uint8_t *)rule
;
1392 struct nh_rmap_obj
*nh_data
;
1394 nh_data
= (struct nh_rmap_obj
*)object
;
1396 return RMAP_NOMATCH
;
1398 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1401 static void *route_match_source_instance_compile(const char *arg
)
1407 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1414 static void route_match_source_instance_free(void *rule
)
1416 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1419 static const struct route_map_rule_cmd route_match_source_instance_cmd
= {
1421 route_match_source_instance
,
1422 route_match_source_instance_compile
,
1423 route_match_source_instance_free
1426 /* `set src A.B.C.D' */
1429 static enum route_map_cmd_result_t
1430 route_set_src(void *rule
, const struct prefix
*prefix
, void *object
)
1432 struct nh_rmap_obj
*nh_data
;
1434 nh_data
= (struct nh_rmap_obj
*)object
;
1435 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1440 /* set src compilation. */
1441 static void *route_set_src_compile(const char *arg
)
1443 union g_addr src
, *psrc
;
1445 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1446 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1447 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1454 /* Free route map's compiled `set src' value. */
1455 static void route_set_src_free(void *rule
)
1457 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1460 /* Set src rule structure. */
1461 static const struct route_map_rule_cmd route_set_src_cmd
= {
1464 route_set_src_compile
,
1468 /* The function checks if the changed routemap specified by parameter rmap
1469 * matches the configured protocol routemaps in proto_rm table. If there is
1470 * a match then rib_update_table() to process the routes.
1472 static void zebra_rib_table_rm_update(const char *rmap
)
1475 struct route_table
*table
;
1476 struct vrf
*vrf
= NULL
;
1477 struct zebra_vrf
*zvrf
= NULL
;
1479 struct route_map
*old
= NULL
;
1481 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1485 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1486 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1487 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1488 if (IS_ZEBRA_DEBUG_EVENT
)
1490 "%s : AFI_IP rmap %s, route type %s",
1492 zebra_route_string(i
));
1494 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1496 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1497 route_map_lookup_by_name(rmap_name
);
1498 /* old is NULL. i.e Route map creation event.
1499 * So update applied_counter.
1500 * If Old is not NULL, i.e It may be routemap
1501 * updation or deletion.
1502 * So no need to update the counter.
1505 route_map_counter_increment(
1506 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1507 /* There is single rib table for all protocols
1509 table
= zvrf
->table
[AFI_IP
][SAFI_UNICAST
];
1513 RIB_UPDATE_RMAP_CHANGE
,
1517 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1518 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1519 if (IS_ZEBRA_DEBUG_EVENT
)
1521 "%s : AFI_IP6 rmap %s, route type %s",
1523 zebra_route_string(i
));
1525 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1527 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1528 route_map_lookup_by_name(rmap_name
);
1530 route_map_counter_increment(
1531 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1532 /* There is single rib table for all protocols
1534 table
= zvrf
->table
[AFI_IP6
][SAFI_UNICAST
];
1538 RIB_UPDATE_RMAP_CHANGE
,
1546 /* The function checks if the changed routemap specified by parameter rmap
1547 * matches the configured protocol routemaps in nht_rm table. If there is
1548 * a match then zebra_evaluate_rnh() to process the nexthops.
1550 static void zebra_nht_rm_update(const char *rmap
)
1553 struct route_table
*table
;
1554 struct vrf
*vrf
= NULL
;
1555 struct zebra_vrf
*zvrf
= NULL
;
1559 struct route_map
*old
= NULL
;
1561 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1565 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1566 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1567 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1568 if (IS_ZEBRA_DEBUG_EVENT
)
1570 "%s : AFI_IP rmap %s, route type %s",
1572 zebra_route_string(i
));
1574 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1576 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1577 route_map_lookup_by_name(rmap_name
);
1579 route_map_counter_increment(
1580 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1581 /* There is single rib table for all protocols
1584 table
= zvrf
->table
[AFI_IP
]
1591 zvrf
, AFI_IP
, 1, NULL
,
1597 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1598 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1599 if (IS_ZEBRA_DEBUG_EVENT
)
1601 "%s : AFI_IP6 rmap %s, route type %s",
1603 zebra_route_string(i
));
1605 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1607 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1608 route_map_lookup_by_name(rmap_name
);
1610 route_map_counter_increment(
1611 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1612 /* There is single rib table for all protocols
1614 if (afi_ipv6
== 0) {
1615 table
= zvrf
->table
[AFI_IP6
]
1622 zvrf
, AFI_IP
, 1, NULL
,
1631 static void zebra_route_map_process_update_cb(char *rmap_name
)
1633 if (IS_ZEBRA_DEBUG_EVENT
)
1634 zlog_debug("Event handler for route-map: %s",
1636 zebra_import_table_rm_update(rmap_name
);
1637 zebra_rib_table_rm_update(rmap_name
);
1638 zebra_nht_rm_update(rmap_name
);
1641 static int zebra_route_map_update_timer(struct thread
*thread
)
1643 if (IS_ZEBRA_DEBUG_EVENT
)
1644 zlog_debug("Event driven route-map update triggered");
1646 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1648 "%u: Routemap update-timer fired, scheduling RIB processing",
1651 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1654 * This code needs to be updated to be:
1655 * 1) VRF Aware <sigh>
1656 * 2) Route-map aware
1661 static void zebra_route_map_set_delay_timer(uint32_t value
)
1663 zebra_rmap_update_timer
= value
;
1664 if (!value
&& zebra_t_rmap_update
) {
1665 /* Event driven route map updates is being disabled */
1666 /* But there's a pending timer. Fire it off now */
1667 THREAD_OFF(zebra_t_rmap_update
);
1668 zebra_route_map_update_timer(NULL
);
1672 void zebra_routemap_finish(void)
1674 /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
1675 zebra_rmap_update_timer
= 0;
1676 /* Thread off if any scheduled already */
1677 THREAD_OFF(zebra_t_rmap_update
);
1682 zebra_route_map_check(afi_t family
, int rib_type
, uint8_t instance
,
1683 const struct prefix
*p
, struct nexthop
*nexthop
,
1684 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1686 struct route_map
*rmap
= NULL
;
1688 route_map_result_t ret
= RMAP_PERMITMATCH
;
1689 struct nh_rmap_obj nh_obj
;
1691 nh_obj
.nexthop
= nexthop
;
1692 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1693 nh_obj
.source_protocol
= rib_type
;
1694 nh_obj
.instance
= instance
;
1698 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
) {
1699 rm_name
= PROTO_RM_NAME(zvrf
, family
, rib_type
);
1700 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1702 if (rm_name
&& !rmap
)
1703 return RMAP_DENYMATCH
;
1706 rm_name
= PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1707 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1709 if (rm_name
&& !rmap
)
1710 return RMAP_DENYMATCH
;
1713 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1719 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1721 return zebra_import_table_routemap
[afi
][table
];
1724 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1727 zebra_import_table_routemap
[afi
][table
] =
1728 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1731 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1733 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1737 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1738 const struct prefix
*p
,
1739 struct nexthop
*nexthop
,
1740 vrf_id_t vrf_id
, route_tag_t tag
,
1741 const char *rmap_name
)
1743 struct route_map
*rmap
= NULL
;
1744 route_map_result_t ret
= RMAP_DENYMATCH
;
1745 struct nh_rmap_obj nh_obj
;
1747 nh_obj
.nexthop
= nexthop
;
1748 nh_obj
.vrf_id
= vrf_id
;
1749 nh_obj
.source_protocol
= re_type
;
1750 nh_obj
.instance
= instance
;
1754 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1755 rmap
= route_map_lookup_by_name(rmap_name
);
1757 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1763 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1764 const struct prefix
*p
,
1765 struct zebra_vrf
*zvrf
,
1766 struct route_entry
*re
,
1767 struct nexthop
*nexthop
)
1769 struct route_map
*rmap
= NULL
;
1770 route_map_result_t ret
= RMAP_PERMITMATCH
;
1771 struct nh_rmap_obj nh_obj
;
1773 nh_obj
.nexthop
= nexthop
;
1774 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1775 nh_obj
.source_protocol
= re
->type
;
1776 nh_obj
.instance
= re
->instance
;
1777 nh_obj
.metric
= re
->metric
;
1778 nh_obj
.tag
= re
->tag
;
1780 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1781 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1782 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1783 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1785 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1790 static void zebra_route_map_mark_update(const char *rmap_name
)
1792 /* rmap_update_timer of 0 means don't do route updates */
1793 if (zebra_rmap_update_timer
)
1794 THREAD_OFF(zebra_t_rmap_update
);
1796 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1797 NULL
, zebra_rmap_update_timer
, &zebra_t_rmap_update
);
1800 static void zebra_route_map_add(const char *rmap_name
)
1802 if (route_map_mark_updated(rmap_name
) == 0)
1803 zebra_route_map_mark_update(rmap_name
);
1805 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1808 static void zebra_route_map_delete(const char *rmap_name
)
1810 if (route_map_mark_updated(rmap_name
) == 0)
1811 zebra_route_map_mark_update(rmap_name
);
1813 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1816 static void zebra_route_map_event(const char *rmap_name
)
1818 if (route_map_mark_updated(rmap_name
) == 0)
1819 zebra_route_map_mark_update(rmap_name
);
1821 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1824 /* ip protocol configuration write function */
1825 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1826 struct zebra_vrf
*zvrf
)
1831 memset(space
, 0, sizeof(space
));
1833 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1834 snprintf(space
, sizeof(space
), "%s", " ");
1836 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1837 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1838 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1839 zebra_route_string(i
),
1840 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1842 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1843 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1844 zebra_route_string(i
),
1845 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1847 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1848 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1849 zebra_route_string(i
),
1850 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1852 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1853 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1854 zebra_route_string(i
),
1855 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1858 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1859 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1860 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1862 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1863 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1864 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1866 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1867 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1868 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1870 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1871 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1872 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1874 if (zvrf_id(zvrf
) == VRF_DEFAULT
1875 && zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1876 vty_out(vty
, "zebra route-map delay-timer %d\n",
1877 zebra_rmap_update_timer
);
1880 void zebra_route_map_init(void)
1882 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1883 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1884 install_element(VRF_NODE
, &ip_protocol_cmd
);
1885 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1886 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1887 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1888 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1889 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1890 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1891 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1892 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1893 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1894 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1895 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1896 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1897 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1898 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1899 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1900 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1901 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1902 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1903 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1907 route_map_add_hook(zebra_route_map_add
);
1908 route_map_delete_hook(zebra_route_map_delete
);
1909 route_map_event_hook(zebra_route_map_event
);
1911 route_map_match_interface_hook(generic_match_add
);
1912 route_map_no_match_interface_hook(generic_match_delete
);
1914 route_map_match_ip_address_hook(generic_match_add
);
1915 route_map_no_match_ip_address_hook(generic_match_delete
);
1917 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1918 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1920 route_map_match_ip_next_hop_hook(generic_match_add
);
1921 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1923 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1924 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1926 route_map_match_ip_next_hop_type_hook(generic_match_add
);
1927 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
1929 route_map_match_tag_hook(generic_match_add
);
1930 route_map_no_match_tag_hook(generic_match_delete
);
1932 route_map_match_ipv6_address_hook(generic_match_add
);
1933 route_map_no_match_ipv6_address_hook(generic_match_delete
);
1935 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
1936 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
1938 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
1939 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
1941 route_map_install_match(&route_match_tag_cmd
);
1942 route_map_install_match(&route_match_interface_cmd
);
1943 route_map_install_match(&route_match_ip_next_hop_cmd
);
1944 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
1945 route_map_install_match(&route_match_ip_address_cmd
);
1946 route_map_install_match(&route_match_ipv6_address_cmd
);
1947 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
1948 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
1949 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
1950 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
1951 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
1952 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
1953 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
1954 route_map_install_match(&route_match_source_protocol_cmd
);
1955 route_map_install_match(&route_match_source_instance_cmd
);
1958 route_map_install_set(&route_set_src_cmd
);
1960 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
1961 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
1962 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
1963 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
1964 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
1965 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
1966 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
1967 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
1968 install_element(RMAP_NODE
, &match_source_instance_cmd
);
1969 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
1972 install_element(RMAP_NODE
, &set_src_cmd
);
1973 install_element(RMAP_NODE
, &no_set_src_cmd
);