]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
Merge pull request #3168 from adharkar/frr-bgp_json
[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_ip_address(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_IP, (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 /* Route map `ip address' match statement. `arg' should be
1139 access-list name. */
1140 static void *route_match_ip_address_compile(const char *arg)
1141 {
1142 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1143 }
1144
1145 /* Free route map's compiled `ip address' value. */
1146 static void route_match_ip_address_free(void *rule)
1147 {
1148 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1149 }
1150
1151 /* Route map commands for ip address matching. */
1152 static struct route_map_rule_cmd route_match_ip_address_cmd = {
1153 "ip address", route_match_ip_address, route_match_ip_address_compile,
1154 route_match_ip_address_free};
1155
1156 /* `match ip address prefix-list PREFIX_LIST' */
1157
1158 static route_map_result_t
1159 route_match_address_prefix_list(void *rule, const struct prefix *prefix,
1160 route_map_object_t type, void *object, afi_t afi)
1161 {
1162 struct prefix_list *plist;
1163
1164 if (type == RMAP_ZEBRA) {
1165 plist = prefix_list_lookup(afi, (char *)rule);
1166 if (plist == NULL)
1167 return RMAP_NOMATCH;
1168
1169 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
1170 ? RMAP_NOMATCH
1171 : RMAP_MATCH);
1172 }
1173 return RMAP_NOMATCH;
1174 }
1175
1176 static route_map_result_t
1177 route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1178 route_map_object_t type, void *object)
1179 {
1180 return (route_match_address_prefix_list(rule, prefix, type, object,
1181 AFI_IP));
1182 }
1183
1184 static void *route_match_address_prefix_list_compile(const char *arg)
1185 {
1186 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1187 }
1188
1189 static void route_match_address_prefix_list_free(void *rule)
1190 {
1191 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1192 }
1193
1194 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
1195 "ip address prefix-list", route_match_ip_address_prefix_list,
1196 route_match_address_prefix_list_compile,
1197 route_match_address_prefix_list_free};
1198
1199 static route_map_result_t
1200 route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1201 route_map_object_t type, void *object)
1202 {
1203 return (route_match_address_prefix_list(rule, prefix, type, object,
1204 AFI_IP6));
1205 }
1206
1207 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
1208 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
1209 route_match_address_prefix_list_compile,
1210 route_match_address_prefix_list_free};
1211
1212 /* `match ip address prefix-len PREFIXLEN' */
1213
1214 static route_map_result_t
1215 route_match_address_prefix_len(void *rule, const struct prefix *prefix,
1216 route_map_object_t type, void *object)
1217 {
1218 uint32_t *prefixlen = (uint32_t *)rule;
1219
1220 if (type == RMAP_ZEBRA) {
1221 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
1222 : RMAP_NOMATCH);
1223 }
1224 return RMAP_NOMATCH;
1225 }
1226
1227 static void *route_match_address_prefix_len_compile(const char *arg)
1228 {
1229 uint32_t *prefix_len;
1230 char *endptr = NULL;
1231 unsigned long tmpval;
1232
1233 /* prefix len value shoud be integer. */
1234 if (!all_digit(arg))
1235 return NULL;
1236
1237 errno = 0;
1238 tmpval = strtoul(arg, &endptr, 10);
1239 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1240 return NULL;
1241
1242 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1243
1244 *prefix_len = tmpval;
1245 return prefix_len;
1246 }
1247
1248 static void route_match_address_prefix_len_free(void *rule)
1249 {
1250 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1251 }
1252
1253 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = {
1254 "ip address prefix-len", route_match_address_prefix_len,
1255 route_match_address_prefix_len_compile,
1256 route_match_address_prefix_len_free};
1257
1258 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = {
1259 "ipv6 address prefix-len", route_match_address_prefix_len,
1260 route_match_address_prefix_len_compile,
1261 route_match_address_prefix_len_free};
1262
1263 /* `match ip nexthop prefix-len PREFIXLEN' */
1264
1265 static route_map_result_t
1266 route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
1267 route_map_object_t type, void *object)
1268 {
1269 uint32_t *prefixlen = (uint32_t *)rule;
1270 struct nh_rmap_obj *nh_data;
1271 struct prefix_ipv4 p;
1272
1273 if (type == RMAP_ZEBRA) {
1274 nh_data = (struct nh_rmap_obj *)object;
1275 if (!nh_data || !nh_data->nexthop)
1276 return RMAP_DENYMATCH;
1277
1278 switch (nh_data->nexthop->type) {
1279 case NEXTHOP_TYPE_IFINDEX:
1280 /* Interface routes can't match ip next-hop */
1281 return RMAP_NOMATCH;
1282 case NEXTHOP_TYPE_IPV4_IFINDEX:
1283 case NEXTHOP_TYPE_IPV4:
1284 p.family = AF_INET;
1285 p.prefix = nh_data->nexthop->gate.ipv4;
1286 p.prefixlen = IPV4_MAX_BITLEN;
1287 break;
1288 default:
1289 return RMAP_NOMATCH;
1290 }
1291 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
1292 : RMAP_NOMATCH);
1293 }
1294 return RMAP_NOMATCH;
1295 }
1296
1297 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
1298 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len,
1299 route_match_address_prefix_len_compile, /* reuse */
1300 route_match_address_prefix_len_free /* reuse */
1301 };
1302
1303 /* `match source-protocol PROTOCOL' */
1304
1305 static route_map_result_t route_match_source_protocol(void *rule,
1306 const struct prefix *p,
1307 route_map_object_t type,
1308 void *object)
1309 {
1310 uint32_t *rib_type = (uint32_t *)rule;
1311 struct nh_rmap_obj *nh_data;
1312
1313 if (type == RMAP_ZEBRA) {
1314 nh_data = (struct nh_rmap_obj *)object;
1315 if (!nh_data)
1316 return RMAP_DENYMATCH;
1317
1318 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1319 : RMAP_NOMATCH);
1320 }
1321 return RMAP_NOMATCH;
1322 }
1323
1324 static void *route_match_source_protocol_compile(const char *arg)
1325 {
1326 uint32_t *rib_type;
1327 int i;
1328
1329 i = proto_name2num(arg);
1330 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1331
1332 *rib_type = i;
1333
1334 return rib_type;
1335 }
1336
1337 static void route_match_source_protocol_free(void *rule)
1338 {
1339 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1340 }
1341
1342 static struct route_map_rule_cmd route_match_source_protocol_cmd = {
1343 "source-protocol", route_match_source_protocol,
1344 route_match_source_protocol_compile, route_match_source_protocol_free};
1345
1346 /* `source-instance` */
1347 static route_map_result_t route_match_source_instance(void *rule,
1348 const struct prefix *p,
1349 route_map_object_t type,
1350 void *object)
1351 {
1352 uint8_t *instance = (uint8_t *)rule;
1353 struct nh_rmap_obj *nh_data;
1354
1355 if (type != RMAP_ZEBRA)
1356 return RMAP_NOMATCH;
1357
1358 nh_data = (struct nh_rmap_obj *)object;
1359 if (!nh_data)
1360 return RMAP_DENYMATCH;
1361
1362 return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1363 }
1364
1365 static void *route_match_source_instance_compile(const char *arg)
1366 {
1367 uint8_t *instance;
1368 int i;
1369
1370 i = atoi(arg);
1371 instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1372
1373 *instance = i;
1374
1375 return instance;
1376 }
1377
1378 static void route_match_source_instance_free(void *rule)
1379 {
1380 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1381 }
1382
1383 static struct route_map_rule_cmd route_match_source_instance_cmd = {
1384 "source-instance", route_match_source_instance,
1385 route_match_source_instance_compile, route_match_source_instance_free};
1386
1387 /* `set src A.B.C.D' */
1388
1389 /* Set src. */
1390 static route_map_result_t route_set_src(void *rule, const struct prefix *prefix,
1391 route_map_object_t type, void *object)
1392 {
1393 struct nh_rmap_obj *nh_data;
1394
1395 if (type == RMAP_ZEBRA) {
1396 nh_data = (struct nh_rmap_obj *)object;
1397 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1398 }
1399 return RMAP_OKAY;
1400 }
1401
1402 /* set src compilation. */
1403 static void *route_set_src_compile(const char *arg)
1404 {
1405 union g_addr src, *psrc;
1406
1407 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1408 || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
1409 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1410 *psrc = src;
1411 return psrc;
1412 }
1413 return NULL;
1414 }
1415
1416 /* Free route map's compiled `set src' value. */
1417 static void route_set_src_free(void *rule)
1418 {
1419 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1420 }
1421
1422 /* Set src rule structure. */
1423 static struct route_map_rule_cmd route_set_src_cmd = {
1424 "src", route_set_src, route_set_src_compile, route_set_src_free,
1425 };
1426
1427 /* The function checks if the changed routemap specified by parameter rmap
1428 * matches the configured protocol routemaps in proto_rm table. If there is
1429 * a match then rib_update_table() to process the routes.
1430 */
1431 static void zebra_rib_table_rm_update(const char *rmap)
1432 {
1433 int i = 0;
1434 struct route_table *table;
1435 struct vrf *vrf = NULL;
1436 struct zebra_vrf *zvrf = NULL;
1437 char *rmap_name;
1438 char afi_ip = 0;
1439 char afi_ipv6 = 0;
1440
1441 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1442 zvrf = vrf->info;
1443 if (!zvrf)
1444 continue;
1445 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1446 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
1447 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1448 if (IS_ZEBRA_DEBUG_EVENT)
1449 zlog_debug(
1450 "%s : AFI_IP rmap %s, route type %s",
1451 __func__, rmap,
1452 zebra_route_string(i));
1453
1454 PROTO_RM_MAP(zvrf, AFI_IP, i) =
1455 route_map_lookup_by_name(rmap_name);
1456 /* There is single rib table for all protocols
1457 */
1458 if (afi_ip == 0) {
1459 table = zvrf->table[AFI_IP]
1460 [SAFI_UNICAST];
1461 if (table) {
1462
1463 afi_ip = 1;
1464 rib_update_table(
1465 table,
1466 RIB_UPDATE_RMAP_CHANGE);
1467 }
1468 }
1469 }
1470 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
1471 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1472 if (IS_ZEBRA_DEBUG_EVENT)
1473 zlog_debug(
1474 "%s : AFI_IP6 rmap %s, route type %s",
1475 __func__, rmap,
1476 zebra_route_string(i));
1477
1478 PROTO_RM_MAP(zvrf, AFI_IP6, i) =
1479 route_map_lookup_by_name(rmap_name);
1480 /* There is single rib table for all protocols
1481 */
1482 if (afi_ipv6 == 0) {
1483 table = zvrf->table[AFI_IP6]
1484 [SAFI_UNICAST];
1485 if (table) {
1486
1487 afi_ipv6 = 1;
1488 rib_update_table(
1489 table,
1490 RIB_UPDATE_RMAP_CHANGE);
1491 }
1492 }
1493 }
1494 }
1495 }
1496 }
1497
1498 /* The function checks if the changed routemap specified by parameter rmap
1499 * matches the configured protocol routemaps in nht_rm table. If there is
1500 * a match then zebra_evaluate_rnh() to process the nexthops.
1501 */
1502 static void zebra_nht_rm_update(const char *rmap)
1503 {
1504 int i = 0;
1505 struct route_table *table;
1506 struct vrf *vrf = NULL;
1507 struct zebra_vrf *zvrf = NULL;
1508 char *rmap_name;
1509 char afi_ip = 0;
1510 char afi_ipv6 = 0;
1511
1512 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1513 zvrf = vrf->info;
1514 if (!zvrf)
1515 continue;
1516 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1517 rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i);
1518 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1519 if (IS_ZEBRA_DEBUG_EVENT)
1520 zlog_debug(
1521 "%s : AFI_IP rmap %s, route type %s",
1522 __func__, rmap,
1523 zebra_route_string(i));
1524
1525 NHT_RM_MAP(zvrf, AFI_IP, i) =
1526 route_map_lookup_by_name(rmap_name);
1527 /* There is single rib table for all protocols
1528 */
1529 if (afi_ip == 0) {
1530 table = zvrf->table[AFI_IP]
1531 [SAFI_UNICAST];
1532 if (table) {
1533
1534 afi_ip = 1;
1535
1536 zebra_evaluate_rnh(
1537 zvrf, AF_INET, 1,
1538 RNH_NEXTHOP_TYPE, NULL);
1539 }
1540 }
1541 }
1542
1543 rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
1544 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1545 if (IS_ZEBRA_DEBUG_EVENT)
1546 zlog_debug(
1547 "%s : AFI_IP6 rmap %s, route type %s",
1548 __func__, rmap,
1549 zebra_route_string(i));
1550
1551 NHT_RM_MAP(zvrf, AFI_IP6, i) =
1552 route_map_lookup_by_name(rmap_name);
1553 /* There is single rib table for all protocols
1554 */
1555 if (afi_ipv6 == 0) {
1556 table = zvrf->table[AFI_IP6]
1557 [SAFI_UNICAST];
1558 if (table) {
1559
1560 afi_ipv6 = 1;
1561
1562 zebra_evaluate_rnh(
1563 zvrf, AF_INET, 1,
1564 RNH_NEXTHOP_TYPE, NULL);
1565 }
1566 }
1567 }
1568 }
1569 }
1570 }
1571
1572 static void zebra_route_map_process_update_cb(char *rmap_name)
1573 {
1574 if (IS_ZEBRA_DEBUG_EVENT)
1575 zlog_debug("Event handler for route-map: %s",
1576 rmap_name);
1577 zebra_import_table_rm_update(rmap_name);
1578 zebra_rib_table_rm_update(rmap_name);
1579 zebra_nht_rm_update(rmap_name);
1580 }
1581
1582 static int zebra_route_map_update_timer(struct thread *thread)
1583 {
1584 zebra_t_rmap_update = NULL;
1585
1586 if (IS_ZEBRA_DEBUG_EVENT)
1587 zlog_debug("Event driven route-map update triggered");
1588
1589 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1590 zlog_debug(
1591 "%u: Routemap update-timer fired, scheduling RIB processing",
1592 VRF_DEFAULT);
1593
1594 route_map_walk_update_list(zebra_route_map_process_update_cb);
1595
1596 /*
1597 * This code needs to be updated to be:
1598 * 1) VRF Aware <sigh>
1599 * 2) Route-map aware
1600 */
1601 return (0);
1602 }
1603
1604 static void zebra_route_map_set_delay_timer(uint32_t value)
1605 {
1606 zebra_rmap_update_timer = value;
1607 if (!value && zebra_t_rmap_update) {
1608 /* Event driven route map updates is being disabled */
1609 /* But there's a pending timer. Fire it off now */
1610 thread_cancel(zebra_t_rmap_update);
1611 zebra_route_map_update_timer(zebra_t_rmap_update);
1612 }
1613 }
1614
1615 void zebra_route_map_write_delay_timer(struct vty *vty)
1616 {
1617 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1618 vty_out(vty, "zebra route-map delay-timer %d\n",
1619 zebra_rmap_update_timer);
1620 return;
1621 }
1622
1623 route_map_result_t
1624 zebra_route_map_check(int family, int rib_type, uint8_t instance,
1625 const struct prefix *p, struct nexthop *nexthop,
1626 struct zebra_vrf *zvrf, route_tag_t tag)
1627 {
1628 struct route_map *rmap = NULL;
1629 route_map_result_t ret = RMAP_MATCH;
1630 struct nh_rmap_obj nh_obj;
1631
1632 nh_obj.nexthop = nexthop;
1633 nh_obj.vrf_id = nexthop->vrf_id;
1634 nh_obj.source_protocol = rib_type;
1635 nh_obj.instance = instance;
1636 nh_obj.metric = 0;
1637 nh_obj.tag = tag;
1638
1639 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1640 rmap = PROTO_RM_MAP(zvrf, family, rib_type);
1641 if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX))
1642 rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
1643 if (rmap) {
1644 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1645 }
1646
1647 return (ret);
1648 }
1649
1650 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1651 {
1652 return zebra_import_table_routemap[afi][table];
1653 }
1654
1655 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1656 uint32_t table)
1657 {
1658 zebra_import_table_routemap[afi][table] =
1659 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1660 }
1661
1662 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1663 {
1664 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1665 }
1666
1667 route_map_result_t
1668 zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1669 const struct prefix *p,
1670 struct nexthop *nexthop,
1671 vrf_id_t vrf_id, route_tag_t tag,
1672 const char *rmap_name)
1673 {
1674 struct route_map *rmap = NULL;
1675 route_map_result_t ret = RMAP_DENYMATCH;
1676 struct nh_rmap_obj nh_obj;
1677
1678 nh_obj.nexthop = nexthop;
1679 nh_obj.vrf_id = vrf_id;
1680 nh_obj.source_protocol = re_type;
1681 nh_obj.instance = instance;
1682 nh_obj.metric = 0;
1683 nh_obj.tag = tag;
1684
1685 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1686 rmap = route_map_lookup_by_name(rmap_name);
1687 if (rmap) {
1688 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1689 }
1690
1691 return (ret);
1692 }
1693
1694 route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
1695 const struct prefix *p,
1696 struct zebra_vrf *zvrf,
1697 struct route_entry *re,
1698 struct nexthop *nexthop)
1699 {
1700 struct route_map *rmap = NULL;
1701 route_map_result_t ret = RMAP_MATCH;
1702 struct nh_rmap_obj nh_obj;
1703
1704 nh_obj.nexthop = nexthop;
1705 nh_obj.vrf_id = nexthop->vrf_id;
1706 nh_obj.source_protocol = re->type;
1707 nh_obj.instance = re->instance;
1708 nh_obj.metric = re->metric;
1709 nh_obj.tag = re->tag;
1710
1711 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1712 rmap = NHT_RM_MAP(zvrf, family, client_proto);
1713 if (!rmap && NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX))
1714 rmap = NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
1715 if (rmap)
1716 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1717
1718 return ret;
1719 }
1720
1721 static void zebra_route_map_mark_update(const char *rmap_name)
1722 {
1723 /* rmap_update_timer of 0 means don't do route updates */
1724 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1725 zebra_t_rmap_update = NULL;
1726 thread_add_timer(zebrad.master, zebra_route_map_update_timer,
1727 NULL, zebra_rmap_update_timer,
1728 &zebra_t_rmap_update);
1729 }
1730 }
1731
1732 static void zebra_route_map_add(const char *rmap_name)
1733 {
1734 if (route_map_mark_updated(rmap_name) == 0)
1735 zebra_route_map_mark_update(rmap_name);
1736
1737 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1738 }
1739
1740 static void zebra_route_map_delete(const char *rmap_name)
1741 {
1742 if (route_map_mark_updated(rmap_name) == 0)
1743 zebra_route_map_mark_update(rmap_name);
1744
1745 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1746 }
1747
1748 static void zebra_route_map_event(route_map_event_t event,
1749 const char *rmap_name)
1750 {
1751 if (route_map_mark_updated(rmap_name) == 0)
1752 zebra_route_map_mark_update(rmap_name);
1753
1754 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1755 }
1756
1757 /* ip protocol configuration write function */
1758 void zebra_routemap_config_write_protocol(struct vty *vty,
1759 struct zebra_vrf *zvrf)
1760 {
1761 int i;
1762 char space[2];
1763
1764 memset(space, 0, sizeof(space));
1765
1766 if (zvrf_id(zvrf) != VRF_DEFAULT)
1767 sprintf(space, "%s", " ");
1768
1769 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1770 if (PROTO_RM_NAME(zvrf, AFI_IP, i))
1771 vty_out(vty, "%sip protocol %s route-map %s\n", space,
1772 zebra_route_string(i),
1773 PROTO_RM_NAME(zvrf, AFI_IP, i));
1774
1775 if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
1776 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
1777 zebra_route_string(i),
1778 PROTO_RM_NAME(zvrf, AFI_IP6, i));
1779
1780 if (NHT_RM_NAME(zvrf, AFI_IP, i))
1781 vty_out(vty, "%sip nht %s route-map %s\n", space,
1782 zebra_route_string(i),
1783 NHT_RM_NAME(zvrf, AFI_IP, i));
1784
1785 if (NHT_RM_NAME(zvrf, AFI_IP6, i))
1786 vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
1787 zebra_route_string(i),
1788 NHT_RM_NAME(zvrf, AFI_IP6, i));
1789 }
1790
1791 if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1792 vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
1793 PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1794
1795 if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1796 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
1797 PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1798
1799 if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1800 vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
1801 NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1802
1803 if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1804 vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
1805 NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1806
1807 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1808 vty_out(vty, "zebra route-map delay-timer %d\n",
1809 zebra_rmap_update_timer);
1810 }
1811
1812 void zebra_route_map_init()
1813 {
1814 install_element(CONFIG_NODE, &ip_protocol_cmd);
1815 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1816 install_element(VRF_NODE, &ip_protocol_cmd);
1817 install_element(VRF_NODE, &no_ip_protocol_cmd);
1818 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1819 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1820 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1821 install_element(VRF_NODE, &ipv6_protocol_cmd);
1822 install_element(VRF_NODE, &no_ipv6_protocol_cmd);
1823 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1824 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1825 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1826 install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
1827 install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
1828 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1829 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1830 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1831 install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
1832 install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1833 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1834 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1835 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1836
1837 route_map_init();
1838
1839 route_map_add_hook(zebra_route_map_add);
1840 route_map_delete_hook(zebra_route_map_delete);
1841 route_map_event_hook(zebra_route_map_event);
1842
1843 route_map_match_interface_hook(generic_match_add);
1844 route_map_no_match_interface_hook(generic_match_delete);
1845
1846 route_map_match_ip_address_hook(generic_match_add);
1847 route_map_no_match_ip_address_hook(generic_match_delete);
1848
1849 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1850 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1851
1852 route_map_match_ip_next_hop_hook(generic_match_add);
1853 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1854
1855 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1856 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1857
1858 route_map_match_tag_hook(generic_match_add);
1859 route_map_no_match_tag_hook(generic_match_delete);
1860
1861 route_map_match_ipv6_address_hook(generic_match_add);
1862 route_map_no_match_ipv6_address_hook(generic_match_delete);
1863
1864 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
1865 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
1866
1867 route_map_install_match(&route_match_tag_cmd);
1868 route_map_install_match(&route_match_interface_cmd);
1869 route_map_install_match(&route_match_ip_next_hop_cmd);
1870 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
1871 route_map_install_match(&route_match_ip_address_cmd);
1872 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
1873 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
1874 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
1875 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
1876 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
1877 route_map_install_match(&route_match_source_protocol_cmd);
1878 route_map_install_match(&route_match_source_instance_cmd);
1879
1880 /* */
1881 route_map_install_set(&route_set_src_cmd);
1882 /* */
1883 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1884 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1885 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
1886 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
1887 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
1888 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1889 install_element(RMAP_NODE, &match_source_protocol_cmd);
1890 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
1891 install_element(RMAP_NODE, &match_source_instance_cmd);
1892 install_element(RMAP_NODE, &no_match_source_instance_cmd);
1893
1894 /* */
1895 install_element(RMAP_NODE, &set_src_cmd);
1896 install_element(RMAP_NODE, &no_set_src_cmd);
1897 }