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