1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2006 IBM Corporation
17 #include "northbound_cli.h"
18 #include "lib/route_types.h"
22 #include "zebra/zebra_router.h"
23 #include "zebra/redistribute.h"
24 #include "zebra/debug.h"
25 #include "zebra/zebra_rnh.h"
26 #include "zebra/zebra_routemap.h"
28 #include "zebra/zebra_routemap_clippy.c"
30 static uint32_t zebra_rmap_update_timer
= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
;
31 static struct thread
*zebra_t_rmap_update
= NULL
;
32 char *zebra_import_table_routemap
[AFI_MAX
][ZEBRA_KERNEL_TABLE_MAX
];
35 struct nexthop
*nexthop
;
37 uint32_t source_protocol
;
43 static void zebra_route_map_set_delay_timer(uint32_t value
);
46 * Match function return 1 if match is success else return 0
48 static enum route_map_cmd_result_t
49 route_match_tag(void *rule
, const struct prefix
*prefix
, void *object
)
52 struct nh_rmap_obj
*nh_data
;
57 if (nh_data
->tag
== *tag
)
63 /* Route map commands for tag matching */
64 static const struct route_map_rule_cmd route_match_tag_cmd
= {
67 route_map_rule_tag_compile
,
68 route_map_rule_tag_free
,
72 /* `match interface IFNAME' */
73 /* Match function return 1 if match is success else return zero. */
74 static enum route_map_cmd_result_t
75 route_match_interface(void *rule
, const struct prefix
*prefix
, void *object
)
77 struct nh_rmap_obj
*nh_data
;
81 if (strcasecmp(ifname
, "any") == 0)
84 if (!nh_data
|| !nh_data
->nexthop
)
86 ifindex
= ifname2ifindex(ifname
, nh_data
->vrf_id
);
89 if (nh_data
->nexthop
->ifindex
== ifindex
)
95 /* Route map `match interface' match statement. `arg' is IFNAME value */
96 static void *route_match_interface_compile(const char *arg
)
98 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
101 /* Free route map's compiled `match interface' value. */
102 static void route_match_interface_free(void *rule
)
104 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
107 static void show_vrf_proto_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
112 vty_out(vty
, "Protocol : route-map\n");
113 vty_out(vty
, "-------------------------------------\n");
115 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
116 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
117 vty_out(vty
, "%-24s : %-10s\n", zebra_route_string(i
),
118 PROTO_RM_NAME(zvrf
, af_type
, i
));
120 vty_out(vty
, "%-24s : none\n", zebra_route_string(i
));
123 if (PROTO_RM_NAME(zvrf
, af_type
, i
))
124 vty_out(vty
, "%-24s : %-10s\n", "any",
125 PROTO_RM_NAME(zvrf
, af_type
, i
));
127 vty_out(vty
, "%-24s : none\n", "any");
130 static void show_vrf_nht_rm(struct vty
*vty
, struct zebra_vrf
*zvrf
,
131 int af_type
, json_object
*json
)
136 vty_out(vty
, "Protocol : route-map\n");
137 vty_out(vty
, "-------------------------------------\n");
140 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
142 if (NHT_RM_NAME(zvrf
, af_type
, i
))
143 json_object_string_add(
144 json
, zebra_route_string(i
),
145 NHT_RM_NAME(zvrf
, af_type
, i
));
147 json_object_string_add(
148 json
, zebra_route_string(i
), "none");
150 if (NHT_RM_NAME(zvrf
, af_type
, i
))
151 vty_out(vty
, "%-24s : %-10s\n",
152 zebra_route_string(i
),
153 NHT_RM_NAME(zvrf
, af_type
, i
));
155 vty_out(vty
, "%-24s : none\n",
156 zebra_route_string(i
));
161 if (NHT_RM_NAME(zvrf
, af_type
, i
))
162 json_object_string_add(json
, "any",
163 NHT_RM_NAME(zvrf
, af_type
, i
));
165 json_object_string_add(json
, "any", "none");
167 if (NHT_RM_NAME(zvrf
, af_type
, i
))
168 vty_out(vty
, "%-24s : %-10s\n", "any",
169 NHT_RM_NAME(zvrf
, af_type
, i
));
171 vty_out(vty
, "%-24s : none\n", "any");
175 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
176 const char *vrf_name
)
178 struct zebra_vrf
*zvrf
;
183 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
184 zvrf
= (struct zebra_vrf
*)vrf
->info
;
187 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
188 show_vrf_proto_rm(vty
, zvrf
, af_type
);
191 vrf_id_t vrf_id
= VRF_DEFAULT
;
194 VRF_GET_ID(vrf_id
, vrf_name
, false);
196 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
200 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
201 show_vrf_proto_rm(vty
, zvrf
, af_type
);
207 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
208 const char *vrf_name
, bool use_json
)
210 struct zebra_vrf
*zvrf
;
211 json_object
*json
= NULL
;
212 json_object
*json_vrfs
= NULL
;
215 json
= json_object_new_object();
216 json_vrfs
= json_object_new_object();
217 json_object_string_add(json
, "afi",
218 (af_type
== AFI_IP
) ? "ipv4" : "ipv6");
225 json_object_object_add(json
, "vrfs", json_vrfs
);
227 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
228 zvrf
= (struct zebra_vrf
*)vrf
->info
;
233 json_object
*json_proto
= NULL
;
234 json_object
*json_vrf
= NULL
;
235 json_vrf
= json_object_new_object();
236 json_object_object_add(
237 json_vrfs
, zvrf
->vrf
->name
, json_vrf
);
238 json_proto
= json_object_new_object();
239 json_object_object_add(json_vrf
, "protocols",
241 show_vrf_nht_rm(vty
, zvrf
, af_type
, json_proto
);
243 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
244 show_vrf_nht_rm(vty
, zvrf
, af_type
, NULL
);
248 json_object
*json_proto
= NULL
;
249 json_object
*json_vrf
= NULL
;
250 vrf_id_t vrf_id
= VRF_DEFAULT
;
253 VRF_GET_ID(vrf_id
, vrf_name
, false);
255 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
257 json_object_free(json
);
258 json_object_free(json_vrfs
);
263 json_object_object_add(json
, "vrfs", json_vrfs
);
264 json_vrf
= json_object_new_object();
265 json_object_object_add(json_vrfs
, zvrf
->vrf
->name
,
267 json_proto
= json_object_new_object();
268 json_object_object_add(json_vrf
, "protocols",
270 show_vrf_nht_rm(vty
, zvrf
, af_type
, json_proto
);
272 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
273 show_vrf_nht_rm(vty
, zvrf
, af_type
, NULL
);
283 /* Route map commands for interface matching */
284 static const struct route_map_rule_cmd route_match_interface_cmd
= {
286 route_match_interface
,
287 route_match_interface_compile
,
288 route_match_interface_free
291 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
292 int rtype
, afi_t afi
, safi_t safi
)
294 struct route_table
*table
;
296 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
297 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
300 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
302 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
303 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
304 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
305 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
306 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
308 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
310 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
312 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
313 zvrf
->vrf
->vrf_id
, rtype
);
314 /* Process routes of interested address-families. */
315 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
317 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
324 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
325 int rtype
, afi_t afi
, safi_t safi
)
327 struct route_table
*table
;
329 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
332 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
334 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
335 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
336 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
338 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
339 zvrf
->vrf
->vrf_id
, rtype
);
340 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
342 /* Process routes of interested address-families. */
343 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
345 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
348 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
353 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
357 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
358 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
361 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
363 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
364 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
365 NHT_RM_MAP(zvrf
, afi
, rtype
) =
366 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
367 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
369 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
370 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
375 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
379 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
382 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
383 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
384 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
385 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
387 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
388 zvrf
->vrf
->vrf_id
, rtype
);
389 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
391 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
393 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
399 match_ip_address_prefix_len
, match_ip_address_prefix_len_cmd
,
400 "match ip address prefix-len (0-32)$length",
403 "Match prefix length of IP address\n"
404 "Match prefix length of IP address\n"
408 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
409 char xpath_value
[XPATH_MAXLEN
];
411 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
413 xpath_value
, sizeof(xpath_value
),
414 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
416 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
418 return nb_cli_apply_changes(vty
, NULL
);
422 no_match_ip_address_prefix_len
, no_match_ip_address_prefix_len_cmd
,
423 "no match ip address prefix-len [(0-32)]",
427 "Match prefix length of IP address\n"
428 "Match prefix length of IP address\n"
432 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
434 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
436 return nb_cli_apply_changes(vty
, NULL
);
440 match_ipv6_address_prefix_len
, match_ipv6_address_prefix_len_cmd
,
441 "match ipv6 address prefix-len (0-128)$length",
444 "Match prefix length of IPv6 address\n"
445 "Match prefix length of IPv6 address\n"
449 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
450 char xpath_value
[XPATH_MAXLEN
];
452 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
454 xpath_value
, sizeof(xpath_value
),
455 "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
457 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
459 return nb_cli_apply_changes(vty
, NULL
);
463 no_match_ipv6_address_prefix_len
, no_match_ipv6_address_prefix_len_cmd
,
464 "no match ipv6 address prefix-len [(0-128)]",
468 "Match prefix length of IPv6 address\n"
469 "Match prefix length of IPv6 address\n"
473 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
475 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
477 return nb_cli_apply_changes(vty
, NULL
);
481 match_ip_nexthop_prefix_len
, match_ip_nexthop_prefix_len_cmd
,
482 "match ip next-hop prefix-len (0-32)$length",
485 "Match prefixlen of nexthop IP address\n"
486 "Match prefixlen of given nexthop\n"
490 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
491 char xpath_value
[XPATH_MAXLEN
];
493 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
495 xpath_value
, sizeof(xpath_value
),
496 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
498 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
500 return nb_cli_apply_changes(vty
, NULL
);
504 no_match_ip_nexthop_prefix_len
, no_match_ip_nexthop_prefix_len_cmd
,
505 "no match ip next-hop prefix-len [(0-32)]",
509 "Match prefixlen of nexthop IP address\n"
510 "Match prefix length of nexthop\n"
514 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
516 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
518 return nb_cli_apply_changes(vty
, NULL
);
522 match_source_protocol
, match_source_protocol_cmd
,
523 "match source-protocol " FRR_REDIST_STR_ZEBRA
"$proto",
525 "Match protocol via which the route was learnt\n"
526 FRR_REDIST_HELP_STR_ZEBRA
)
529 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
530 char xpath_value
[XPATH_MAXLEN
];
532 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
533 snprintf(xpath_value
, sizeof(xpath_value
),
534 "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
536 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, proto
);
538 return nb_cli_apply_changes(vty
, NULL
);
542 no_match_source_protocol
, no_match_source_protocol_cmd
,
543 "no match source-protocol [" FRR_REDIST_STR_ZEBRA
"]",
546 "Match protocol via which the route was learnt\n"
547 FRR_REDIST_HELP_STR_ZEBRA
)
550 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
552 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
554 return nb_cli_apply_changes(vty
, NULL
);
558 match_source_instance
, match_source_instance_cmd
,
559 "match source-instance (0-255)$instance",
561 "Match the protocol's instance number\n"
562 "The instance number\n")
565 "./match-condition[condition='frr-zebra-route-map:source-instance']";
566 char xpath_value
[XPATH_MAXLEN
];
568 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
569 snprintf(xpath_value
, sizeof(xpath_value
),
570 "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
572 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, instance_str
);
574 return nb_cli_apply_changes(vty
, NULL
);
578 no_match_source_instance
, no_match_source_instance_cmd
,
579 "no match source-instance [(0-255)]",
581 "Match the protocol's instance number\n"
582 "The instance number\n")
585 "./match-condition[condition='frr-zebra-route-map:source-instance']";
587 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
589 return nb_cli_apply_changes(vty
, NULL
);
595 set_src
, set_src_cmd
,
596 "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
598 "src address for route\n"
600 "IPv6 src address\n")
603 "./set-action[action='frr-zebra-route-map:src-address']";
604 char xpath_value
[XPATH_MAXLEN
];
606 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
609 xpath_value
, sizeof(xpath_value
),
610 "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
612 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
616 xpath_value
, sizeof(xpath_value
),
617 "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
619 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
623 return nb_cli_apply_changes(vty
, NULL
);
627 no_set_src
, no_set_src_cmd
,
628 "no set src [<A.B.C.D|X:X::X:X>]",
631 "Source address for route\n"
636 "./set-action[action='frr-zebra-route-map:src-address']";
638 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
640 return nb_cli_apply_changes(vty
, NULL
);
643 DEFUN_YANG (zebra_route_map_timer
,
644 zebra_route_map_timer_cmd
,
645 "zebra route-map delay-timer (0-600)",
647 "Set route-map parameters\n"
648 "Time to wait before route-map updates are processed\n"
649 "0 means route-map changes are run immediately instead of delaying\n")
652 uint32_t rmap_delay_timer
;
654 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
655 zebra_route_map_set_delay_timer(rmap_delay_timer
);
657 return (CMD_SUCCESS
);
660 DEFUN_YANG (no_zebra_route_map_timer
,
661 no_zebra_route_map_timer_cmd
,
662 "no zebra route-map delay-timer [(0-600)]",
665 "Set route-map parameters\n"
666 "Reset delay-timer to default value, 30 secs\n"
667 "0 means route-map changes are run immediately instead of delaying\n")
669 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
671 return (CMD_SUCCESS
);
674 DEFPY_YANG (ip_protocol
,
676 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
677 " $proto route-map ROUTE-MAP$rmap",
679 "Filter routing info exchanged between zebra and protocol\n"
680 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
681 "Specify route-map\n"
689 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
694 if (strcasecmp(proto
, "any") == 0)
695 rtype
= ZEBRA_ROUTE_MAX
;
697 rtype
= proto_name2num(proto
);
699 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
700 return CMD_WARNING_CONFIG_FAILED
;
703 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
708 DEFPY_YANG (no_ip_protocol
,
710 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
711 " $proto [route-map ROUTE-MAP$rmap]",
714 "Stop filtering routing info between zebra and protocol\n"
715 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
716 "Specify route-map\n"
723 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
728 if (strcasecmp(proto
, "any") == 0)
729 rtype
= ZEBRA_ROUTE_MAX
;
731 rtype
= proto_name2num(proto
);
733 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
734 return CMD_WARNING_CONFIG_FAILED
;
737 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
742 DEFPY_YANG (show_ip_protocol
,
743 show_ip_protocol_cmd
,
744 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
747 "IP protocol filtering status\n"
748 VRF_FULL_CMD_HELP_STR
)
750 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
755 DEFPY_YANG (ipv6_protocol
,
757 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
758 " $proto route-map ROUTE-MAP$rmap",
760 "Filter IPv6 routing info exchanged between zebra and protocol\n"
761 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
762 "Specify route-map\n"
770 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
775 if (strcasecmp(proto
, "any") == 0)
776 rtype
= ZEBRA_ROUTE_MAX
;
778 rtype
= proto_name2num(proto
);
780 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
781 return CMD_WARNING_CONFIG_FAILED
;
784 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
789 DEFPY_YANG (no_ipv6_protocol
,
790 no_ipv6_protocol_cmd
,
791 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
792 " $proto [route-map ROUTE-MAP$rmap]",
795 "Stop filtering IPv6 routing info between zebra and protocol\n"
796 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
797 "Specify route-map\n"
804 ZEBRA_DECLVAR_CONTEXT_VRF(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_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
823 DEFPY_YANG (show_ipv6_protocol
,
824 show_ipv6_protocol_cmd
,
825 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
828 "IPv6 protocol filtering status\n"
829 VRF_FULL_CMD_HELP_STR
)
831 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
836 DEFPY_YANG (ip_protocol_nht_rmap
,
837 ip_protocol_nht_rmap_cmd
,
838 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
839 " $proto route-map ROUTE-MAP$rmap",
841 "Filter Next Hop tracking route resolution\n"
842 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
843 "Specify route map\n"
852 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
857 if (strcasecmp(proto
, "any") == 0)
858 rtype
= ZEBRA_ROUTE_MAX
;
860 rtype
= proto_name2num(proto
);
862 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
863 return CMD_WARNING_CONFIG_FAILED
;
866 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
871 DEFPY_YANG (no_ip_protocol_nht_rmap
,
872 no_ip_protocol_nht_rmap_cmd
,
873 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
874 " $proto route-map [ROUTE-MAP$rmap]",
877 "Filter Next Hop tracking route resolution\n"
878 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
879 "Specify route map\n"
886 ZEBRA_DECLVAR_CONTEXT_VRF(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_del(zvrf
, rmap
, rtype
, AFI_IP
);
905 DEFPY_YANG (show_ip_protocol_nht
,
906 show_ip_protocol_nht_cmd
,
907 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
910 "IPv4 nexthop tracking table\n"
911 "IPv4 Next Hop tracking filtering status\n"
917 bool uj
= use_json(argc
, argv
);
919 ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
, uj
);
924 DEFPY_YANG (ipv6_protocol_nht_rmap
,
925 ipv6_protocol_nht_rmap_cmd
,
926 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
927 " $proto route-map ROUTE-MAP$rmap",
929 "Filter Next Hop tracking route resolution\n"
930 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
931 "Specify route map\n"
939 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
944 if (strcasecmp(proto
, "any") == 0)
945 rtype
= ZEBRA_ROUTE_MAX
;
947 rtype
= proto_name2num(proto
);
949 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
950 return CMD_WARNING_CONFIG_FAILED
;
953 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
958 DEFPY_YANG (no_ipv6_protocol_nht_rmap
,
959 no_ipv6_protocol_nht_rmap_cmd
,
960 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
961 " $proto [route-map ROUTE-MAP$rmap]",
964 "Filter Next Hop tracking route resolution\n"
965 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
966 "Specify route map\n"
973 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
978 if (strcasecmp(proto
, "any") == 0)
979 rtype
= ZEBRA_ROUTE_MAX
;
981 rtype
= proto_name2num(proto
);
983 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
984 return CMD_WARNING_CONFIG_FAILED
;
987 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
992 DEFPY_YANG (show_ipv6_protocol_nht
,
993 show_ipv6_protocol_nht_cmd
,
994 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
997 "IPv6 nexthop tracking table\n"
998 "IPv6 Next Hop tracking filtering status\n"
1004 bool uj
= use_json(argc
, argv
);
1006 ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
, uj
);
1011 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1013 /* `match ip next-hop IP_ACCESS_LIST' */
1015 /* Match function return 1 if match is success else return zero. */
1016 static enum route_map_cmd_result_t
1017 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
, void *object
)
1019 struct access_list
*alist
;
1020 struct nh_rmap_obj
*nh_data
;
1021 struct prefix_ipv4 p
;
1025 return RMAP_NOMATCH
;
1027 switch (nh_data
->nexthop
->type
) {
1028 case NEXTHOP_TYPE_IFINDEX
:
1029 /* Interface routes can't match ip next-hop */
1030 return RMAP_NOMATCH
;
1031 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1032 case NEXTHOP_TYPE_IPV4
:
1034 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1035 p
.prefixlen
= IPV4_MAX_BITLEN
;
1037 case NEXTHOP_TYPE_IPV6
:
1038 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1039 case NEXTHOP_TYPE_BLACKHOLE
:
1040 return RMAP_NOMATCH
;
1042 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
1043 if (alist
== NULL
) {
1044 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1046 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
1047 __func__
, (char *)rule
);
1048 return RMAP_NOMATCH
;
1051 return (access_list_apply(alist
, &p
) == FILTER_DENY
? RMAP_NOMATCH
1055 /* Route map `ip next-hop' match statement. `arg' should be
1056 access-list name. */
1057 static void *route_match_ip_next_hop_compile(const char *arg
)
1059 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1062 /* Free route map's compiled `. */
1063 static void route_match_ip_next_hop_free(void *rule
)
1065 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1068 /* Route map commands for ip next-hop matching. */
1069 static const struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1071 route_match_ip_next_hop
,
1072 route_match_ip_next_hop_compile
,
1073 route_match_ip_next_hop_free
1076 /* `match ip next-hop prefix-list PREFIX_LIST' */
1078 static enum route_map_cmd_result_t
1079 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1082 struct prefix_list
*plist
;
1083 struct nh_rmap_obj
*nh_data
;
1084 struct prefix_ipv4 p
;
1086 nh_data
= (struct nh_rmap_obj
*)object
;
1088 return RMAP_NOMATCH
;
1090 switch (nh_data
->nexthop
->type
) {
1091 case NEXTHOP_TYPE_IFINDEX
:
1092 /* Interface routes can't match ip next-hop */
1093 return RMAP_NOMATCH
;
1094 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1095 case NEXTHOP_TYPE_IPV4
:
1097 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1098 p
.prefixlen
= IPV4_MAX_BITLEN
;
1100 case NEXTHOP_TYPE_IPV6
:
1101 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1102 case NEXTHOP_TYPE_BLACKHOLE
:
1103 return RMAP_NOMATCH
;
1105 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1106 if (plist
== NULL
) {
1107 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1109 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
1110 __func__
, (char *)rule
);
1111 return RMAP_NOMATCH
;
1114 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
? RMAP_NOMATCH
1118 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1120 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1123 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1125 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1128 static const struct route_map_rule_cmd
1129 route_match_ip_next_hop_prefix_list_cmd
= {
1130 "ip next-hop prefix-list",
1131 route_match_ip_next_hop_prefix_list
,
1132 route_match_ip_next_hop_prefix_list_compile
,
1133 route_match_ip_next_hop_prefix_list_free
1136 /* `match ip address IP_ACCESS_LIST' */
1138 /* Match function should return 1 if match is success else return
1140 static enum route_map_cmd_result_t
1141 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1144 struct access_list
*alist
;
1146 alist
= access_list_lookup(afi
, (char *)rule
);
1147 if (alist
== NULL
) {
1148 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1150 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
1151 __func__
, (char *)rule
);
1152 return RMAP_NOMATCH
;
1155 return (access_list_apply(alist
, prefix
) == FILTER_DENY
? RMAP_NOMATCH
1159 static enum route_map_cmd_result_t
1160 route_match_ip_address(void *rule
, const struct prefix
*prefix
, void *object
)
1162 return route_match_address(AFI_IP
, rule
, prefix
, object
);
1165 static enum route_map_cmd_result_t
1166 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
, void *object
)
1168 return route_match_address(AFI_IP6
, rule
, prefix
, object
);
1171 /* Route map `ip address' match statement. `arg' should be
1172 access-list name. */
1173 static void *route_match_address_compile(const char *arg
)
1175 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1178 /* Free route map's compiled `ip address' value. */
1179 static void route_match_address_free(void *rule
)
1181 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1184 /* Route map commands for ip address matching. */
1185 static const struct route_map_rule_cmd route_match_ip_address_cmd
= {
1187 route_match_ip_address
,
1188 route_match_address_compile
,
1189 route_match_address_free
1192 /* Route map commands for ipv6 address matching. */
1193 static const struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1195 route_match_ipv6_address
,
1196 route_match_address_compile
,
1197 route_match_address_free
1200 /* `match ip address prefix-list PREFIX_LIST' */
1202 static enum route_map_cmd_result_t
1203 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1204 void *object
, afi_t afi
)
1206 struct prefix_list
*plist
;
1208 plist
= prefix_list_lookup(afi
, (char *)rule
);
1209 if (plist
== NULL
) {
1210 if (CHECK_FLAG(rmap_debug
, DEBUG_ROUTEMAP_DETAIL
))
1212 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
1213 __func__
, (char *)rule
);
1214 return RMAP_NOMATCH
;
1217 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
1221 static enum route_map_cmd_result_t
1222 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1225 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP
));
1228 static void *route_match_address_prefix_list_compile(const char *arg
)
1230 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1233 static void route_match_address_prefix_list_free(void *rule
)
1235 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1238 static const struct route_map_rule_cmd
1239 route_match_ip_address_prefix_list_cmd
= {
1240 "ip address prefix-list",
1241 route_match_ip_address_prefix_list
,
1242 route_match_address_prefix_list_compile
,
1243 route_match_address_prefix_list_free
1246 static enum route_map_cmd_result_t
1247 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1250 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP6
));
1253 static const struct route_map_rule_cmd
1254 route_match_ipv6_address_prefix_list_cmd
= {
1255 "ipv6 address prefix-list",
1256 route_match_ipv6_address_prefix_list
,
1257 route_match_address_prefix_list_compile
,
1258 route_match_address_prefix_list_free
1261 /* `match ipv6 next-hop type <TYPE>' */
1263 static enum route_map_cmd_result_t
1264 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1267 struct nh_rmap_obj
*nh_data
;
1269 if (prefix
->family
== AF_INET6
) {
1270 nh_data
= (struct nh_rmap_obj
*)object
;
1272 return RMAP_NOMATCH
;
1274 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1278 return RMAP_NOMATCH
;
1281 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1283 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1286 static void route_match_ipv6_next_hop_type_free(void *rule
)
1288 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1291 static const struct route_map_rule_cmd
1292 route_match_ipv6_next_hop_type_cmd
= {
1293 "ipv6 next-hop type",
1294 route_match_ipv6_next_hop_type
,
1295 route_match_ipv6_next_hop_type_compile
,
1296 route_match_ipv6_next_hop_type_free
1299 /* `match ip address prefix-len PREFIXLEN' */
1301 static enum route_map_cmd_result_t
1302 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1305 uint32_t *prefixlen
= (uint32_t *)rule
;
1307 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1310 static void *route_match_address_prefix_len_compile(const char *arg
)
1312 uint32_t *prefix_len
;
1313 char *endptr
= NULL
;
1314 unsigned long tmpval
;
1316 /* prefix len value shoud be integer. */
1317 if (!all_digit(arg
))
1321 tmpval
= strtoul(arg
, &endptr
, 10);
1322 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1325 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1327 *prefix_len
= tmpval
;
1331 static void route_match_address_prefix_len_free(void *rule
)
1333 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1336 static const struct route_map_rule_cmd
1337 route_match_ip_address_prefix_len_cmd
= {
1338 "ip address prefix-len",
1339 route_match_address_prefix_len
,
1340 route_match_address_prefix_len_compile
,
1341 route_match_address_prefix_len_free
1344 static const struct route_map_rule_cmd
1345 route_match_ipv6_address_prefix_len_cmd
= {
1346 "ipv6 address prefix-len",
1347 route_match_address_prefix_len
,
1348 route_match_address_prefix_len_compile
,
1349 route_match_address_prefix_len_free
1352 /* `match ip nexthop prefix-len PREFIXLEN' */
1354 static enum route_map_cmd_result_t
1355 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1358 uint32_t *prefixlen
= (uint32_t *)rule
;
1359 struct nh_rmap_obj
*nh_data
;
1360 struct prefix_ipv4 p
;
1362 nh_data
= (struct nh_rmap_obj
*)object
;
1363 if (!nh_data
|| !nh_data
->nexthop
)
1364 return RMAP_NOMATCH
;
1366 switch (nh_data
->nexthop
->type
) {
1367 case NEXTHOP_TYPE_IFINDEX
:
1368 /* Interface routes can't match ip next-hop */
1369 return RMAP_NOMATCH
;
1370 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1371 case NEXTHOP_TYPE_IPV4
:
1373 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1374 p
.prefixlen
= IPV4_MAX_BITLEN
;
1376 case NEXTHOP_TYPE_IPV6
:
1377 case NEXTHOP_TYPE_IPV6_IFINDEX
:
1378 case NEXTHOP_TYPE_BLACKHOLE
:
1379 return RMAP_NOMATCH
;
1381 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1384 static const struct route_map_rule_cmd
1385 route_match_ip_nexthop_prefix_len_cmd
= {
1386 "ip next-hop prefix-len",
1387 route_match_ip_nexthop_prefix_len
,
1388 route_match_address_prefix_len_compile
, /* reuse */
1389 route_match_address_prefix_len_free
/* reuse */
1392 /* `match ip next-hop type <blackhole>' */
1394 static enum route_map_cmd_result_t
1395 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1398 struct nh_rmap_obj
*nh_data
;
1400 if (prefix
->family
== AF_INET
) {
1401 nh_data
= (struct nh_rmap_obj
*)object
;
1403 return RMAP_NOMATCH
;
1405 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1409 return RMAP_NOMATCH
;
1412 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1414 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1417 static void route_match_ip_next_hop_type_free(void *rule
)
1419 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1422 static const struct route_map_rule_cmd
1423 route_match_ip_next_hop_type_cmd
= {
1425 route_match_ip_next_hop_type
,
1426 route_match_ip_next_hop_type_compile
,
1427 route_match_ip_next_hop_type_free
1430 /* `match source-protocol PROTOCOL' */
1432 static enum route_map_cmd_result_t
1433 route_match_source_protocol(void *rule
, const struct prefix
*p
, void *object
)
1435 uint32_t *rib_type
= (uint32_t *)rule
;
1436 struct nh_rmap_obj
*nh_data
;
1438 nh_data
= (struct nh_rmap_obj
*)object
;
1440 return RMAP_NOMATCH
;
1442 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1446 static void *route_match_source_protocol_compile(const char *arg
)
1451 i
= proto_name2num(arg
);
1452 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1459 static void route_match_source_protocol_free(void *rule
)
1461 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1464 static const struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1466 route_match_source_protocol
,
1467 route_match_source_protocol_compile
,
1468 route_match_source_protocol_free
1471 /* `source-instance` */
1472 static enum route_map_cmd_result_t
1473 route_match_source_instance(void *rule
, const struct prefix
*p
, void *object
)
1475 uint8_t *instance
= (uint8_t *)rule
;
1476 struct nh_rmap_obj
*nh_data
;
1478 nh_data
= (struct nh_rmap_obj
*)object
;
1480 return RMAP_NOMATCH
;
1482 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1485 static void *route_match_source_instance_compile(const char *arg
)
1491 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1498 static void route_match_source_instance_free(void *rule
)
1500 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1503 static const struct route_map_rule_cmd route_match_source_instance_cmd
= {
1505 route_match_source_instance
,
1506 route_match_source_instance_compile
,
1507 route_match_source_instance_free
1510 /* `set src A.B.C.D' */
1513 static enum route_map_cmd_result_t
1514 route_set_src(void *rule
, const struct prefix
*prefix
, void *object
)
1516 struct nh_rmap_obj
*nh_data
;
1518 nh_data
= (struct nh_rmap_obj
*)object
;
1519 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1524 /* set src compilation. */
1525 static void *route_set_src_compile(const char *arg
)
1527 union g_addr src
, *psrc
;
1529 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1530 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1531 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1538 /* Free route map's compiled `set src' value. */
1539 static void route_set_src_free(void *rule
)
1541 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1544 /* Set src rule structure. */
1545 static const struct route_map_rule_cmd route_set_src_cmd
= {
1548 route_set_src_compile
,
1552 /* The function checks if the changed routemap specified by parameter rmap
1553 * matches the configured protocol routemaps in proto_rm table. If there is
1554 * a match then rib_update_table() to process the routes.
1556 static void zebra_rib_table_rm_update(const char *rmap
)
1559 struct route_table
*table
;
1560 struct vrf
*vrf
= NULL
;
1561 struct zebra_vrf
*zvrf
= NULL
;
1563 struct route_map
*old
= NULL
;
1565 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1569 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1570 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1571 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1572 if (IS_ZEBRA_DEBUG_EVENT
)
1574 "%s : AFI_IP rmap %s, route type %s",
1576 zebra_route_string(i
));
1578 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1580 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1581 route_map_lookup_by_name(rmap_name
);
1582 /* old is NULL. i.e Route map creation event.
1583 * So update applied_counter.
1584 * If Old is not NULL, i.e It may be routemap
1585 * updation or deletion.
1586 * So no need to update the counter.
1589 route_map_counter_increment(
1590 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1591 /* There is single rib table for all protocols
1593 table
= zvrf
->table
[AFI_IP
][SAFI_UNICAST
];
1597 RIB_UPDATE_RMAP_CHANGE
,
1601 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1602 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1603 if (IS_ZEBRA_DEBUG_EVENT
)
1605 "%s : AFI_IP6 rmap %s, route type %s",
1607 zebra_route_string(i
));
1609 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1611 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1612 route_map_lookup_by_name(rmap_name
);
1614 route_map_counter_increment(
1615 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1616 /* There is single rib table for all protocols
1618 table
= zvrf
->table
[AFI_IP6
][SAFI_UNICAST
];
1622 RIB_UPDATE_RMAP_CHANGE
,
1630 /* The function checks if the changed routemap specified by parameter rmap
1631 * matches the configured protocol routemaps in nht_rm table. If there is
1632 * a match then zebra_evaluate_rnh() to process the nexthops.
1634 static void zebra_nht_rm_update(const char *rmap
)
1637 struct route_table
*table
;
1638 struct vrf
*vrf
= NULL
;
1639 struct zebra_vrf
*zvrf
= NULL
;
1643 struct route_map
*old
= NULL
;
1645 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1649 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1650 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1651 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1652 if (IS_ZEBRA_DEBUG_EVENT
)
1654 "%s : AFI_IP rmap %s, route type %s",
1656 zebra_route_string(i
));
1658 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1660 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1661 route_map_lookup_by_name(rmap_name
);
1663 route_map_counter_increment(
1664 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1665 /* There is single rib table for all protocols
1668 table
= zvrf
->table
[AFI_IP
]
1675 zvrf
, AFI_IP
, 1, NULL
,
1681 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1682 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1683 if (IS_ZEBRA_DEBUG_EVENT
)
1685 "%s : AFI_IP6 rmap %s, route type %s",
1687 zebra_route_string(i
));
1689 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1691 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1692 route_map_lookup_by_name(rmap_name
);
1694 route_map_counter_increment(
1695 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1696 /* There is single rib table for all protocols
1698 if (afi_ipv6
== 0) {
1699 table
= zvrf
->table
[AFI_IP6
]
1706 zvrf
, AFI_IP
, 1, NULL
,
1715 static void zebra_route_map_process_update_cb(char *rmap_name
)
1717 if (IS_ZEBRA_DEBUG_EVENT
)
1718 zlog_debug("Event handler for route-map: %s",
1720 zebra_import_table_rm_update(rmap_name
);
1721 zebra_rib_table_rm_update(rmap_name
);
1722 zebra_nht_rm_update(rmap_name
);
1725 static void zebra_route_map_update_timer(struct thread
*thread
)
1727 if (IS_ZEBRA_DEBUG_EVENT
)
1728 zlog_debug("Event driven route-map update triggered");
1730 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1732 "%u: Routemap update-timer fired, scheduling RIB processing",
1735 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1738 * This code needs to be updated to be:
1739 * 1) VRF Aware <sigh>
1740 * 2) Route-map aware
1744 static void zebra_route_map_set_delay_timer(uint32_t value
)
1746 zebra_rmap_update_timer
= value
;
1747 if (!value
&& zebra_t_rmap_update
) {
1748 /* Event driven route map updates is being disabled */
1749 /* But there's a pending timer. Fire it off now */
1750 THREAD_OFF(zebra_t_rmap_update
);
1751 zebra_route_map_update_timer(NULL
);
1755 void zebra_routemap_finish(void)
1757 /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
1758 zebra_rmap_update_timer
= 0;
1759 /* Thread off if any scheduled already */
1760 THREAD_OFF(zebra_t_rmap_update
);
1765 zebra_route_map_check(afi_t family
, int rib_type
, uint8_t instance
,
1766 const struct prefix
*p
, struct nexthop
*nexthop
,
1767 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1769 struct route_map
*rmap
= NULL
;
1771 route_map_result_t ret
= RMAP_PERMITMATCH
;
1772 struct nh_rmap_obj nh_obj
;
1774 nh_obj
.nexthop
= nexthop
;
1775 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1776 nh_obj
.source_protocol
= rib_type
;
1777 nh_obj
.instance
= instance
;
1781 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
) {
1782 rm_name
= PROTO_RM_NAME(zvrf
, family
, rib_type
);
1783 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1785 if (rm_name
&& !rmap
)
1786 return RMAP_DENYMATCH
;
1789 rm_name
= PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1790 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1792 if (rm_name
&& !rmap
)
1793 return RMAP_DENYMATCH
;
1796 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1802 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1804 return zebra_import_table_routemap
[afi
][table
];
1807 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1810 zebra_import_table_routemap
[afi
][table
] =
1811 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1814 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1816 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1820 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1821 const struct prefix
*p
,
1822 struct nexthop
*nexthop
,
1823 vrf_id_t vrf_id
, route_tag_t tag
,
1824 const char *rmap_name
)
1826 struct route_map
*rmap
= NULL
;
1827 route_map_result_t ret
= RMAP_DENYMATCH
;
1828 struct nh_rmap_obj nh_obj
;
1830 nh_obj
.nexthop
= nexthop
;
1831 nh_obj
.vrf_id
= vrf_id
;
1832 nh_obj
.source_protocol
= re_type
;
1833 nh_obj
.instance
= instance
;
1837 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1838 rmap
= route_map_lookup_by_name(rmap_name
);
1840 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1846 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1847 const struct prefix
*p
,
1848 struct zebra_vrf
*zvrf
,
1849 struct route_entry
*re
,
1850 struct nexthop
*nexthop
)
1852 struct route_map
*rmap
= NULL
;
1853 route_map_result_t ret
= RMAP_PERMITMATCH
;
1854 struct nh_rmap_obj nh_obj
;
1856 nh_obj
.nexthop
= nexthop
;
1857 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1858 nh_obj
.source_protocol
= re
->type
;
1859 nh_obj
.instance
= re
->instance
;
1860 nh_obj
.metric
= re
->metric
;
1861 nh_obj
.tag
= re
->tag
;
1863 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1864 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1865 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1866 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1868 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1873 static void zebra_route_map_mark_update(const char *rmap_name
)
1875 /* rmap_update_timer of 0 means don't do route updates */
1876 if (zebra_rmap_update_timer
)
1877 THREAD_OFF(zebra_t_rmap_update
);
1879 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1880 NULL
, zebra_rmap_update_timer
, &zebra_t_rmap_update
);
1883 static void zebra_route_map_add(const char *rmap_name
)
1885 if (route_map_mark_updated(rmap_name
) == 0)
1886 zebra_route_map_mark_update(rmap_name
);
1888 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1891 static void zebra_route_map_delete(const char *rmap_name
)
1893 if (route_map_mark_updated(rmap_name
) == 0)
1894 zebra_route_map_mark_update(rmap_name
);
1896 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1899 static void zebra_route_map_event(const char *rmap_name
)
1901 if (route_map_mark_updated(rmap_name
) == 0)
1902 zebra_route_map_mark_update(rmap_name
);
1904 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1907 void zebra_routemap_vrf_delete(struct zebra_vrf
*zvrf
)
1912 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1913 for (type
= 0; type
<= ZEBRA_ROUTE_MAX
; type
++) {
1914 if (PROTO_RM_NAME(zvrf
, afi
, type
))
1915 XFREE(MTYPE_ROUTE_MAP_NAME
,
1916 PROTO_RM_NAME(zvrf
, afi
, type
));
1917 if (NHT_RM_NAME(zvrf
, afi
, type
))
1918 XFREE(MTYPE_ROUTE_MAP_NAME
,
1919 NHT_RM_NAME(zvrf
, afi
, type
));
1924 /* ip protocol configuration write function */
1925 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1926 struct zebra_vrf
*zvrf
)
1931 memset(space
, 0, sizeof(space
));
1933 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1934 snprintf(space
, sizeof(space
), "%s", " ");
1936 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1937 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1938 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1939 zebra_route_string(i
),
1940 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1942 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1943 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1944 zebra_route_string(i
),
1945 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1947 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1948 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1949 zebra_route_string(i
),
1950 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1952 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1953 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1954 zebra_route_string(i
),
1955 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1958 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1959 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1960 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1962 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1963 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1964 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1966 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1967 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1968 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1970 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1971 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1972 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1974 if (zvrf_id(zvrf
) == VRF_DEFAULT
1975 && zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1976 vty_out(vty
, "zebra route-map delay-timer %d\n",
1977 zebra_rmap_update_timer
);
1980 void zebra_route_map_init(void)
1982 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1983 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1984 install_element(VRF_NODE
, &ip_protocol_cmd
);
1985 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1986 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1987 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1988 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1989 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1990 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1991 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1992 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1993 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1994 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1995 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1996 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1997 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1998 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1999 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
2000 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
2001 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
2002 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
2003 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
2007 route_map_add_hook(zebra_route_map_add
);
2008 route_map_delete_hook(zebra_route_map_delete
);
2009 route_map_event_hook(zebra_route_map_event
);
2011 route_map_match_interface_hook(generic_match_add
);
2012 route_map_no_match_interface_hook(generic_match_delete
);
2014 route_map_match_ip_address_hook(generic_match_add
);
2015 route_map_no_match_ip_address_hook(generic_match_delete
);
2017 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
2018 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
2020 route_map_match_ip_next_hop_hook(generic_match_add
);
2021 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
2023 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
2024 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
2026 route_map_match_ip_next_hop_type_hook(generic_match_add
);
2027 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
2029 route_map_match_tag_hook(generic_match_add
);
2030 route_map_no_match_tag_hook(generic_match_delete
);
2032 route_map_match_ipv6_address_hook(generic_match_add
);
2033 route_map_no_match_ipv6_address_hook(generic_match_delete
);
2035 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
2036 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
2038 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
2039 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
2041 route_map_install_match(&route_match_tag_cmd
);
2042 route_map_install_match(&route_match_interface_cmd
);
2043 route_map_install_match(&route_match_ip_next_hop_cmd
);
2044 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
2045 route_map_install_match(&route_match_ip_address_cmd
);
2046 route_map_install_match(&route_match_ipv6_address_cmd
);
2047 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
2048 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
2049 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
2050 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
2051 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
2052 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
2053 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
2054 route_map_install_match(&route_match_source_protocol_cmd
);
2055 route_map_install_match(&route_match_source_instance_cmd
);
2058 route_map_install_set(&route_set_src_cmd
);
2060 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
2061 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
2062 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
2063 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
2064 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
2065 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
2066 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
2067 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
2068 install_element(RMAP_NODE
, &match_source_instance_cmd
);
2069 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
2072 install_element(RMAP_NODE
, &set_src_cmd
);
2073 install_element(RMAP_NODE
, &no_set_src_cmd
);