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