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