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