]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_routemap.c
rmap: Add hooks into zebra,ospf,rip for `match ip next-hop type blackhole`
[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);
67 int ret;
9ca25fed 68 int retval = CMD_SUCCESS;
d62a17ae 69
70 ret = route_map_add_match(index, command, arg);
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:
81 if (type != RMAP_EVENT_MATCH_ADDED) {
82 route_map_upd8_dependency(type, arg, index->map->name);
d62a17ae 83 }
9ca25fed 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);
95 int 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
d62a17ae 114 ret = route_map_delete_match(index, command, arg);
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:
125 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
126 route_map_upd8_dependency(type, dep_name, rmap_name);
127 break;
5921ef9a 128 }
518f0eb1 129
0a22ddfb
QY
130 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
131 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
518f0eb1 132
9ca25fed 133 return retval;
5921ef9a
PJ
134}
135
ca84c8ef
DS
136/* 'match tag TAG'
137 * Match function return 1 if match is success else return 0
138 */
123214ef
MS
139static route_map_result_t route_match_tag(void *rule,
140 const struct prefix *prefix,
d62a17ae 141 route_map_object_t type, void *object)
ca84c8ef 142{
d62a17ae 143 route_tag_t *tag;
144 struct nh_rmap_obj *nh_data;
ca84c8ef 145
d62a17ae 146 if (type == RMAP_ZEBRA) {
147 tag = rule;
148 nh_data = object;
ca84c8ef 149
d62a17ae 150 if (nh_data->tag == *tag)
151 return RMAP_MATCH;
152 }
153 return RMAP_NOMATCH;
ca84c8ef
DS
154}
155
ca84c8ef 156/* Route map commands for tag matching */
d62a17ae 157static struct route_map_rule_cmd route_match_tag_cmd = {
9d303b37 158 "tag", route_match_tag, route_map_rule_tag_compile,
d62a17ae 159 route_map_rule_tag_free,
ca84c8ef
DS
160};
161
6b0655a2 162
5921ef9a
PJ
163/* `match interface IFNAME' */
164/* Match function return 1 if match is success else return zero. */
d62a17ae 165static route_map_result_t route_match_interface(void *rule,
123214ef 166 const struct prefix *prefix,
d62a17ae 167 route_map_object_t type,
168 void *object)
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
206 vty_out(vty, "Protocol : route-map\n");
207 vty_out(vty, "------------------------\n");
208
209 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
210 if (PROTO_RM_NAME(zvrf, af_type, i))
211 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
212 PROTO_RM_NAME(zvrf, af_type, i));
213 else
214 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
215 }
216
217 if (PROTO_RM_NAME(zvrf, af_type, i))
218 vty_out(vty, "%-10s : %-10s\n", "any",
219 PROTO_RM_NAME(zvrf, af_type, i));
220 else
221 vty_out(vty, "%-10s : none\n", "any");
222}
223
224static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
225 int af_type)
226{
227 int i;
228
229 vty_out(vty, "Protocol : route-map\n");
230 vty_out(vty, "------------------------\n");
231
232 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
233 if (NHT_RM_NAME(zvrf, af_type, i))
234 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
235 NHT_RM_NAME(zvrf, af_type, i));
236 else
237 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
238 }
239
240 if (NHT_RM_NAME(zvrf, af_type, i))
241 vty_out(vty, "%-10s : %-10s\n", "any",
242 NHT_RM_NAME(zvrf, af_type, i));
243 else
244 vty_out(vty, "%-10s : none\n", "any");
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
708 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
709
710 if (!zvrf)
711 return CMD_WARNING;
d62a17ae 712
713 if (strcasecmp(proto, "any") == 0)
214e5c26 714 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 715 else
214e5c26 716 rtype = proto_name2num(proto);
717 if (rtype < 0) {
d62a17ae 718 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
719 return CMD_WARNING_CONFIG_FAILED;
720 }
518f0eb1 721
214e5c26 722 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
b84c7253 723
214e5c26 724 return ret;
518f0eb1
DS
725}
726
214e5c26 727DEFPY (no_ip_protocol,
518f0eb1 728 no_ip_protocol_cmd,
214e5c26 729 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
730 " $proto [route-map ROUTE-MAP$rmap]",
518f0eb1 731 NO_STR
9f0ea7d4
DS
732 IP_STR
733 "Stop filtering routing info between zebra and protocol\n"
ab0181ee 734 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
214e5c26 735 "Specify route-map\n"
7757e5e1 736 "Route map name\n")
518f0eb1 737{
214e5c26 738 int ret, rtype;
739
740 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
741
742 if (!zvrf)
743 return CMD_WARNING;
518f0eb1 744
d62a17ae 745 if (strcasecmp(proto, "any") == 0)
214e5c26 746 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 747 else
214e5c26 748 rtype = proto_name2num(proto);
749 if (rtype < 0) {
d62a17ae 750 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
751 return CMD_WARNING_CONFIG_FAILED;
752 }
7757e5e1 753
214e5c26 754 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
518f0eb1 755
214e5c26 756 return ret;
518f0eb1
DS
757}
758
7cf16e19 759DEFPY (show_ip_protocol,
518f0eb1 760 show_ip_protocol_cmd,
7cf16e19 761 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
762 SHOW_STR
763 IP_STR
764 "IP protocol filtering status\n"
765 VRF_FULL_CMD_HELP_STR)
518f0eb1 766{
7cf16e19 767 int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name);
518f0eb1 768
7cf16e19 769 return ret;
518f0eb1
DS
770}
771
214e5c26 772DEFPY (ipv6_protocol,
0aabccc0 773 ipv6_protocol_cmd,
214e5c26 774 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
775 " $proto route-map ROUTE-MAP$rmap",
0aabccc0
DD
776 IP6_STR
777 "Filter IPv6 routing info exchanged between zebra and protocol\n"
ab0181ee 778 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
214e5c26 779 "Specify route-map\n"
0aabccc0
DD
780 "Route map name\n")
781{
214e5c26 782 int ret, rtype;
783
784 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
785
786 if (!zvrf)
787 return CMD_WARNING;
d62a17ae 788
789 if (strcasecmp(proto, "any") == 0)
214e5c26 790 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 791 else
214e5c26 792 rtype = proto_name2num(proto);
793 if (rtype < 0) {
d62a17ae 794 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
795 return CMD_WARNING_CONFIG_FAILED;
796 }
0aabccc0 797
214e5c26 798 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
b84c7253 799
214e5c26 800 return ret;
0aabccc0
DD
801}
802
214e5c26 803DEFPY (no_ipv6_protocol,
0aabccc0 804 no_ipv6_protocol_cmd,
214e5c26 805 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
806 " $proto [route-map ROUTE-MAP$rmap]",
0aabccc0
DD
807 NO_STR
808 IP6_STR
809 "Stop filtering IPv6 routing info between zebra and protocol\n"
ab0181ee 810 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
214e5c26 811 "Specify route-map\n"
7757e5e1 812 "Route map name\n")
0aabccc0 813{
214e5c26 814 int ret, rtype;
815
816 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
817
818 if (!zvrf)
819 return CMD_WARNING;
d62a17ae 820
821 if (strcasecmp(proto, "any") == 0)
214e5c26 822 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 823 else
214e5c26 824 rtype = proto_name2num(proto);
825 if (rtype < 0) {
d62a17ae 826 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
827 return CMD_WARNING_CONFIG_FAILED;
828 }
b84c7253 829
214e5c26 830 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
b84c7253 831
214e5c26 832 return ret;
0aabccc0
DD
833}
834
7cf16e19 835DEFPY (show_ipv6_protocol,
0aabccc0 836 show_ipv6_protocol_cmd,
7cf16e19 837 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
838 SHOW_STR
839 IP6_STR
840 "IPv6 protocol filtering status\n"
841 VRF_FULL_CMD_HELP_STR)
0aabccc0 842{
7cf16e19 843 int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name);
0aabccc0 844
7cf16e19 845 return ret;
0aabccc0
DD
846}
847
214e5c26 848DEFPY (ip_protocol_nht_rmap,
9f0ea7d4 849 ip_protocol_nht_rmap_cmd,
214e5c26 850 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
851 " $proto route-map ROUTE-MAP$rmap",
9f0ea7d4
DS
852 IP_STR
853 "Filter Next Hop tracking route resolution\n"
ab0181ee 854 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1 855 "Specify route map\n"
9f0ea7d4
DS
856 "Route map name\n")
857{
214e5c26 858
859 int ret, rtype;
860
861 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
862
863 if (!zvrf)
864 return CMD_WARNING;
d62a17ae 865
866 if (strcasecmp(proto, "any") == 0)
214e5c26 867 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 868 else
214e5c26 869 rtype = proto_name2num(proto);
870 if (rtype < 0) {
d62a17ae 871 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
872 return CMD_WARNING_CONFIG_FAILED;
873 }
6d53d7b1 874
214e5c26 875 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
9f0ea7d4 876
214e5c26 877 return ret;
9f0ea7d4
DS
878}
879
214e5c26 880DEFPY (no_ip_protocol_nht_rmap,
9f0ea7d4 881 no_ip_protocol_nht_rmap_cmd,
214e5c26 882 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
883 " $proto route-map [ROUTE-MAP$rmap]",
9f0ea7d4
DS
884 NO_STR
885 IP_STR
886 "Filter Next Hop tracking route resolution\n"
3b14d86e 887 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1
QY
888 "Specify route map\n"
889 "Route map name\n")
9f0ea7d4 890{
214e5c26 891 int ret, rtype;
55cb6743 892
214e5c26 893 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
9f0ea7d4 894
214e5c26 895 if (!zvrf)
896 return CMD_WARNING;
897
898 if (strcasecmp(proto, "any") == 0)
899 rtype = ZEBRA_ROUTE_MAX;
900 else
901 rtype = proto_name2num(proto);
902 if (rtype < 0) {
d62a17ae 903 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
904 return CMD_WARNING_CONFIG_FAILED;
905 }
55cb6743 906
214e5c26 907 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
9f0ea7d4 908
214e5c26 909 return ret;
9f0ea7d4
DS
910}
911
7cf16e19 912DEFPY (show_ip_protocol_nht,
9f0ea7d4 913 show_ip_protocol_nht_cmd,
7cf16e19 914 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
3a2d747c
QY
915 SHOW_STR
916 IP_STR
917 "IP nexthop tracking table\n"
7cf16e19 918 "IP Next Hop tracking filtering status\n"
919 VRF_FULL_CMD_HELP_STR)
9f0ea7d4 920{
7cf16e19 921 int ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name);
9f0ea7d4 922
7cf16e19 923 return ret;
9f0ea7d4
DS
924}
925
214e5c26 926DEFPY (ipv6_protocol_nht_rmap,
9f0ea7d4 927 ipv6_protocol_nht_rmap_cmd,
214e5c26 928 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
929 " $proto route-map ROUTE-MAP$rmap",
9f0ea7d4
DS
930 IP6_STR
931 "Filter Next Hop tracking route resolution\n"
ab0181ee 932 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1 933 "Specify route map\n"
9f0ea7d4
DS
934 "Route map name\n")
935{
214e5c26 936 int ret, rtype;
937
938 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
939
940 if (!zvrf)
941 return CMD_WARNING;
d62a17ae 942
943 if (strcasecmp(proto, "any") == 0)
214e5c26 944 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 945 else
214e5c26 946 rtype = proto_name2num(proto);
947 if (rtype < 0) {
d62a17ae 948 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
949 return CMD_WARNING_CONFIG_FAILED;
950 }
6d53d7b1 951
214e5c26 952 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
6d53d7b1 953
214e5c26 954 return ret;
9f0ea7d4
DS
955}
956
214e5c26 957DEFPY (no_ipv6_protocol_nht_rmap,
9f0ea7d4 958 no_ipv6_protocol_nht_rmap_cmd,
214e5c26 959 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
960 " $proto [route-map ROUTE-MAP$rmap]",
9f0ea7d4
DS
961 NO_STR
962 IP6_STR
963 "Filter Next Hop tracking route resolution\n"
3b14d86e 964 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1
QY
965 "Specify route map\n"
966 "Route map name\n")
9f0ea7d4 967{
214e5c26 968 int ret, rtype;
969
970 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
971
972 if (!zvrf)
973 return CMD_WARNING;
d62a17ae 974
975 if (strcasecmp(proto, "any") == 0)
214e5c26 976 rtype = ZEBRA_ROUTE_MAX;
d62a17ae 977 else
214e5c26 978 rtype = proto_name2num(proto);
979 if (rtype < 0) {
d62a17ae 980 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
981 return CMD_WARNING_CONFIG_FAILED;
982 }
9f0ea7d4 983
214e5c26 984 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
813d4307 985
214e5c26 986 return ret;
9f0ea7d4
DS
987}
988
7cf16e19 989DEFPY (show_ipv6_protocol_nht,
9f0ea7d4 990 show_ipv6_protocol_nht_cmd,
7cf16e19 991 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
3a2d747c
QY
992 SHOW_STR
993 IP6_STR
994 "Next Hop filtering status\n"
7cf16e19 995 "Route-map\n"
996 VRF_FULL_CMD_HELP_STR)
9f0ea7d4 997{
7cf16e19 998 int ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name);
9f0ea7d4 999
7cf16e19 1000 return ret;
9f0ea7d4
DS
1001}
1002
5921ef9a
PJ
1003/*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1004
1005/* `match ip next-hop IP_ACCESS_LIST' */
1006
1007/* Match function return 1 if match is success else return zero. */
d62a17ae 1008static route_map_result_t route_match_ip_next_hop(void *rule,
123214ef 1009 const struct prefix *prefix,
d62a17ae 1010 route_map_object_t type,
1011 void *object)
1012{
1013 struct access_list *alist;
1014 struct nh_rmap_obj *nh_data;
1015 struct prefix_ipv4 p;
1016
1017 if (type == RMAP_ZEBRA) {
1018 nh_data = object;
1019 if (!nh_data)
1020 return RMAP_DENYMATCH;
1021
1022 switch (nh_data->nexthop->type) {
1023 case NEXTHOP_TYPE_IFINDEX:
1024 /* Interface routes can't match ip next-hop */
1025 return RMAP_NOMATCH;
1026 case NEXTHOP_TYPE_IPV4_IFINDEX:
1027 case NEXTHOP_TYPE_IPV4:
1028 p.family = AF_INET;
1029 p.prefix = nh_data->nexthop->gate.ipv4;
1030 p.prefixlen = IPV4_MAX_BITLEN;
1031 break;
1032 default:
1033 return RMAP_NOMATCH;
1034 }
1035 alist = access_list_lookup(AFI_IP, (char *)rule);
1036 if (alist == NULL)
1037 return RMAP_NOMATCH;
1038
1039 return (access_list_apply(alist, &p) == FILTER_DENY
1040 ? RMAP_NOMATCH
1041 : RMAP_MATCH);
1042 }
5921ef9a 1043 return RMAP_NOMATCH;
5921ef9a
PJ
1044}
1045
1046/* Route map `ip next-hop' match statement. `arg' should be
1047 access-list name. */
d62a17ae 1048static void *route_match_ip_next_hop_compile(const char *arg)
5921ef9a 1049{
d62a17ae 1050 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
5921ef9a
PJ
1051}
1052
1053/* Free route map's compiled `. */
d62a17ae 1054static void route_match_ip_next_hop_free(void *rule)
5921ef9a 1055{
d62a17ae 1056 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
5921ef9a
PJ
1057}
1058
1059/* Route map commands for ip next-hop matching. */
d62a17ae 1060static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
1061 "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
1062 route_match_ip_next_hop_free};
6b0655a2 1063
5921ef9a
PJ
1064/* `match ip next-hop prefix-list PREFIX_LIST' */
1065
1066static route_map_result_t
123214ef 1067route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
d62a17ae 1068 route_map_object_t type, void *object)
5921ef9a 1069{
d62a17ae 1070 struct prefix_list *plist;
1071 struct nh_rmap_obj *nh_data;
1072 struct prefix_ipv4 p;
1073
1074 if (type == RMAP_ZEBRA) {
1075 nh_data = (struct nh_rmap_obj *)object;
1076 if (!nh_data)
1077 return RMAP_DENYMATCH;
1078
1079 switch (nh_data->nexthop->type) {
1080 case NEXTHOP_TYPE_IFINDEX:
1081 /* Interface routes can't match ip next-hop */
1082 return RMAP_NOMATCH;
1083 case NEXTHOP_TYPE_IPV4_IFINDEX:
1084 case NEXTHOP_TYPE_IPV4:
1085 p.family = AF_INET;
1086 p.prefix = nh_data->nexthop->gate.ipv4;
1087 p.prefixlen = IPV4_MAX_BITLEN;
1088 break;
1089 default:
1090 return RMAP_NOMATCH;
1091 }
1092 plist = prefix_list_lookup(AFI_IP, (char *)rule);
1093 if (plist == NULL)
1094 return RMAP_NOMATCH;
1095
1096 return (prefix_list_apply(plist, &p) == PREFIX_DENY
1097 ? RMAP_NOMATCH
1098 : RMAP_MATCH);
1099 }
1100 return RMAP_NOMATCH;
5921ef9a
PJ
1101}
1102
d62a17ae 1103static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
5921ef9a 1104{
d62a17ae 1105 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
5921ef9a
PJ
1106}
1107
d62a17ae 1108static void route_match_ip_next_hop_prefix_list_free(void *rule)
5921ef9a 1109{
d62a17ae 1110 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
5921ef9a
PJ
1111}
1112
d62a17ae 1113static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
1114 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
1115 route_match_ip_next_hop_prefix_list_compile,
1116 route_match_ip_next_hop_prefix_list_free};
6b0655a2 1117
5921ef9a
PJ
1118/* `match ip address IP_ACCESS_LIST' */
1119
1120/* Match function should return 1 if match is success else return
1121 zero. */
86405f9e
DS
1122static route_map_result_t route_match_address(afi_t afi, void *rule,
1123 const struct prefix *prefix,
1124 route_map_object_t type,
1125 void *object)
5921ef9a 1126{
d62a17ae 1127 struct access_list *alist;
1128
1129 if (type == RMAP_ZEBRA) {
86405f9e 1130 alist = access_list_lookup(afi, (char *)rule);
d62a17ae 1131 if (alist == NULL)
1132 return RMAP_NOMATCH;
5921ef9a 1133
d62a17ae 1134 return (access_list_apply(alist, prefix) == FILTER_DENY
1135 ? RMAP_NOMATCH
1136 : RMAP_MATCH);
1137 }
5921ef9a 1138 return RMAP_NOMATCH;
5921ef9a
PJ
1139}
1140
86405f9e
DS
1141static route_map_result_t route_match_ip_address(void *rule,
1142 const struct prefix *prefix,
1143 route_map_object_t type,
1144 void *object)
1145{
1146 return route_match_address(AFI_IP, rule, prefix, type, object);
1147}
1148
1149static route_map_result_t route_match_ipv6_address(void *rule,
1150 const struct prefix *prefix,
1151 route_map_object_t type,
1152 void *object)
1153
1154{
1155 return route_match_address(AFI_IP6, rule, prefix, type, object);
1156}
1157
5921ef9a
PJ
1158/* Route map `ip address' match statement. `arg' should be
1159 access-list name. */
86405f9e 1160static void *route_match_address_compile(const char *arg)
5921ef9a 1161{
d62a17ae 1162 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
5921ef9a
PJ
1163}
1164
1165/* Free route map's compiled `ip address' value. */
86405f9e 1166static void route_match_address_free(void *rule)
5921ef9a 1167{
d62a17ae 1168 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
5921ef9a
PJ
1169}
1170
1171/* Route map commands for ip address matching. */
d62a17ae 1172static struct route_map_rule_cmd route_match_ip_address_cmd = {
86405f9e
DS
1173 "ip address", route_match_ip_address, route_match_address_compile,
1174 route_match_address_free};
1175
1176/* Route map commands for ipv6 address matching. */
1177static struct route_map_rule_cmd route_match_ipv6_address_cmd = {
1178 "ipv6 address", route_match_ipv6_address, route_match_address_compile,
1179 route_match_address_free};
6b0655a2 1180
5921ef9a
PJ
1181/* `match ip address prefix-list PREFIX_LIST' */
1182
1183static route_map_result_t
01ba4505 1184route_match_address_prefix_list(void *rule, const struct prefix *prefix,
1185 route_map_object_t type, void *object, afi_t afi)
5921ef9a 1186{
d62a17ae 1187 struct prefix_list *plist;
1188
1189 if (type == RMAP_ZEBRA) {
01ba4505 1190 plist = prefix_list_lookup(afi, (char *)rule);
d62a17ae 1191 if (plist == NULL)
1192 return RMAP_NOMATCH;
5921ef9a 1193
d62a17ae 1194 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
1195 ? RMAP_NOMATCH
1196 : RMAP_MATCH);
1197 }
5921ef9a 1198 return RMAP_NOMATCH;
5921ef9a
PJ
1199}
1200
01ba4505 1201static route_map_result_t
1202route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1203 route_map_object_t type, void *object)
1204{
1205 return (route_match_address_prefix_list(rule, prefix, type, object,
1206 AFI_IP));
1207}
1208
1209static void *route_match_address_prefix_list_compile(const char *arg)
5921ef9a 1210{
d62a17ae 1211 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
5921ef9a
PJ
1212}
1213
01ba4505 1214static void route_match_address_prefix_list_free(void *rule)
5921ef9a 1215{
d62a17ae 1216 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
5921ef9a
PJ
1217}
1218
d62a17ae 1219static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
1220 "ip address prefix-list", route_match_ip_address_prefix_list,
01ba4505 1221 route_match_address_prefix_list_compile,
1222 route_match_address_prefix_list_free};
1223
1224static route_map_result_t
1225route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1226 route_map_object_t type, void *object)
1227{
1228 return (route_match_address_prefix_list(rule, prefix, type, object,
1229 AFI_IP6));
1230}
5921ef9a 1231
01ba4505 1232static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
1233 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
1234 route_match_address_prefix_list_compile,
1235 route_match_address_prefix_list_free};
6b0655a2 1236
2d818099
DA
1237/* `match ipv6 next-hop type <TYPE>' */
1238
1239static route_map_result_t
1240route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1241 route_map_object_t type, void *object)
1242{
1243 struct nh_rmap_obj *nh_data;
1244
1245 if (type == RMAP_ZEBRA && prefix->family == AF_INET6) {
1246 nh_data = (struct nh_rmap_obj *)object;
1247 if (!nh_data)
1248 return RMAP_DENYMATCH;
1249
1250 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1251 return RMAP_MATCH;
1252 }
1253 return RMAP_NOMATCH;
1254}
1255
1256static void *route_match_ipv6_next_hop_type_compile(const char *arg)
1257{
1258 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1259}
1260
1261static void route_match_ipv6_next_hop_type_free(void *rule)
1262{
1263 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1264}
1265
1266struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
1267 "ipv6 next-hop type", route_match_ipv6_next_hop_type,
1268 route_match_ipv6_next_hop_type_compile,
1269 route_match_ipv6_next_hop_type_free};
1270
9f0ea7d4
DS
1271/* `match ip address prefix-len PREFIXLEN' */
1272
1273static route_map_result_t
123214ef 1274route_match_address_prefix_len(void *rule, const struct prefix *prefix,
5165d46f 1275 route_map_object_t type, void *object)
9f0ea7d4 1276{
d7c0a89a 1277 uint32_t *prefixlen = (uint32_t *)rule;
9f0ea7d4 1278
d62a17ae 1279 if (type == RMAP_ZEBRA) {
1280 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
1281 : RMAP_NOMATCH);
1282 }
1283 return RMAP_NOMATCH;
9f0ea7d4
DS
1284}
1285
5165d46f 1286static void *route_match_address_prefix_len_compile(const char *arg)
9f0ea7d4 1287{
d7c0a89a 1288 uint32_t *prefix_len;
d62a17ae 1289 char *endptr = NULL;
1290 unsigned long tmpval;
9f0ea7d4 1291
d62a17ae 1292 /* prefix len value shoud be integer. */
1293 if (!all_digit(arg))
1294 return NULL;
9f0ea7d4 1295
d62a17ae 1296 errno = 0;
1297 tmpval = strtoul(arg, &endptr, 10);
1298 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1299 return NULL;
9f0ea7d4 1300
d7c0a89a 1301 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
9f0ea7d4 1302
d62a17ae 1303 *prefix_len = tmpval;
1304 return prefix_len;
9f0ea7d4
DS
1305}
1306
5165d46f 1307static void route_match_address_prefix_len_free(void *rule)
9f0ea7d4 1308{
d62a17ae 1309 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
9f0ea7d4
DS
1310}
1311
d62a17ae 1312static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = {
5165d46f
DS
1313 "ip address prefix-len", route_match_address_prefix_len,
1314 route_match_address_prefix_len_compile,
1315 route_match_address_prefix_len_free};
9f0ea7d4 1316
5165d46f
DS
1317static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = {
1318 "ipv6 address prefix-len", route_match_address_prefix_len,
1319 route_match_address_prefix_len_compile,
1320 route_match_address_prefix_len_free};
9f0ea7d4
DS
1321
1322/* `match ip nexthop prefix-len PREFIXLEN' */
1323
1324static route_map_result_t
123214ef 1325route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
d62a17ae 1326 route_map_object_t type, void *object)
1327{
d7c0a89a 1328 uint32_t *prefixlen = (uint32_t *)rule;
d62a17ae 1329 struct nh_rmap_obj *nh_data;
1330 struct prefix_ipv4 p;
1331
1332 if (type == RMAP_ZEBRA) {
1333 nh_data = (struct nh_rmap_obj *)object;
1334 if (!nh_data || !nh_data->nexthop)
1335 return RMAP_DENYMATCH;
1336
1337 switch (nh_data->nexthop->type) {
1338 case NEXTHOP_TYPE_IFINDEX:
1339 /* Interface routes can't match ip next-hop */
1340 return RMAP_NOMATCH;
1341 case NEXTHOP_TYPE_IPV4_IFINDEX:
1342 case NEXTHOP_TYPE_IPV4:
1343 p.family = AF_INET;
1344 p.prefix = nh_data->nexthop->gate.ipv4;
1345 p.prefixlen = IPV4_MAX_BITLEN;
1346 break;
1347 default:
1348 return RMAP_NOMATCH;
1349 }
1350 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
1351 : RMAP_NOMATCH);
1352 }
1353 return RMAP_NOMATCH;
1354}
1355
1356static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
1357 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len,
5165d46f
DS
1358 route_match_address_prefix_len_compile, /* reuse */
1359 route_match_address_prefix_len_free /* reuse */
9f0ea7d4
DS
1360};
1361
2d818099
DA
1362/* `match ip next-hop type <blackhole>' */
1363
1364static route_map_result_t
1365route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
1366 route_map_object_t type, void *object)
1367{
1368 struct nh_rmap_obj *nh_data;
1369
1370 if (type == RMAP_ZEBRA && prefix->family == AF_INET) {
1371 nh_data = (struct nh_rmap_obj *)object;
1372 if (!nh_data)
1373 return RMAP_DENYMATCH;
1374
1375 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1376 return RMAP_MATCH;
1377 }
1378 return RMAP_NOMATCH;
1379}
1380
1381static void *route_match_ip_next_hop_type_compile(const char *arg)
1382{
1383 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1384}
1385
1386static void route_match_ip_next_hop_type_free(void *rule)
1387{
1388 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1389}
1390
1391static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
1392 "ip next-hop type", route_match_ip_next_hop_type,
1393 route_match_ip_next_hop_type_compile,
1394 route_match_ip_next_hop_type_free};
1395
9f0ea7d4
DS
1396/* `match source-protocol PROTOCOL' */
1397
d62a17ae 1398static route_map_result_t route_match_source_protocol(void *rule,
123214ef 1399 const struct prefix *p,
d62a17ae 1400 route_map_object_t type,
1401 void *object)
9f0ea7d4 1402{
d7c0a89a 1403 uint32_t *rib_type = (uint32_t *)rule;
d62a17ae 1404 struct nh_rmap_obj *nh_data;
9f0ea7d4 1405
d62a17ae 1406 if (type == RMAP_ZEBRA) {
1407 nh_data = (struct nh_rmap_obj *)object;
1408 if (!nh_data)
1409 return RMAP_DENYMATCH;
9f0ea7d4 1410
d62a17ae 1411 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1412 : RMAP_NOMATCH);
1413 }
1414 return RMAP_NOMATCH;
9f0ea7d4
DS
1415}
1416
d62a17ae 1417static void *route_match_source_protocol_compile(const char *arg)
9f0ea7d4 1418{
d7c0a89a 1419 uint32_t *rib_type;
d62a17ae 1420 int i;
9f0ea7d4 1421
d62a17ae 1422 i = proto_name2num(arg);
d7c0a89a 1423 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
9f0ea7d4 1424
d62a17ae 1425 *rib_type = i;
9f0ea7d4 1426
d62a17ae 1427 return rib_type;
9f0ea7d4
DS
1428}
1429
d62a17ae 1430static void route_match_source_protocol_free(void *rule)
9f0ea7d4 1431{
d62a17ae 1432 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
9f0ea7d4
DS
1433}
1434
d62a17ae 1435static struct route_map_rule_cmd route_match_source_protocol_cmd = {
1436 "source-protocol", route_match_source_protocol,
1437 route_match_source_protocol_compile, route_match_source_protocol_free};
9f0ea7d4 1438
633a66a5
DS
1439/* `source-instance` */
1440static route_map_result_t route_match_source_instance(void *rule,
123214ef 1441 const struct prefix *p,
633a66a5
DS
1442 route_map_object_t type,
1443 void *object)
1444{
1445 uint8_t *instance = (uint8_t *)rule;
1446 struct nh_rmap_obj *nh_data;
1447
1448 if (type != RMAP_ZEBRA)
1449 return RMAP_NOMATCH;
1450
1451 nh_data = (struct nh_rmap_obj *)object;
1452 if (!nh_data)
1453 return RMAP_DENYMATCH;
1454
1455 return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1456}
1457
1458static void *route_match_source_instance_compile(const char *arg)
1459{
1460 uint8_t *instance;
1461 int i;
1462
1463 i = atoi(arg);
1464 instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1465
1466 *instance = i;
1467
1468 return instance;
1469}
1470
1471static void route_match_source_instance_free(void *rule)
1472{
1473 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1474}
1475
1476static struct route_map_rule_cmd route_match_source_instance_cmd = {
1477 "source-instance", route_match_source_instance,
1478 route_match_source_instance_compile, route_match_source_instance_free};
1479
5921ef9a
PJ
1480/* `set src A.B.C.D' */
1481
1482/* Set src. */
123214ef 1483static route_map_result_t route_set_src(void *rule, const struct prefix *prefix,
d62a17ae 1484 route_map_object_t type, void *object)
5921ef9a 1485{
d62a17ae 1486 struct nh_rmap_obj *nh_data;
9f0ea7d4 1487
d62a17ae 1488 if (type == RMAP_ZEBRA) {
1489 nh_data = (struct nh_rmap_obj *)object;
1490 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1491 }
1492 return RMAP_OKAY;
5921ef9a
PJ
1493}
1494
1495/* set src compilation. */
d62a17ae 1496static void *route_set_src_compile(const char *arg)
5921ef9a 1497{
d62a17ae 1498 union g_addr src, *psrc;
5921ef9a 1499
d62a17ae 1500 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
17a21721 1501 || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
d62a17ae 1502 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1503 *psrc = src;
1504 return psrc;
1505 }
1506 return NULL;
5921ef9a
PJ
1507}
1508
1509/* Free route map's compiled `set src' value. */
d62a17ae 1510static void route_set_src_free(void *rule)
5921ef9a 1511{
d62a17ae 1512 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
5921ef9a
PJ
1513}
1514
1515/* Set src rule structure. */
d62a17ae 1516static struct route_map_rule_cmd route_set_src_cmd = {
9d303b37 1517 "src", route_set_src, route_set_src_compile, route_set_src_free,
5921ef9a
PJ
1518};
1519
d5b8c216 1520/* The function checks if the changed routemap specified by parameter rmap
1521 * matches the configured protocol routemaps in proto_rm table. If there is
1522 * a match then rib_update_table() to process the routes.
1523 */
1524static void zebra_rib_table_rm_update(const char *rmap)
1525{
1526 int i = 0;
1527 struct route_table *table;
ac6eebce 1528 struct vrf *vrf = NULL;
1529 struct zebra_vrf *zvrf = NULL;
d5b8c216 1530 char *rmap_name;
1531 char afi_ip = 0;
1532 char afi_ipv6 = 0;
54e80c76 1533 struct route_map *old = NULL;
d5b8c216 1534
ac6eebce 1535 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1536 zvrf = vrf->info;
1537 if (!zvrf)
1538 continue;
1539 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1540 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
1541 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1542 if (IS_ZEBRA_DEBUG_EVENT)
1543 zlog_debug(
1544 "%s : AFI_IP rmap %s, route type %s",
1545 __func__, rmap,
1546 zebra_route_string(i));
1547
54e80c76 1548 old = PROTO_RM_MAP(zvrf, AFI_IP, i);
1549
ac6eebce 1550 PROTO_RM_MAP(zvrf, AFI_IP, i) =
1551 route_map_lookup_by_name(rmap_name);
54e80c76 1552 /* old is NULL. i.e Route map creation event.
1553 * So update applied_counter.
1554 * If Old is not NULL, i.e It may be routemap
1555 * updation or deletion.
1556 * So no need to update the counter.
1557 */
1558 if (!old)
1559 route_map_counter_increment(
1560 PROTO_RM_MAP(zvrf, AFI_IP, i));
ac6eebce 1561 /* There is single rib table for all protocols
1562 */
1563 if (afi_ip == 0) {
1564 table = zvrf->table[AFI_IP]
1565 [SAFI_UNICAST];
1566 if (table) {
1567
1568 afi_ip = 1;
1569 rib_update_table(
1570 table,
1571 RIB_UPDATE_RMAP_CHANGE);
1572 }
d5b8c216 1573 }
1574 }
ac6eebce 1575 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
1576 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1577 if (IS_ZEBRA_DEBUG_EVENT)
1578 zlog_debug(
1579 "%s : AFI_IP6 rmap %s, route type %s",
1580 __func__, rmap,
1581 zebra_route_string(i));
1582
54e80c76 1583 old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
1584
ac6eebce 1585 PROTO_RM_MAP(zvrf, AFI_IP6, i) =
1586 route_map_lookup_by_name(rmap_name);
54e80c76 1587 if (!old)
1588 route_map_counter_increment(
1589 PROTO_RM_MAP(zvrf, AFI_IP6, i));
ac6eebce 1590 /* There is single rib table for all protocols
1591 */
1592 if (afi_ipv6 == 0) {
1593 table = zvrf->table[AFI_IP6]
1594 [SAFI_UNICAST];
1595 if (table) {
1596
1597 afi_ipv6 = 1;
1598 rib_update_table(
1599 table,
1600 RIB_UPDATE_RMAP_CHANGE);
1601 }
d5b8c216 1602 }
1603 }
1604 }
1605 }
1606}
1607
1608/* The function checks if the changed routemap specified by parameter rmap
1609 * matches the configured protocol routemaps in nht_rm table. If there is
1610 * a match then zebra_evaluate_rnh() to process the nexthops.
1611 */
1612static void zebra_nht_rm_update(const char *rmap)
1613{
1614 int i = 0;
ac6eebce 1615 struct route_table *table;
1616 struct vrf *vrf = NULL;
1617 struct zebra_vrf *zvrf = NULL;
d5b8c216 1618 char *rmap_name;
1619 char afi_ip = 0;
1620 char afi_ipv6 = 0;
54e80c76 1621 struct route_map *old = NULL;
d5b8c216 1622
ac6eebce 1623 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1624 zvrf = vrf->info;
1625 if (!zvrf)
1626 continue;
1627 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1628 rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i);
1629 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1630 if (IS_ZEBRA_DEBUG_EVENT)
1631 zlog_debug(
1632 "%s : AFI_IP rmap %s, route type %s",
1633 __func__, rmap,
1634 zebra_route_string(i));
1635
54e80c76 1636 old = NHT_RM_MAP(zvrf, AFI_IP, i);
1637
ac6eebce 1638 NHT_RM_MAP(zvrf, AFI_IP, i) =
1639 route_map_lookup_by_name(rmap_name);
54e80c76 1640 if (!old)
1641 route_map_counter_increment(
1642 NHT_RM_MAP(zvrf, AFI_IP, i));
ac6eebce 1643 /* There is single rib table for all protocols
1644 */
1645 if (afi_ip == 0) {
1646 table = zvrf->table[AFI_IP]
1647 [SAFI_UNICAST];
1648 if (table) {
1649
1650 afi_ip = 1;
1651
1652 zebra_evaluate_rnh(
73bf60a0 1653 zvrf, AFI_IP, 1,
ac6eebce 1654 RNH_NEXTHOP_TYPE, NULL);
1655 }
1656 }
d5b8c216 1657 }
ac6eebce 1658
1659 rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
1660 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1661 if (IS_ZEBRA_DEBUG_EVENT)
1662 zlog_debug(
1663 "%s : AFI_IP6 rmap %s, route type %s",
1664 __func__, rmap,
1665 zebra_route_string(i));
1666
54e80c76 1667 old = NHT_RM_MAP(zvrf, AFI_IP6, i);
1668
ac6eebce 1669 NHT_RM_MAP(zvrf, AFI_IP6, i) =
1670 route_map_lookup_by_name(rmap_name);
54e80c76 1671 if (!old)
1672 route_map_counter_increment(
1673 NHT_RM_MAP(zvrf, AFI_IP6, i));
ac6eebce 1674 /* There is single rib table for all protocols
1675 */
1676 if (afi_ipv6 == 0) {
1677 table = zvrf->table[AFI_IP6]
1678 [SAFI_UNICAST];
1679 if (table) {
1680
1681 afi_ipv6 = 1;
1682
1683 zebra_evaluate_rnh(
73bf60a0 1684 zvrf, AFI_IP, 1,
ac6eebce 1685 RNH_NEXTHOP_TYPE, NULL);
1686 }
1687 }
d5b8c216 1688 }
1689 }
1690 }
1691}
1692
46a69f10 1693static void zebra_route_map_process_update_cb(char *rmap_name)
75a2b29d
DS
1694{
1695 if (IS_ZEBRA_DEBUG_EVENT)
1696 zlog_debug("Event handler for route-map: %s",
1697 rmap_name);
d5b8c216 1698 zebra_import_table_rm_update(rmap_name);
1699 zebra_rib_table_rm_update(rmap_name);
1700 zebra_nht_rm_update(rmap_name);
75a2b29d
DS
1701}
1702
d62a17ae 1703static int zebra_route_map_update_timer(struct thread *thread)
518f0eb1 1704{
d62a17ae 1705 zebra_t_rmap_update = NULL;
518f0eb1 1706
d62a17ae 1707 if (IS_ZEBRA_DEBUG_EVENT)
1708 zlog_debug("Event driven route-map update triggered");
518f0eb1 1709
d62a17ae 1710 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1711 zlog_debug(
1712 "%u: Routemap update-timer fired, scheduling RIB processing",
1713 VRF_DEFAULT);
b84c7253 1714
75a2b29d
DS
1715 route_map_walk_update_list(zebra_route_map_process_update_cb);
1716
1717 /*
1718 * This code needs to be updated to be:
1719 * 1) VRF Aware <sigh>
1720 * 2) Route-map aware
1721 */
d62a17ae 1722 return (0);
518f0eb1
DS
1723}
1724
d7c0a89a 1725static void zebra_route_map_set_delay_timer(uint32_t value)
518f0eb1 1726{
d62a17ae 1727 zebra_rmap_update_timer = value;
1728 if (!value && zebra_t_rmap_update) {
1729 /* Event driven route map updates is being disabled */
1730 /* But there's a pending timer. Fire it off now */
1731 thread_cancel(zebra_t_rmap_update);
1732 zebra_route_map_update_timer(zebra_t_rmap_update);
1733 }
518f0eb1
DS
1734}
1735
d62a17ae 1736void zebra_route_map_write_delay_timer(struct vty *vty)
518f0eb1 1737{
d62a17ae 1738 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1739 vty_out(vty, "zebra route-map delay-timer %d\n",
1740 zebra_rmap_update_timer);
1741 return;
518f0eb1
DS
1742}
1743
ac6eebce 1744route_map_result_t
1745zebra_route_map_check(int family, int rib_type, uint8_t instance,
1746 const struct prefix *p, struct nexthop *nexthop,
1747 struct zebra_vrf *zvrf, route_tag_t tag)
518f0eb1 1748{
d62a17ae 1749 struct route_map *rmap = NULL;
1750 route_map_result_t ret = RMAP_MATCH;
1751 struct nh_rmap_obj nh_obj;
9f0ea7d4 1752
d62a17ae 1753 nh_obj.nexthop = nexthop;
ac6eebce 1754 nh_obj.vrf_id = nexthop->vrf_id;
d62a17ae 1755 nh_obj.source_protocol = rib_type;
633a66a5 1756 nh_obj.instance = instance;
d62a17ae 1757 nh_obj.metric = 0;
1758 nh_obj.tag = tag;
518f0eb1 1759
d62a17ae 1760 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
ac6eebce 1761 rmap = PROTO_RM_MAP(zvrf, family, rib_type);
1762 if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX))
1763 rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
d62a17ae 1764 if (rmap) {
123214ef 1765 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
d62a17ae 1766 }
9f0ea7d4 1767
d62a17ae 1768 return (ret);
9f0ea7d4
DS
1769}
1770
d62a17ae 1771char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
8902474b 1772{
d62a17ae 1773 return zebra_import_table_routemap[afi][table];
8902474b
DS
1774}
1775
d62a17ae 1776void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1777 uint32_t table)
8902474b 1778{
d62a17ae 1779 zebra_import_table_routemap[afi][table] =
1780 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
8902474b
DS
1781}
1782
d62a17ae 1783void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
8902474b 1784{
d62a17ae 1785 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
8902474b
DS
1786}
1787
1788route_map_result_t
633a66a5 1789zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
123214ef
MS
1790 const struct prefix *p,
1791 struct nexthop *nexthop,
633a66a5
DS
1792 vrf_id_t vrf_id, route_tag_t tag,
1793 const char *rmap_name)
d62a17ae 1794{
1795 struct route_map *rmap = NULL;
1796 route_map_result_t ret = RMAP_DENYMATCH;
1797 struct nh_rmap_obj nh_obj;
1798
1799 nh_obj.nexthop = nexthop;
1800 nh_obj.vrf_id = vrf_id;
1801 nh_obj.source_protocol = re_type;
633a66a5 1802 nh_obj.instance = instance;
d62a17ae 1803 nh_obj.metric = 0;
1804 nh_obj.tag = tag;
1805
1806 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1807 rmap = route_map_lookup_by_name(rmap_name);
1808 if (rmap) {
1809 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1810 }
8902474b 1811
d62a17ae 1812 return (ret);
8902474b
DS
1813}
1814
73bf60a0 1815route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
123214ef 1816 const struct prefix *p,
ac6eebce 1817 struct zebra_vrf *zvrf,
d62a17ae 1818 struct route_entry *re,
1819 struct nexthop *nexthop)
9f0ea7d4 1820{
d62a17ae 1821 struct route_map *rmap = NULL;
1822 route_map_result_t ret = RMAP_MATCH;
1823 struct nh_rmap_obj nh_obj;
9f0ea7d4 1824
d62a17ae 1825 nh_obj.nexthop = nexthop;
4a7371e9 1826 nh_obj.vrf_id = nexthop->vrf_id;
d62a17ae 1827 nh_obj.source_protocol = re->type;
633a66a5 1828 nh_obj.instance = re->instance;
d62a17ae 1829 nh_obj.metric = re->metric;
1830 nh_obj.tag = re->tag;
9f0ea7d4 1831
d62a17ae 1832 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
73bf60a0
RW
1833 rmap = NHT_RM_MAP(zvrf, afi, client_proto);
1834 if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
1835 rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
123214ef 1836 if (rmap)
d62a17ae 1837 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
518f0eb1 1838
123214ef 1839 return ret;
518f0eb1
DS
1840}
1841
d62a17ae 1842static void zebra_route_map_mark_update(const char *rmap_name)
518f0eb1 1843{
d62a17ae 1844 /* rmap_update_timer of 0 means don't do route updates */
1845 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1846 zebra_t_rmap_update = NULL;
3801e764 1847 thread_add_timer(zrouter.master, zebra_route_map_update_timer,
d62a17ae 1848 NULL, zebra_rmap_update_timer,
1849 &zebra_t_rmap_update);
1850 }
518f0eb1
DS
1851}
1852
d62a17ae 1853static void zebra_route_map_add(const char *rmap_name)
518f0eb1 1854{
75a2b29d
DS
1855 if (route_map_mark_updated(rmap_name) == 0)
1856 zebra_route_map_mark_update(rmap_name);
1857
d62a17ae 1858 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
518f0eb1
DS
1859}
1860
d62a17ae 1861static void zebra_route_map_delete(const char *rmap_name)
518f0eb1 1862{
75a2b29d
DS
1863 if (route_map_mark_updated(rmap_name) == 0)
1864 zebra_route_map_mark_update(rmap_name);
1865
d62a17ae 1866 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
518f0eb1
DS
1867}
1868
d62a17ae 1869static void zebra_route_map_event(route_map_event_t event,
1870 const char *rmap_name)
518f0eb1 1871{
75a2b29d
DS
1872 if (route_map_mark_updated(rmap_name) == 0)
1873 zebra_route_map_mark_update(rmap_name);
1874
d62a17ae 1875 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
518f0eb1
DS
1876}
1877
1878/* ip protocol configuration write function */
7cf16e19 1879void zebra_routemap_config_write_protocol(struct vty *vty,
1880 struct zebra_vrf *zvrf)
d62a17ae 1881{
1882 int i;
7cf16e19 1883 char space[2];
d62a17ae 1884
7cf16e19 1885 memset(space, 0, sizeof(space));
d62a17ae 1886
7cf16e19 1887 if (zvrf_id(zvrf) != VRF_DEFAULT)
1888 sprintf(space, "%s", " ");
d62a17ae 1889
7cf16e19 1890 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1891 if (PROTO_RM_NAME(zvrf, AFI_IP, i))
1892 vty_out(vty, "%sip protocol %s route-map %s\n", space,
1893 zebra_route_string(i),
1894 PROTO_RM_NAME(zvrf, AFI_IP, i));
1895
1896 if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
1897 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
1898 zebra_route_string(i),
1899 PROTO_RM_NAME(zvrf, AFI_IP6, i));
1900
1901 if (NHT_RM_NAME(zvrf, AFI_IP, i))
1902 vty_out(vty, "%sip nht %s route-map %s\n", space,
1903 zebra_route_string(i),
1904 NHT_RM_NAME(zvrf, AFI_IP, i));
1905
1906 if (NHT_RM_NAME(zvrf, AFI_IP6, i))
1907 vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
1908 zebra_route_string(i),
1909 NHT_RM_NAME(zvrf, AFI_IP6, i));
d62a17ae 1910 }
1911
7cf16e19 1912 if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1913 vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
1914 PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
d62a17ae 1915
7cf16e19 1916 if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1917 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
1918 PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
d62a17ae 1919
7cf16e19 1920 if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1921 vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
1922 NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
d62a17ae 1923
7cf16e19 1924 if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1925 vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
1926 NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
d62a17ae 1927
1928 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1929 vty_out(vty, "zebra route-map delay-timer %d\n",
1930 zebra_rmap_update_timer);
1931}
1932
4d762f26 1933void zebra_route_map_init(void)
d62a17ae 1934{
1935 install_element(CONFIG_NODE, &ip_protocol_cmd);
1936 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
214e5c26 1937 install_element(VRF_NODE, &ip_protocol_cmd);
1938 install_element(VRF_NODE, &no_ip_protocol_cmd);
d62a17ae 1939 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1940 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1941 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
214e5c26 1942 install_element(VRF_NODE, &ipv6_protocol_cmd);
1943 install_element(VRF_NODE, &no_ipv6_protocol_cmd);
d62a17ae 1944 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1945 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1946 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
214e5c26 1947 install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
1948 install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
d62a17ae 1949 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1950 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1951 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
214e5c26 1952 install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
1953 install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
d62a17ae 1954 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1955 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1956 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1957
1958 route_map_init();
1959
1960 route_map_add_hook(zebra_route_map_add);
1961 route_map_delete_hook(zebra_route_map_delete);
1962 route_map_event_hook(zebra_route_map_event);
1963
1964 route_map_match_interface_hook(generic_match_add);
1965 route_map_no_match_interface_hook(generic_match_delete);
1966
1967 route_map_match_ip_address_hook(generic_match_add);
1968 route_map_no_match_ip_address_hook(generic_match_delete);
1969
1970 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1971 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1972
1973 route_map_match_ip_next_hop_hook(generic_match_add);
1974 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1975
1976 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1977 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1978
2d818099
DA
1979 route_map_match_ip_next_hop_type_hook(generic_match_add);
1980 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
1981
d62a17ae 1982 route_map_match_tag_hook(generic_match_add);
1983 route_map_no_match_tag_hook(generic_match_delete);
1984
01ba4505 1985 route_map_match_ipv6_address_hook(generic_match_add);
1986 route_map_no_match_ipv6_address_hook(generic_match_delete);
1987
1988 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
1989 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
1990
2d818099
DA
1991 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
1992 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
1993
d62a17ae 1994 route_map_install_match(&route_match_tag_cmd);
1995 route_map_install_match(&route_match_interface_cmd);
1996 route_map_install_match(&route_match_ip_next_hop_cmd);
1997 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
1998 route_map_install_match(&route_match_ip_address_cmd);
86405f9e 1999 route_map_install_match(&route_match_ipv6_address_cmd);
d62a17ae 2000 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
01ba4505 2001 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
d62a17ae 2002 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
5165d46f 2003 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
d62a17ae 2004 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
2d818099
DA
2005 route_map_install_match(&route_match_ip_next_hop_type_cmd);
2006 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 2007 route_map_install_match(&route_match_source_protocol_cmd);
633a66a5
DS
2008 route_map_install_match(&route_match_source_instance_cmd);
2009
d62a17ae 2010 /* */
2011 route_map_install_set(&route_set_src_cmd);
2012 /* */
2013 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
2014 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
2015 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
5165d46f
DS
2016 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
2017 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
d62a17ae 2018 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
2019 install_element(RMAP_NODE, &match_source_protocol_cmd);
2020 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
633a66a5
DS
2021 install_element(RMAP_NODE, &match_source_instance_cmd);
2022 install_element(RMAP_NODE, &no_match_source_instance_cmd);
2023
d62a17ae 2024 /* */
2025 install_element(RMAP_NODE, &set_src_cmd);
2026 install_element(RMAP_NODE, &no_set_src_cmd);
5921ef9a 2027}