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