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