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