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