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