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