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