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