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