]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
Merge pull request #12762 from sri-mohan1/sri-bable
[mirror_frr.git] / zebra / zebra_routemap.c
1 /* zebra routemap.
2 * Copyright (C) 2006 IBM Corporation
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
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
19 */
20
21 #include <zebra.h>
22
23 #include "memory.h"
24 #include "prefix.h"
25 #include "rib.h"
26 #include "vty.h"
27 #include "routemap.h"
28 #include "command.h"
29 #include "filter.h"
30 #include "plist.h"
31 #include "nexthop.h"
32 #include "northbound_cli.h"
33 #include "lib/route_types.h"
34 #include "vrf.h"
35 #include "frrstr.h"
36
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"
42
43 #include "zebra/zebra_routemap_clippy.c"
44
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];
48
49 struct nh_rmap_obj {
50 struct nexthop *nexthop;
51 vrf_id_t vrf_id;
52 uint32_t source_protocol;
53 uint8_t instance;
54 int metric;
55 route_tag_t tag;
56 };
57
58 static void zebra_route_map_set_delay_timer(uint32_t value);
59
60 /* 'match tag TAG'
61 * Match function return 1 if match is success else return 0
62 */
63 static enum route_map_cmd_result_t
64 route_match_tag(void *rule, const struct prefix *prefix, void *object)
65 {
66 route_tag_t *tag;
67 struct nh_rmap_obj *nh_data;
68
69 tag = rule;
70 nh_data = object;
71
72 if (nh_data->tag == *tag)
73 return RMAP_MATCH;
74
75 return RMAP_NOMATCH;
76 }
77
78 /* Route map commands for tag matching */
79 static const struct route_map_rule_cmd route_match_tag_cmd = {
80 "tag",
81 route_match_tag,
82 route_map_rule_tag_compile,
83 route_map_rule_tag_free,
84 };
85
86
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)
91 {
92 struct nh_rmap_obj *nh_data;
93 char *ifname = rule;
94 ifindex_t ifindex;
95
96 if (strcasecmp(ifname, "any") == 0)
97 return RMAP_MATCH;
98 nh_data = object;
99 if (!nh_data || !nh_data->nexthop)
100 return RMAP_NOMATCH;
101 ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
102 if (ifindex == 0)
103 return RMAP_NOMATCH;
104 if (nh_data->nexthop->ifindex == ifindex)
105 return RMAP_MATCH;
106
107 return RMAP_NOMATCH;
108 }
109
110 /* Route map `match interface' match statement. `arg' is IFNAME value */
111 static void *route_match_interface_compile(const char *arg)
112 {
113 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
114 }
115
116 /* Free route map's compiled `match interface' value. */
117 static void route_match_interface_free(void *rule)
118 {
119 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
120 }
121
122 static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf,
123 int af_type)
124 {
125 int i;
126
127 vty_out(vty, "Protocol : route-map\n");
128 vty_out(vty, "-------------------------------------\n");
129
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));
134 else
135 vty_out(vty, "%-24s : none\n", zebra_route_string(i));
136 }
137
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));
141 else
142 vty_out(vty, "%-24s : none\n", "any");
143 }
144
145 static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
146 int af_type, json_object *json)
147 {
148 int i;
149
150 if (!json) {
151 vty_out(vty, "Protocol : route-map\n");
152 vty_out(vty, "-------------------------------------\n");
153 }
154
155 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
156 if (json) {
157 if (NHT_RM_NAME(zvrf, af_type, i))
158 json_object_string_add(
159 json, zebra_route_string(i),
160 NHT_RM_NAME(zvrf, af_type, i));
161 else
162 json_object_string_add(
163 json, zebra_route_string(i), "none");
164 } else {
165 if (NHT_RM_NAME(zvrf, af_type, i))
166 vty_out(vty, "%-24s : %-10s\n",
167 zebra_route_string(i),
168 NHT_RM_NAME(zvrf, af_type, i));
169 else
170 vty_out(vty, "%-24s : none\n",
171 zebra_route_string(i));
172 }
173 }
174
175 if (json) {
176 if (NHT_RM_NAME(zvrf, af_type, i))
177 json_object_string_add(json, "any",
178 NHT_RM_NAME(zvrf, af_type, i));
179 else
180 json_object_string_add(json, "any", "none");
181 } else {
182 if (NHT_RM_NAME(zvrf, af_type, i))
183 vty_out(vty, "%-24s : %-10s\n", "any",
184 NHT_RM_NAME(zvrf, af_type, i));
185 else
186 vty_out(vty, "%-24s : none\n", "any");
187 }
188 }
189
190 static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all,
191 const char *vrf_name)
192 {
193 struct zebra_vrf *zvrf;
194
195 if (vrf_all) {
196 struct vrf *vrf;
197
198 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
199 zvrf = (struct zebra_vrf *)vrf->info;
200 if (zvrf == NULL)
201 continue;
202 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
203 show_vrf_proto_rm(vty, zvrf, af_type);
204 }
205 } else {
206 vrf_id_t vrf_id = VRF_DEFAULT;
207
208 if (vrf_name)
209 VRF_GET_ID(vrf_id, vrf_name, false);
210
211 zvrf = zebra_vrf_lookup_by_id(vrf_id);
212 if (!zvrf)
213 return CMD_SUCCESS;
214
215 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
216 show_vrf_proto_rm(vty, zvrf, af_type);
217 }
218
219 return CMD_SUCCESS;
220 }
221
222 static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all,
223 const char *vrf_name, bool use_json)
224 {
225 struct zebra_vrf *zvrf;
226 json_object *json = NULL;
227 json_object *json_vrfs = NULL;
228
229 if (use_json) {
230 json = json_object_new_object();
231 json_vrfs = json_object_new_object();
232 json_object_string_add(json, "afi",
233 (af_type == AFI_IP) ? "ipv4" : "ipv6");
234 }
235
236 if (vrf_all) {
237 struct vrf *vrf;
238
239 if (use_json)
240 json_object_object_add(json, "vrfs", json_vrfs);
241
242 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
243 zvrf = (struct zebra_vrf *)vrf->info;
244 if (zvrf == NULL)
245 continue;
246
247 if (use_json) {
248 json_object *json_proto = NULL;
249 json_object *json_vrf = NULL;
250 json_vrf = json_object_new_object();
251 json_object_object_add(
252 json_vrfs, zvrf->vrf->name, json_vrf);
253 json_proto = json_object_new_object();
254 json_object_object_add(json_vrf, "protocols",
255 json_proto);
256 show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
257 } else {
258 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
259 show_vrf_nht_rm(vty, zvrf, af_type, NULL);
260 }
261 }
262 } else {
263 json_object *json_proto = NULL;
264 json_object *json_vrf = NULL;
265 vrf_id_t vrf_id = VRF_DEFAULT;
266
267 if (vrf_name)
268 VRF_GET_ID(vrf_id, vrf_name, false);
269
270 zvrf = zebra_vrf_lookup_by_id(vrf_id);
271 if (!zvrf) {
272 json_object_free(json);
273 json_object_free(json_vrfs);
274 return CMD_SUCCESS;
275 }
276
277 if (use_json) {
278 json_object_object_add(json, "vrfs", json_vrfs);
279 json_vrf = json_object_new_object();
280 json_object_object_add(json_vrfs, zvrf->vrf->name,
281 json_vrf);
282 json_proto = json_object_new_object();
283 json_object_object_add(json_vrf, "protocols",
284 json_proto);
285 show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
286 } else {
287 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
288 show_vrf_nht_rm(vty, zvrf, af_type, NULL);
289 }
290 }
291
292 if (use_json)
293 vty_json(vty, json);
294
295 return CMD_SUCCESS;
296 }
297
298 /* Route map commands for interface matching */
299 static const struct route_map_rule_cmd route_match_interface_cmd = {
300 "interface",
301 route_match_interface,
302 route_match_interface_compile,
303 route_match_interface_free
304 };
305
306 static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
307 int rtype, afi_t afi, safi_t safi)
308 {
309 struct route_table *table;
310
311 if (PROTO_RM_NAME(zvrf, afi, rtype)) {
312 if (strcmp(PROTO_RM_NAME(zvrf, afi, rtype), rmap) == 0)
313 return CMD_SUCCESS;
314
315 XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
316 }
317 route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
318 PROTO_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
319 PROTO_RM_MAP(zvrf, afi, rtype) =
320 route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype));
321 route_map_counter_increment(PROTO_RM_MAP(zvrf, afi, rtype));
322
323 if (PROTO_RM_MAP(zvrf, afi, rtype)) {
324
325 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
326 zlog_debug(
327 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
328 zvrf->vrf->vrf_id, rtype);
329 /* Process routes of interested address-families. */
330 table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
331 if (table)
332 rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
333 rtype);
334 }
335
336 return CMD_SUCCESS;
337 }
338
339 static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
340 int rtype, afi_t afi, safi_t safi)
341 {
342 struct route_table *table;
343
344 if (!PROTO_RM_NAME(zvrf, afi, rtype))
345 return CMD_SUCCESS;
346
347 if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) {
348
349 route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
350 if (PROTO_RM_MAP(zvrf, afi, rtype)) {
351 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
352 zlog_debug(
353 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
354 zvrf->vrf->vrf_id, rtype);
355 PROTO_RM_MAP(zvrf, afi, rtype) = NULL;
356
357 /* Process routes of interested address-families. */
358 table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
359 if (table)
360 rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
361 rtype);
362 }
363 XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
364 }
365 return CMD_SUCCESS;
366 }
367
368 static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
369 int afi)
370 {
371
372 if (NHT_RM_NAME(zvrf, afi, rtype)) {
373 if (strcmp(NHT_RM_NAME(zvrf, afi, rtype), rmap) == 0)
374 return CMD_SUCCESS;
375
376 XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
377 }
378 route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
379 NHT_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
380 NHT_RM_MAP(zvrf, afi, rtype) =
381 route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype));
382 route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
383
384 if (NHT_RM_MAP(zvrf, afi, rtype))
385 zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
386
387 return CMD_SUCCESS;
388 }
389
390 static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
391 int afi)
392 {
393
394 if (!NHT_RM_NAME(zvrf, afi, rtype))
395 return CMD_SUCCESS;
396
397 if (!rmap || strcmp(rmap, NHT_RM_NAME(zvrf, afi, rtype)) == 0) {
398 route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
399 if (NHT_RM_MAP(zvrf, afi, rtype)) {
400 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
401 zlog_debug(
402 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
403 zvrf->vrf->vrf_id, rtype);
404 NHT_RM_MAP(zvrf, afi, rtype) = NULL;
405
406 zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
407 }
408 XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
409 }
410 return CMD_SUCCESS;
411 }
412
413 DEFPY_YANG(
414 match_ip_address_prefix_len, match_ip_address_prefix_len_cmd,
415 "match ip address prefix-len (0-32)$length",
416 MATCH_STR
417 IP_STR
418 "Match prefix length of IP address\n"
419 "Match prefix length of IP address\n"
420 "Prefix length\n")
421 {
422 const char *xpath =
423 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
424 char xpath_value[XPATH_MAXLEN];
425
426 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
427 snprintf(
428 xpath_value, sizeof(xpath_value),
429 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
430 xpath);
431 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
432
433 return nb_cli_apply_changes(vty, NULL);
434 }
435
436 DEFPY_YANG(
437 no_match_ip_address_prefix_len, no_match_ip_address_prefix_len_cmd,
438 "no match ip address prefix-len [(0-32)]",
439 NO_STR
440 MATCH_STR
441 IP_STR
442 "Match prefix length of IP address\n"
443 "Match prefix length of IP address\n"
444 "Prefix length\n")
445 {
446 const char *xpath =
447 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
448
449 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
450
451 return nb_cli_apply_changes(vty, NULL);
452 }
453
454 DEFPY_YANG(
455 match_ipv6_address_prefix_len, match_ipv6_address_prefix_len_cmd,
456 "match ipv6 address prefix-len (0-128)$length",
457 MATCH_STR
458 IPV6_STR
459 "Match prefix length of IPv6 address\n"
460 "Match prefix length of IPv6 address\n"
461 "Prefix length\n")
462 {
463 const char *xpath =
464 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
465 char xpath_value[XPATH_MAXLEN];
466
467 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
468 snprintf(
469 xpath_value, sizeof(xpath_value),
470 "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
471 xpath);
472 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
473
474 return nb_cli_apply_changes(vty, NULL);
475 }
476
477 DEFPY_YANG(
478 no_match_ipv6_address_prefix_len, no_match_ipv6_address_prefix_len_cmd,
479 "no match ipv6 address prefix-len [(0-128)]",
480 NO_STR
481 MATCH_STR
482 IPV6_STR
483 "Match prefix length of IPv6 address\n"
484 "Match prefix length of IPv6 address\n"
485 "Prefix length\n")
486 {
487 const char *xpath =
488 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
489
490 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
491
492 return nb_cli_apply_changes(vty, NULL);
493 }
494
495 DEFPY_YANG(
496 match_ip_nexthop_prefix_len, match_ip_nexthop_prefix_len_cmd,
497 "match ip next-hop prefix-len (0-32)$length",
498 MATCH_STR
499 IP_STR
500 "Match prefixlen of nexthop IP address\n"
501 "Match prefixlen of given nexthop\n"
502 "Prefix length\n")
503 {
504 const char *xpath =
505 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
506 char xpath_value[XPATH_MAXLEN];
507
508 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
509 snprintf(
510 xpath_value, sizeof(xpath_value),
511 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
512 xpath);
513 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
514
515 return nb_cli_apply_changes(vty, NULL);
516 }
517
518 DEFPY_YANG(
519 no_match_ip_nexthop_prefix_len, no_match_ip_nexthop_prefix_len_cmd,
520 "no match ip next-hop prefix-len [(0-32)]",
521 NO_STR
522 MATCH_STR
523 IP_STR
524 "Match prefixlen of nexthop IP address\n"
525 "Match prefix length of nexthop\n"
526 "Prefix length\n")
527 {
528 const char *xpath =
529 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
530
531 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
532
533 return nb_cli_apply_changes(vty, NULL);
534 }
535
536 DEFPY_YANG(
537 match_source_protocol, match_source_protocol_cmd,
538 "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
539 MATCH_STR
540 "Match protocol via which the route was learnt\n"
541 FRR_REDIST_HELP_STR_ZEBRA)
542 {
543 const char *xpath =
544 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
545 char xpath_value[XPATH_MAXLEN];
546
547 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
548 snprintf(xpath_value, sizeof(xpath_value),
549 "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
550 xpath);
551 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
552
553 return nb_cli_apply_changes(vty, NULL);
554 }
555
556 DEFPY_YANG(
557 no_match_source_protocol, no_match_source_protocol_cmd,
558 "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
559 NO_STR
560 MATCH_STR
561 "Match protocol via which the route was learnt\n"
562 FRR_REDIST_HELP_STR_ZEBRA)
563 {
564 const char *xpath =
565 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
566
567 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
568
569 return nb_cli_apply_changes(vty, NULL);
570 }
571
572 DEFPY_YANG(
573 match_source_instance, match_source_instance_cmd,
574 "match source-instance (0-255)$instance",
575 MATCH_STR
576 "Match the protocol's instance number\n"
577 "The instance number\n")
578 {
579 const char *xpath =
580 "./match-condition[condition='frr-zebra-route-map:source-instance']";
581 char xpath_value[XPATH_MAXLEN];
582
583 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
584 snprintf(xpath_value, sizeof(xpath_value),
585 "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
586 xpath);
587 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, instance_str);
588
589 return nb_cli_apply_changes(vty, NULL);
590 }
591
592 DEFPY_YANG(
593 no_match_source_instance, no_match_source_instance_cmd,
594 "no match source-instance [(0-255)]",
595 NO_STR MATCH_STR
596 "Match the protocol's instance number\n"
597 "The instance number\n")
598 {
599 const char *xpath =
600 "./match-condition[condition='frr-zebra-route-map:source-instance']";
601
602 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
603
604 return nb_cli_apply_changes(vty, NULL);
605 }
606
607 /* set functions */
608
609 DEFPY_YANG(
610 set_src, set_src_cmd,
611 "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
612 SET_STR
613 "src address for route\n"
614 "IPv4 src address\n"
615 "IPv6 src address\n")
616 {
617 const char *xpath =
618 "./set-action[action='frr-zebra-route-map:src-address']";
619 char xpath_value[XPATH_MAXLEN];
620
621 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
622 if (addrv4_str) {
623 snprintf(
624 xpath_value, sizeof(xpath_value),
625 "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
626 xpath);
627 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
628 addrv4_str);
629 } else {
630 snprintf(
631 xpath_value, sizeof(xpath_value),
632 "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
633 xpath);
634 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
635 addrv6_str);
636 }
637
638 return nb_cli_apply_changes(vty, NULL);
639 }
640
641 DEFPY_YANG(
642 no_set_src, no_set_src_cmd,
643 "no set src [<A.B.C.D|X:X::X:X>]",
644 NO_STR
645 SET_STR
646 "Source address for route\n"
647 "IPv4 address\n"
648 "IPv6 address\n")
649 {
650 const char *xpath =
651 "./set-action[action='frr-zebra-route-map:src-address']";
652
653 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
654
655 return nb_cli_apply_changes(vty, NULL);
656 }
657
658 DEFUN_YANG (zebra_route_map_timer,
659 zebra_route_map_timer_cmd,
660 "zebra route-map delay-timer (0-600)",
661 ZEBRA_STR
662 "Set route-map parameters\n"
663 "Time to wait before route-map updates are processed\n"
664 "0 means route-map changes are run immediately instead of delaying\n")
665 {
666 int idx_number = 3;
667 uint32_t rmap_delay_timer;
668
669 rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
670 zebra_route_map_set_delay_timer(rmap_delay_timer);
671
672 return (CMD_SUCCESS);
673 }
674
675 DEFUN_YANG (no_zebra_route_map_timer,
676 no_zebra_route_map_timer_cmd,
677 "no zebra route-map delay-timer [(0-600)]",
678 NO_STR
679 ZEBRA_STR
680 "Set route-map parameters\n"
681 "Reset delay-timer to default value, 30 secs\n"
682 "0 means route-map changes are run immediately instead of delaying\n")
683 {
684 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
685
686 return (CMD_SUCCESS);
687 }
688
689 DEFPY_YANG (ip_protocol,
690 ip_protocol_cmd,
691 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
692 " $proto route-map ROUTE-MAP$rmap",
693 IP_STR
694 "Filter routing info exchanged between zebra and protocol\n"
695 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
696 "Specify route-map\n"
697 "Route map name\n")
698 {
699 int ret, rtype;
700
701 assert(proto);
702 assert(rmap);
703
704 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
705
706 if (!zvrf)
707 return CMD_WARNING;
708
709 if (strcasecmp(proto, "any") == 0)
710 rtype = ZEBRA_ROUTE_MAX;
711 else
712 rtype = proto_name2num(proto);
713 if (rtype < 0) {
714 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
715 return CMD_WARNING_CONFIG_FAILED;
716 }
717
718 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
719
720 return ret;
721 }
722
723 DEFPY_YANG (no_ip_protocol,
724 no_ip_protocol_cmd,
725 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
726 " $proto [route-map ROUTE-MAP$rmap]",
727 NO_STR
728 IP_STR
729 "Stop filtering routing info between zebra and protocol\n"
730 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
731 "Specify route-map\n"
732 "Route map name\n")
733 {
734 int ret, rtype;
735
736 assert(proto);
737
738 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
739
740 if (!zvrf)
741 return CMD_WARNING;
742
743 if (strcasecmp(proto, "any") == 0)
744 rtype = ZEBRA_ROUTE_MAX;
745 else
746 rtype = proto_name2num(proto);
747 if (rtype < 0) {
748 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
749 return CMD_WARNING_CONFIG_FAILED;
750 }
751
752 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
753
754 return ret;
755 }
756
757 DEFPY_YANG (show_ip_protocol,
758 show_ip_protocol_cmd,
759 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
760 SHOW_STR
761 IP_STR
762 "IP protocol filtering status\n"
763 VRF_FULL_CMD_HELP_STR)
764 {
765 int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name);
766
767 return ret;
768 }
769
770 DEFPY_YANG (ipv6_protocol,
771 ipv6_protocol_cmd,
772 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
773 " $proto route-map ROUTE-MAP$rmap",
774 IP6_STR
775 "Filter IPv6 routing info exchanged between zebra and protocol\n"
776 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
777 "Specify route-map\n"
778 "Route map name\n")
779 {
780 int ret, rtype;
781
782 assert(rmap);
783 assert(proto);
784
785 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
786
787 if (!zvrf)
788 return CMD_WARNING;
789
790 if (strcasecmp(proto, "any") == 0)
791 rtype = ZEBRA_ROUTE_MAX;
792 else
793 rtype = proto_name2num(proto);
794 if (rtype < 0) {
795 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
796 return CMD_WARNING_CONFIG_FAILED;
797 }
798
799 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
800
801 return ret;
802 }
803
804 DEFPY_YANG (no_ipv6_protocol,
805 no_ipv6_protocol_cmd,
806 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
807 " $proto [route-map ROUTE-MAP$rmap]",
808 NO_STR
809 IP6_STR
810 "Stop filtering IPv6 routing info between zebra and protocol\n"
811 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
812 "Specify route-map\n"
813 "Route map name\n")
814 {
815 int ret, rtype;
816
817 assert(proto);
818
819 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
820
821 if (!zvrf)
822 return CMD_WARNING;
823
824 if (strcasecmp(proto, "any") == 0)
825 rtype = ZEBRA_ROUTE_MAX;
826 else
827 rtype = proto_name2num(proto);
828 if (rtype < 0) {
829 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
830 return CMD_WARNING_CONFIG_FAILED;
831 }
832
833 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
834
835 return ret;
836 }
837
838 DEFPY_YANG (show_ipv6_protocol,
839 show_ipv6_protocol_cmd,
840 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
841 SHOW_STR
842 IP6_STR
843 "IPv6 protocol filtering status\n"
844 VRF_FULL_CMD_HELP_STR)
845 {
846 int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name);
847
848 return ret;
849 }
850
851 DEFPY_YANG (ip_protocol_nht_rmap,
852 ip_protocol_nht_rmap_cmd,
853 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
854 " $proto route-map ROUTE-MAP$rmap",
855 IP_STR
856 "Filter Next Hop tracking route resolution\n"
857 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
858 "Specify route map\n"
859 "Route map name\n")
860 {
861
862 int ret, rtype;
863
864 assert(proto);
865 assert(rmap);
866
867 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
868
869 if (!zvrf)
870 return CMD_WARNING;
871
872 if (strcasecmp(proto, "any") == 0)
873 rtype = ZEBRA_ROUTE_MAX;
874 else
875 rtype = proto_name2num(proto);
876 if (rtype < 0) {
877 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
878 return CMD_WARNING_CONFIG_FAILED;
879 }
880
881 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
882
883 return ret;
884 }
885
886 DEFPY_YANG (no_ip_protocol_nht_rmap,
887 no_ip_protocol_nht_rmap_cmd,
888 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
889 " $proto route-map [ROUTE-MAP$rmap]",
890 NO_STR
891 IP_STR
892 "Filter Next Hop tracking route resolution\n"
893 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
894 "Specify route map\n"
895 "Route map name\n")
896 {
897 int ret, rtype;
898
899 assert(proto);
900
901 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
902
903 if (!zvrf)
904 return CMD_WARNING;
905
906 if (strcasecmp(proto, "any") == 0)
907 rtype = ZEBRA_ROUTE_MAX;
908 else
909 rtype = proto_name2num(proto);
910 if (rtype < 0) {
911 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
912 return CMD_WARNING_CONFIG_FAILED;
913 }
914
915 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
916
917 return ret;
918 }
919
920 DEFPY_YANG (show_ip_protocol_nht,
921 show_ip_protocol_nht_cmd,
922 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
923 SHOW_STR
924 IP_STR
925 "IPv4 nexthop tracking table\n"
926 "IPv4 Next Hop tracking filtering status\n"
927 VRF_CMD_HELP_STR
928 "All VRFs\n"
929 JSON_STR)
930 {
931 int ret;
932 bool uj = use_json(argc, argv);
933
934 ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name, uj);
935
936 return ret;
937 }
938
939 DEFPY_YANG (ipv6_protocol_nht_rmap,
940 ipv6_protocol_nht_rmap_cmd,
941 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
942 " $proto route-map ROUTE-MAP$rmap",
943 IP6_STR
944 "Filter Next Hop tracking route resolution\n"
945 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
946 "Specify route map\n"
947 "Route map name\n")
948 {
949 int ret, rtype;
950
951 assert(rmap);
952 assert(proto);
953
954 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
955
956 if (!zvrf)
957 return CMD_WARNING;
958
959 if (strcasecmp(proto, "any") == 0)
960 rtype = ZEBRA_ROUTE_MAX;
961 else
962 rtype = proto_name2num(proto);
963 if (rtype < 0) {
964 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
965 return CMD_WARNING_CONFIG_FAILED;
966 }
967
968 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
969
970 return ret;
971 }
972
973 DEFPY_YANG (no_ipv6_protocol_nht_rmap,
974 no_ipv6_protocol_nht_rmap_cmd,
975 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
976 " $proto [route-map ROUTE-MAP$rmap]",
977 NO_STR
978 IP6_STR
979 "Filter Next Hop tracking route resolution\n"
980 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
981 "Specify route map\n"
982 "Route map name\n")
983 {
984 int ret, rtype;
985
986 assert(proto);
987
988 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
989
990 if (!zvrf)
991 return CMD_WARNING;
992
993 if (strcasecmp(proto, "any") == 0)
994 rtype = ZEBRA_ROUTE_MAX;
995 else
996 rtype = proto_name2num(proto);
997 if (rtype < 0) {
998 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
999 return CMD_WARNING_CONFIG_FAILED;
1000 }
1001
1002 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
1003
1004 return ret;
1005 }
1006
1007 DEFPY_YANG (show_ipv6_protocol_nht,
1008 show_ipv6_protocol_nht_cmd,
1009 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
1010 SHOW_STR
1011 IP6_STR
1012 "IPv6 nexthop tracking table\n"
1013 "IPv6 Next Hop tracking filtering status\n"
1014 VRF_CMD_HELP_STR
1015 "All VRFs\n"
1016 JSON_STR)
1017 {
1018 int ret;
1019 bool uj = use_json(argc, argv);
1020
1021 ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name, uj);
1022
1023 return ret;
1024 }
1025
1026 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1027
1028 /* `match ip next-hop IP_ACCESS_LIST' */
1029
1030 /* Match function return 1 if match is success else return zero. */
1031 static enum route_map_cmd_result_t
1032 route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
1033 {
1034 struct access_list *alist;
1035 struct nh_rmap_obj *nh_data;
1036 struct prefix_ipv4 p;
1037
1038 nh_data = object;
1039 if (!nh_data)
1040 return RMAP_NOMATCH;
1041
1042 switch (nh_data->nexthop->type) {
1043 case NEXTHOP_TYPE_IFINDEX:
1044 /* Interface routes can't match ip next-hop */
1045 return RMAP_NOMATCH;
1046 case NEXTHOP_TYPE_IPV4_IFINDEX:
1047 case NEXTHOP_TYPE_IPV4:
1048 p.family = AF_INET;
1049 p.prefix = nh_data->nexthop->gate.ipv4;
1050 p.prefixlen = IPV4_MAX_BITLEN;
1051 break;
1052 case NEXTHOP_TYPE_IPV6:
1053 case NEXTHOP_TYPE_IPV6_IFINDEX:
1054 case NEXTHOP_TYPE_BLACKHOLE:
1055 return RMAP_NOMATCH;
1056 }
1057 alist = access_list_lookup(AFI_IP, (char *)rule);
1058 if (alist == NULL)
1059 return RMAP_NOMATCH;
1060
1061 return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
1062 : RMAP_MATCH);
1063 }
1064
1065 /* Route map `ip next-hop' match statement. `arg' should be
1066 access-list name. */
1067 static void *route_match_ip_next_hop_compile(const char *arg)
1068 {
1069 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1070 }
1071
1072 /* Free route map's compiled `. */
1073 static void route_match_ip_next_hop_free(void *rule)
1074 {
1075 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1076 }
1077
1078 /* Route map commands for ip next-hop matching. */
1079 static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
1080 "ip next-hop",
1081 route_match_ip_next_hop,
1082 route_match_ip_next_hop_compile,
1083 route_match_ip_next_hop_free
1084 };
1085
1086 /* `match ip next-hop prefix-list PREFIX_LIST' */
1087
1088 static enum route_map_cmd_result_t
1089 route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
1090 void *object)
1091 {
1092 struct prefix_list *plist;
1093 struct nh_rmap_obj *nh_data;
1094 struct prefix_ipv4 p;
1095
1096 nh_data = (struct nh_rmap_obj *)object;
1097 if (!nh_data)
1098 return RMAP_NOMATCH;
1099
1100 switch (nh_data->nexthop->type) {
1101 case NEXTHOP_TYPE_IFINDEX:
1102 /* Interface routes can't match ip next-hop */
1103 return RMAP_NOMATCH;
1104 case NEXTHOP_TYPE_IPV4_IFINDEX:
1105 case NEXTHOP_TYPE_IPV4:
1106 p.family = AF_INET;
1107 p.prefix = nh_data->nexthop->gate.ipv4;
1108 p.prefixlen = IPV4_MAX_BITLEN;
1109 break;
1110 case NEXTHOP_TYPE_IPV6:
1111 case NEXTHOP_TYPE_IPV6_IFINDEX:
1112 case NEXTHOP_TYPE_BLACKHOLE:
1113 return RMAP_NOMATCH;
1114 }
1115 plist = prefix_list_lookup(AFI_IP, (char *)rule);
1116 if (plist == NULL)
1117 return RMAP_NOMATCH;
1118
1119 return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
1120 : RMAP_MATCH);
1121 }
1122
1123 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
1124 {
1125 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1126 }
1127
1128 static void route_match_ip_next_hop_prefix_list_free(void *rule)
1129 {
1130 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1131 }
1132
1133 static const struct route_map_rule_cmd
1134 route_match_ip_next_hop_prefix_list_cmd = {
1135 "ip next-hop prefix-list",
1136 route_match_ip_next_hop_prefix_list,
1137 route_match_ip_next_hop_prefix_list_compile,
1138 route_match_ip_next_hop_prefix_list_free
1139 };
1140
1141 /* `match ip address IP_ACCESS_LIST' */
1142
1143 /* Match function should return 1 if match is success else return
1144 zero. */
1145 static enum route_map_cmd_result_t
1146 route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
1147 void *object)
1148 {
1149 struct access_list *alist;
1150
1151 alist = access_list_lookup(afi, (char *)rule);
1152 if (alist == NULL)
1153 return RMAP_NOMATCH;
1154
1155 return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
1156 : RMAP_MATCH);
1157 }
1158
1159 static enum route_map_cmd_result_t
1160 route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
1161 {
1162 return route_match_address(AFI_IP, rule, prefix, object);
1163 }
1164
1165 static enum route_map_cmd_result_t
1166 route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
1167 {
1168 return route_match_address(AFI_IP6, rule, prefix, object);
1169 }
1170
1171 /* Route map `ip address' match statement. `arg' should be
1172 access-list name. */
1173 static void *route_match_address_compile(const char *arg)
1174 {
1175 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1176 }
1177
1178 /* Free route map's compiled `ip address' value. */
1179 static void route_match_address_free(void *rule)
1180 {
1181 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1182 }
1183
1184 /* Route map commands for ip address matching. */
1185 static const struct route_map_rule_cmd route_match_ip_address_cmd = {
1186 "ip address",
1187 route_match_ip_address,
1188 route_match_address_compile,
1189 route_match_address_free
1190 };
1191
1192 /* Route map commands for ipv6 address matching. */
1193 static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
1194 "ipv6 address",
1195 route_match_ipv6_address,
1196 route_match_address_compile,
1197 route_match_address_free
1198 };
1199
1200 /* `match ip address prefix-list PREFIX_LIST' */
1201
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)
1205 {
1206 struct prefix_list *plist;
1207
1208 plist = prefix_list_lookup(afi, (char *)rule);
1209 if (plist == NULL)
1210 return RMAP_NOMATCH;
1211
1212 return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
1213 : RMAP_MATCH);
1214 }
1215
1216 static enum route_map_cmd_result_t
1217 route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1218 void *object)
1219 {
1220 return (route_match_address_prefix_list(rule, prefix, object, AFI_IP));
1221 }
1222
1223 static void *route_match_address_prefix_list_compile(const char *arg)
1224 {
1225 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1226 }
1227
1228 static void route_match_address_prefix_list_free(void *rule)
1229 {
1230 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1231 }
1232
1233 static const struct route_map_rule_cmd
1234 route_match_ip_address_prefix_list_cmd = {
1235 "ip address prefix-list",
1236 route_match_ip_address_prefix_list,
1237 route_match_address_prefix_list_compile,
1238 route_match_address_prefix_list_free
1239 };
1240
1241 static enum route_map_cmd_result_t
1242 route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1243 void *object)
1244 {
1245 return (route_match_address_prefix_list(rule, prefix, object, AFI_IP6));
1246 }
1247
1248 static const struct route_map_rule_cmd
1249 route_match_ipv6_address_prefix_list_cmd = {
1250 "ipv6 address prefix-list",
1251 route_match_ipv6_address_prefix_list,
1252 route_match_address_prefix_list_compile,
1253 route_match_address_prefix_list_free
1254 };
1255
1256 /* `match ipv6 next-hop type <TYPE>' */
1257
1258 static enum route_map_cmd_result_t
1259 route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1260 void *object)
1261 {
1262 struct nh_rmap_obj *nh_data;
1263
1264 if (prefix->family == AF_INET6) {
1265 nh_data = (struct nh_rmap_obj *)object;
1266 if (!nh_data)
1267 return RMAP_NOMATCH;
1268
1269 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1270 return RMAP_MATCH;
1271 }
1272
1273 return RMAP_NOMATCH;
1274 }
1275
1276 static void *route_match_ipv6_next_hop_type_compile(const char *arg)
1277 {
1278 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1279 }
1280
1281 static void route_match_ipv6_next_hop_type_free(void *rule)
1282 {
1283 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1284 }
1285
1286 static const struct route_map_rule_cmd
1287 route_match_ipv6_next_hop_type_cmd = {
1288 "ipv6 next-hop type",
1289 route_match_ipv6_next_hop_type,
1290 route_match_ipv6_next_hop_type_compile,
1291 route_match_ipv6_next_hop_type_free
1292 };
1293
1294 /* `match ip address prefix-len PREFIXLEN' */
1295
1296 static enum route_map_cmd_result_t
1297 route_match_address_prefix_len(void *rule, const struct prefix *prefix,
1298 void *object)
1299 {
1300 uint32_t *prefixlen = (uint32_t *)rule;
1301
1302 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1303 }
1304
1305 static void *route_match_address_prefix_len_compile(const char *arg)
1306 {
1307 uint32_t *prefix_len;
1308 char *endptr = NULL;
1309 unsigned long tmpval;
1310
1311 /* prefix len value shoud be integer. */
1312 if (!all_digit(arg))
1313 return NULL;
1314
1315 errno = 0;
1316 tmpval = strtoul(arg, &endptr, 10);
1317 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1318 return NULL;
1319
1320 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1321
1322 *prefix_len = tmpval;
1323 return prefix_len;
1324 }
1325
1326 static void route_match_address_prefix_len_free(void *rule)
1327 {
1328 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1329 }
1330
1331 static const struct route_map_rule_cmd
1332 route_match_ip_address_prefix_len_cmd = {
1333 "ip address prefix-len",
1334 route_match_address_prefix_len,
1335 route_match_address_prefix_len_compile,
1336 route_match_address_prefix_len_free
1337 };
1338
1339 static const struct route_map_rule_cmd
1340 route_match_ipv6_address_prefix_len_cmd = {
1341 "ipv6 address prefix-len",
1342 route_match_address_prefix_len,
1343 route_match_address_prefix_len_compile,
1344 route_match_address_prefix_len_free
1345 };
1346
1347 /* `match ip nexthop prefix-len PREFIXLEN' */
1348
1349 static enum route_map_cmd_result_t
1350 route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
1351 void *object)
1352 {
1353 uint32_t *prefixlen = (uint32_t *)rule;
1354 struct nh_rmap_obj *nh_data;
1355 struct prefix_ipv4 p;
1356
1357 nh_data = (struct nh_rmap_obj *)object;
1358 if (!nh_data || !nh_data->nexthop)
1359 return RMAP_NOMATCH;
1360
1361 switch (nh_data->nexthop->type) {
1362 case NEXTHOP_TYPE_IFINDEX:
1363 /* Interface routes can't match ip next-hop */
1364 return RMAP_NOMATCH;
1365 case NEXTHOP_TYPE_IPV4_IFINDEX:
1366 case NEXTHOP_TYPE_IPV4:
1367 p.family = AF_INET;
1368 p.prefix = nh_data->nexthop->gate.ipv4;
1369 p.prefixlen = IPV4_MAX_BITLEN;
1370 break;
1371 case NEXTHOP_TYPE_IPV6:
1372 case NEXTHOP_TYPE_IPV6_IFINDEX:
1373 case NEXTHOP_TYPE_BLACKHOLE:
1374 return RMAP_NOMATCH;
1375 }
1376 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1377 }
1378
1379 static const struct route_map_rule_cmd
1380 route_match_ip_nexthop_prefix_len_cmd = {
1381 "ip next-hop prefix-len",
1382 route_match_ip_nexthop_prefix_len,
1383 route_match_address_prefix_len_compile, /* reuse */
1384 route_match_address_prefix_len_free /* reuse */
1385 };
1386
1387 /* `match ip next-hop type <blackhole>' */
1388
1389 static enum route_map_cmd_result_t
1390 route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
1391 void *object)
1392 {
1393 struct nh_rmap_obj *nh_data;
1394
1395 if (prefix->family == AF_INET) {
1396 nh_data = (struct nh_rmap_obj *)object;
1397 if (!nh_data)
1398 return RMAP_NOMATCH;
1399
1400 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1401 return RMAP_MATCH;
1402 }
1403
1404 return RMAP_NOMATCH;
1405 }
1406
1407 static void *route_match_ip_next_hop_type_compile(const char *arg)
1408 {
1409 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1410 }
1411
1412 static void route_match_ip_next_hop_type_free(void *rule)
1413 {
1414 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1415 }
1416
1417 static const struct route_map_rule_cmd
1418 route_match_ip_next_hop_type_cmd = {
1419 "ip next-hop type",
1420 route_match_ip_next_hop_type,
1421 route_match_ip_next_hop_type_compile,
1422 route_match_ip_next_hop_type_free
1423 };
1424
1425 /* `match source-protocol PROTOCOL' */
1426
1427 static enum route_map_cmd_result_t
1428 route_match_source_protocol(void *rule, const struct prefix *p, void *object)
1429 {
1430 uint32_t *rib_type = (uint32_t *)rule;
1431 struct nh_rmap_obj *nh_data;
1432
1433 nh_data = (struct nh_rmap_obj *)object;
1434 if (!nh_data)
1435 return RMAP_NOMATCH;
1436
1437 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1438 : RMAP_NOMATCH);
1439 }
1440
1441 static void *route_match_source_protocol_compile(const char *arg)
1442 {
1443 uint32_t *rib_type;
1444 int i;
1445
1446 i = proto_name2num(arg);
1447 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1448
1449 *rib_type = i;
1450
1451 return rib_type;
1452 }
1453
1454 static void route_match_source_protocol_free(void *rule)
1455 {
1456 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1457 }
1458
1459 static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
1460 "source-protocol",
1461 route_match_source_protocol,
1462 route_match_source_protocol_compile,
1463 route_match_source_protocol_free
1464 };
1465
1466 /* `source-instance` */
1467 static enum route_map_cmd_result_t
1468 route_match_source_instance(void *rule, const struct prefix *p, void *object)
1469 {
1470 uint8_t *instance = (uint8_t *)rule;
1471 struct nh_rmap_obj *nh_data;
1472
1473 nh_data = (struct nh_rmap_obj *)object;
1474 if (!nh_data)
1475 return RMAP_NOMATCH;
1476
1477 return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1478 }
1479
1480 static void *route_match_source_instance_compile(const char *arg)
1481 {
1482 uint8_t *instance;
1483 int i;
1484
1485 i = atoi(arg);
1486 instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1487
1488 *instance = i;
1489
1490 return instance;
1491 }
1492
1493 static void route_match_source_instance_free(void *rule)
1494 {
1495 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1496 }
1497
1498 static const struct route_map_rule_cmd route_match_source_instance_cmd = {
1499 "source-instance",
1500 route_match_source_instance,
1501 route_match_source_instance_compile,
1502 route_match_source_instance_free
1503 };
1504
1505 /* `set src A.B.C.D' */
1506
1507 /* Set src. */
1508 static enum route_map_cmd_result_t
1509 route_set_src(void *rule, const struct prefix *prefix, void *object)
1510 {
1511 struct nh_rmap_obj *nh_data;
1512
1513 nh_data = (struct nh_rmap_obj *)object;
1514 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1515
1516 return RMAP_OKAY;
1517 }
1518
1519 /* set src compilation. */
1520 static void *route_set_src_compile(const char *arg)
1521 {
1522 union g_addr src, *psrc;
1523
1524 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1525 || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
1526 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1527 *psrc = src;
1528 return psrc;
1529 }
1530 return NULL;
1531 }
1532
1533 /* Free route map's compiled `set src' value. */
1534 static void route_set_src_free(void *rule)
1535 {
1536 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1537 }
1538
1539 /* Set src rule structure. */
1540 static const struct route_map_rule_cmd route_set_src_cmd = {
1541 "src",
1542 route_set_src,
1543 route_set_src_compile,
1544 route_set_src_free,
1545 };
1546
1547 /* The function checks if the changed routemap specified by parameter rmap
1548 * matches the configured protocol routemaps in proto_rm table. If there is
1549 * a match then rib_update_table() to process the routes.
1550 */
1551 static void zebra_rib_table_rm_update(const char *rmap)
1552 {
1553 int i = 0;
1554 struct route_table *table;
1555 struct vrf *vrf = NULL;
1556 struct zebra_vrf *zvrf = NULL;
1557 char *rmap_name;
1558 struct route_map *old = NULL;
1559
1560 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1561 zvrf = vrf->info;
1562 if (!zvrf)
1563 continue;
1564 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1565 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
1566 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1567 if (IS_ZEBRA_DEBUG_EVENT)
1568 zlog_debug(
1569 "%s : AFI_IP rmap %s, route type %s",
1570 __func__, rmap,
1571 zebra_route_string(i));
1572
1573 old = PROTO_RM_MAP(zvrf, AFI_IP, i);
1574
1575 PROTO_RM_MAP(zvrf, AFI_IP, i) =
1576 route_map_lookup_by_name(rmap_name);
1577 /* old is NULL. i.e Route map creation event.
1578 * So update applied_counter.
1579 * If Old is not NULL, i.e It may be routemap
1580 * updation or deletion.
1581 * So no need to update the counter.
1582 */
1583 if (!old)
1584 route_map_counter_increment(
1585 PROTO_RM_MAP(zvrf, AFI_IP, i));
1586 /* There is single rib table for all protocols
1587 */
1588 table = zvrf->table[AFI_IP][SAFI_UNICAST];
1589 if (table) {
1590 rib_update_table(
1591 table,
1592 RIB_UPDATE_RMAP_CHANGE,
1593 i);
1594 }
1595 }
1596 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
1597 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1598 if (IS_ZEBRA_DEBUG_EVENT)
1599 zlog_debug(
1600 "%s : AFI_IP6 rmap %s, route type %s",
1601 __func__, rmap,
1602 zebra_route_string(i));
1603
1604 old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
1605
1606 PROTO_RM_MAP(zvrf, AFI_IP6, i) =
1607 route_map_lookup_by_name(rmap_name);
1608 if (!old)
1609 route_map_counter_increment(
1610 PROTO_RM_MAP(zvrf, AFI_IP6, i));
1611 /* There is single rib table for all protocols
1612 */
1613 table = zvrf->table[AFI_IP6][SAFI_UNICAST];
1614 if (table) {
1615 rib_update_table(
1616 table,
1617 RIB_UPDATE_RMAP_CHANGE,
1618 i);
1619 }
1620 }
1621 }
1622 }
1623 }
1624
1625 /* The function checks if the changed routemap specified by parameter rmap
1626 * matches the configured protocol routemaps in nht_rm table. If there is
1627 * a match then zebra_evaluate_rnh() to process the nexthops.
1628 */
1629 static void zebra_nht_rm_update(const char *rmap)
1630 {
1631 int i = 0;
1632 struct route_table *table;
1633 struct vrf *vrf = NULL;
1634 struct zebra_vrf *zvrf = NULL;
1635 char *rmap_name;
1636 char afi_ip = 0;
1637 char afi_ipv6 = 0;
1638 struct route_map *old = NULL;
1639
1640 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1641 zvrf = vrf->info;
1642 if (!zvrf)
1643 continue;
1644 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1645 rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i);
1646 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1647 if (IS_ZEBRA_DEBUG_EVENT)
1648 zlog_debug(
1649 "%s : AFI_IP rmap %s, route type %s",
1650 __func__, rmap,
1651 zebra_route_string(i));
1652
1653 old = NHT_RM_MAP(zvrf, AFI_IP, i);
1654
1655 NHT_RM_MAP(zvrf, AFI_IP, i) =
1656 route_map_lookup_by_name(rmap_name);
1657 if (!old)
1658 route_map_counter_increment(
1659 NHT_RM_MAP(zvrf, AFI_IP, i));
1660 /* There is single rib table for all protocols
1661 */
1662 if (afi_ip == 0) {
1663 table = zvrf->table[AFI_IP]
1664 [SAFI_UNICAST];
1665 if (table) {
1666
1667 afi_ip = 1;
1668
1669 zebra_evaluate_rnh(
1670 zvrf, AFI_IP, 1, NULL,
1671 SAFI_UNICAST);
1672 }
1673 }
1674 }
1675
1676 rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
1677 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1678 if (IS_ZEBRA_DEBUG_EVENT)
1679 zlog_debug(
1680 "%s : AFI_IP6 rmap %s, route type %s",
1681 __func__, rmap,
1682 zebra_route_string(i));
1683
1684 old = NHT_RM_MAP(zvrf, AFI_IP6, i);
1685
1686 NHT_RM_MAP(zvrf, AFI_IP6, i) =
1687 route_map_lookup_by_name(rmap_name);
1688 if (!old)
1689 route_map_counter_increment(
1690 NHT_RM_MAP(zvrf, AFI_IP6, i));
1691 /* There is single rib table for all protocols
1692 */
1693 if (afi_ipv6 == 0) {
1694 table = zvrf->table[AFI_IP6]
1695 [SAFI_UNICAST];
1696 if (table) {
1697
1698 afi_ipv6 = 1;
1699
1700 zebra_evaluate_rnh(
1701 zvrf, AFI_IP, 1, NULL,
1702 SAFI_UNICAST);
1703 }
1704 }
1705 }
1706 }
1707 }
1708 }
1709
1710 static void zebra_route_map_process_update_cb(char *rmap_name)
1711 {
1712 if (IS_ZEBRA_DEBUG_EVENT)
1713 zlog_debug("Event handler for route-map: %s",
1714 rmap_name);
1715 zebra_import_table_rm_update(rmap_name);
1716 zebra_rib_table_rm_update(rmap_name);
1717 zebra_nht_rm_update(rmap_name);
1718 }
1719
1720 static void zebra_route_map_update_timer(struct thread *thread)
1721 {
1722 if (IS_ZEBRA_DEBUG_EVENT)
1723 zlog_debug("Event driven route-map update triggered");
1724
1725 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1726 zlog_debug(
1727 "%u: Routemap update-timer fired, scheduling RIB processing",
1728 VRF_DEFAULT);
1729
1730 route_map_walk_update_list(zebra_route_map_process_update_cb);
1731
1732 /*
1733 * This code needs to be updated to be:
1734 * 1) VRF Aware <sigh>
1735 * 2) Route-map aware
1736 */
1737 }
1738
1739 static void zebra_route_map_set_delay_timer(uint32_t value)
1740 {
1741 zebra_rmap_update_timer = value;
1742 if (!value && zebra_t_rmap_update) {
1743 /* Event driven route map updates is being disabled */
1744 /* But there's a pending timer. Fire it off now */
1745 THREAD_OFF(zebra_t_rmap_update);
1746 zebra_route_map_update_timer(NULL);
1747 }
1748 }
1749
1750 void zebra_routemap_finish(void)
1751 {
1752 /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
1753 zebra_rmap_update_timer = 0;
1754 /* Thread off if any scheduled already */
1755 THREAD_OFF(zebra_t_rmap_update);
1756 route_map_finish();
1757 }
1758
1759 route_map_result_t
1760 zebra_route_map_check(afi_t family, int rib_type, uint8_t instance,
1761 const struct prefix *p, struct nexthop *nexthop,
1762 struct zebra_vrf *zvrf, route_tag_t tag)
1763 {
1764 struct route_map *rmap = NULL;
1765 char *rm_name;
1766 route_map_result_t ret = RMAP_PERMITMATCH;
1767 struct nh_rmap_obj nh_obj;
1768
1769 nh_obj.nexthop = nexthop;
1770 nh_obj.vrf_id = nexthop->vrf_id;
1771 nh_obj.source_protocol = rib_type;
1772 nh_obj.instance = instance;
1773 nh_obj.metric = 0;
1774 nh_obj.tag = tag;
1775
1776 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) {
1777 rm_name = PROTO_RM_NAME(zvrf, family, rib_type);
1778 rmap = PROTO_RM_MAP(zvrf, family, rib_type);
1779
1780 if (rm_name && !rmap)
1781 return RMAP_DENYMATCH;
1782 }
1783 if (!rmap) {
1784 rm_name = PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX);
1785 rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
1786
1787 if (rm_name && !rmap)
1788 return RMAP_DENYMATCH;
1789 }
1790 if (rmap) {
1791 ret = route_map_apply(rmap, p, &nh_obj);
1792 }
1793
1794 return (ret);
1795 }
1796
1797 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1798 {
1799 return zebra_import_table_routemap[afi][table];
1800 }
1801
1802 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1803 uint32_t table)
1804 {
1805 zebra_import_table_routemap[afi][table] =
1806 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1807 }
1808
1809 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1810 {
1811 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1812 }
1813
1814 route_map_result_t
1815 zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1816 const struct prefix *p,
1817 struct nexthop *nexthop,
1818 vrf_id_t vrf_id, route_tag_t tag,
1819 const char *rmap_name)
1820 {
1821 struct route_map *rmap = NULL;
1822 route_map_result_t ret = RMAP_DENYMATCH;
1823 struct nh_rmap_obj nh_obj;
1824
1825 nh_obj.nexthop = nexthop;
1826 nh_obj.vrf_id = vrf_id;
1827 nh_obj.source_protocol = re_type;
1828 nh_obj.instance = instance;
1829 nh_obj.metric = 0;
1830 nh_obj.tag = tag;
1831
1832 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1833 rmap = route_map_lookup_by_name(rmap_name);
1834 if (rmap) {
1835 ret = route_map_apply(rmap, p, &nh_obj);
1836 }
1837
1838 return (ret);
1839 }
1840
1841 route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
1842 const struct prefix *p,
1843 struct zebra_vrf *zvrf,
1844 struct route_entry *re,
1845 struct nexthop *nexthop)
1846 {
1847 struct route_map *rmap = NULL;
1848 route_map_result_t ret = RMAP_PERMITMATCH;
1849 struct nh_rmap_obj nh_obj;
1850
1851 nh_obj.nexthop = nexthop;
1852 nh_obj.vrf_id = nexthop->vrf_id;
1853 nh_obj.source_protocol = re->type;
1854 nh_obj.instance = re->instance;
1855 nh_obj.metric = re->metric;
1856 nh_obj.tag = re->tag;
1857
1858 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1859 rmap = NHT_RM_MAP(zvrf, afi, client_proto);
1860 if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
1861 rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
1862 if (rmap)
1863 ret = route_map_apply(rmap, p, &nh_obj);
1864
1865 return ret;
1866 }
1867
1868 static void zebra_route_map_mark_update(const char *rmap_name)
1869 {
1870 /* rmap_update_timer of 0 means don't do route updates */
1871 if (zebra_rmap_update_timer)
1872 THREAD_OFF(zebra_t_rmap_update);
1873
1874 thread_add_timer(zrouter.master, zebra_route_map_update_timer,
1875 NULL, zebra_rmap_update_timer, &zebra_t_rmap_update);
1876 }
1877
1878 static void zebra_route_map_add(const char *rmap_name)
1879 {
1880 if (route_map_mark_updated(rmap_name) == 0)
1881 zebra_route_map_mark_update(rmap_name);
1882
1883 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1884 }
1885
1886 static void zebra_route_map_delete(const char *rmap_name)
1887 {
1888 if (route_map_mark_updated(rmap_name) == 0)
1889 zebra_route_map_mark_update(rmap_name);
1890
1891 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1892 }
1893
1894 static void zebra_route_map_event(const char *rmap_name)
1895 {
1896 if (route_map_mark_updated(rmap_name) == 0)
1897 zebra_route_map_mark_update(rmap_name);
1898
1899 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1900 }
1901
1902 void zebra_routemap_vrf_delete(struct zebra_vrf *zvrf)
1903 {
1904 afi_t afi;
1905 uint8_t type;
1906
1907 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1908 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
1909 if (PROTO_RM_NAME(zvrf, afi, type))
1910 XFREE(MTYPE_ROUTE_MAP_NAME,
1911 PROTO_RM_NAME(zvrf, afi, type));
1912 if (NHT_RM_NAME(zvrf, afi, type))
1913 XFREE(MTYPE_ROUTE_MAP_NAME,
1914 NHT_RM_NAME(zvrf, afi, type));
1915 }
1916 }
1917 }
1918
1919 /* ip protocol configuration write function */
1920 void zebra_routemap_config_write_protocol(struct vty *vty,
1921 struct zebra_vrf *zvrf)
1922 {
1923 int i;
1924 char space[2];
1925
1926 memset(space, 0, sizeof(space));
1927
1928 if (zvrf_id(zvrf) != VRF_DEFAULT)
1929 snprintf(space, sizeof(space), "%s", " ");
1930
1931 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1932 if (PROTO_RM_NAME(zvrf, AFI_IP, i))
1933 vty_out(vty, "%sip protocol %s route-map %s\n", space,
1934 zebra_route_string(i),
1935 PROTO_RM_NAME(zvrf, AFI_IP, i));
1936
1937 if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
1938 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
1939 zebra_route_string(i),
1940 PROTO_RM_NAME(zvrf, AFI_IP6, i));
1941
1942 if (NHT_RM_NAME(zvrf, AFI_IP, i))
1943 vty_out(vty, "%sip nht %s route-map %s\n", space,
1944 zebra_route_string(i),
1945 NHT_RM_NAME(zvrf, AFI_IP, i));
1946
1947 if (NHT_RM_NAME(zvrf, AFI_IP6, i))
1948 vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
1949 zebra_route_string(i),
1950 NHT_RM_NAME(zvrf, AFI_IP6, i));
1951 }
1952
1953 if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1954 vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
1955 PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1956
1957 if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1958 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
1959 PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1960
1961 if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1962 vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
1963 NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1964
1965 if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1966 vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
1967 NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1968
1969 if (zvrf_id(zvrf) == VRF_DEFAULT
1970 && zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1971 vty_out(vty, "zebra route-map delay-timer %d\n",
1972 zebra_rmap_update_timer);
1973 }
1974
1975 void zebra_route_map_init(void)
1976 {
1977 install_element(CONFIG_NODE, &ip_protocol_cmd);
1978 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1979 install_element(VRF_NODE, &ip_protocol_cmd);
1980 install_element(VRF_NODE, &no_ip_protocol_cmd);
1981 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1982 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1983 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1984 install_element(VRF_NODE, &ipv6_protocol_cmd);
1985 install_element(VRF_NODE, &no_ipv6_protocol_cmd);
1986 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1987 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1988 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1989 install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
1990 install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
1991 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1992 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1993 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1994 install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
1995 install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1996 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1997 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1998 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1999
2000 route_map_init();
2001
2002 route_map_add_hook(zebra_route_map_add);
2003 route_map_delete_hook(zebra_route_map_delete);
2004 route_map_event_hook(zebra_route_map_event);
2005
2006 route_map_match_interface_hook(generic_match_add);
2007 route_map_no_match_interface_hook(generic_match_delete);
2008
2009 route_map_match_ip_address_hook(generic_match_add);
2010 route_map_no_match_ip_address_hook(generic_match_delete);
2011
2012 route_map_match_ip_address_prefix_list_hook(generic_match_add);
2013 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
2014
2015 route_map_match_ip_next_hop_hook(generic_match_add);
2016 route_map_no_match_ip_next_hop_hook(generic_match_delete);
2017
2018 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
2019 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
2020
2021 route_map_match_ip_next_hop_type_hook(generic_match_add);
2022 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
2023
2024 route_map_match_tag_hook(generic_match_add);
2025 route_map_no_match_tag_hook(generic_match_delete);
2026
2027 route_map_match_ipv6_address_hook(generic_match_add);
2028 route_map_no_match_ipv6_address_hook(generic_match_delete);
2029
2030 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
2031 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
2032
2033 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
2034 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
2035
2036 route_map_install_match(&route_match_tag_cmd);
2037 route_map_install_match(&route_match_interface_cmd);
2038 route_map_install_match(&route_match_ip_next_hop_cmd);
2039 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
2040 route_map_install_match(&route_match_ip_address_cmd);
2041 route_map_install_match(&route_match_ipv6_address_cmd);
2042 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
2043 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
2044 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
2045 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
2046 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
2047 route_map_install_match(&route_match_ip_next_hop_type_cmd);
2048 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
2049 route_map_install_match(&route_match_source_protocol_cmd);
2050 route_map_install_match(&route_match_source_instance_cmd);
2051
2052 /* */
2053 route_map_install_set(&route_set_src_cmd);
2054 /* */
2055 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
2056 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
2057 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
2058 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
2059 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
2060 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
2061 install_element(RMAP_NODE, &match_source_protocol_cmd);
2062 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
2063 install_element(RMAP_NODE, &match_source_instance_cmd);
2064 install_element(RMAP_NODE, &no_match_source_instance_cmd);
2065
2066 /* */
2067 install_element(RMAP_NODE, &set_src_cmd);
2068 install_element(RMAP_NODE, &no_set_src_cmd);
2069 }