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