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