]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
Merge pull request #1383 from chiragshah6/ospf_vrf_dev
[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
35 #include "zebra/zserv.h"
36 #include "zebra/redistribute.h"
37 #include "zebra/debug.h"
38 #include "zebra/zebra_rnh.h"
39 #include "zebra/zebra_routemap.h"
40
41 static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
42 static struct thread *zebra_t_rmap_update = NULL;
43 char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */
44 /* NH Tracking route map */
45 char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */
46 char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
47
48 struct nh_rmap_obj {
49 struct nexthop *nexthop;
50 vrf_id_t vrf_id;
51 u_int32_t source_protocol;
52 int metric;
53 route_tag_t tag;
54 };
55
56 static void zebra_route_map_set_delay_timer(u_int32_t value);
57
58
59 /* Add zebra route map rule */
60 static int zebra_route_match_add(struct vty *vty, const char *command,
61 const char *arg, route_map_event_t type)
62 {
63 VTY_DECLVAR_CONTEXT(route_map_index, index);
64 int ret;
65 int retval = CMD_SUCCESS;
66
67 ret = route_map_add_match(index, command, arg);
68 switch (ret) {
69 case RMAP_RULE_MISSING:
70 vty_out(vty, "%% Zebra Can't find rule.\n");
71 retval = CMD_WARNING_CONFIG_FAILED;
72 break;
73 case RMAP_COMPILE_ERROR:
74 vty_out(vty, "%% Zebra Argument is malformed.\n");
75 retval = CMD_WARNING_CONFIG_FAILED;
76 break;
77 case RMAP_COMPILE_SUCCESS:
78 if (type != RMAP_EVENT_MATCH_ADDED) {
79 route_map_upd8_dependency(type, arg, index->map->name);
80 }
81 break;
82 }
83
84 return retval;
85 }
86
87 /* Delete zebra route map rule. */
88 static int zebra_route_match_delete(struct vty *vty, const char *command,
89 const char *arg, route_map_event_t type)
90 {
91 VTY_DECLVAR_CONTEXT(route_map_index, index);
92 int ret;
93 int retval = CMD_SUCCESS;
94 char *dep_name = NULL;
95 const char *tmpstr;
96 char *rmap_name = NULL;
97
98 if (type != RMAP_EVENT_MATCH_DELETED) {
99 /* ignore the mundane, the types without any dependency */
100 if (arg == NULL) {
101 if ((tmpstr = route_map_get_match_arg(index, command))
102 != NULL)
103 dep_name =
104 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
105 } else {
106 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
107 }
108 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
109 }
110
111 ret = route_map_delete_match(index, command, arg);
112 switch (ret) {
113 case RMAP_RULE_MISSING:
114 vty_out(vty, "%% Zebra Can't find rule.\n");
115 retval = CMD_WARNING_CONFIG_FAILED;
116 break;
117 case RMAP_COMPILE_ERROR:
118 vty_out(vty, "%% Zebra Argument is malformed.\n");
119 retval = CMD_WARNING_CONFIG_FAILED;
120 break;
121 case RMAP_COMPILE_SUCCESS:
122 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
123 route_map_upd8_dependency(type, dep_name, rmap_name);
124 break;
125 }
126
127 if (dep_name)
128 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
129 if (rmap_name)
130 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
131
132 return retval;
133 }
134
135 /* 'match tag TAG'
136 * Match function return 1 if match is success else return 0
137 */
138 static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
139 route_map_object_t type, void *object)
140 {
141 route_tag_t *tag;
142 struct nh_rmap_obj *nh_data;
143
144 if (type == RMAP_ZEBRA) {
145 tag = rule;
146 nh_data = object;
147
148 if (nh_data->tag == *tag)
149 return RMAP_MATCH;
150 }
151 return RMAP_NOMATCH;
152 }
153
154 /* Route map commands for tag matching */
155 static struct route_map_rule_cmd route_match_tag_cmd = {
156 "tag", route_match_tag, route_map_rule_tag_compile,
157 route_map_rule_tag_free,
158 };
159
160
161 /* `match interface IFNAME' */
162 /* Match function return 1 if match is success else return zero. */
163 static route_map_result_t route_match_interface(void *rule,
164 struct prefix *prefix,
165 route_map_object_t type,
166 void *object)
167 {
168 struct nh_rmap_obj *nh_data;
169 char *ifname = rule;
170 ifindex_t ifindex;
171
172 if (type == RMAP_ZEBRA) {
173 if (strcasecmp(ifname, "any") == 0)
174 return RMAP_MATCH;
175 nh_data = object;
176 if (!nh_data || !nh_data->nexthop)
177 return RMAP_NOMATCH;
178 ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
179 if (ifindex == 0)
180 return RMAP_NOMATCH;
181 if (nh_data->nexthop->ifindex == ifindex)
182 return RMAP_MATCH;
183 }
184 return RMAP_NOMATCH;
185 }
186
187 /* Route map `match interface' match statement. `arg' is IFNAME value */
188 static void *route_match_interface_compile(const char *arg)
189 {
190 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
191 }
192
193 /* Free route map's compiled `match interface' value. */
194 static void route_match_interface_free(void *rule)
195 {
196 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
197 }
198
199 /* Route map commands for interface matching */
200 struct route_map_rule_cmd route_match_interface_cmd = {
201 "interface", route_match_interface, route_match_interface_compile,
202 route_match_interface_free};
203
204 DEFUN (match_ip_address_prefix_len,
205 match_ip_address_prefix_len_cmd,
206 "match ip address prefix-len (0-32)",
207 MATCH_STR
208 IP_STR
209 "Match prefix length of ip address\n"
210 "Match prefix length of ip address\n"
211 "Prefix length\n")
212 {
213 return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg,
214 RMAP_EVENT_MATCH_ADDED);
215 }
216
217 DEFUN (no_match_ip_address_prefix_len,
218 no_match_ip_address_prefix_len_cmd,
219 "no match ip address prefix-len [(0-32)]",
220 NO_STR
221 MATCH_STR
222 IP_STR
223 "Match prefix length of ip address\n"
224 "Match prefix length of ip address\n"
225 "Prefix length\n")
226 {
227 char *plen = (argc == 6) ? argv[5]->arg : NULL;
228 return zebra_route_match_delete(vty, "ip address prefix-len", plen,
229 RMAP_EVENT_MATCH_DELETED);
230 }
231
232
233 DEFUN (match_ip_nexthop_prefix_len,
234 match_ip_nexthop_prefix_len_cmd,
235 "match ip next-hop prefix-len (0-32)",
236 MATCH_STR
237 IP_STR
238 "Match prefixlen of nexthop ip address\n"
239 "Match prefixlen of given nexthop\n"
240 "Prefix length\n")
241 {
242 return zebra_route_match_add(vty, "ip next-hop prefix-len",
243 argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
244 }
245
246 DEFUN (no_match_ip_nexthop_prefix_len,
247 no_match_ip_nexthop_prefix_len_cmd,
248 "no match ip next-hop prefix-len [(0-32)]",
249 NO_STR
250 MATCH_STR
251 IP_STR
252 "Match prefixlen of nexthop ip address\n"
253 "Match prefix length of nexthop\n"
254 "Prefix length\n")
255 {
256 char *plen = (argc == 6) ? argv[5]->arg : NULL;
257 return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen,
258 RMAP_EVENT_MATCH_DELETED);
259 }
260
261
262 DEFUN (match_source_protocol,
263 match_source_protocol_cmd,
264 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>",
265 MATCH_STR
266 "Match protocol via which the route was learnt\n"
267 "BGP protocol\n"
268 "OSPF protocol\n"
269 "RIP protocol\n"
270 "RIPNG protocol\n"
271 "ISIS protocol\n"
272 "OSPF6 protocol\n"
273 "PIM protocol\n"
274 "NHRP protocol\n"
275 "EIGRP protocol\n"
276 "BABEL protocol\n"
277 "Routes from directly connected peer\n"
278 "Routes from system configuration\n"
279 "Routes from kernel\n"
280 "Statically configured routes\n")
281 {
282 char *proto = argv[2]->text;
283 int i;
284
285 i = proto_name2num(proto);
286 if (i < 0) {
287 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
288 return CMD_WARNING_CONFIG_FAILED;
289 }
290 return zebra_route_match_add(vty, "source-protocol", proto,
291 RMAP_EVENT_MATCH_ADDED);
292 }
293
294 DEFUN (no_match_source_protocol,
295 no_match_source_protocol_cmd,
296 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>]",
297 NO_STR
298 MATCH_STR
299 "No match protocol via which the route was learnt\n"
300 "BGP protocol\n"
301 "OSPF protocol\n"
302 "RIP protocol\n"
303 "RIPNG protocol\n"
304 "ISIS protocol\n"
305 "OSPF6 protocol\n"
306 "PIM protocol\n"
307 "NHRP protocol\n"
308 "EIGRP protocol\n"
309 "BABEL protocol\n"
310 "Routes from directly connected peer\n"
311 "Routes from system configuration\n"
312 "Routes from kernel\n"
313 "Statically configured routes\n")
314 {
315 char *proto = (argc == 4) ? argv[3]->text : NULL;
316 return zebra_route_match_delete(vty, "source-protocol", proto,
317 RMAP_EVENT_MATCH_DELETED);
318 }
319
320 /* set functions */
321
322 DEFUN (set_src,
323 set_src_cmd,
324 "set src <A.B.C.D|X:X::X:X>",
325 SET_STR
326 "src address for route\n"
327 "IPv4 src address\n"
328 "IPv6 src address\n")
329 {
330 int idx_ip = 2;
331 union g_addr src;
332 struct interface *pif = NULL;
333 int family;
334 struct prefix p;
335 struct vrf *vrf;
336
337 if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) {
338 if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) {
339 vty_out(vty, "%% not a valid IPv4/v6 address\n");
340 return CMD_WARNING_CONFIG_FAILED;
341 }
342
343 p.family = family = AF_INET6;
344 p.u.prefix6 = src.ipv6;
345 p.prefixlen = IPV6_MAX_BITLEN;
346 } else {
347 p.family = family = AF_INET;
348 p.u.prefix4 = src.ipv4;
349 p.prefixlen = IPV4_MAX_BITLEN;
350 }
351
352 if (!zebra_check_addr(&p)) {
353 vty_out(vty, "%% not a valid source IPv4/v6 address\n");
354 return CMD_WARNING_CONFIG_FAILED;
355 }
356
357 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
358 if (family == AF_INET)
359 pif = if_lookup_exact_address((void *)&src.ipv4,
360 AF_INET, vrf->vrf_id);
361 else if (family == AF_INET6)
362 pif = if_lookup_exact_address((void *)&src.ipv6,
363 AF_INET6, vrf->vrf_id);
364
365 if (pif != NULL)
366 break;
367 }
368
369 if (!pif) {
370 vty_out(vty, "%% not a local address\n");
371 return CMD_WARNING_CONFIG_FAILED;
372 }
373
374 VTY_DECLVAR_CONTEXT(route_map_index, index);
375 return generic_set_add(vty, index, "src", argv[idx_ip]->arg);
376 }
377
378 DEFUN (no_set_src,
379 no_set_src_cmd,
380 "no set src [<A.B.C.D|X:X::X:X>]",
381 NO_STR
382 SET_STR
383 "Source address for route\n"
384 "IPv4 address\n"
385 "IPv6 address\n")
386 {
387 char *ip = (argc == 4) ? argv[3]->arg : NULL;
388 VTY_DECLVAR_CONTEXT(route_map_index, index);
389 return generic_set_delete(vty, index, "src", ip);
390 }
391
392 DEFUN (zebra_route_map_timer,
393 zebra_route_map_timer_cmd,
394 "zebra route-map delay-timer (0-600)",
395 ZEBRA_STR
396 "Set route-map parameters\n"
397 "Time to wait before route-map updates are processed\n"
398 "0 means event-driven updates are disabled\n")
399 {
400 int idx_number = 3;
401 u_int32_t rmap_delay_timer;
402
403 rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
404 zebra_route_map_set_delay_timer(rmap_delay_timer);
405
406 return (CMD_SUCCESS);
407 }
408
409 DEFUN (no_zebra_route_map_timer,
410 no_zebra_route_map_timer_cmd,
411 "no zebra route-map delay-timer [(0-600)]",
412 NO_STR
413 ZEBRA_STR
414 "Set route-map parameters\n"
415 "Reset delay-timer to default value, 30 secs\n"
416 "0 means event-driven updates are disabled\n")
417 {
418 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
419
420 return (CMD_SUCCESS);
421 }
422
423
424 DEFUN (ip_protocol,
425 ip_protocol_cmd,
426 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
427 IP_STR
428 "Filter routing info exchanged between zebra and protocol\n"
429 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
430 "Specify route-map\n"
431 "Route map name\n")
432 {
433 char *proto = argv[2]->text;
434 char *rmap = argv[4]->arg;
435 int i;
436
437 if (strcasecmp(proto, "any") == 0)
438 i = ZEBRA_ROUTE_MAX;
439 else
440 i = proto_name2num(proto);
441 if (i < 0) {
442 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
443 return CMD_WARNING_CONFIG_FAILED;
444 }
445 if (proto_rm[AFI_IP][i]) {
446 if (strcmp(proto_rm[AFI_IP][i], rmap) == 0)
447 return CMD_SUCCESS;
448
449 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
450 }
451 proto_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
452
453 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
454 zlog_debug(
455 "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
456 VRF_DEFAULT, proto);
457
458 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
459 return CMD_SUCCESS;
460 }
461
462 DEFUN (no_ip_protocol,
463 no_ip_protocol_cmd,
464 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
465 NO_STR
466 IP_STR
467 "Stop filtering routing info between zebra and protocol\n"
468 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
469 "Specify route map\n"
470 "Route map name\n")
471 {
472 char *proto = argv[3]->text;
473 char *rmap = (argc == 6) ? argv[5]->arg : NULL;
474 int i;
475
476 if (strcasecmp(proto, "any") == 0)
477 i = ZEBRA_ROUTE_MAX;
478 else
479 i = proto_name2num(proto);
480
481 if (i < 0) {
482 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
483 return CMD_WARNING_CONFIG_FAILED;
484 }
485
486 if (!proto_rm[AFI_IP][i])
487 return CMD_SUCCESS;
488
489 if (!rmap || strcmp(rmap, proto_rm[AFI_IP][i]) == 0) {
490 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
491 proto_rm[AFI_IP][i] = NULL;
492
493 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
494 zlog_debug(
495 "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
496 VRF_DEFAULT, proto);
497 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
498 }
499 return CMD_SUCCESS;
500 }
501
502 DEFUN (show_ip_protocol,
503 show_ip_protocol_cmd,
504 "show ip protocol",
505 SHOW_STR
506 IP_STR
507 "IP protocol filtering status\n")
508 {
509 int i;
510
511 vty_out(vty, "Protocol : route-map \n");
512 vty_out(vty, "------------------------\n");
513 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
514 if (proto_rm[AFI_IP][i])
515 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
516 proto_rm[AFI_IP][i]);
517 else
518 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
519 }
520 if (proto_rm[AFI_IP][i])
521 vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP][i]);
522 else
523 vty_out(vty, "%-10s : none\n", "any");
524
525 return CMD_SUCCESS;
526 }
527
528 DEFUN (ipv6_protocol,
529 ipv6_protocol_cmd,
530 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
531 IP6_STR
532 "Filter IPv6 routing info exchanged between zebra and protocol\n"
533 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
534 "Specify route map\n"
535 "Route map name\n")
536 {
537 char *proto = argv[2]->text;
538 char *rmap = argv[4]->arg;
539 int i;
540
541 if (strcasecmp(proto, "any") == 0)
542 i = ZEBRA_ROUTE_MAX;
543 else
544 i = proto_name2num(proto);
545 if (i < 0) {
546 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
547 return CMD_WARNING_CONFIG_FAILED;
548 }
549 if (proto_rm[AFI_IP6][i]) {
550 if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0)
551 return CMD_SUCCESS;
552
553 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
554 }
555 proto_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
556
557 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
558 zlog_debug(
559 "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
560 VRF_DEFAULT, proto);
561
562 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
563 return CMD_SUCCESS;
564 }
565
566 DEFUN (no_ipv6_protocol,
567 no_ipv6_protocol_cmd,
568 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
569 NO_STR
570 IP6_STR
571 "Stop filtering IPv6 routing info between zebra and protocol\n"
572 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
573 "Specify route map\n"
574 "Route map name\n")
575 {
576 const char *proto = argv[3]->text;
577 const char *rmap = (argc == 6) ? argv[5]->arg : NULL;
578 int i;
579
580 if (strcasecmp(proto, "any") == 0)
581 i = ZEBRA_ROUTE_MAX;
582 else
583 i = proto_name2num(proto);
584 if (i < 0) {
585 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
586 return CMD_WARNING_CONFIG_FAILED;
587 }
588 if (!proto_rm[AFI_IP6][i])
589 return CMD_SUCCESS;
590
591 if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) {
592 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
593 proto_rm[AFI_IP6][i] = NULL;
594
595 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
596 zlog_debug(
597 "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
598 VRF_DEFAULT, proto);
599
600 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
601 }
602 return CMD_SUCCESS;
603 }
604
605 DEFUN (show_ipv6_protocol,
606 show_ipv6_protocol_cmd,
607 "show ipv6 protocol",
608 SHOW_STR
609 IP6_STR
610 "IPv6 protocol filtering status\n")
611 {
612 int i;
613
614 vty_out(vty, "Protocol : route-map \n");
615 vty_out(vty, "------------------------\n");
616 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
617 if (proto_rm[AFI_IP6][i])
618 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
619 proto_rm[AFI_IP6][i]);
620 else
621 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
622 }
623 if (proto_rm[AFI_IP6][i])
624 vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP6][i]);
625 else
626 vty_out(vty, "%-10s : none\n", "any");
627
628 return CMD_SUCCESS;
629 }
630
631 DEFUN (ip_protocol_nht_rmap,
632 ip_protocol_nht_rmap_cmd,
633 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
634 IP_STR
635 "Filter Next Hop tracking route resolution\n"
636 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
637 "Specify route map\n"
638 "Route map name\n")
639 {
640 char *proto = argv[2]->text;
641 char *rmap = argv[4]->arg;
642 int i;
643
644 if (strcasecmp(proto, "any") == 0)
645 i = ZEBRA_ROUTE_MAX;
646 else
647 i = proto_name2num(proto);
648 if (i < 0) {
649 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
650 return CMD_WARNING_CONFIG_FAILED;
651 }
652 if (nht_rm[AFI_IP][i]) {
653 if (strcmp(nht_rm[AFI_IP][i], rmap) == 0)
654 return CMD_SUCCESS;
655
656 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
657 }
658
659 nht_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
660 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
661
662 return CMD_SUCCESS;
663 }
664
665 DEFUN (no_ip_protocol_nht_rmap,
666 no_ip_protocol_nht_rmap_cmd,
667 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
668 NO_STR
669 IP_STR
670 "Filter Next Hop tracking route resolution\n"
671 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
672 "Specify route map\n"
673 "Route map name\n")
674 {
675 int idx = 0;
676 char *proto = argv[3]->text;
677 char *rmap = argv_find(argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg
678 : NULL;
679
680 int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX
681 : proto_name2num(proto);
682
683 if (i < 0) {
684 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
685 return CMD_WARNING_CONFIG_FAILED;
686 }
687
688 if (!nht_rm[AFI_IP][i])
689 return CMD_SUCCESS;
690
691 if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) {
692 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
693 nht_rm[AFI_IP][i] = NULL;
694 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
695 }
696 return CMD_SUCCESS;
697 }
698
699 DEFUN (show_ip_protocol_nht,
700 show_ip_protocol_nht_cmd,
701 "show ip nht route-map",
702 SHOW_STR
703 IP_STR
704 "IP nexthop tracking table\n"
705 "IP Next Hop tracking filtering status\n")
706 {
707 int i;
708
709 vty_out(vty, "Protocol : route-map \n");
710 vty_out(vty, "------------------------\n");
711 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
712 if (nht_rm[AFI_IP][i])
713 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
714 nht_rm[AFI_IP][i]);
715 else
716 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
717 }
718 if (nht_rm[AFI_IP][i])
719 vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP][i]);
720 else
721 vty_out(vty, "%-10s : none\n", "any");
722
723 return CMD_SUCCESS;
724 }
725
726 DEFUN (ipv6_protocol_nht_rmap,
727 ipv6_protocol_nht_rmap_cmd,
728 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
729 IP6_STR
730 "Filter Next Hop tracking route resolution\n"
731 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
732 "Specify route map\n"
733 "Route map name\n")
734 {
735 char *proto = argv[2]->text;
736 char *rmap = argv[4]->arg;
737 int i;
738
739 if (strcasecmp(proto, "any") == 0)
740 i = ZEBRA_ROUTE_MAX;
741 else
742 i = proto_name2num(proto);
743 if (i < 0) {
744 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
745 return CMD_WARNING_CONFIG_FAILED;
746 }
747 if (nht_rm[AFI_IP6][i])
748 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
749 nht_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
750 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
751
752 return CMD_SUCCESS;
753 }
754
755 DEFUN (no_ipv6_protocol_nht_rmap,
756 no_ipv6_protocol_nht_rmap_cmd,
757 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
758 NO_STR
759 IP6_STR
760 "Filter Next Hop tracking route resolution\n"
761 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
762 "Specify route map\n"
763 "Route map name\n")
764 {
765 char *proto = argv[3]->text;
766 char *rmap = (argc == 6) ? argv[5]->arg : NULL;
767 int i;
768
769 if (strcasecmp(proto, "any") == 0)
770 i = ZEBRA_ROUTE_MAX;
771 else
772 i = proto_name2num(proto);
773 if (i < 0) {
774 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
775 return CMD_WARNING_CONFIG_FAILED;
776 }
777
778 if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) {
779 vty_out(vty, "invalid route-map \"%s\"\n", rmap);
780 return CMD_WARNING_CONFIG_FAILED;
781 }
782
783 if (nht_rm[AFI_IP6][i]) {
784 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
785 nht_rm[AFI_IP6][i] = NULL;
786 }
787
788 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
789
790 return CMD_SUCCESS;
791 }
792
793 DEFUN (show_ipv6_protocol_nht,
794 show_ipv6_protocol_nht_cmd,
795 "show ipv6 nht route-map",
796 SHOW_STR
797 IP6_STR
798 "Next Hop filtering status\n"
799 "Route-map\n")
800 {
801 int i;
802
803 vty_out(vty, "Protocol : route-map \n");
804 vty_out(vty, "------------------------\n");
805 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
806 if (nht_rm[AFI_IP6][i])
807 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
808 nht_rm[AFI_IP6][i]);
809 else
810 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
811 }
812 if (nht_rm[AFI_IP][i])
813 vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP6][i]);
814 else
815 vty_out(vty, "%-10s : none\n", "any");
816
817 return CMD_SUCCESS;
818 }
819
820 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
821
822 /* `match ip next-hop IP_ACCESS_LIST' */
823
824 /* Match function return 1 if match is success else return zero. */
825 static route_map_result_t route_match_ip_next_hop(void *rule,
826 struct prefix *prefix,
827 route_map_object_t type,
828 void *object)
829 {
830 struct access_list *alist;
831 struct nh_rmap_obj *nh_data;
832 struct prefix_ipv4 p;
833
834 if (type == RMAP_ZEBRA) {
835 nh_data = object;
836 if (!nh_data)
837 return RMAP_DENYMATCH;
838
839 switch (nh_data->nexthop->type) {
840 case NEXTHOP_TYPE_IFINDEX:
841 /* Interface routes can't match ip next-hop */
842 return RMAP_NOMATCH;
843 case NEXTHOP_TYPE_IPV4_IFINDEX:
844 case NEXTHOP_TYPE_IPV4:
845 p.family = AF_INET;
846 p.prefix = nh_data->nexthop->gate.ipv4;
847 p.prefixlen = IPV4_MAX_BITLEN;
848 break;
849 default:
850 return RMAP_NOMATCH;
851 }
852 alist = access_list_lookup(AFI_IP, (char *)rule);
853 if (alist == NULL)
854 return RMAP_NOMATCH;
855
856 return (access_list_apply(alist, &p) == FILTER_DENY
857 ? RMAP_NOMATCH
858 : RMAP_MATCH);
859 }
860 return RMAP_NOMATCH;
861 }
862
863 /* Route map `ip next-hop' match statement. `arg' should be
864 access-list name. */
865 static void *route_match_ip_next_hop_compile(const char *arg)
866 {
867 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
868 }
869
870 /* Free route map's compiled `. */
871 static void route_match_ip_next_hop_free(void *rule)
872 {
873 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
874 }
875
876 /* Route map commands for ip next-hop matching. */
877 static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
878 "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
879 route_match_ip_next_hop_free};
880
881 /* `match ip next-hop prefix-list PREFIX_LIST' */
882
883 static route_map_result_t
884 route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
885 route_map_object_t type, void *object)
886 {
887 struct prefix_list *plist;
888 struct nh_rmap_obj *nh_data;
889 struct prefix_ipv4 p;
890
891 if (type == RMAP_ZEBRA) {
892 nh_data = (struct nh_rmap_obj *)object;
893 if (!nh_data)
894 return RMAP_DENYMATCH;
895
896 switch (nh_data->nexthop->type) {
897 case NEXTHOP_TYPE_IFINDEX:
898 /* Interface routes can't match ip next-hop */
899 return RMAP_NOMATCH;
900 case NEXTHOP_TYPE_IPV4_IFINDEX:
901 case NEXTHOP_TYPE_IPV4:
902 p.family = AF_INET;
903 p.prefix = nh_data->nexthop->gate.ipv4;
904 p.prefixlen = IPV4_MAX_BITLEN;
905 break;
906 default:
907 return RMAP_NOMATCH;
908 }
909 plist = prefix_list_lookup(AFI_IP, (char *)rule);
910 if (plist == NULL)
911 return RMAP_NOMATCH;
912
913 return (prefix_list_apply(plist, &p) == PREFIX_DENY
914 ? RMAP_NOMATCH
915 : RMAP_MATCH);
916 }
917 return RMAP_NOMATCH;
918 }
919
920 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
921 {
922 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
923 }
924
925 static void route_match_ip_next_hop_prefix_list_free(void *rule)
926 {
927 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
928 }
929
930 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
931 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
932 route_match_ip_next_hop_prefix_list_compile,
933 route_match_ip_next_hop_prefix_list_free};
934
935 /* `match ip address IP_ACCESS_LIST' */
936
937 /* Match function should return 1 if match is success else return
938 zero. */
939 static route_map_result_t route_match_ip_address(void *rule,
940 struct prefix *prefix,
941 route_map_object_t type,
942 void *object)
943 {
944 struct access_list *alist;
945
946 if (type == RMAP_ZEBRA) {
947 alist = access_list_lookup(AFI_IP, (char *)rule);
948 if (alist == NULL)
949 return RMAP_NOMATCH;
950
951 return (access_list_apply(alist, prefix) == FILTER_DENY
952 ? RMAP_NOMATCH
953 : RMAP_MATCH);
954 }
955 return RMAP_NOMATCH;
956 }
957
958 /* Route map `ip address' match statement. `arg' should be
959 access-list name. */
960 static void *route_match_ip_address_compile(const char *arg)
961 {
962 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
963 }
964
965 /* Free route map's compiled `ip address' value. */
966 static void route_match_ip_address_free(void *rule)
967 {
968 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
969 }
970
971 /* Route map commands for ip address matching. */
972 static struct route_map_rule_cmd route_match_ip_address_cmd = {
973 "ip address", route_match_ip_address, route_match_ip_address_compile,
974 route_match_ip_address_free};
975
976 /* `match ip address prefix-list PREFIX_LIST' */
977
978 static route_map_result_t
979 route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
980 route_map_object_t type, void *object)
981 {
982 struct prefix_list *plist;
983
984 if (type == RMAP_ZEBRA) {
985 plist = prefix_list_lookup(AFI_IP, (char *)rule);
986 if (plist == NULL)
987 return RMAP_NOMATCH;
988
989 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
990 ? RMAP_NOMATCH
991 : RMAP_MATCH);
992 }
993 return RMAP_NOMATCH;
994 }
995
996 static void *route_match_ip_address_prefix_list_compile(const char *arg)
997 {
998 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
999 }
1000
1001 static void route_match_ip_address_prefix_list_free(void *rule)
1002 {
1003 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1004 }
1005
1006 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
1007 "ip address prefix-list", route_match_ip_address_prefix_list,
1008 route_match_ip_address_prefix_list_compile,
1009 route_match_ip_address_prefix_list_free};
1010
1011
1012 /* `match ip address prefix-len PREFIXLEN' */
1013
1014 static route_map_result_t
1015 route_match_ip_address_prefix_len(void *rule, struct prefix *prefix,
1016 route_map_object_t type, void *object)
1017 {
1018 u_int32_t *prefixlen = (u_int32_t *)rule;
1019
1020 if (type == RMAP_ZEBRA) {
1021 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
1022 : RMAP_NOMATCH);
1023 }
1024 return RMAP_NOMATCH;
1025 }
1026
1027 static void *route_match_ip_address_prefix_len_compile(const char *arg)
1028 {
1029 u_int32_t *prefix_len;
1030 char *endptr = NULL;
1031 unsigned long tmpval;
1032
1033 /* prefix len value shoud be integer. */
1034 if (!all_digit(arg))
1035 return NULL;
1036
1037 errno = 0;
1038 tmpval = strtoul(arg, &endptr, 10);
1039 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1040 return NULL;
1041
1042 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t));
1043
1044 if (!prefix_len)
1045 return prefix_len;
1046
1047 *prefix_len = tmpval;
1048 return prefix_len;
1049 }
1050
1051 static void route_match_ip_address_prefix_len_free(void *rule)
1052 {
1053 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1054 }
1055
1056 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = {
1057 "ip address prefix-len", route_match_ip_address_prefix_len,
1058 route_match_ip_address_prefix_len_compile,
1059 route_match_ip_address_prefix_len_free};
1060
1061
1062 /* `match ip nexthop prefix-len PREFIXLEN' */
1063
1064 static route_map_result_t
1065 route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix,
1066 route_map_object_t type, void *object)
1067 {
1068 u_int32_t *prefixlen = (u_int32_t *)rule;
1069 struct nh_rmap_obj *nh_data;
1070 struct prefix_ipv4 p;
1071
1072 if (type == RMAP_ZEBRA) {
1073 nh_data = (struct nh_rmap_obj *)object;
1074 if (!nh_data || !nh_data->nexthop)
1075 return RMAP_DENYMATCH;
1076
1077 switch (nh_data->nexthop->type) {
1078 case NEXTHOP_TYPE_IFINDEX:
1079 /* Interface routes can't match ip next-hop */
1080 return RMAP_NOMATCH;
1081 case NEXTHOP_TYPE_IPV4_IFINDEX:
1082 case NEXTHOP_TYPE_IPV4:
1083 p.family = AF_INET;
1084 p.prefix = nh_data->nexthop->gate.ipv4;
1085 p.prefixlen = IPV4_MAX_BITLEN;
1086 break;
1087 default:
1088 return RMAP_NOMATCH;
1089 }
1090 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
1091 : RMAP_NOMATCH);
1092 }
1093 return RMAP_NOMATCH;
1094 }
1095
1096 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
1097 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len,
1098 route_match_ip_address_prefix_len_compile, /* reuse */
1099 route_match_ip_address_prefix_len_free /* reuse */
1100 };
1101
1102 /* `match source-protocol PROTOCOL' */
1103
1104 static route_map_result_t route_match_source_protocol(void *rule,
1105 struct prefix *prefix,
1106 route_map_object_t type,
1107 void *object)
1108 {
1109 u_int32_t *rib_type = (u_int32_t *)rule;
1110 struct nh_rmap_obj *nh_data;
1111
1112 if (type == RMAP_ZEBRA) {
1113 nh_data = (struct nh_rmap_obj *)object;
1114 if (!nh_data)
1115 return RMAP_DENYMATCH;
1116
1117 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1118 : RMAP_NOMATCH);
1119 }
1120 return RMAP_NOMATCH;
1121 }
1122
1123 static void *route_match_source_protocol_compile(const char *arg)
1124 {
1125 u_int32_t *rib_type;
1126 int i;
1127
1128 i = proto_name2num(arg);
1129 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t));
1130
1131 *rib_type = i;
1132
1133 return rib_type;
1134 }
1135
1136 static void route_match_source_protocol_free(void *rule)
1137 {
1138 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1139 }
1140
1141 static struct route_map_rule_cmd route_match_source_protocol_cmd = {
1142 "source-protocol", route_match_source_protocol,
1143 route_match_source_protocol_compile, route_match_source_protocol_free};
1144
1145 /* `set src A.B.C.D' */
1146
1147 /* Set src. */
1148 static route_map_result_t route_set_src(void *rule, struct prefix *prefix,
1149 route_map_object_t type, void *object)
1150 {
1151 struct nh_rmap_obj *nh_data;
1152
1153 if (type == RMAP_ZEBRA) {
1154 nh_data = (struct nh_rmap_obj *)object;
1155 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1156 }
1157 return RMAP_OKAY;
1158 }
1159
1160 /* set src compilation. */
1161 static void *route_set_src_compile(const char *arg)
1162 {
1163 union g_addr src, *psrc;
1164
1165 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1166 || (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) {
1167 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1168 *psrc = src;
1169 return psrc;
1170 }
1171 return NULL;
1172 }
1173
1174 /* Free route map's compiled `set src' value. */
1175 static void route_set_src_free(void *rule)
1176 {
1177 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1178 }
1179
1180 /* Set src rule structure. */
1181 static struct route_map_rule_cmd route_set_src_cmd = {
1182 "src", route_set_src, route_set_src_compile, route_set_src_free,
1183 };
1184
1185 static int zebra_route_map_update_timer(struct thread *thread)
1186 {
1187 zebra_t_rmap_update = NULL;
1188
1189 if (IS_ZEBRA_DEBUG_EVENT)
1190 zlog_debug("Event driven route-map update triggered");
1191
1192 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1193 zlog_debug(
1194 "%u: Routemap update-timer fired, scheduling RIB processing",
1195 VRF_DEFAULT);
1196
1197 zebra_import_table_rm_update();
1198 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
1199 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1200 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1201
1202 return (0);
1203 }
1204
1205 static void zebra_route_map_set_delay_timer(u_int32_t value)
1206 {
1207 zebra_rmap_update_timer = value;
1208 if (!value && zebra_t_rmap_update) {
1209 /* Event driven route map updates is being disabled */
1210 /* But there's a pending timer. Fire it off now */
1211 thread_cancel(zebra_t_rmap_update);
1212 zebra_route_map_update_timer(zebra_t_rmap_update);
1213 }
1214 }
1215
1216 void zebra_route_map_write_delay_timer(struct vty *vty)
1217 {
1218 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1219 vty_out(vty, "zebra route-map delay-timer %d\n",
1220 zebra_rmap_update_timer);
1221 return;
1222 }
1223
1224 route_map_result_t zebra_route_map_check(int family, int rib_type,
1225 struct prefix *p,
1226 struct nexthop *nexthop,
1227 vrf_id_t vrf_id, route_tag_t tag)
1228 {
1229 struct route_map *rmap = NULL;
1230 route_map_result_t ret = RMAP_MATCH;
1231 struct nh_rmap_obj nh_obj;
1232
1233 nh_obj.nexthop = nexthop;
1234 nh_obj.vrf_id = vrf_id;
1235 nh_obj.source_protocol = rib_type;
1236 nh_obj.metric = 0;
1237 nh_obj.tag = tag;
1238
1239 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1240 rmap = route_map_lookup_by_name(proto_rm[family][rib_type]);
1241 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1242 rmap = route_map_lookup_by_name(
1243 proto_rm[family][ZEBRA_ROUTE_MAX]);
1244 if (rmap) {
1245 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1246 }
1247
1248 return (ret);
1249 }
1250
1251 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1252 {
1253 return zebra_import_table_routemap[afi][table];
1254 }
1255
1256 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1257 uint32_t table)
1258 {
1259 zebra_import_table_routemap[afi][table] =
1260 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1261 }
1262
1263 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1264 {
1265 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1266 }
1267
1268 route_map_result_t
1269 zebra_import_table_route_map_check(int family, int re_type, struct prefix *p,
1270 struct nexthop *nexthop, vrf_id_t vrf_id,
1271 route_tag_t tag, const char *rmap_name)
1272 {
1273 struct route_map *rmap = NULL;
1274 route_map_result_t ret = RMAP_DENYMATCH;
1275 struct nh_rmap_obj nh_obj;
1276
1277 nh_obj.nexthop = nexthop;
1278 nh_obj.vrf_id = vrf_id;
1279 nh_obj.source_protocol = re_type;
1280 nh_obj.metric = 0;
1281 nh_obj.tag = tag;
1282
1283 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1284 rmap = route_map_lookup_by_name(rmap_name);
1285 if (rmap) {
1286 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1287 }
1288
1289 return (ret);
1290 }
1291
1292 route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
1293 struct prefix *p,
1294 struct route_entry *re,
1295 struct nexthop *nexthop)
1296 {
1297 struct route_map *rmap = NULL;
1298 route_map_result_t ret = RMAP_MATCH;
1299 struct nh_rmap_obj nh_obj;
1300
1301 nh_obj.nexthop = nexthop;
1302 nh_obj.vrf_id = re->vrf_id;
1303 nh_obj.source_protocol = re->type;
1304 nh_obj.metric = re->metric;
1305 nh_obj.tag = re->tag;
1306
1307 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1308 rmap = route_map_lookup_by_name(nht_rm[family][client_proto]);
1309 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1310 rmap = route_map_lookup_by_name(
1311 nht_rm[family][ZEBRA_ROUTE_MAX]);
1312 if (rmap) {
1313 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1314 }
1315
1316 return (ret);
1317 }
1318
1319 static void zebra_route_map_mark_update(const char *rmap_name)
1320 {
1321 /* rmap_update_timer of 0 means don't do route updates */
1322 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1323 zebra_t_rmap_update = NULL;
1324 thread_add_timer(zebrad.master, zebra_route_map_update_timer,
1325 NULL, zebra_rmap_update_timer,
1326 &zebra_t_rmap_update);
1327 }
1328 }
1329
1330 static void zebra_route_map_add(const char *rmap_name)
1331 {
1332 zebra_route_map_mark_update(rmap_name);
1333 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1334 }
1335
1336 static void zebra_route_map_delete(const char *rmap_name)
1337 {
1338 zebra_route_map_mark_update(rmap_name);
1339 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1340 }
1341
1342 static void zebra_route_map_event(route_map_event_t event,
1343 const char *rmap_name)
1344 {
1345 zebra_route_map_mark_update(rmap_name);
1346 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1347 }
1348
1349 /* ip protocol configuration write function */
1350 void zebra_routemap_config_write_protocol(struct vty *vty)
1351 {
1352 int i;
1353
1354 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1355 if (proto_rm[AFI_IP][i])
1356 vty_out(vty, "ip protocol %s route-map %s\n",
1357 zebra_route_string(i), proto_rm[AFI_IP][i]);
1358
1359 if (proto_rm[AFI_IP6][i])
1360 vty_out(vty, "ipv6 protocol %s route-map %s\n",
1361 zebra_route_string(i), proto_rm[AFI_IP6][i]);
1362
1363 if (nht_rm[AFI_IP][i])
1364 vty_out(vty, "ip nht %s route-map %s\n",
1365 zebra_route_string(i), nht_rm[AFI_IP][i]);
1366
1367 if (nht_rm[AFI_IP6][i])
1368 vty_out(vty, "ipv6 nht %s route-map %s\n",
1369 zebra_route_string(i), nht_rm[AFI_IP6][i]);
1370 }
1371
1372 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1373 vty_out(vty, "ip protocol %s route-map %s\n", "any",
1374 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1375
1376 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1377 vty_out(vty, "ipv6 protocol %s route-map %s\n", "any",
1378 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1379
1380 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1381 vty_out(vty, "ip nht %s route-map %s\n", "any",
1382 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1383
1384 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1385 vty_out(vty, "ipv6 nht %s route-map %s\n", "any",
1386 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1387
1388 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1389 vty_out(vty, "zebra route-map delay-timer %d\n",
1390 zebra_rmap_update_timer);
1391 }
1392
1393 void zebra_route_map_init()
1394 {
1395 install_element(CONFIG_NODE, &ip_protocol_cmd);
1396 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1397 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1398 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1399 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1400 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1401 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1402 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1403 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1404 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1405 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1406 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1407 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1408 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1409
1410 route_map_init();
1411
1412 route_map_add_hook(zebra_route_map_add);
1413 route_map_delete_hook(zebra_route_map_delete);
1414 route_map_event_hook(zebra_route_map_event);
1415
1416 route_map_match_interface_hook(generic_match_add);
1417 route_map_no_match_interface_hook(generic_match_delete);
1418
1419 route_map_match_ip_address_hook(generic_match_add);
1420 route_map_no_match_ip_address_hook(generic_match_delete);
1421
1422 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1423 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1424
1425 route_map_match_ip_next_hop_hook(generic_match_add);
1426 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1427
1428 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1429 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1430
1431 route_map_match_tag_hook(generic_match_add);
1432 route_map_no_match_tag_hook(generic_match_delete);
1433
1434 route_map_install_match(&route_match_tag_cmd);
1435 route_map_install_match(&route_match_interface_cmd);
1436 route_map_install_match(&route_match_ip_next_hop_cmd);
1437 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
1438 route_map_install_match(&route_match_ip_address_cmd);
1439 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
1440 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
1441 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
1442 route_map_install_match(&route_match_source_protocol_cmd);
1443 /* */
1444 route_map_install_set(&route_set_src_cmd);
1445 /* */
1446 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1447 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1448 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
1449 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1450 install_element(RMAP_NODE, &match_source_protocol_cmd);
1451 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
1452 /* */
1453 install_element(RMAP_NODE, &set_src_cmd);
1454 install_element(RMAP_NODE, &no_set_src_cmd);
1455 }