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