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