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
,
150 vty_out(vty
, "Protocol : route-map\n");
151 vty_out(vty
, "-------------------------------------\n");
153 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
154 if (NHT_RM_NAME(zvrf
, af_type
, i
))
155 vty_out(vty
, "%-24s : %-10s\n", zebra_route_string(i
),
156 NHT_RM_NAME(zvrf
, af_type
, i
));
158 vty_out(vty
, "%-24s : none\n", zebra_route_string(i
));
161 if (NHT_RM_NAME(zvrf
, af_type
, i
))
162 vty_out(vty
, "%-24s : %-10s\n", "any",
163 NHT_RM_NAME(zvrf
, af_type
, i
));
165 vty_out(vty
, "%-24s : none\n", "any");
168 static int show_proto_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
169 const char *vrf_name
)
171 struct zebra_vrf
*zvrf
;
176 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
177 zvrf
= (struct zebra_vrf
*)vrf
->info
;
180 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
181 show_vrf_proto_rm(vty
, zvrf
, af_type
);
184 vrf_id_t vrf_id
= VRF_DEFAULT
;
187 VRF_GET_ID(vrf_id
, vrf_name
, false);
189 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
193 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
194 show_vrf_proto_rm(vty
, zvrf
, af_type
);
200 static int show_nht_rm(struct vty
*vty
, int af_type
, const char *vrf_all
,
201 const char *vrf_name
)
203 struct zebra_vrf
*zvrf
;
208 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
209 zvrf
= (struct zebra_vrf
*)vrf
->info
;
213 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
214 show_vrf_nht_rm(vty
, zvrf
, af_type
);
217 vrf_id_t vrf_id
= VRF_DEFAULT
;
220 VRF_GET_ID(vrf_id
, vrf_name
, false);
222 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
226 vty_out(vty
, "VRF: %s\n", zvrf
->vrf
->name
);
227 show_vrf_nht_rm(vty
, zvrf
, af_type
);
233 /* Route map commands for interface matching */
234 static const struct route_map_rule_cmd route_match_interface_cmd
= {
236 route_match_interface
,
237 route_match_interface_compile
,
238 route_match_interface_free
241 static int ip_protocol_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
,
242 int rtype
, afi_t afi
, safi_t safi
)
244 struct route_table
*table
;
246 if (PROTO_RM_NAME(zvrf
, afi
, rtype
)) {
247 if (strcmp(PROTO_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
250 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
252 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
253 PROTO_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
254 PROTO_RM_MAP(zvrf
, afi
, rtype
) =
255 route_map_lookup_by_name(PROTO_RM_NAME(zvrf
, afi
, rtype
));
256 route_map_counter_increment(PROTO_RM_MAP(zvrf
, afi
, rtype
));
258 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
260 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
262 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
263 zvrf
->vrf
->vrf_id
, rtype
);
264 /* Process routes of interested address-families. */
265 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
267 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
274 static int ip_protocol_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
,
275 int rtype
, afi_t afi
, safi_t safi
)
277 struct route_table
*table
;
279 if (!PROTO_RM_NAME(zvrf
, afi
, rtype
))
282 if (!rmap
|| strcmp(rmap
, PROTO_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
284 route_map_counter_decrement(PROTO_RM_MAP(zvrf
, afi
, rtype
));
285 if (PROTO_RM_MAP(zvrf
, afi
, rtype
)) {
286 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
288 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
289 zvrf
->vrf
->vrf_id
, rtype
);
290 PROTO_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
292 /* Process routes of interested address-families. */
293 table
= zebra_vrf_table(afi
, safi
, zvrf
->vrf
->vrf_id
);
295 rib_update_table(table
, RIB_UPDATE_RMAP_CHANGE
,
298 XFREE(MTYPE_ROUTE_MAP_NAME
, PROTO_RM_NAME(zvrf
, afi
, rtype
));
303 static int ip_nht_rm_add(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
307 if (NHT_RM_NAME(zvrf
, afi
, rtype
)) {
308 if (strcmp(NHT_RM_NAME(zvrf
, afi
, rtype
), rmap
) == 0)
311 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
313 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
314 NHT_RM_NAME(zvrf
, afi
, rtype
) = XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
315 NHT_RM_MAP(zvrf
, afi
, rtype
) =
316 route_map_lookup_by_name(NHT_RM_NAME(zvrf
, afi
, rtype
));
317 route_map_counter_increment(NHT_RM_MAP(zvrf
, afi
, rtype
));
319 if (NHT_RM_MAP(zvrf
, afi
, rtype
))
320 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
325 static int ip_nht_rm_del(struct zebra_vrf
*zvrf
, const char *rmap
, int rtype
,
329 if (!NHT_RM_NAME(zvrf
, afi
, rtype
))
332 if (!rmap
|| strcmp(rmap
, NHT_RM_NAME(zvrf
, afi
, rtype
)) == 0) {
333 route_map_counter_decrement(NHT_RM_MAP(zvrf
, afi
, rtype
));
334 if (NHT_RM_MAP(zvrf
, afi
, rtype
)) {
335 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
337 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
338 zvrf
->vrf
->vrf_id
, rtype
);
339 NHT_RM_MAP(zvrf
, afi
, rtype
) = NULL
;
341 zebra_evaluate_rnh(zvrf
, AFI_IP
, 1, NULL
, SAFI_UNICAST
);
343 XFREE(MTYPE_ROUTE_MAP_NAME
, NHT_RM_NAME(zvrf
, afi
, rtype
));
349 match_ip_address_prefix_len
, match_ip_address_prefix_len_cmd
,
350 "match ip address prefix-len (0-32)$length",
353 "Match prefix length of IP address\n"
354 "Match prefix length of IP address\n"
358 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
359 char xpath_value
[XPATH_MAXLEN
];
361 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
363 xpath_value
, sizeof(xpath_value
),
364 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
366 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
368 return nb_cli_apply_changes(vty
, NULL
);
372 no_match_ip_address_prefix_len
, no_match_ip_address_prefix_len_cmd
,
373 "no match ip address prefix-len [(0-32)]",
377 "Match prefix length of IP address\n"
378 "Match prefix length of IP address\n"
382 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
384 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
386 return nb_cli_apply_changes(vty
, NULL
);
390 match_ipv6_address_prefix_len
, match_ipv6_address_prefix_len_cmd
,
391 "match ipv6 address prefix-len (0-128)$length",
394 "Match prefix length of IPv6 address\n"
395 "Match prefix length of IPv6 address\n"
399 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
400 char xpath_value
[XPATH_MAXLEN
];
402 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
404 xpath_value
, sizeof(xpath_value
),
405 "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
407 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
409 return nb_cli_apply_changes(vty
, NULL
);
413 no_match_ipv6_address_prefix_len
, no_match_ipv6_address_prefix_len_cmd
,
414 "no match ipv6 address prefix-len [(0-128)]",
418 "Match prefix length of IPv6 address\n"
419 "Match prefix length of IPv6 address\n"
423 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
425 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
427 return nb_cli_apply_changes(vty
, NULL
);
431 match_ip_nexthop_prefix_len
, match_ip_nexthop_prefix_len_cmd
,
432 "match ip next-hop prefix-len (0-32)$length",
435 "Match prefixlen of nexthop IP address\n"
436 "Match prefixlen of given nexthop\n"
440 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
441 char xpath_value
[XPATH_MAXLEN
];
443 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
445 xpath_value
, sizeof(xpath_value
),
446 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
448 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, length_str
);
450 return nb_cli_apply_changes(vty
, NULL
);
454 no_match_ip_nexthop_prefix_len
, no_match_ip_nexthop_prefix_len_cmd
,
455 "no match ip next-hop prefix-len [(0-32)]",
459 "Match prefixlen of nexthop IP address\n"
460 "Match prefix length of nexthop\n"
464 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
466 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
468 return nb_cli_apply_changes(vty
, NULL
);
472 match_source_protocol
, match_source_protocol_cmd
,
473 "match source-protocol " FRR_REDIST_STR_ZEBRA
"$proto",
475 "Match protocol via which the route was learnt\n"
476 FRR_REDIST_HELP_STR_ZEBRA
)
479 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
480 char xpath_value
[XPATH_MAXLEN
];
482 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
483 snprintf(xpath_value
, sizeof(xpath_value
),
484 "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
486 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, proto
);
488 return nb_cli_apply_changes(vty
, NULL
);
492 no_match_source_protocol
, no_match_source_protocol_cmd
,
493 "no match source-protocol [" FRR_REDIST_STR_ZEBRA
"]",
496 "Match protocol via which the route was learnt\n"
497 FRR_REDIST_HELP_STR_ZEBRA
)
500 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
502 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
504 return nb_cli_apply_changes(vty
, NULL
);
508 match_source_instance
, match_source_instance_cmd
,
509 "match source-instance (0-255)$instance",
511 "Match the protocol's instance number\n"
512 "The instance number\n")
515 "./match-condition[condition='frr-zebra-route-map:source-instance']";
516 char xpath_value
[XPATH_MAXLEN
];
518 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
519 snprintf(xpath_value
, sizeof(xpath_value
),
520 "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
522 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, instance_str
);
524 return nb_cli_apply_changes(vty
, NULL
);
528 no_match_source_instance
, no_match_source_instance_cmd
,
529 "no match source-instance [(0-255)]",
531 "Match the protocol's instance number\n"
532 "The instance number\n")
535 "./match-condition[condition='frr-zebra-route-map:source-instance']";
537 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
539 return nb_cli_apply_changes(vty
, NULL
);
545 set_src
, set_src_cmd
,
546 "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
548 "src address for route\n"
550 "IPv6 src address\n")
553 "./set-action[action='frr-zebra-route-map:src-address']";
554 char xpath_value
[XPATH_MAXLEN
];
556 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
559 xpath_value
, sizeof(xpath_value
),
560 "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
562 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
566 xpath_value
, sizeof(xpath_value
),
567 "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
569 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
,
573 return nb_cli_apply_changes(vty
, NULL
);
577 no_set_src
, no_set_src_cmd
,
578 "no set src [<A.B.C.D|X:X::X:X>]",
581 "Source address for route\n"
586 "./set-action[action='frr-zebra-route-map:src-address']";
588 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
590 return nb_cli_apply_changes(vty
, NULL
);
593 DEFUN_YANG (zebra_route_map_timer
,
594 zebra_route_map_timer_cmd
,
595 "zebra route-map delay-timer (0-600)",
597 "Set route-map parameters\n"
598 "Time to wait before route-map updates are processed\n"
599 "0 means route-map changes are run immediately instead of delaying\n")
602 uint32_t rmap_delay_timer
;
604 rmap_delay_timer
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
605 zebra_route_map_set_delay_timer(rmap_delay_timer
);
607 return (CMD_SUCCESS
);
610 DEFUN_YANG (no_zebra_route_map_timer
,
611 no_zebra_route_map_timer_cmd
,
612 "no zebra route-map delay-timer [(0-600)]",
615 "Set route-map parameters\n"
616 "Reset delay-timer to default value, 30 secs\n"
617 "0 means route-map changes are run immediately instead of delaying\n")
619 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
);
621 return (CMD_SUCCESS
);
624 DEFPY_YANG (ip_protocol
,
626 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
627 " $proto route-map ROUTE-MAP$rmap",
629 "Filter routing info exchanged between zebra and protocol\n"
630 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
631 "Specify route-map\n"
639 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
644 if (strcasecmp(proto
, "any") == 0)
645 rtype
= ZEBRA_ROUTE_MAX
;
647 rtype
= proto_name2num(proto
);
649 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
650 return CMD_WARNING_CONFIG_FAILED
;
653 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
658 DEFPY_YANG (no_ip_protocol
,
660 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
661 " $proto [route-map ROUTE-MAP$rmap]",
664 "Stop filtering routing info between zebra and protocol\n"
665 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
666 "Specify route-map\n"
673 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
678 if (strcasecmp(proto
, "any") == 0)
679 rtype
= ZEBRA_ROUTE_MAX
;
681 rtype
= proto_name2num(proto
);
683 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
684 return CMD_WARNING_CONFIG_FAILED
;
687 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP
, SAFI_UNICAST
);
692 DEFPY_YANG (show_ip_protocol
,
693 show_ip_protocol_cmd
,
694 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
697 "IP protocol filtering status\n"
698 VRF_FULL_CMD_HELP_STR
)
700 int ret
= show_proto_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
705 DEFPY_YANG (ipv6_protocol
,
707 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
708 " $proto route-map ROUTE-MAP$rmap",
710 "Filter IPv6 routing info exchanged between zebra and protocol\n"
711 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
712 "Specify route-map\n"
720 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
725 if (strcasecmp(proto
, "any") == 0)
726 rtype
= ZEBRA_ROUTE_MAX
;
728 rtype
= proto_name2num(proto
);
730 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
731 return CMD_WARNING_CONFIG_FAILED
;
734 ret
= ip_protocol_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
739 DEFPY_YANG (no_ipv6_protocol
,
740 no_ipv6_protocol_cmd
,
741 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
742 " $proto [route-map ROUTE-MAP$rmap]",
745 "Stop filtering IPv6 routing info between zebra and protocol\n"
746 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
747 "Specify route-map\n"
754 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
759 if (strcasecmp(proto
, "any") == 0)
760 rtype
= ZEBRA_ROUTE_MAX
;
762 rtype
= proto_name2num(proto
);
764 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
765 return CMD_WARNING_CONFIG_FAILED
;
768 ret
= ip_protocol_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
, SAFI_UNICAST
);
773 DEFPY_YANG (show_ipv6_protocol
,
774 show_ipv6_protocol_cmd
,
775 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
778 "IPv6 protocol filtering status\n"
779 VRF_FULL_CMD_HELP_STR
)
781 int ret
= show_proto_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
786 DEFPY_YANG (ip_protocol_nht_rmap
,
787 ip_protocol_nht_rmap_cmd
,
788 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
789 " $proto route-map ROUTE-MAP$rmap",
791 "Filter Next Hop tracking route resolution\n"
792 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
793 "Specify route map\n"
802 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
807 if (strcasecmp(proto
, "any") == 0)
808 rtype
= ZEBRA_ROUTE_MAX
;
810 rtype
= proto_name2num(proto
);
812 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
813 return CMD_WARNING_CONFIG_FAILED
;
816 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP
);
821 DEFPY_YANG (no_ip_protocol_nht_rmap
,
822 no_ip_protocol_nht_rmap_cmd
,
823 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
824 " $proto route-map [ROUTE-MAP$rmap]",
827 "Filter Next Hop tracking route resolution\n"
828 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
829 "Specify route map\n"
836 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
841 if (strcasecmp(proto
, "any") == 0)
842 rtype
= ZEBRA_ROUTE_MAX
;
844 rtype
= proto_name2num(proto
);
846 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
847 return CMD_WARNING_CONFIG_FAILED
;
850 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP
);
855 DEFPY_YANG (show_ip_protocol_nht
,
856 show_ip_protocol_nht_cmd
,
857 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
860 "IP nexthop tracking table\n"
861 "IP Next Hop tracking filtering status\n"
862 VRF_FULL_CMD_HELP_STR
)
864 int ret
= show_nht_rm(vty
, AFI_IP
, vrf_all
, vrf_name
);
869 DEFPY_YANG (ipv6_protocol_nht_rmap
,
870 ipv6_protocol_nht_rmap_cmd
,
871 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
872 " $proto route-map ROUTE-MAP$rmap",
874 "Filter Next Hop tracking route resolution\n"
875 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
876 "Specify route map\n"
884 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
889 if (strcasecmp(proto
, "any") == 0)
890 rtype
= ZEBRA_ROUTE_MAX
;
892 rtype
= proto_name2num(proto
);
894 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
895 return CMD_WARNING_CONFIG_FAILED
;
898 ret
= ip_nht_rm_add(zvrf
, rmap
, rtype
, AFI_IP6
);
903 DEFPY_YANG (no_ipv6_protocol_nht_rmap
,
904 no_ipv6_protocol_nht_rmap_cmd
,
905 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
906 " $proto [route-map ROUTE-MAP$rmap]",
909 "Filter Next Hop tracking route resolution\n"
910 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
911 "Specify route map\n"
918 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
923 if (strcasecmp(proto
, "any") == 0)
924 rtype
= ZEBRA_ROUTE_MAX
;
926 rtype
= proto_name2num(proto
);
928 vty_out(vty
, "invalid protocol name \"%s\"\n", proto
);
929 return CMD_WARNING_CONFIG_FAILED
;
932 ret
= ip_nht_rm_del(zvrf
, rmap
, rtype
, AFI_IP6
);
937 DEFPY_YANG (show_ipv6_protocol_nht
,
938 show_ipv6_protocol_nht_cmd
,
939 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
942 "Next Hop filtering status\n"
944 VRF_FULL_CMD_HELP_STR
)
946 int ret
= show_nht_rm(vty
, AFI_IP6
, vrf_all
, vrf_name
);
951 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
953 /* `match ip next-hop IP_ACCESS_LIST' */
955 /* Match function return 1 if match is success else return zero. */
956 static enum route_map_cmd_result_t
957 route_match_ip_next_hop(void *rule
, const struct prefix
*prefix
, void *object
)
959 struct access_list
*alist
;
960 struct nh_rmap_obj
*nh_data
;
961 struct prefix_ipv4 p
;
967 switch (nh_data
->nexthop
->type
) {
968 case NEXTHOP_TYPE_IFINDEX
:
969 /* Interface routes can't match ip next-hop */
971 case NEXTHOP_TYPE_IPV4_IFINDEX
:
972 case NEXTHOP_TYPE_IPV4
:
974 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
975 p
.prefixlen
= IPV4_MAX_BITLEN
;
980 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
984 return (access_list_apply(alist
, &p
) == FILTER_DENY
? RMAP_NOMATCH
988 /* Route map `ip next-hop' match statement. `arg' should be
990 static void *route_match_ip_next_hop_compile(const char *arg
)
992 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
995 /* Free route map's compiled `. */
996 static void route_match_ip_next_hop_free(void *rule
)
998 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1001 /* Route map commands for ip next-hop matching. */
1002 static const struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
1004 route_match_ip_next_hop
,
1005 route_match_ip_next_hop_compile
,
1006 route_match_ip_next_hop_free
1009 /* `match ip next-hop prefix-list PREFIX_LIST' */
1011 static enum route_map_cmd_result_t
1012 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
1015 struct prefix_list
*plist
;
1016 struct nh_rmap_obj
*nh_data
;
1017 struct prefix_ipv4 p
;
1019 nh_data
= (struct nh_rmap_obj
*)object
;
1021 return RMAP_NOMATCH
;
1023 switch (nh_data
->nexthop
->type
) {
1024 case NEXTHOP_TYPE_IFINDEX
:
1025 /* Interface routes can't match ip next-hop */
1026 return RMAP_NOMATCH
;
1027 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1028 case NEXTHOP_TYPE_IPV4
:
1030 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1031 p
.prefixlen
= IPV4_MAX_BITLEN
;
1034 return RMAP_NOMATCH
;
1036 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
1038 return RMAP_NOMATCH
;
1040 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
? RMAP_NOMATCH
1044 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
1046 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1049 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
1051 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1054 static const struct route_map_rule_cmd
1055 route_match_ip_next_hop_prefix_list_cmd
= {
1056 "ip next-hop prefix-list",
1057 route_match_ip_next_hop_prefix_list
,
1058 route_match_ip_next_hop_prefix_list_compile
,
1059 route_match_ip_next_hop_prefix_list_free
1062 /* `match ip address IP_ACCESS_LIST' */
1064 /* Match function should return 1 if match is success else return
1066 static enum route_map_cmd_result_t
1067 route_match_address(afi_t afi
, void *rule
, const struct prefix
*prefix
,
1070 struct access_list
*alist
;
1072 alist
= access_list_lookup(afi
, (char *)rule
);
1074 return RMAP_NOMATCH
;
1076 return (access_list_apply(alist
, prefix
) == FILTER_DENY
? RMAP_NOMATCH
1080 static enum route_map_cmd_result_t
1081 route_match_ip_address(void *rule
, const struct prefix
*prefix
, void *object
)
1083 return route_match_address(AFI_IP
, rule
, prefix
, object
);
1086 static enum route_map_cmd_result_t
1087 route_match_ipv6_address(void *rule
, const struct prefix
*prefix
, void *object
)
1089 return route_match_address(AFI_IP6
, rule
, prefix
, object
);
1092 /* Route map `ip address' match statement. `arg' should be
1093 access-list name. */
1094 static void *route_match_address_compile(const char *arg
)
1096 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1099 /* Free route map's compiled `ip address' value. */
1100 static void route_match_address_free(void *rule
)
1102 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1105 /* Route map commands for ip address matching. */
1106 static const struct route_map_rule_cmd route_match_ip_address_cmd
= {
1108 route_match_ip_address
,
1109 route_match_address_compile
,
1110 route_match_address_free
1113 /* Route map commands for ipv6 address matching. */
1114 static const struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
1116 route_match_ipv6_address
,
1117 route_match_address_compile
,
1118 route_match_address_free
1121 /* `match ip address prefix-list PREFIX_LIST' */
1123 static enum route_map_cmd_result_t
1124 route_match_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1125 void *object
, afi_t afi
)
1127 struct prefix_list
*plist
;
1129 plist
= prefix_list_lookup(afi
, (char *)rule
);
1131 return RMAP_NOMATCH
;
1133 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
? RMAP_NOMATCH
1137 static enum route_map_cmd_result_t
1138 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1141 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP
));
1144 static void *route_match_address_prefix_list_compile(const char *arg
)
1146 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1149 static void route_match_address_prefix_list_free(void *rule
)
1151 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1154 static const struct route_map_rule_cmd
1155 route_match_ip_address_prefix_list_cmd
= {
1156 "ip address prefix-list",
1157 route_match_ip_address_prefix_list
,
1158 route_match_address_prefix_list_compile
,
1159 route_match_address_prefix_list_free
1162 static enum route_map_cmd_result_t
1163 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
1166 return (route_match_address_prefix_list(rule
, prefix
, object
, AFI_IP6
));
1169 static const struct route_map_rule_cmd
1170 route_match_ipv6_address_prefix_list_cmd
= {
1171 "ipv6 address prefix-list",
1172 route_match_ipv6_address_prefix_list
,
1173 route_match_address_prefix_list_compile
,
1174 route_match_address_prefix_list_free
1177 /* `match ipv6 next-hop type <TYPE>' */
1179 static enum route_map_cmd_result_t
1180 route_match_ipv6_next_hop_type(void *rule
, const struct prefix
*prefix
,
1183 struct nh_rmap_obj
*nh_data
;
1185 if (prefix
->family
== AF_INET6
) {
1186 nh_data
= (struct nh_rmap_obj
*)object
;
1188 return RMAP_NOMATCH
;
1190 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1194 return RMAP_NOMATCH
;
1197 static void *route_match_ipv6_next_hop_type_compile(const char *arg
)
1199 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1202 static void route_match_ipv6_next_hop_type_free(void *rule
)
1204 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1207 static const struct route_map_rule_cmd
1208 route_match_ipv6_next_hop_type_cmd
= {
1209 "ipv6 next-hop type",
1210 route_match_ipv6_next_hop_type
,
1211 route_match_ipv6_next_hop_type_compile
,
1212 route_match_ipv6_next_hop_type_free
1215 /* `match ip address prefix-len PREFIXLEN' */
1217 static enum route_map_cmd_result_t
1218 route_match_address_prefix_len(void *rule
, const struct prefix
*prefix
,
1221 uint32_t *prefixlen
= (uint32_t *)rule
;
1223 return ((prefix
->prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1226 static void *route_match_address_prefix_len_compile(const char *arg
)
1228 uint32_t *prefix_len
;
1229 char *endptr
= NULL
;
1230 unsigned long tmpval
;
1232 /* prefix len value shoud be integer. */
1233 if (!all_digit(arg
))
1237 tmpval
= strtoul(arg
, &endptr
, 10);
1238 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
1241 prefix_len
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1243 *prefix_len
= tmpval
;
1247 static void route_match_address_prefix_len_free(void *rule
)
1249 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1252 static const struct route_map_rule_cmd
1253 route_match_ip_address_prefix_len_cmd
= {
1254 "ip address prefix-len",
1255 route_match_address_prefix_len
,
1256 route_match_address_prefix_len_compile
,
1257 route_match_address_prefix_len_free
1260 static const struct route_map_rule_cmd
1261 route_match_ipv6_address_prefix_len_cmd
= {
1262 "ipv6 address prefix-len",
1263 route_match_address_prefix_len
,
1264 route_match_address_prefix_len_compile
,
1265 route_match_address_prefix_len_free
1268 /* `match ip nexthop prefix-len PREFIXLEN' */
1270 static enum route_map_cmd_result_t
1271 route_match_ip_nexthop_prefix_len(void *rule
, const struct prefix
*prefix
,
1274 uint32_t *prefixlen
= (uint32_t *)rule
;
1275 struct nh_rmap_obj
*nh_data
;
1276 struct prefix_ipv4 p
;
1278 nh_data
= (struct nh_rmap_obj
*)object
;
1279 if (!nh_data
|| !nh_data
->nexthop
)
1280 return RMAP_NOMATCH
;
1282 switch (nh_data
->nexthop
->type
) {
1283 case NEXTHOP_TYPE_IFINDEX
:
1284 /* Interface routes can't match ip next-hop */
1285 return RMAP_NOMATCH
;
1286 case NEXTHOP_TYPE_IPV4_IFINDEX
:
1287 case NEXTHOP_TYPE_IPV4
:
1289 p
.prefix
= nh_data
->nexthop
->gate
.ipv4
;
1290 p
.prefixlen
= IPV4_MAX_BITLEN
;
1293 return RMAP_NOMATCH
;
1295 return ((p
.prefixlen
== *prefixlen
) ? RMAP_MATCH
: RMAP_NOMATCH
);
1298 static const struct route_map_rule_cmd
1299 route_match_ip_nexthop_prefix_len_cmd
= {
1300 "ip next-hop prefix-len",
1301 route_match_ip_nexthop_prefix_len
,
1302 route_match_address_prefix_len_compile
, /* reuse */
1303 route_match_address_prefix_len_free
/* reuse */
1306 /* `match ip next-hop type <blackhole>' */
1308 static enum route_map_cmd_result_t
1309 route_match_ip_next_hop_type(void *rule
, const struct prefix
*prefix
,
1312 struct nh_rmap_obj
*nh_data
;
1314 if (prefix
->family
== AF_INET
) {
1315 nh_data
= (struct nh_rmap_obj
*)object
;
1317 return RMAP_NOMATCH
;
1319 if (nh_data
->nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
)
1323 return RMAP_NOMATCH
;
1326 static void *route_match_ip_next_hop_type_compile(const char *arg
)
1328 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1331 static void route_match_ip_next_hop_type_free(void *rule
)
1333 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1336 static const struct route_map_rule_cmd
1337 route_match_ip_next_hop_type_cmd
= {
1339 route_match_ip_next_hop_type
,
1340 route_match_ip_next_hop_type_compile
,
1341 route_match_ip_next_hop_type_free
1344 /* `match source-protocol PROTOCOL' */
1346 static enum route_map_cmd_result_t
1347 route_match_source_protocol(void *rule
, const struct prefix
*p
, void *object
)
1349 uint32_t *rib_type
= (uint32_t *)rule
;
1350 struct nh_rmap_obj
*nh_data
;
1352 nh_data
= (struct nh_rmap_obj
*)object
;
1354 return RMAP_NOMATCH
;
1356 return ((nh_data
->source_protocol
== *rib_type
) ? RMAP_MATCH
1360 static void *route_match_source_protocol_compile(const char *arg
)
1365 i
= proto_name2num(arg
);
1366 rib_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
1373 static void route_match_source_protocol_free(void *rule
)
1375 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1378 static const struct route_map_rule_cmd route_match_source_protocol_cmd
= {
1380 route_match_source_protocol
,
1381 route_match_source_protocol_compile
,
1382 route_match_source_protocol_free
1385 /* `source-instance` */
1386 static enum route_map_cmd_result_t
1387 route_match_source_instance(void *rule
, const struct prefix
*p
, void *object
)
1389 uint8_t *instance
= (uint8_t *)rule
;
1390 struct nh_rmap_obj
*nh_data
;
1392 nh_data
= (struct nh_rmap_obj
*)object
;
1394 return RMAP_NOMATCH
;
1396 return (nh_data
->instance
== *instance
) ? RMAP_MATCH
: RMAP_NOMATCH
;
1399 static void *route_match_source_instance_compile(const char *arg
)
1405 instance
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1412 static void route_match_source_instance_free(void *rule
)
1414 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1417 static const struct route_map_rule_cmd route_match_source_instance_cmd
= {
1419 route_match_source_instance
,
1420 route_match_source_instance_compile
,
1421 route_match_source_instance_free
1424 /* `set src A.B.C.D' */
1427 static enum route_map_cmd_result_t
1428 route_set_src(void *rule
, const struct prefix
*prefix
, void *object
)
1430 struct nh_rmap_obj
*nh_data
;
1432 nh_data
= (struct nh_rmap_obj
*)object
;
1433 nh_data
->nexthop
->rmap_src
= *(union g_addr
*)rule
;
1438 /* set src compilation. */
1439 static void *route_set_src_compile(const char *arg
)
1441 union g_addr src
, *psrc
;
1443 if ((inet_pton(AF_INET6
, arg
, &src
.ipv6
) == 1)
1444 || (inet_pton(AF_INET
, arg
, &src
.ipv4
) == 1)) {
1445 psrc
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(union g_addr
));
1452 /* Free route map's compiled `set src' value. */
1453 static void route_set_src_free(void *rule
)
1455 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1458 /* Set src rule structure. */
1459 static const struct route_map_rule_cmd route_set_src_cmd
= {
1462 route_set_src_compile
,
1466 /* The function checks if the changed routemap specified by parameter rmap
1467 * matches the configured protocol routemaps in proto_rm table. If there is
1468 * a match then rib_update_table() to process the routes.
1470 static void zebra_rib_table_rm_update(const char *rmap
)
1473 struct route_table
*table
;
1474 struct vrf
*vrf
= NULL
;
1475 struct zebra_vrf
*zvrf
= NULL
;
1477 struct route_map
*old
= NULL
;
1479 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1483 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1484 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP
, i
);
1485 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1486 if (IS_ZEBRA_DEBUG_EVENT
)
1488 "%s : AFI_IP rmap %s, route type %s",
1490 zebra_route_string(i
));
1492 old
= PROTO_RM_MAP(zvrf
, AFI_IP
, i
);
1494 PROTO_RM_MAP(zvrf
, AFI_IP
, i
) =
1495 route_map_lookup_by_name(rmap_name
);
1496 /* old is NULL. i.e Route map creation event.
1497 * So update applied_counter.
1498 * If Old is not NULL, i.e It may be routemap
1499 * updation or deletion.
1500 * So no need to update the counter.
1503 route_map_counter_increment(
1504 PROTO_RM_MAP(zvrf
, AFI_IP
, i
));
1505 /* There is single rib table for all protocols
1507 table
= zvrf
->table
[AFI_IP
][SAFI_UNICAST
];
1511 RIB_UPDATE_RMAP_CHANGE
,
1515 rmap_name
= PROTO_RM_NAME(zvrf
, AFI_IP6
, i
);
1516 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1517 if (IS_ZEBRA_DEBUG_EVENT
)
1519 "%s : AFI_IP6 rmap %s, route type %s",
1521 zebra_route_string(i
));
1523 old
= PROTO_RM_MAP(zvrf
, AFI_IP6
, i
);
1525 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
) =
1526 route_map_lookup_by_name(rmap_name
);
1528 route_map_counter_increment(
1529 PROTO_RM_MAP(zvrf
, AFI_IP6
, i
));
1530 /* There is single rib table for all protocols
1532 table
= zvrf
->table
[AFI_IP6
][SAFI_UNICAST
];
1536 RIB_UPDATE_RMAP_CHANGE
,
1544 /* The function checks if the changed routemap specified by parameter rmap
1545 * matches the configured protocol routemaps in nht_rm table. If there is
1546 * a match then zebra_evaluate_rnh() to process the nexthops.
1548 static void zebra_nht_rm_update(const char *rmap
)
1551 struct route_table
*table
;
1552 struct vrf
*vrf
= NULL
;
1553 struct zebra_vrf
*zvrf
= NULL
;
1557 struct route_map
*old
= NULL
;
1559 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1563 for (i
= 0; i
<= ZEBRA_ROUTE_MAX
; i
++) {
1564 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP
, i
);
1565 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1566 if (IS_ZEBRA_DEBUG_EVENT
)
1568 "%s : AFI_IP rmap %s, route type %s",
1570 zebra_route_string(i
));
1572 old
= NHT_RM_MAP(zvrf
, AFI_IP
, i
);
1574 NHT_RM_MAP(zvrf
, AFI_IP
, i
) =
1575 route_map_lookup_by_name(rmap_name
);
1577 route_map_counter_increment(
1578 NHT_RM_MAP(zvrf
, AFI_IP
, i
));
1579 /* There is single rib table for all protocols
1582 table
= zvrf
->table
[AFI_IP
]
1589 zvrf
, AFI_IP
, 1, NULL
,
1595 rmap_name
= NHT_RM_NAME(zvrf
, AFI_IP6
, i
);
1596 if (rmap_name
&& (strcmp(rmap_name
, rmap
) == 0)) {
1597 if (IS_ZEBRA_DEBUG_EVENT
)
1599 "%s : AFI_IP6 rmap %s, route type %s",
1601 zebra_route_string(i
));
1603 old
= NHT_RM_MAP(zvrf
, AFI_IP6
, i
);
1605 NHT_RM_MAP(zvrf
, AFI_IP6
, i
) =
1606 route_map_lookup_by_name(rmap_name
);
1608 route_map_counter_increment(
1609 NHT_RM_MAP(zvrf
, AFI_IP6
, i
));
1610 /* There is single rib table for all protocols
1612 if (afi_ipv6
== 0) {
1613 table
= zvrf
->table
[AFI_IP6
]
1620 zvrf
, AFI_IP
, 1, NULL
,
1629 static void zebra_route_map_process_update_cb(char *rmap_name
)
1631 if (IS_ZEBRA_DEBUG_EVENT
)
1632 zlog_debug("Event handler for route-map: %s",
1634 zebra_import_table_rm_update(rmap_name
);
1635 zebra_rib_table_rm_update(rmap_name
);
1636 zebra_nht_rm_update(rmap_name
);
1639 static void zebra_route_map_update_timer(struct thread
*thread
)
1641 if (IS_ZEBRA_DEBUG_EVENT
)
1642 zlog_debug("Event driven route-map update triggered");
1644 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
1646 "%u: Routemap update-timer fired, scheduling RIB processing",
1649 route_map_walk_update_list(zebra_route_map_process_update_cb
);
1652 * This code needs to be updated to be:
1653 * 1) VRF Aware <sigh>
1654 * 2) Route-map aware
1658 static void zebra_route_map_set_delay_timer(uint32_t value
)
1660 zebra_rmap_update_timer
= value
;
1661 if (!value
&& zebra_t_rmap_update
) {
1662 /* Event driven route map updates is being disabled */
1663 /* But there's a pending timer. Fire it off now */
1664 THREAD_OFF(zebra_t_rmap_update
);
1665 zebra_route_map_update_timer(NULL
);
1669 void zebra_routemap_finish(void)
1671 /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
1672 zebra_rmap_update_timer
= 0;
1673 /* Thread off if any scheduled already */
1674 THREAD_OFF(zebra_t_rmap_update
);
1679 zebra_route_map_check(afi_t family
, int rib_type
, uint8_t instance
,
1680 const struct prefix
*p
, struct nexthop
*nexthop
,
1681 struct zebra_vrf
*zvrf
, route_tag_t tag
)
1683 struct route_map
*rmap
= NULL
;
1685 route_map_result_t ret
= RMAP_PERMITMATCH
;
1686 struct nh_rmap_obj nh_obj
;
1688 nh_obj
.nexthop
= nexthop
;
1689 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1690 nh_obj
.source_protocol
= rib_type
;
1691 nh_obj
.instance
= instance
;
1695 if (rib_type
>= 0 && rib_type
< ZEBRA_ROUTE_MAX
) {
1696 rm_name
= PROTO_RM_NAME(zvrf
, family
, rib_type
);
1697 rmap
= PROTO_RM_MAP(zvrf
, family
, rib_type
);
1699 if (rm_name
&& !rmap
)
1700 return RMAP_DENYMATCH
;
1703 rm_name
= PROTO_RM_NAME(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1704 rmap
= PROTO_RM_MAP(zvrf
, family
, ZEBRA_ROUTE_MAX
);
1706 if (rm_name
&& !rmap
)
1707 return RMAP_DENYMATCH
;
1710 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1716 char *zebra_get_import_table_route_map(afi_t afi
, uint32_t table
)
1718 return zebra_import_table_routemap
[afi
][table
];
1721 void zebra_add_import_table_route_map(afi_t afi
, const char *rmap_name
,
1724 zebra_import_table_routemap
[afi
][table
] =
1725 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
1728 void zebra_del_import_table_route_map(afi_t afi
, uint32_t table
)
1730 XFREE(MTYPE_ROUTE_MAP_NAME
, zebra_import_table_routemap
[afi
][table
]);
1734 zebra_import_table_route_map_check(int family
, int re_type
, uint8_t instance
,
1735 const struct prefix
*p
,
1736 struct nexthop
*nexthop
,
1737 vrf_id_t vrf_id
, route_tag_t tag
,
1738 const char *rmap_name
)
1740 struct route_map
*rmap
= NULL
;
1741 route_map_result_t ret
= RMAP_DENYMATCH
;
1742 struct nh_rmap_obj nh_obj
;
1744 nh_obj
.nexthop
= nexthop
;
1745 nh_obj
.vrf_id
= vrf_id
;
1746 nh_obj
.source_protocol
= re_type
;
1747 nh_obj
.instance
= instance
;
1751 if (re_type
>= 0 && re_type
< ZEBRA_ROUTE_MAX
)
1752 rmap
= route_map_lookup_by_name(rmap_name
);
1754 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1760 route_map_result_t
zebra_nht_route_map_check(afi_t afi
, int client_proto
,
1761 const struct prefix
*p
,
1762 struct zebra_vrf
*zvrf
,
1763 struct route_entry
*re
,
1764 struct nexthop
*nexthop
)
1766 struct route_map
*rmap
= NULL
;
1767 route_map_result_t ret
= RMAP_PERMITMATCH
;
1768 struct nh_rmap_obj nh_obj
;
1770 nh_obj
.nexthop
= nexthop
;
1771 nh_obj
.vrf_id
= nexthop
->vrf_id
;
1772 nh_obj
.source_protocol
= re
->type
;
1773 nh_obj
.instance
= re
->instance
;
1774 nh_obj
.metric
= re
->metric
;
1775 nh_obj
.tag
= re
->tag
;
1777 if (client_proto
>= 0 && client_proto
< ZEBRA_ROUTE_MAX
)
1778 rmap
= NHT_RM_MAP(zvrf
, afi
, client_proto
);
1779 if (!rmap
&& NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
))
1780 rmap
= NHT_RM_MAP(zvrf
, afi
, ZEBRA_ROUTE_MAX
);
1782 ret
= route_map_apply(rmap
, p
, &nh_obj
);
1787 static void zebra_route_map_mark_update(const char *rmap_name
)
1789 /* rmap_update_timer of 0 means don't do route updates */
1790 if (zebra_rmap_update_timer
)
1791 THREAD_OFF(zebra_t_rmap_update
);
1793 thread_add_timer(zrouter
.master
, zebra_route_map_update_timer
,
1794 NULL
, zebra_rmap_update_timer
, &zebra_t_rmap_update
);
1797 static void zebra_route_map_add(const char *rmap_name
)
1799 if (route_map_mark_updated(rmap_name
) == 0)
1800 zebra_route_map_mark_update(rmap_name
);
1802 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1805 static void zebra_route_map_delete(const char *rmap_name
)
1807 if (route_map_mark_updated(rmap_name
) == 0)
1808 zebra_route_map_mark_update(rmap_name
);
1810 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
1813 static void zebra_route_map_event(const char *rmap_name
)
1815 if (route_map_mark_updated(rmap_name
) == 0)
1816 zebra_route_map_mark_update(rmap_name
);
1818 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
1821 /* ip protocol configuration write function */
1822 void zebra_routemap_config_write_protocol(struct vty
*vty
,
1823 struct zebra_vrf
*zvrf
)
1828 memset(space
, 0, sizeof(space
));
1830 if (zvrf_id(zvrf
) != VRF_DEFAULT
)
1831 snprintf(space
, sizeof(space
), "%s", " ");
1833 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
1834 if (PROTO_RM_NAME(zvrf
, AFI_IP
, i
))
1835 vty_out(vty
, "%sip protocol %s route-map %s\n", space
,
1836 zebra_route_string(i
),
1837 PROTO_RM_NAME(zvrf
, AFI_IP
, i
));
1839 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, i
))
1840 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
,
1841 zebra_route_string(i
),
1842 PROTO_RM_NAME(zvrf
, AFI_IP6
, i
));
1844 if (NHT_RM_NAME(zvrf
, AFI_IP
, i
))
1845 vty_out(vty
, "%sip nht %s route-map %s\n", space
,
1846 zebra_route_string(i
),
1847 NHT_RM_NAME(zvrf
, AFI_IP
, i
));
1849 if (NHT_RM_NAME(zvrf
, AFI_IP6
, i
))
1850 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
,
1851 zebra_route_string(i
),
1852 NHT_RM_NAME(zvrf
, AFI_IP6
, i
));
1855 if (PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1856 vty_out(vty
, "%sip protocol %s route-map %s\n", space
, "any",
1857 PROTO_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1859 if (PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1860 vty_out(vty
, "%sipv6 protocol %s route-map %s\n", space
, "any",
1861 PROTO_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1863 if (NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
))
1864 vty_out(vty
, "%sip nht %s route-map %s\n", space
, "any",
1865 NHT_RM_NAME(zvrf
, AFI_IP
, ZEBRA_ROUTE_MAX
));
1867 if (NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
))
1868 vty_out(vty
, "%sipv6 nht %s route-map %s\n", space
, "any",
1869 NHT_RM_NAME(zvrf
, AFI_IP6
, ZEBRA_ROUTE_MAX
));
1871 if (zvrf_id(zvrf
) == VRF_DEFAULT
1872 && zebra_rmap_update_timer
!= ZEBRA_RMAP_DEFAULT_UPDATE_TIMER
)
1873 vty_out(vty
, "zebra route-map delay-timer %d\n",
1874 zebra_rmap_update_timer
);
1877 void zebra_route_map_init(void)
1879 install_element(CONFIG_NODE
, &ip_protocol_cmd
);
1880 install_element(CONFIG_NODE
, &no_ip_protocol_cmd
);
1881 install_element(VRF_NODE
, &ip_protocol_cmd
);
1882 install_element(VRF_NODE
, &no_ip_protocol_cmd
);
1883 install_element(VIEW_NODE
, &show_ip_protocol_cmd
);
1884 install_element(CONFIG_NODE
, &ipv6_protocol_cmd
);
1885 install_element(CONFIG_NODE
, &no_ipv6_protocol_cmd
);
1886 install_element(VRF_NODE
, &ipv6_protocol_cmd
);
1887 install_element(VRF_NODE
, &no_ipv6_protocol_cmd
);
1888 install_element(VIEW_NODE
, &show_ipv6_protocol_cmd
);
1889 install_element(CONFIG_NODE
, &ip_protocol_nht_rmap_cmd
);
1890 install_element(CONFIG_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1891 install_element(VRF_NODE
, &ip_protocol_nht_rmap_cmd
);
1892 install_element(VRF_NODE
, &no_ip_protocol_nht_rmap_cmd
);
1893 install_element(VIEW_NODE
, &show_ip_protocol_nht_cmd
);
1894 install_element(CONFIG_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1895 install_element(CONFIG_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1896 install_element(VRF_NODE
, &ipv6_protocol_nht_rmap_cmd
);
1897 install_element(VRF_NODE
, &no_ipv6_protocol_nht_rmap_cmd
);
1898 install_element(VIEW_NODE
, &show_ipv6_protocol_nht_cmd
);
1899 install_element(CONFIG_NODE
, &zebra_route_map_timer_cmd
);
1900 install_element(CONFIG_NODE
, &no_zebra_route_map_timer_cmd
);
1904 route_map_add_hook(zebra_route_map_add
);
1905 route_map_delete_hook(zebra_route_map_delete
);
1906 route_map_event_hook(zebra_route_map_event
);
1908 route_map_match_interface_hook(generic_match_add
);
1909 route_map_no_match_interface_hook(generic_match_delete
);
1911 route_map_match_ip_address_hook(generic_match_add
);
1912 route_map_no_match_ip_address_hook(generic_match_delete
);
1914 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
1915 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
1917 route_map_match_ip_next_hop_hook(generic_match_add
);
1918 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
1920 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
1921 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
1923 route_map_match_ip_next_hop_type_hook(generic_match_add
);
1924 route_map_no_match_ip_next_hop_type_hook(generic_match_delete
);
1926 route_map_match_tag_hook(generic_match_add
);
1927 route_map_no_match_tag_hook(generic_match_delete
);
1929 route_map_match_ipv6_address_hook(generic_match_add
);
1930 route_map_no_match_ipv6_address_hook(generic_match_delete
);
1932 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
1933 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
1935 route_map_match_ipv6_next_hop_type_hook(generic_match_add
);
1936 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete
);
1938 route_map_install_match(&route_match_tag_cmd
);
1939 route_map_install_match(&route_match_interface_cmd
);
1940 route_map_install_match(&route_match_ip_next_hop_cmd
);
1941 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
1942 route_map_install_match(&route_match_ip_address_cmd
);
1943 route_map_install_match(&route_match_ipv6_address_cmd
);
1944 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
1945 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
1946 route_map_install_match(&route_match_ip_address_prefix_len_cmd
);
1947 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd
);
1948 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd
);
1949 route_map_install_match(&route_match_ip_next_hop_type_cmd
);
1950 route_map_install_match(&route_match_ipv6_next_hop_type_cmd
);
1951 route_map_install_match(&route_match_source_protocol_cmd
);
1952 route_map_install_match(&route_match_source_instance_cmd
);
1955 route_map_install_set(&route_set_src_cmd
);
1957 install_element(RMAP_NODE
, &match_ip_nexthop_prefix_len_cmd
);
1958 install_element(RMAP_NODE
, &no_match_ip_nexthop_prefix_len_cmd
);
1959 install_element(RMAP_NODE
, &match_ip_address_prefix_len_cmd
);
1960 install_element(RMAP_NODE
, &match_ipv6_address_prefix_len_cmd
);
1961 install_element(RMAP_NODE
, &no_match_ipv6_address_prefix_len_cmd
);
1962 install_element(RMAP_NODE
, &no_match_ip_address_prefix_len_cmd
);
1963 install_element(RMAP_NODE
, &match_source_protocol_cmd
);
1964 install_element(RMAP_NODE
, &no_match_source_protocol_cmd
);
1965 install_element(RMAP_NODE
, &match_source_instance_cmd
);
1966 install_element(RMAP_NODE
, &no_match_source_instance_cmd
);
1969 install_element(RMAP_NODE
, &set_src_cmd
);
1970 install_element(RMAP_NODE
, &no_set_src_cmd
);