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 #include "zebra/zebra_routemap_clippy.c"
45 static uint32_t zebra_rmap_update_timer
= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
;
46 static struct thread
*zebra_t_rmap_update
= NULL
;
47 char *zebra_import_table_routemap
[AFI_MAX
][ZEBRA_KERNEL_TABLE_MAX
];
50 struct nexthop
*nexthop
;
52 uint32_t source_protocol
;
58 static void zebra_route_map_set_delay_timer(uint32_t value
);
61 * Match function return 1 if match is success else return 0
63 static enum route_map_cmd_result_t
64 route_match_tag(void *rule
, const struct prefix
*prefix
, void *object
)
67 struct nh_rmap_obj
*nh_data
;
72 if (nh_data
->tag
== *tag
)
78 /* Route map commands for tag matching */
79 static const struct route_map_rule_cmd route_match_tag_cmd
= {
82 route_map_rule_tag_compile
,
83 route_map_rule_tag_free
,
87 /* `match interface IFNAME' */
88 /* Match function return 1 if match is success else return zero. */
89 static enum route_map_cmd_result_t
90 route_match_interface(void *rule
, const struct prefix
*prefix
, void *object
)
92 struct nh_rmap_obj
*nh_data
;
96 if (strcasecmp(ifname
, "any") == 0)
99 if (!nh_data
|| !nh_data
->nexthop
)
101 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
104 if (nh_data
->nexthop
->ifindex
== ifindex
)
110 /* Route map `match interface' match statement. `arg' is IFNAME value */
111 static void *route_match_interface_compile(const char *arg
)
113 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
116 /* Free route map's compiled `match interface' value. */
117 static void route_match_interface_free(void *rule
)
119 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
122 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
127 vty_out(vty
, "Protocol : route-map\n");
128 vty_out(vty
, "-------------------------------------\n");
130 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
131 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
132 vty_out(vty
, "%-24s : %-10s\n", zebra_route_string(i
),
133 PROTO_RM_NAME(zvrf
, af_type
, i
));
135 vty_out(vty
, "%-24s : none\n", zebra_route_string(i
));
138 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
139 vty_out(vty
, "%-24s : %-10s\n", "any",
140 PROTO_RM_NAME(zvrf
, af_type
, i
));
142 vty_out(vty
, "%-24s : none\n", "any");
145 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
146 int af_type
, json_object
*json
)
151 vty_out(vty
, "Protocol : route-map\n");
152 vty_out(vty
, "-------------------------------------\n");
155 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
157 if (NHT_RM_NAME(zvrf
, af_type
, i
))
158 json_object_string_add(
159 json
, zebra_route_string(i
),
160 NHT_RM_NAME(zvrf
, af_type
, i
));
162 json_object_string_add(
163 json
, zebra_route_string(i
), "none");
165 if (NHT_RM_NAME(zvrf
, af_type
, i
))
166 vty_out(vty
, "%-24s : %-10s\n",
167 zebra_route_string(i
),
168 NHT_RM_NAME(zvrf
, af_type
, i
));
170 vty_out(vty
, "%-24s : none\n",
171 zebra_route_string(i
));
176 if (NHT_RM_NAME(zvrf
, af_type
, i
))
177 json_object_string_add(json
, "any",
178 NHT_RM_NAME(zvrf
, af_type
, i
));
180 json_object_string_add(json
, "any", "none");
182 if (NHT_RM_NAME(zvrf
, af_type
, i
))
183 vty_out(vty
, "%-24s : %-10s\n", "any",
184 NHT_RM_NAME(zvrf
, af_type
, i
));
186 vty_out(vty
, "%-24s : none\n", "any");
190 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
191 const char *vrf_name
)
193 struct zebra_vrf
*zvrf
;
198 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
199 zvrf
= (struct zebra_vrf
*)vrf
->info
;
202 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
203 show_vrf_proto_rm(vty
, zvrf
, af_type
);
206 vrf_id_t vrf_id
= VRF_DEFAULT
;
209 VRF_GET_ID(vrf_id
, vrf_name
, false);
211 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
215 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
216 show_vrf_proto_rm(vty
, zvrf
, af_type
);
222 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
223 const char *vrf_name
, bool use_json
)
225 struct zebra_vrf
*zvrf
;
226 json_object
*json
= NULL
;
227 json_object
*json_vrfs
= NULL
;
230 json
= json_object_new_object();
231 json_vrfs
= json_object_new_object();
232 json_object_string_add(json
, "afi",
233 (af_type
== AFI_IP
) ? "ipv4" : "ipv6");
240 json_object_object_add(json
, "vrfs", json_vrfs
);
242 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
243 zvrf
= (struct zebra_vrf
*)vrf
->info
;
248 json_object
*json_proto
= NULL
;
249 json_object
*json_vrf
= NULL
;
250 json_vrf
= json_object_new_object();
251 json_object_object_add(
252 json_vrfs
, zvrf
->vrf
->name
, json_vrf
);
253 json_proto
= json_object_new_object();
254 json_object_object_add(json_vrf
, "protocols",
256 show_vrf_nht_rm(vty
, zvrf
, af_type
, json_proto
);
258 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
259 show_vrf_nht_rm(vty
, zvrf
, af_type
, NULL
);
263 json_object
*json_proto
= NULL
;
264 json_object
*json_vrf
= NULL
;
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
);
272 json_object_free(json
);
273 json_object_free(json_vrfs
);
278 json_object_object_add(json
, "vrfs", json_vrfs
);
279 json_vrf
= json_object_new_object();
280 json_object_object_add(json_vrfs
, zvrf
->vrf
->name
,
282 json_proto
= json_object_new_object();
283 json_object_object_add(json_vrf
, "protocols",
285 show_vrf_nht_rm(vty
, zvrf
, af_type
, json_proto
);
287 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
288 show_vrf_nht_rm(vty
, zvrf
, af_type
, NULL
);
298 /* Route map commands for interface matching */
299 static const struct route_map_rule_cmd route_match_interface_cmd
= {
301 route_match_interface
,
302 route_match_interface_compile
,
303 route_match_interface_free
306 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
307 int rtype
, afi_t afi
, safi_t safi
)
309 struct route_table
*table
;
311 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
312 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
315 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
317 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
318 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
319 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
320 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
321 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
323 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
325 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
327 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
328 zvrf
->vrf
->vrf_id
, rtype
);
329 /* Process routes of interested address-families. */
330 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
332 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
339 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
340 int rtype
, afi_t afi
, safi_t safi
)
342 struct route_table
*table
;
344 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
347 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
349 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
350 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
351 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
353 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
354 zvrf
->vrf
->vrf_id
, rtype
);
355 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
357 /* Process routes of interested address-families. */
358 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
360 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
363 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
368 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
372 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
373 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
376 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
378 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
379 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
380 NHT_RM_MAP(zvrf
, afi
, rtype
) =
381 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
382 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
384 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
385 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
390 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
394 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
397 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
398 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
399 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
400 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
402 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
403 zvrf
->vrf
->vrf_id
, rtype
);
404 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
406 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
408 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
414 match_ip_address_prefix_len
, match_ip_address_prefix_len_cmd
,
415 "match ip address prefix-len (0-32)$length",
418 "Match prefix length of IP address\n"
419 "Match prefix length of IP address\n"
423 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
424 char xpath_value
[XPATH_MAXLEN
];
426 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
428 xpath_value
, sizeof(xpath_value
),
429 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
431 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
433 return nb_cli_apply_changes(vty
, NULL
);
437 no_match_ip_address_prefix_len
, no_match_ip_address_prefix_len_cmd
,
438 "no match ip address prefix-len [(0-32)]",
442 "Match prefix length of IP address\n"
443 "Match prefix length of IP address\n"
447 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
449 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
451 return nb_cli_apply_changes(vty
, NULL
);
455 match_ipv6_address_prefix_len
, match_ipv6_address_prefix_len_cmd
,
456 "match ipv6 address prefix-len (0-128)$length",
459 "Match prefix length of IPv6 address\n"
460 "Match prefix length of IPv6 address\n"
464 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
465 char xpath_value
[XPATH_MAXLEN
];
467 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
469 xpath_value
, sizeof(xpath_value
),
470 "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
472 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
474 return nb_cli_apply_changes(vty
, NULL
);
478 no_match_ipv6_address_prefix_len
, no_match_ipv6_address_prefix_len_cmd
,
479 "no match ipv6 address prefix-len [(0-128)]",
483 "Match prefix length of IPv6 address\n"
484 "Match prefix length of IPv6 address\n"
488 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
490 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
492 return nb_cli_apply_changes(vty
, NULL
);
496 match_ip_nexthop_prefix_len
, match_ip_nexthop_prefix_len_cmd
,
497 "match ip next-hop prefix-len (0-32)$length",
500 "Match prefixlen of nexthop IP address\n"
501 "Match prefixlen of given nexthop\n"
505 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
506 char xpath_value
[XPATH_MAXLEN
];
508 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
510 xpath_value
, sizeof(xpath_value
),
511 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
513 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
515 return nb_cli_apply_changes(vty
, NULL
);
519 no_match_ip_nexthop_prefix_len
, no_match_ip_nexthop_prefix_len_cmd
,
520 "no match ip next-hop prefix-len [(0-32)]",
524 "Match prefixlen of nexthop IP address\n"
525 "Match prefix length of nexthop\n"
529 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
531 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
533 return nb_cli_apply_changes(vty
, NULL
);
537 match_source_protocol
, match_source_protocol_cmd
,
538 "match source-protocol " FRR_REDIST_STR_ZEBRA
"$proto",
540 "Match protocol via which the route was learnt\n"
541 FRR_REDIST_HELP_STR_ZEBRA
)
544 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
545 char xpath_value
[XPATH_MAXLEN
];
547 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
548 snprintf(xpath_value
, sizeof(xpath_value
),
549 "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
551 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, proto
);
553 return nb_cli_apply_changes(vty
, NULL
);
557 no_match_source_protocol
, no_match_source_protocol_cmd
,
558 "no match source-protocol [" FRR_REDIST_STR_ZEBRA
"]",
561 "Match protocol via which the route was learnt\n"
562 FRR_REDIST_HELP_STR_ZEBRA
)
565 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
567 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
569 return nb_cli_apply_changes(vty
, NULL
);
573 match_source_instance
, match_source_instance_cmd
,
574 "match source-instance (0-255)$instance",
576 "Match the protocol's instance number\n"
577 "The instance number\n")
580 "./match-condition[condition='frr-zebra-route-map:source-instance']";
581 char xpath_value
[XPATH_MAXLEN
];
583 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
584 snprintf(xpath_value
, sizeof(xpath_value
),
585 "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
587 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, instance_str
);
589 return nb_cli_apply_changes(vty
, NULL
);
593 no_match_source_instance
, no_match_source_instance_cmd
,
594 "no match source-instance [(0-255)]",
596 "Match the protocol's instance number\n"
597 "The instance number\n")
600 "./match-condition[condition='frr-zebra-route-map:source-instance']";
602 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
604 return nb_cli_apply_changes(vty
, NULL
);
610 set_src
, set_src_cmd
,
611 "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
613 "src address for route\n"
615 "IPv6 src address\n")
618 "./set-action[action='frr-zebra-route-map:src-address']";
619 char xpath_value
[XPATH_MAXLEN
];
621 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
624 xpath_value
, sizeof(xpath_value
),
625 "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
627 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
631 xpath_value
, sizeof(xpath_value
),
632 "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
634 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
638 return nb_cli_apply_changes(vty
, NULL
);
642 no_set_src
, no_set_src_cmd
,
643 "no set src [<A.B.C.D|X:X::X:X>]",
646 "Source address for route\n"
651 "./set-action[action='frr-zebra-route-map:src-address']";
653 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
655 return nb_cli_apply_changes(vty
, NULL
);
658 DEFUN_YANG (zebra_route_map_timer
,
659 zebra_route_map_timer_cmd
,
660 "zebra route-map delay-timer (0-600)",
662 "Set route-map parameters\n"
663 "Time to wait before route-map updates are processed\n"
664 "0 means route-map changes are run immediately instead of delaying\n")
667 uint32_t rmap_delay_timer
;
669 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
670 zebra_route_map_set_delay_timer(rmap_delay_timer
);
672 return (CMD_SUCCESS
);
675 DEFUN_YANG (no_zebra_route_map_timer
,
676 no_zebra_route_map_timer_cmd
,
677 "no zebra route-map delay-timer [(0-600)]",
680 "Set route-map parameters\n"
681 "Reset delay-timer to default value, 30 secs\n"
682 "0 means route-map changes are run immediately instead of delaying\n")
684 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
686 return (CMD_SUCCESS
);
689 DEFPY_YANG (ip_protocol
,
691 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
692 " $proto route-map ROUTE-MAP$rmap",
694 "Filter routing info exchanged between zebra and protocol\n"
695 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
696 "Specify route-map\n"
704 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
709 if (strcasecmp(proto
, "any") == 0)
710 rtype
= ZEBRA_ROUTE_MAX
;
712 rtype
= proto_name2num(proto
);
714 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
715 return CMD_WARNING_CONFIG_FAILED
;
718 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
723 DEFPY_YANG (no_ip_protocol
,
725 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
726 " $proto [route-map ROUTE-MAP$rmap]",
729 "Stop filtering routing info between zebra and protocol\n"
730 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
731 "Specify route-map\n"
738 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
743 if (strcasecmp(proto
, "any") == 0)
744 rtype
= ZEBRA_ROUTE_MAX
;
746 rtype
= proto_name2num(proto
);
748 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
749 return CMD_WARNING_CONFIG_FAILED
;
752 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
757 DEFPY_YANG (show_ip_protocol
,
758 show_ip_protocol_cmd
,
759 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
762 "IP protocol filtering status\n"
763 VRF_FULL_CMD_HELP_STR
)
765 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
770 DEFPY_YANG (ipv6_protocol
,
772 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
773 " $proto route-map ROUTE-MAP$rmap",
775 "Filter IPv6 routing info exchanged between zebra and protocol\n"
776 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
777 "Specify route-map\n"
785 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
790 if (strcasecmp(proto
, "any") == 0)
791 rtype
= ZEBRA_ROUTE_MAX
;
793 rtype
= proto_name2num(proto
);
795 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
796 return CMD_WARNING_CONFIG_FAILED
;
799 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
804 DEFPY_YANG (no_ipv6_protocol
,
805 no_ipv6_protocol_cmd
,
806 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
807 " $proto [route-map ROUTE-MAP$rmap]",
810 "Stop filtering IPv6 routing info between zebra and protocol\n"
811 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
812 "Specify route-map\n"
819 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
824 if (strcasecmp(proto
, "any") == 0)
825 rtype
= ZEBRA_ROUTE_MAX
;
827 rtype
= proto_name2num(proto
);
829 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
830 return CMD_WARNING_CONFIG_FAILED
;
833 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
838 DEFPY_YANG (show_ipv6_protocol
,
839 show_ipv6_protocol_cmd
,
840 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
843 "IPv6 protocol filtering status\n"
844 VRF_FULL_CMD_HELP_STR
)
846 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
851 DEFPY_YANG (ip_protocol_nht_rmap
,
852 ip_protocol_nht_rmap_cmd
,
853 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
854 " $proto route-map ROUTE-MAP$rmap",
856 "Filter Next Hop tracking route resolution\n"
857 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
858 "Specify route map\n"
867 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
872 if (strcasecmp(proto
, "any") == 0)
873 rtype
= ZEBRA_ROUTE_MAX
;
875 rtype
= proto_name2num(proto
);
877 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
878 return CMD_WARNING_CONFIG_FAILED
;
881 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
886 DEFPY_YANG (no_ip_protocol_nht_rmap
,
887 no_ip_protocol_nht_rmap_cmd
,
888 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
889 " $proto route-map [ROUTE-MAP$rmap]",
892 "Filter Next Hop tracking route resolution\n"
893 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
894 "Specify route map\n"
901 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
906 if (strcasecmp(proto
, "any") == 0)
907 rtype
= ZEBRA_ROUTE_MAX
;
909 rtype
= proto_name2num(proto
);
911 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
912 return CMD_WARNING_CONFIG_FAILED
;
915 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
920 DEFPY_YANG (show_ip_protocol_nht
,
921 show_ip_protocol_nht_cmd
,
922 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
925 "IPv4 nexthop tracking table\n"
926 "IPv4 Next Hop tracking filtering status\n"
932 bool uj
= use_json(argc
, argv
);
934 ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
, uj
);
939 DEFPY_YANG (ipv6_protocol_nht_rmap
,
940 ipv6_protocol_nht_rmap_cmd
,
941 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
942 " $proto route-map ROUTE-MAP$rmap",
944 "Filter Next Hop tracking route resolution\n"
945 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
946 "Specify route map\n"
954 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
959 if (strcasecmp(proto
, "any") == 0)
960 rtype
= ZEBRA_ROUTE_MAX
;
962 rtype
= proto_name2num(proto
);
964 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
965 return CMD_WARNING_CONFIG_FAILED
;
968 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
973 DEFPY_YANG (no_ipv6_protocol_nht_rmap
,
974 no_ipv6_protocol_nht_rmap_cmd
,
975 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
976 " $proto [route-map ROUTE-MAP$rmap]",
979 "Filter Next Hop tracking route resolution\n"
980 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
981 "Specify route map\n"
988 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
993 if (strcasecmp(proto
, "any") == 0)
994 rtype
= ZEBRA_ROUTE_MAX
;
996 rtype
= proto_name2num(proto
);
998 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
999 return CMD_WARNING_CONFIG_FAILED
;
1002 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
1007 DEFPY_YANG (show_ipv6_protocol_nht
,
1008 show_ipv6_protocol_nht_cmd
,
1009 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
1012 "IPv6 nexthop tracking table\n"
1013 "IPv6 Next Hop tracking filtering status\n"
1019 bool uj
= use_json(argc
, argv
);
1021 ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
, uj
);
1026 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1028 /* `match ip next-hop IP_ACCESS_LIST' */
1030 /* Match function return 1 if match is success else return zero. */
1031 static enum route_map_cmd_result_t
1032 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
, void *object
)
1034 struct access_list
*alist
;
1035 struct nh_rmap_obj
*nh_data
;
1036 struct prefix_ipv4 p
;
1040 return RMAP_NOMATCH
;
1042 switch (nh_data
->nexthop
->type
) {
1043 case NEXTHOP_TYPE_IFINDEX
:
1044 /* Interface routes can't match ip next-hop */
1045 return RMAP_NOMATCH
;
1046 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1047 case NEXTHOP_TYPE_IPV4
:
1049 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1050 p
.prefixlen
= IPV4_MAX_BITLEN
;
1052 case NEXTHOP_TYPE_IPV6
:
1053 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1054 case NEXTHOP_TYPE_BLACKHOLE
:
1055 return RMAP_NOMATCH
;
1057 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1058 if (alist
== NULL
) {
1059 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1061 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
1062 __func__
, (char *)rule
);
1063 return RMAP_NOMATCH
;
1066 return (access_list_apply(alist
, &p
) == FILTER_DENY
? RMAP_NOMATCH
1070 /* Route map `ip next-hop' match statement. `arg' should be
1071 access-list name. */
1072 static void *route_match_ip_next_hop_compile(const char *arg
)
1074 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1077 /* Free route map's compiled `. */
1078 static void route_match_ip_next_hop_free(void *rule
)
1080 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1083 /* Route map commands for ip next-hop matching. */
1084 static const struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1086 route_match_ip_next_hop
,
1087 route_match_ip_next_hop_compile
,
1088 route_match_ip_next_hop_free
1091 /* `match ip next-hop prefix-list PREFIX_LIST' */
1093 static enum route_map_cmd_result_t
1094 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1097 struct prefix_list
*plist
;
1098 struct nh_rmap_obj
*nh_data
;
1099 struct prefix_ipv4 p
;
1101 nh_data
= (struct nh_rmap_obj
*)object
;
1103 return RMAP_NOMATCH
;
1105 switch (nh_data
->nexthop
->type
) {
1106 case NEXTHOP_TYPE_IFINDEX
:
1107 /* Interface routes can't match ip next-hop */
1108 return RMAP_NOMATCH
;
1109 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1110 case NEXTHOP_TYPE_IPV4
:
1112 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1113 p
.prefixlen
= IPV4_MAX_BITLEN
;
1115 case NEXTHOP_TYPE_IPV6
:
1116 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1117 case NEXTHOP_TYPE_BLACKHOLE
:
1118 return RMAP_NOMATCH
;
1120 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1121 if (plist
== NULL
) {
1122 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1124 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
1125 __func__
, (char *)rule
);
1126 return RMAP_NOMATCH
;
1129 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
? RMAP_NOMATCH
1133 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1135 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1138 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1140 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1143 static const struct route_map_rule_cmd
1144 route_match_ip_next_hop_prefix_list_cmd
= {
1145 "ip next-hop prefix-list",
1146 route_match_ip_next_hop_prefix_list
,
1147 route_match_ip_next_hop_prefix_list_compile
,
1148 route_match_ip_next_hop_prefix_list_free
1151 /* `match ip address IP_ACCESS_LIST' */
1153 /* Match function should return 1 if match is success else return
1155 static enum route_map_cmd_result_t
1156 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1159 struct access_list
*alist
;
1161 alist
= access_list_lookup(afi
, (char *)rule
);
1162 if (alist
== NULL
) {
1163 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1165 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
1166 __func__
, (char *)rule
);
1167 return RMAP_NOMATCH
;
1170 return (access_list_apply(alist
, prefix
) == FILTER_DENY
? RMAP_NOMATCH
1174 static enum route_map_cmd_result_t
1175 route_match_ip_address(void *rule
, const struct prefix
*prefix
, void *object
)
1177 return route_match_address(AFI_IP
, rule
, prefix
, object
);
1180 static enum route_map_cmd_result_t
1181 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
, void *object
)
1183 return route_match_address(AFI_IP6
, rule
, prefix
, object
);
1186 /* Route map `ip address' match statement. `arg' should be
1187 access-list name. */
1188 static void *route_match_address_compile(const char *arg
)
1190 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1193 /* Free route map's compiled `ip address' value. */
1194 static void route_match_address_free(void *rule
)
1196 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1199 /* Route map commands for ip address matching. */
1200 static const struct route_map_rule_cmd route_match_ip_address_cmd
= {
1202 route_match_ip_address
,
1203 route_match_address_compile
,
1204 route_match_address_free
1207 /* Route map commands for ipv6 address matching. */
1208 static const struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1210 route_match_ipv6_address
,
1211 route_match_address_compile
,
1212 route_match_address_free
1215 /* `match ip address prefix-list PREFIX_LIST' */
1217 static enum route_map_cmd_result_t
1218 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1219 void *object
, afi_t afi
)
1221 struct prefix_list
*plist
;
1223 plist
= prefix_list_lookup(afi
, (char *)rule
);
1224 if (plist
== NULL
) {
1225 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1227 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
1228 __func__
, (char *)rule
);
1229 return RMAP_NOMATCH
;
1232 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
1236 static enum route_map_cmd_result_t
1237 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1240 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP
));
1243 static void *route_match_address_prefix_list_compile(const char *arg
)
1245 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1248 static void route_match_address_prefix_list_free(void *rule
)
1250 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1253 static const struct route_map_rule_cmd
1254 route_match_ip_address_prefix_list_cmd
= {
1255 "ip address prefix-list",
1256 route_match_ip_address_prefix_list
,
1257 route_match_address_prefix_list_compile
,
1258 route_match_address_prefix_list_free
1261 static enum route_map_cmd_result_t
1262 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1265 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP6
));
1268 static const struct route_map_rule_cmd
1269 route_match_ipv6_address_prefix_list_cmd
= {
1270 "ipv6 address prefix-list",
1271 route_match_ipv6_address_prefix_list
,
1272 route_match_address_prefix_list_compile
,
1273 route_match_address_prefix_list_free
1276 /* `match ipv6 next-hop type <TYPE>' */
1278 static enum route_map_cmd_result_t
1279 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1282 struct nh_rmap_obj
*nh_data
;
1284 if (prefix
->family
== AF_INET6
) {
1285 nh_data
= (struct nh_rmap_obj
*)object
;
1287 return RMAP_NOMATCH
;
1289 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1293 return RMAP_NOMATCH
;
1296 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1298 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1301 static void route_match_ipv6_next_hop_type_free(void *rule
)
1303 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1306 static const struct route_map_rule_cmd
1307 route_match_ipv6_next_hop_type_cmd
= {
1308 "ipv6 next-hop type",
1309 route_match_ipv6_next_hop_type
,
1310 route_match_ipv6_next_hop_type_compile
,
1311 route_match_ipv6_next_hop_type_free
1314 /* `match ip address prefix-len PREFIXLEN' */
1316 static enum route_map_cmd_result_t
1317 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1320 uint32_t *prefixlen
= (uint32_t *)rule
;
1322 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1325 static void *route_match_address_prefix_len_compile(const char *arg
)
1327 uint32_t *prefix_len
;
1328 char *endptr
= NULL
;
1329 unsigned long tmpval
;
1331 /* prefix len value shoud be integer. */
1332 if (!all_digit(arg
))
1336 tmpval
= strtoul(arg
, &endptr
, 10);
1337 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1340 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1342 *prefix_len
= tmpval
;
1346 static void route_match_address_prefix_len_free(void *rule
)
1348 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1351 static const struct route_map_rule_cmd
1352 route_match_ip_address_prefix_len_cmd
= {
1353 "ip address prefix-len",
1354 route_match_address_prefix_len
,
1355 route_match_address_prefix_len_compile
,
1356 route_match_address_prefix_len_free
1359 static const struct route_map_rule_cmd
1360 route_match_ipv6_address_prefix_len_cmd
= {
1361 "ipv6 address prefix-len",
1362 route_match_address_prefix_len
,
1363 route_match_address_prefix_len_compile
,
1364 route_match_address_prefix_len_free
1367 /* `match ip nexthop prefix-len PREFIXLEN' */
1369 static enum route_map_cmd_result_t
1370 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1373 uint32_t *prefixlen
= (uint32_t *)rule
;
1374 struct nh_rmap_obj
*nh_data
;
1375 struct prefix_ipv4 p
;
1377 nh_data
= (struct nh_rmap_obj
*)object
;
1378 if (!nh_data
|| !nh_data
->nexthop
)
1379 return RMAP_NOMATCH
;
1381 switch (nh_data
->nexthop
->type
) {
1382 case NEXTHOP_TYPE_IFINDEX
:
1383 /* Interface routes can't match ip next-hop */
1384 return RMAP_NOMATCH
;
1385 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1386 case NEXTHOP_TYPE_IPV4
:
1388 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1389 p
.prefixlen
= IPV4_MAX_BITLEN
;
1391 case NEXTHOP_TYPE_IPV6
:
1392 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1393 case NEXTHOP_TYPE_BLACKHOLE
:
1394 return RMAP_NOMATCH
;
1396 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1399 static const struct route_map_rule_cmd
1400 route_match_ip_nexthop_prefix_len_cmd
= {
1401 "ip next-hop prefix-len",
1402 route_match_ip_nexthop_prefix_len
,
1403 route_match_address_prefix_len_compile
, /* reuse */
1404 route_match_address_prefix_len_free
/* reuse */
1407 /* `match ip next-hop type <blackhole>' */
1409 static enum route_map_cmd_result_t
1410 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1413 struct nh_rmap_obj
*nh_data
;
1415 if (prefix
->family
== AF_INET
) {
1416 nh_data
= (struct nh_rmap_obj
*)object
;
1418 return RMAP_NOMATCH
;
1420 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1424 return RMAP_NOMATCH
;
1427 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1429 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1432 static void route_match_ip_next_hop_type_free(void *rule
)
1434 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1437 static const struct route_map_rule_cmd
1438 route_match_ip_next_hop_type_cmd
= {
1440 route_match_ip_next_hop_type
,
1441 route_match_ip_next_hop_type_compile
,
1442 route_match_ip_next_hop_type_free
1445 /* `match source-protocol PROTOCOL' */
1447 static enum route_map_cmd_result_t
1448 route_match_source_protocol(void *rule
, const struct prefix
*p
, void *object
)
1450 uint32_t *rib_type
= (uint32_t *)rule
;
1451 struct nh_rmap_obj
*nh_data
;
1453 nh_data
= (struct nh_rmap_obj
*)object
;
1455 return RMAP_NOMATCH
;
1457 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1461 static void *route_match_source_protocol_compile(const char *arg
)
1466 i
= proto_name2num(arg
);
1467 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1474 static void route_match_source_protocol_free(void *rule
)
1476 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1479 static const struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1481 route_match_source_protocol
,
1482 route_match_source_protocol_compile
,
1483 route_match_source_protocol_free
1486 /* `source-instance` */
1487 static enum route_map_cmd_result_t
1488 route_match_source_instance(void *rule
, const struct prefix
*p
, void *object
)
1490 uint8_t *instance
= (uint8_t *)rule
;
1491 struct nh_rmap_obj
*nh_data
;
1493 nh_data
= (struct nh_rmap_obj
*)object
;
1495 return RMAP_NOMATCH
;
1497 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1500 static void *route_match_source_instance_compile(const char *arg
)
1506 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1513 static void route_match_source_instance_free(void *rule
)
1515 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1518 static const struct route_map_rule_cmd route_match_source_instance_cmd
= {
1520 route_match_source_instance
,
1521 route_match_source_instance_compile
,
1522 route_match_source_instance_free
1525 /* `set src A.B.C.D' */
1528 static enum route_map_cmd_result_t
1529 route_set_src(void *rule
, const struct prefix
*prefix
, void *object
)
1531 struct nh_rmap_obj
*nh_data
;
1533 nh_data
= (struct nh_rmap_obj
*)object
;
1534 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1539 /* set src compilation. */
1540 static void *route_set_src_compile(const char *arg
)
1542 union g_addr src
, *psrc
;
1544 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1545 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1546 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1553 /* Free route map's compiled `set src' value. */
1554 static void route_set_src_free(void *rule
)
1556 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1559 /* Set src rule structure. */
1560 static const struct route_map_rule_cmd route_set_src_cmd
= {
1563 route_set_src_compile
,
1567 /* The function checks if the changed routemap specified by parameter rmap
1568 * matches the configured protocol routemaps in proto_rm table. If there is
1569 * a match then rib_update_table() to process the routes.
1571 static void zebra_rib_table_rm_update(const char *rmap
)
1574 struct route_table
*table
;
1575 struct vrf
*vrf
= NULL
;
1576 struct zebra_vrf
*zvrf
= NULL
;
1578 struct route_map
*old
= NULL
;
1580 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1584 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1585 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1586 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1587 if (IS_ZEBRA_DEBUG_EVENT
)
1589 "%s : AFI_IP rmap %s, route type %s",
1591 zebra_route_string(i
));
1593 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1595 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1596 route_map_lookup_by_name(rmap_name
);
1597 /* old is NULL. i.e Route map creation event.
1598 * So update applied_counter.
1599 * If Old is not NULL, i.e It may be routemap
1600 * updation or deletion.
1601 * So no need to update the counter.
1604 route_map_counter_increment(
1605 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1606 /* There is single rib table for all protocols
1608 table
= zvrf
->table
[AFI_IP
][SAFI_UNICAST
];
1612 RIB_UPDATE_RMAP_CHANGE
,
1616 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1617 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1618 if (IS_ZEBRA_DEBUG_EVENT
)
1620 "%s : AFI_IP6 rmap %s, route type %s",
1622 zebra_route_string(i
));
1624 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1626 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1627 route_map_lookup_by_name(rmap_name
);
1629 route_map_counter_increment(
1630 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1631 /* There is single rib table for all protocols
1633 table
= zvrf
->table
[AFI_IP6
][SAFI_UNICAST
];
1637 RIB_UPDATE_RMAP_CHANGE
,
1645 /* The function checks if the changed routemap specified by parameter rmap
1646 * matches the configured protocol routemaps in nht_rm table. If there is
1647 * a match then zebra_evaluate_rnh() to process the nexthops.
1649 static void zebra_nht_rm_update(const char *rmap
)
1652 struct route_table
*table
;
1653 struct vrf
*vrf
= NULL
;
1654 struct zebra_vrf
*zvrf
= NULL
;
1658 struct route_map
*old
= NULL
;
1660 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1664 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1665 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1666 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1667 if (IS_ZEBRA_DEBUG_EVENT
)
1669 "%s : AFI_IP rmap %s, route type %s",
1671 zebra_route_string(i
));
1673 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1675 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1676 route_map_lookup_by_name(rmap_name
);
1678 route_map_counter_increment(
1679 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1680 /* There is single rib table for all protocols
1683 table
= zvrf
->table
[AFI_IP
]
1690 zvrf
, AFI_IP
, 1, NULL
,
1696 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1697 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1698 if (IS_ZEBRA_DEBUG_EVENT
)
1700 "%s : AFI_IP6 rmap %s, route type %s",
1702 zebra_route_string(i
));
1704 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1706 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1707 route_map_lookup_by_name(rmap_name
);
1709 route_map_counter_increment(
1710 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1711 /* There is single rib table for all protocols
1713 if (afi_ipv6
== 0) {
1714 table
= zvrf
->table
[AFI_IP6
]
1721 zvrf
, AFI_IP
, 1, NULL
,
1730 static void zebra_route_map_process_update_cb(char *rmap_name
)
1732 if (IS_ZEBRA_DEBUG_EVENT
)
1733 zlog_debug("Event handler for route-map: %s",
1735 zebra_import_table_rm_update(rmap_name
);
1736 zebra_rib_table_rm_update(rmap_name
);
1737 zebra_nht_rm_update(rmap_name
);
1740 static void zebra_route_map_update_timer(struct thread
*thread
)
1742 if (IS_ZEBRA_DEBUG_EVENT
)
1743 zlog_debug("Event driven route-map update triggered");
1745 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1747 "%u: Routemap update-timer fired, scheduling RIB processing",
1750 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1753 * This code needs to be updated to be:
1754 * 1) VRF Aware <sigh>
1755 * 2) Route-map aware
1759 static void zebra_route_map_set_delay_timer(uint32_t value
)
1761 zebra_rmap_update_timer
= value
;
1762 if (!value
&& zebra_t_rmap_update
) {
1763 /* Event driven route map updates is being disabled */
1764 /* But there's a pending timer. Fire it off now */
1765 THREAD_OFF(zebra_t_rmap_update
);
1766 zebra_route_map_update_timer(NULL
);
1770 void zebra_routemap_finish(void)
1772 /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
1773 zebra_rmap_update_timer
= 0;
1774 /* Thread off if any scheduled already */
1775 THREAD_OFF(zebra_t_rmap_update
);
1780 zebra_route_map_check(afi_t family
, int rib_type
, uint8_t instance
,
1781 const struct prefix
*p
, struct nexthop
*nexthop
,
1782 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1784 struct route_map
*rmap
= NULL
;
1786 route_map_result_t ret
= RMAP_PERMITMATCH
;
1787 struct nh_rmap_obj nh_obj
;
1789 nh_obj
.nexthop
= nexthop
;
1790 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1791 nh_obj
.source_protocol
= rib_type
;
1792 nh_obj
.instance
= instance
;
1796 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
) {
1797 rm_name
= PROTO_RM_NAME(zvrf
, family
, rib_type
);
1798 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1800 if (rm_name
&& !rmap
)
1801 return RMAP_DENYMATCH
;
1804 rm_name
= PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1805 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1807 if (rm_name
&& !rmap
)
1808 return RMAP_DENYMATCH
;
1811 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1817 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1819 return zebra_import_table_routemap
[afi
][table
];
1822 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1825 zebra_import_table_routemap
[afi
][table
] =
1826 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1829 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1831 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1835 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1836 const struct prefix
*p
,
1837 struct nexthop
*nexthop
,
1838 vrf_id_t vrf_id
, route_tag_t tag
,
1839 const char *rmap_name
)
1841 struct route_map
*rmap
= NULL
;
1842 route_map_result_t ret
= RMAP_DENYMATCH
;
1843 struct nh_rmap_obj nh_obj
;
1845 nh_obj
.nexthop
= nexthop
;
1846 nh_obj
.vrf_id
= vrf_id
;
1847 nh_obj
.source_protocol
= re_type
;
1848 nh_obj
.instance
= instance
;
1852 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1853 rmap
= route_map_lookup_by_name(rmap_name
);
1855 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1861 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1862 const struct prefix
*p
,
1863 struct zebra_vrf
*zvrf
,
1864 struct route_entry
*re
,
1865 struct nexthop
*nexthop
)
1867 struct route_map
*rmap
= NULL
;
1868 route_map_result_t ret
= RMAP_PERMITMATCH
;
1869 struct nh_rmap_obj nh_obj
;
1871 nh_obj
.nexthop
= nexthop
;
1872 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1873 nh_obj
.source_protocol
= re
->type
;
1874 nh_obj
.instance
= re
->instance
;
1875 nh_obj
.metric
= re
->metric
;
1876 nh_obj
.tag
= re
->tag
;
1878 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1879 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1880 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1881 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1883 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1888 static void zebra_route_map_mark_update(const char *rmap_name
)
1890 /* rmap_update_timer of 0 means don't do route updates */
1891 if (zebra_rmap_update_timer
)
1892 THREAD_OFF(zebra_t_rmap_update
);
1894 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1895 NULL
, zebra_rmap_update_timer
, &zebra_t_rmap_update
);
1898 static void zebra_route_map_add(const char *rmap_name
)
1900 if (route_map_mark_updated(rmap_name
) == 0)
1901 zebra_route_map_mark_update(rmap_name
);
1903 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1906 static void zebra_route_map_delete(const char *rmap_name
)
1908 if (route_map_mark_updated(rmap_name
) == 0)
1909 zebra_route_map_mark_update(rmap_name
);
1911 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1914 static void zebra_route_map_event(const char *rmap_name
)
1916 if (route_map_mark_updated(rmap_name
) == 0)
1917 zebra_route_map_mark_update(rmap_name
);
1919 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1922 void zebra_routemap_vrf_delete(struct zebra_vrf
*zvrf
)
1927 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1928 for (type
= 0; type
<= ZEBRA_ROUTE_MAX
; type
++) {
1929 if (PROTO_RM_NAME(zvrf
, afi
, type
))
1930 XFREE(MTYPE_ROUTE_MAP_NAME
,
1931 PROTO_RM_NAME(zvrf
, afi
, type
));
1932 if (NHT_RM_NAME(zvrf
, afi
, type
))
1933 XFREE(MTYPE_ROUTE_MAP_NAME
,
1934 NHT_RM_NAME(zvrf
, afi
, type
));
1939 /* ip protocol configuration write function */
1940 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1941 struct zebra_vrf
*zvrf
)
1946 memset(space
, 0, sizeof(space
));
1948 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1949 snprintf(space
, sizeof(space
), "%s", " ");
1951 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1952 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1953 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1954 zebra_route_string(i
),
1955 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1957 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1958 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1959 zebra_route_string(i
),
1960 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1962 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1963 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1964 zebra_route_string(i
),
1965 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1967 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1968 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1969 zebra_route_string(i
),
1970 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1973 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1974 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1975 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1977 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1978 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1979 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1981 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1982 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1983 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1985 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1986 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1987 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1989 if (zvrf_id(zvrf
) == VRF_DEFAULT
1990 && zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1991 vty_out(vty
, "zebra route-map delay-timer %d\n",
1992 zebra_rmap_update_timer
);
1995 void zebra_route_map_init(void)
1997 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1998 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1999 install_element(VRF_NODE
, &ip_protocol_cmd
);
2000 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
2001 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
2002 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
2003 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
2004 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
2005 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
2006 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
2007 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
2008 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
2009 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
2010 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
2011 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
2012 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
2013 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
2014 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
2015 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
2016 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
2017 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
2018 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
2022 route_map_add_hook(zebra_route_map_add
);
2023 route_map_delete_hook(zebra_route_map_delete
);
2024 route_map_event_hook(zebra_route_map_event
);
2026 route_map_match_interface_hook(generic_match_add
);
2027 route_map_no_match_interface_hook(generic_match_delete
);
2029 route_map_match_ip_address_hook(generic_match_add
);
2030 route_map_no_match_ip_address_hook(generic_match_delete
);
2032 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
2033 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
2035 route_map_match_ip_next_hop_hook(generic_match_add
);
2036 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
2038 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
2039 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
2041 route_map_match_ip_next_hop_type_hook(generic_match_add
);
2042 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
2044 route_map_match_tag_hook(generic_match_add
);
2045 route_map_no_match_tag_hook(generic_match_delete
);
2047 route_map_match_ipv6_address_hook(generic_match_add
);
2048 route_map_no_match_ipv6_address_hook(generic_match_delete
);
2050 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
2051 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
2053 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
2054 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
2056 route_map_install_match(&route_match_tag_cmd
);
2057 route_map_install_match(&route_match_interface_cmd
);
2058 route_map_install_match(&route_match_ip_next_hop_cmd
);
2059 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
2060 route_map_install_match(&route_match_ip_address_cmd
);
2061 route_map_install_match(&route_match_ipv6_address_cmd
);
2062 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
2063 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
2064 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
2065 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
2066 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
2067 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
2068 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
2069 route_map_install_match(&route_match_source_protocol_cmd
);
2070 route_map_install_match(&route_match_source_instance_cmd
);
2073 route_map_install_set(&route_set_src_cmd
);
2075 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
2076 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
2077 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
2078 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
2079 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
2080 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
2081 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
2082 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
2083 install_element(RMAP_NODE
, &match_source_instance_cmd
);
2084 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
2087 install_element(RMAP_NODE
, &set_src_cmd
);
2088 install_element(RMAP_NODE
, &no_set_src_cmd
);