]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
bgpd: update routemap scripting example
[mirror_frr.git] / bgpd / bgp_routemap.c
CommitLineData
718e3744 1/* Route map function of bgpd.
896014f4
DL
2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
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 *
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
19 */
718e3744 20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "filter.h"
25#include "routemap.h"
26#include "command.h"
27#include "linklist.h"
28#include "plist.h"
29#include "memory.h"
30#include "log.h"
5dbb0a7b 31#include "frrlua.h"
25f45887 32#ifdef HAVE_LIBPCREPOSIX
d62a17ae 33#include <pcreposix.h>
718e3744 34#else
d62a17ae 35#include <regex.h>
25f45887 36#endif /* HAVE_LIBPCREPOSIX */
718e3744 37#include "buffer.h"
38#include "sockunion.h"
518f0eb1 39#include "hash.h"
3f9c7369 40#include "queue.h"
5d5ba018 41#include "frrstr.h"
5920b3eb 42#include "network.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_table.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_aspath.h"
518f0eb1 48#include "bgpd/bgp_packet.h"
718e3744 49#include "bgpd/bgp_route.h"
73ac8160 50#include "bgpd/bgp_zebra.h"
718e3744 51#include "bgpd/bgp_regex.h"
52#include "bgpd/bgp_community.h"
53#include "bgpd/bgp_clist.h"
54#include "bgpd/bgp_filter.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
320da874 58#include "bgpd/bgp_vty.h"
73ac8160 59#include "bgpd/bgp_debug.h"
d37ba549
MK
60#include "bgpd/bgp_evpn.h"
61#include "bgpd/bgp_evpn_private.h"
62982d5a 62#include "bgpd/bgp_evpn_vty.h"
ddb5b488 63#include "bgpd/bgp_mplsvpn.h"
2e59405f
DS
64#include "bgpd/bgp_pbr.h"
65#include "bgpd/bgp_flowspec_util.h"
82b692c0 66#include "bgpd/bgp_encap_types.h"
b1875e65 67#include "bgpd/bgp_mpath.h"
b4becb06 68#include "bgpd/bgp_script.h"
718e3744 69
49e5a4a0 70#ifdef ENABLE_BGP_VNC
d62a17ae 71#include "bgpd/rfapi/bgp_rfapi_cfg.h"
65efcfce 72#endif
518f0eb1 73
1dcc9e5b
CS
74#ifndef VTYSH_EXTRACT_PL
75#include "bgpd/bgp_routemap_clippy.c"
76#endif
77
718e3744 78/* Memo of route-map commands.
79
80o Cisco route-map
81
82 match as-path : Done
83 community : Done
bc413143 84 interface : Done
718e3744 85 ip address : Done
86 ip next-hop : Done
c1643bb7 87 ip route-source : Done
718e3744 88 ip prefix-list : Done
89 ipv6 address : Done
90 ipv6 next-hop : Done
91 ipv6 route-source: (This will not be implemented by bgpd)
92 ipv6 prefix-list : Done
93 length : (This will not be implemented by bgpd)
94 metric : Done
95 route-type : (This will not be implemented by bgpd)
0d9551dc 96 tag : Done
af291c15 97 local-preference : Done
718e3744 98
99 set as-path prepend : Done
100 as-path tag : Not yet
101 automatic-tag : (This will not be implemented by bgpd)
102 community : Done
57d187bc
JS
103 large-community : Done
104 large-comm-list : Done
718e3744 105 comm-list : Not yet
106 dampning : Not yet
107 default : (This will not be implemented by bgpd)
108 interface : (This will not be implemented by bgpd)
109 ip default : (This will not be implemented by bgpd)
110 ip next-hop : Done
111 ip precedence : (This will not be implemented by bgpd)
112 ip tos : (This will not be implemented by bgpd)
113 level : (This will not be implemented by bgpd)
114 local-preference : Done
115 metric : Done
116 metric-type : Not yet
117 origin : Done
0d9551dc 118 tag : Done
718e3744 119 weight : Done
951745bd 120 table : Done
718e3744 121
515e500c 122o Local extensions
718e3744 123
124 set ipv6 next-hop global: Done
161995ea 125 set ipv6 next-hop prefer-global: Done
718e3744 126 set ipv6 next-hop local : Done
841f7a57 127 set as-path exclude : Done
718e3744 128
e52702f2 129*/
6b0655a2 130
d62a17ae 131/* generic value manipulation to be shared in multiple rules */
76759f4f
TT
132
133#define RMAP_VALUE_SET 0
134#define RMAP_VALUE_ADD 1
135#define RMAP_VALUE_SUB 2
136
d62a17ae 137struct rmap_value {
d7c0a89a
QY
138 uint8_t action;
139 uint8_t variable;
140 uint32_t value;
76759f4f
TT
141};
142
d7c0a89a 143static int route_value_match(struct rmap_value *rv, uint32_t value)
d62a17ae 144{
145 if (rv->variable == 0 && value == rv->value)
146 return RMAP_MATCH;
76759f4f 147
d62a17ae 148 return RMAP_NOMATCH;
76759f4f
TT
149}
150
d7c0a89a
QY
151static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
152 struct peer *peer)
76759f4f 153{
d7c0a89a 154 uint32_t value;
baa376fc 155
d62a17ae 156 switch (rv->variable) {
157 case 1:
158 value = peer->rtt;
159 break;
160 default:
161 value = rv->value;
162 break;
163 }
76759f4f 164
d62a17ae 165 switch (rv->action) {
166 case RMAP_VALUE_ADD:
167 if (current > UINT32_MAX - value)
168 return UINT32_MAX;
169 return current + value;
170 case RMAP_VALUE_SUB:
171 if (current <= value)
172 return 0;
173 return current - value;
174 default:
175 return value;
176 }
76759f4f
TT
177}
178
d62a17ae 179static void *route_value_compile(const char *arg)
76759f4f 180{
d7c0a89a 181 uint8_t action = RMAP_VALUE_SET, var = 0;
d62a17ae 182 unsigned long larg = 0;
183 char *endptr = NULL;
184 struct rmap_value *rv;
76759f4f 185
d62a17ae 186 if (arg[0] == '+') {
187 action = RMAP_VALUE_ADD;
188 arg++;
189 } else if (arg[0] == '-') {
190 action = RMAP_VALUE_SUB;
191 arg++;
192 }
76759f4f 193
d62a17ae 194 if (all_digit(arg)) {
195 errno = 0;
196 larg = strtoul(arg, &endptr, 10);
197 if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
198 return NULL;
199 } else {
200 if (strcmp(arg, "rtt") == 0)
201 var = 1;
202 else
203 return NULL;
204 }
76759f4f 205
d62a17ae 206 rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
76759f4f 207
d62a17ae 208 rv->action = action;
209 rv->variable = var;
210 rv->value = larg;
211 return rv;
76759f4f
TT
212}
213
d62a17ae 214static void route_value_free(void *rule)
76759f4f 215{
d62a17ae 216 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
76759f4f
TT
217}
218
d62a17ae 219/* generic as path object to be shared in multiple rules */
374f12f9 220
d62a17ae 221static void *route_aspath_compile(const char *arg)
374f12f9 222{
d62a17ae 223 struct aspath *aspath;
374f12f9 224
d62a17ae 225 aspath = aspath_str2aspath(arg);
226 if (!aspath)
227 return NULL;
228 return aspath;
374f12f9
TT
229}
230
d62a17ae 231static void route_aspath_free(void *rule)
374f12f9 232{
d62a17ae 233 struct aspath *aspath = rule;
234 aspath_free(aspath);
374f12f9
TT
235}
236
8c3433e4
DS
237struct bgp_match_peer_compiled {
238 char *interface;
239 union sockunion su;
240};
241
242/* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
fee0f4c6 243
244/* Compares the peer specified in the 'match peer' clause with the peer
18ee8310 245 received in bgp_path_info->peer. If it is the same, or if the peer structure
fee0f4c6 246 received is a peer_group containing it, returns RMAP_MATCH. */
b68885f9 247static enum route_map_cmd_result_t
1782514f 248route_match_peer(void *rule, const struct prefix *prefix, void *object)
d62a17ae 249{
8c3433e4 250 struct bgp_match_peer_compiled *pc;
d62a17ae 251 union sockunion *su;
252 union sockunion su_def = {
253 .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
254 struct peer_group *group;
255 struct peer *peer;
256 struct listnode *node, *nnode;
257
1782514f
DS
258 pc = rule;
259 su = &pc->su;
260 peer = ((struct bgp_path_info *)object)->peer;
d62a17ae 261
1782514f
DS
262 if (pc->interface) {
263 if (!peer->conf_if)
264 return RMAP_NOMATCH;
8c3433e4 265
1782514f
DS
266 if (strcmp(peer->conf_if, pc->interface) == 0)
267 return RMAP_MATCH;
8c3433e4 268
1782514f
DS
269 return RMAP_NOMATCH;
270 }
8c3433e4 271
1782514f
DS
272 /* If su='0.0.0.0' (command 'match peer local'), and it's a
273 NETWORK,
274 REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
275 => return RMAP_MATCH
276 */
277 if (sockunion_same(su, &su_def)) {
278 int ret;
279 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
280 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE)
281 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE)
282 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
283 ret = RMAP_MATCH;
284 else
285 ret = RMAP_NOMATCH;
286 return ret;
287 }
288
289 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
290 if (sockunion_same(su, &peer->su))
291 return RMAP_MATCH;
d62a17ae 292
1782514f
DS
293 return RMAP_NOMATCH;
294 } else {
295 group = peer->group;
296 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
d62a17ae 297 if (sockunion_same(su, &peer->su))
298 return RMAP_MATCH;
d62a17ae 299 }
1782514f 300 return RMAP_NOMATCH;
d62a17ae 301 }
1782514f 302
d62a17ae 303 return RMAP_NOMATCH;
304}
305
306static void *route_match_peer_compile(const char *arg)
307{
8c3433e4 308 struct bgp_match_peer_compiled *pc;
d62a17ae 309 int ret;
310
a633d869 311 pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
8c3433e4 312 sizeof(struct bgp_match_peer_compiled));
d62a17ae 313
8c3433e4 314 ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
d62a17ae 315 if (ret < 0) {
8c3433e4
DS
316 pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
317 return pc;
d62a17ae 318 }
319
8c3433e4 320 return pc;
fee0f4c6 321}
322
323/* Free route map's compiled `ip address' value. */
d62a17ae 324static void route_match_peer_free(void *rule)
fee0f4c6 325{
8c3433e4
DS
326 struct bgp_match_peer_compiled *pc = rule;
327
0a22ddfb 328 XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
8c3433e4 329
d62a17ae 330 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
fee0f4c6 331}
332
333/* Route map commands for ip address matching. */
364deb04
DL
334static const struct route_map_rule_cmd route_match_peer_cmd = {
335 "peer",
336 route_match_peer,
337 route_match_peer_compile,
338 route_match_peer_free
339};
fee0f4c6 340
1d7c7ace 341#if defined(HAVE_LUA)
0fe6a43d
QY
342
343enum frrlua_rm_status {
344 /*
b4becb06 345 * Script function run failure. This will translate into a deny
0fe6a43d
QY
346 */
347 LUA_RM_FAILURE = 0,
348 /*
349 * No Match was found for the route map function
350 */
351 LUA_RM_NOMATCH,
352 /*
b4becb06 353 * Match was found but no changes were made to the incoming data.
0fe6a43d
QY
354 */
355 LUA_RM_MATCH,
356 /*
b4becb06 357 * Match was found and data was modified, so figure out what changed
0fe6a43d
QY
358 */
359 LUA_RM_MATCH_AND_CHANGE,
360};
361
b4becb06
QY
362static enum route_map_cmd_result_t
363route_match_script(void *rule, const struct prefix *prefix, void *object)
0fe6a43d 364{
b4becb06
QY
365 const char *scriptname = rule;
366 struct bgp_path_info *path = (struct bgp_path_info *)object;
367
368 struct frrscript *fs = frrscript_load(scriptname, NULL);
0fe6a43d 369
b4becb06
QY
370 if (!fs) {
371 zlog_err("Issue loading script rule; defaulting to no match");
372 return RMAP_NOMATCH;
0fe6a43d
QY
373 }
374
b4becb06
QY
375 enum frrlua_rm_status status_failure = LUA_RM_FAILURE,
376 status_nomatch = LUA_RM_NOMATCH,
377 status_match = LUA_RM_MATCH,
378 status_match_and_change = LUA_RM_MATCH_AND_CHANGE;
379
380 /* Make result values available */
381 struct frrscript_env env[] = {
382 {"integer", "RM_FAILURE", &status_failure},
383 {"integer", "RM_NOMATCH", &status_nomatch},
384 {"integer", "RM_MATCH", &status_match},
385 {"integer", "RM_MATCH_AND_CHANGE", &status_match_and_change},
386 {"integer", "action", &status_failure},
387 {"prefix", "prefix", prefix},
388 {"attr", "attributes", path->attr},
389 {"peer", "peer", path->peer},
390 {}};
391
392 struct frrscript_env results[] = {
393 {"integer", "action"},
394 {"attr", "attributes"},
395 {},
396 };
397
398 int result = frrscript_call(fs, env);
399
400 if (result) {
401 zlog_err("Issue running script rule; defaulting to no match");
402 return RMAP_NOMATCH;
403 }
0fe6a43d 404
b4becb06
QY
405 enum frrlua_rm_status *lrm_status =
406 frrscript_get_result(fs, &results[0]);
1d7c7ace 407
b4becb06 408 int status = RMAP_NOMATCH;
1d7c7ace 409
b4becb06 410 switch (*lrm_status) {
1d7c7ace 411 case LUA_RM_FAILURE:
b4becb06
QY
412 zlog_err(
413 "Executing route-map match script '%s' failed; defaulting to no match",
414 scriptname);
415 status = RMAP_NOMATCH;
1d7c7ace
DS
416 break;
417 case LUA_RM_NOMATCH:
b4becb06 418 status = RMAP_NOMATCH;
1d7c7ace
DS
419 break;
420 case LUA_RM_MATCH_AND_CHANGE:
b4becb06
QY
421 status = RMAP_MATCH;
422 zlog_debug("Updating attribute based on script's values");
423
424 uint32_t locpref = 0;
425 struct attr *newattr = frrscript_get_result(fs, &results[1]);
426
427 path->attr->med = newattr->med;
428
40381db7
DS
429 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
430 locpref = path->attr->local_pref;
b4becb06
QY
431 if (locpref != newattr->local_pref) {
432 SET_FLAG(path->attr->flag,
433 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
434 path->attr->local_pref = newattr->local_pref;
1d7c7ace 435 }
b4becb06
QY
436
437 aspath_free(newattr->aspath);
438 XFREE(MTYPE_TMP, newattr);
1d7c7ace
DS
439 break;
440 case LUA_RM_MATCH:
1d7c7ace
DS
441 status = RMAP_MATCH;
442 break;
443 }
b4becb06
QY
444
445 XFREE(MTYPE_TMP, lrm_status);
446 frrscript_unload(fs);
447
1d7c7ace
DS
448 return status;
449}
450
b4becb06 451static void *route_match_script_compile(const char *arg)
1d7c7ace 452{
b4becb06
QY
453 char *scriptname;
454
455 scriptname = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1d7c7ace 456
b4becb06 457 return scriptname;
1d7c7ace
DS
458}
459
b4becb06 460static void route_match_script_free(void *rule)
1d7c7ace
DS
461{
462 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
463}
464
b4becb06
QY
465static const struct route_map_rule_cmd route_match_script_cmd = {
466 "script",
467 route_match_script,
468 route_match_script_compile,
469 route_match_script_free
1d7c7ace
DS
470};
471#endif
472
718e3744 473/* `match ip address IP_ACCESS_LIST' */
474
475/* Match function should return 1 if match is success else return
476 zero. */
b68885f9 477static enum route_map_cmd_result_t
1782514f 478route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
d62a17ae 479{
480 struct access_list *alist;
d62a17ae 481
1782514f 482 if (prefix->family == AF_INET) {
d62a17ae 483 alist = access_list_lookup(AFI_IP, (char *)rule);
484 if (alist == NULL)
485 return RMAP_NOMATCH;
486
487 return (access_list_apply(alist, prefix) == FILTER_DENY
488 ? RMAP_NOMATCH
489 : RMAP_MATCH);
490 }
718e3744 491 return RMAP_NOMATCH;
718e3744 492}
493
494/* Route map `ip address' match statement. `arg' should be
495 access-list name. */
d62a17ae 496static void *route_match_ip_address_compile(const char *arg)
718e3744 497{
d62a17ae 498 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 499}
500
501/* Free route map's compiled `ip address' value. */
d62a17ae 502static void route_match_ip_address_free(void *rule)
718e3744 503{
d62a17ae 504 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 505}
506
507/* Route map commands for ip address matching. */
364deb04
DL
508static const struct route_map_rule_cmd route_match_ip_address_cmd = {
509 "ip address",
510 route_match_ip_address,
511 route_match_ip_address_compile,
512 route_match_ip_address_free
513};
6b0655a2 514
718e3744 515/* `match ip next-hop IP_ADDRESS' */
516
517/* Match function return 1 if match is success else return zero. */
b68885f9 518static enum route_map_cmd_result_t
1782514f 519route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
d62a17ae 520{
521 struct access_list *alist;
9b6d8fcf 522 struct bgp_path_info *path;
d62a17ae 523 struct prefix_ipv4 p;
524
1782514f 525 if (prefix->family == AF_INET) {
9b6d8fcf 526 path = object;
d62a17ae 527 p.family = AF_INET;
9b6d8fcf 528 p.prefix = path->attr->nexthop;
d62a17ae 529 p.prefixlen = IPV4_MAX_BITLEN;
530
531 alist = access_list_lookup(AFI_IP, (char *)rule);
532 if (alist == NULL)
533 return RMAP_NOMATCH;
534
535 return (access_list_apply(alist, &p) == FILTER_DENY
536 ? RMAP_NOMATCH
537 : RMAP_MATCH);
538 }
718e3744 539 return RMAP_NOMATCH;
718e3744 540}
541
542/* Route map `ip next-hop' match statement. `arg' is
543 access-list name. */
d62a17ae 544static void *route_match_ip_next_hop_compile(const char *arg)
718e3744 545{
d62a17ae 546 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 547}
548
549/* Free route map's compiled `ip address' value. */
d62a17ae 550static void route_match_ip_next_hop_free(void *rule)
718e3744 551{
d62a17ae 552 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 553}
554
555/* Route map commands for ip next-hop matching. */
364deb04
DL
556static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
557 "ip next-hop",
558 route_match_ip_next_hop,
559 route_match_ip_next_hop_compile,
560 route_match_ip_next_hop_free
561};
6b0655a2 562
c1643bb7 563/* `match ip route-source ACCESS-LIST' */
564
565/* Match function return 1 if match is success else return zero. */
b68885f9 566static enum route_map_cmd_result_t
1782514f 567route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
d62a17ae 568{
569 struct access_list *alist;
9b6d8fcf 570 struct bgp_path_info *path;
d62a17ae 571 struct peer *peer;
572 struct prefix_ipv4 p;
573
1782514f 574 if (pfx->family == AF_INET) {
9b6d8fcf
DS
575 path = object;
576 peer = path->peer;
d62a17ae 577
578 if (!peer || sockunion_family(&peer->su) != AF_INET)
579 return RMAP_NOMATCH;
580
581 p.family = AF_INET;
582 p.prefix = peer->su.sin.sin_addr;
583 p.prefixlen = IPV4_MAX_BITLEN;
584
585 alist = access_list_lookup(AFI_IP, (char *)rule);
586 if (alist == NULL)
587 return RMAP_NOMATCH;
588
589 return (access_list_apply(alist, &p) == FILTER_DENY
590 ? RMAP_NOMATCH
591 : RMAP_MATCH);
592 }
c1643bb7 593 return RMAP_NOMATCH;
c1643bb7 594}
595
596/* Route map `ip route-source' match statement. `arg' is
597 access-list name. */
d62a17ae 598static void *route_match_ip_route_source_compile(const char *arg)
c1643bb7 599{
d62a17ae 600 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 601}
602
603/* Free route map's compiled `ip address' value. */
d62a17ae 604static void route_match_ip_route_source_free(void *rule)
c1643bb7 605{
d62a17ae 606 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 607}
608
609/* Route map commands for ip route-source matching. */
364deb04
DL
610static const struct route_map_rule_cmd route_match_ip_route_source_cmd = {
611 "ip route-source",
612 route_match_ip_route_source,
613 route_match_ip_route_source_compile,
614 route_match_ip_route_source_free
615};
6b0655a2 616
b68885f9
LK
617static enum route_map_cmd_result_t
618route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
619 const struct prefix *p)
2e59405f
DS
620{
621 int ret;
622 struct bgp_pbr_entry_main api;
623
624 memset(&api, 0, sizeof(api));
625
1840384b
PG
626 if (family2afi(p->u.prefix_flowspec.family) != afi)
627 return RMAP_NOMATCH;
628
2e59405f
DS
629 /* extract match from flowspec entries */
630 ret = bgp_flowspec_match_rules_fill(
631 (uint8_t *)p->u.prefix_flowspec.ptr,
1840384b
PG
632 p->u.prefix_flowspec.prefixlen, &api,
633 afi);
2e59405f
DS
634 if (ret < 0)
635 return RMAP_NOMATCH;
636 if (api.match_bitmask & PREFIX_DST_PRESENT ||
637 api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
638 if (family2afi((&api.dst_prefix)->family) != afi)
639 return RMAP_NOMATCH;
640 return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
641 ? RMAP_NOMATCH
642 : RMAP_MATCH;
643 } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
644 api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
645 if (family2afi((&api.src_prefix)->family) != afi)
646 return RMAP_NOMATCH;
647 return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
648 ? RMAP_NOMATCH
649 : RMAP_MATCH);
650 }
651 return RMAP_NOMATCH;
652}
718e3744 653
b68885f9 654static enum route_map_cmd_result_t
2e59405f 655route_match_address_prefix_list(void *rule, afi_t afi,
1782514f 656 const struct prefix *prefix, void *object)
718e3744 657{
d62a17ae 658 struct prefix_list *plist;
718e3744 659
2e59405f
DS
660 plist = prefix_list_lookup(afi, (char *)rule);
661 if (plist == NULL)
662 return RMAP_NOMATCH;
663
664 if (prefix->family == AF_FLOWSPEC)
665 return route_match_prefix_list_flowspec(afi, plist,
666 prefix);
667 return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
668 : RMAP_MATCH);
669}
670
b68885f9 671static enum route_map_cmd_result_t
2e59405f 672route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1782514f 673 void *object)
2e59405f 674{
1782514f 675 return route_match_address_prefix_list(rule, AFI_IP, prefix, object);
718e3744 676}
677
d62a17ae 678static void *route_match_ip_address_prefix_list_compile(const char *arg)
718e3744 679{
d62a17ae 680 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 681}
682
d62a17ae 683static void route_match_ip_address_prefix_list_free(void *rule)
718e3744 684{
d62a17ae 685 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 686}
687
364deb04
DL
688static const struct route_map_rule_cmd
689 route_match_ip_address_prefix_list_cmd = {
690 "ip address prefix-list",
691 route_match_ip_address_prefix_list,
d62a17ae 692 route_match_ip_address_prefix_list_compile,
364deb04
DL
693 route_match_ip_address_prefix_list_free
694};
6b0655a2 695
718e3744 696/* `match ip next-hop prefix-list PREFIX_LIST' */
697
b68885f9 698static enum route_map_cmd_result_t
123214ef 699route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
1782514f 700 void *object)
718e3744 701{
d62a17ae 702 struct prefix_list *plist;
9b6d8fcf 703 struct bgp_path_info *path;
d62a17ae 704 struct prefix_ipv4 p;
718e3744 705
1782514f 706 if (prefix->family == AF_INET) {
9b6d8fcf 707 path = object;
d62a17ae 708 p.family = AF_INET;
9b6d8fcf 709 p.prefix = path->attr->nexthop;
d62a17ae 710 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 711
d62a17ae 712 plist = prefix_list_lookup(AFI_IP, (char *)rule);
713 if (plist == NULL)
714 return RMAP_NOMATCH;
718e3744 715
d62a17ae 716 return (prefix_list_apply(plist, &p) == PREFIX_DENY
717 ? RMAP_NOMATCH
718 : RMAP_MATCH);
719 }
720 return RMAP_NOMATCH;
718e3744 721}
722
d62a17ae 723static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
718e3744 724{
d62a17ae 725 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 726}
727
d62a17ae 728static void route_match_ip_next_hop_prefix_list_free(void *rule)
718e3744 729{
d62a17ae 730 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 731}
732
364deb04
DL
733static const struct route_map_rule_cmd
734 route_match_ip_next_hop_prefix_list_cmd = {
735 "ip next-hop prefix-list",
736 route_match_ip_next_hop_prefix_list,
d62a17ae 737 route_match_ip_next_hop_prefix_list_compile,
364deb04
DL
738 route_match_ip_next_hop_prefix_list_free
739};
6b0655a2 740
61ad901e
DA
741/* `match ip next-hop type <blackhole>' */
742
b68885f9 743static enum route_map_cmd_result_t
61ad901e 744route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
1782514f 745 void *object)
61ad901e 746{
9b6d8fcf 747 struct bgp_path_info *path;
61ad901e 748
1782514f 749 if (prefix->family == AF_INET) {
9b6d8fcf 750 path = (struct bgp_path_info *)object;
05864da7 751 if (!path)
b68885f9 752 return RMAP_NOMATCH;
61ad901e
DA
753
754 /* If nexthop interface's index can't be resolved and nexthop is
755 set to any address then mark it as type `blackhole`.
756 This logic works for matching kernel/static routes like:
757 `ip route add blackhole 10.0.0.1`. */
9b6d8fcf
DS
758 if (path->attr->nexthop.s_addr == INADDR_ANY
759 && !path->attr->nh_ifindex)
61ad901e
DA
760 return RMAP_MATCH;
761 }
762 return RMAP_NOMATCH;
763}
764
765static void *route_match_ip_next_hop_type_compile(const char *arg)
766{
767 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
768}
769
770static void route_match_ip_next_hop_type_free(void *rule)
771{
772 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
773}
774
364deb04
DL
775static const struct route_map_rule_cmd
776 route_match_ip_next_hop_type_cmd = {
777 "ip next-hop type",
778 route_match_ip_next_hop_type,
61ad901e 779 route_match_ip_next_hop_type_compile,
364deb04
DL
780 route_match_ip_next_hop_type_free
781};
61ad901e 782
c1643bb7 783/* `match ip route-source prefix-list PREFIX_LIST' */
784
b68885f9 785static enum route_map_cmd_result_t
1782514f
DS
786route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
787 void *object)
c1643bb7 788{
d62a17ae 789 struct prefix_list *plist;
9b6d8fcf 790 struct bgp_path_info *path;
d62a17ae 791 struct peer *peer;
792 struct prefix_ipv4 p;
c1643bb7 793
1782514f 794 if (prefix->family == AF_INET) {
9b6d8fcf
DS
795 path = object;
796 peer = path->peer;
c1643bb7 797
d62a17ae 798 if (!peer || sockunion_family(&peer->su) != AF_INET)
799 return RMAP_NOMATCH;
c1643bb7 800
d62a17ae 801 p.family = AF_INET;
802 p.prefix = peer->su.sin.sin_addr;
803 p.prefixlen = IPV4_MAX_BITLEN;
c1643bb7 804
d62a17ae 805 plist = prefix_list_lookup(AFI_IP, (char *)rule);
806 if (plist == NULL)
807 return RMAP_NOMATCH;
c1643bb7 808
d62a17ae 809 return (prefix_list_apply(plist, &p) == PREFIX_DENY
810 ? RMAP_NOMATCH
811 : RMAP_MATCH);
812 }
813 return RMAP_NOMATCH;
c1643bb7 814}
815
d62a17ae 816static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
c1643bb7 817{
d62a17ae 818 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 819}
820
d62a17ae 821static void route_match_ip_route_source_prefix_list_free(void *rule)
c1643bb7 822{
d62a17ae 823 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 824}
825
364deb04
DL
826static const struct route_map_rule_cmd
827 route_match_ip_route_source_prefix_list_cmd = {
828 "ip route-source prefix-list",
829 route_match_ip_route_source_prefix_list,
d62a17ae 830 route_match_ip_route_source_prefix_list_compile,
364deb04
DL
831 route_match_ip_route_source_prefix_list_free
832};
6b0655a2 833
6fb219da
MK
834/* `match evpn default-route' */
835
836/* Match function should return 1 if match is success else 0 */
b68885f9 837static enum route_map_cmd_result_t
1782514f 838route_match_evpn_default_route(void *rule, const struct prefix *p, void *object)
6fb219da 839{
1782514f 840 if (is_evpn_prefix_default(p))
6fb219da
MK
841 return RMAP_MATCH;
842
843 return RMAP_NOMATCH;
844}
845
846/* Route map commands for default-route matching. */
364deb04
DL
847static const struct route_map_rule_cmd
848 route_match_evpn_default_route_cmd = {
849 "evpn default-route",
850 route_match_evpn_default_route,
851 NULL,
852 NULL
853};
6fb219da 854
d37ba549
MK
855/* `match mac address MAC_ACCESS_LIST' */
856
857/* Match function should return 1 if match is success else return
858 zero. */
b68885f9 859static enum route_map_cmd_result_t
1782514f 860route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
d37ba549
MK
861{
862 struct access_list *alist;
0f6476cc 863 struct prefix p;
d37ba549 864
1782514f
DS
865 alist = access_list_lookup(AFI_L2VPN, (char *)rule);
866 if (alist == NULL)
867 return RMAP_NOMATCH;
d37ba549 868
1782514f
DS
869 if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
870 return RMAP_NOMATCH;
d37ba549 871
1782514f
DS
872 p.family = AF_ETHERNET;
873 p.prefixlen = ETH_ALEN * 8;
874 p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
0f6476cc 875
1782514f
DS
876 return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
877 : RMAP_MATCH);
d37ba549
MK
878}
879
880/* Route map `mac address' match statement. `arg' should be
881 access-list name. */
882static void *route_match_mac_address_compile(const char *arg)
883{
884 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
885}
886
887/* Free route map's compiled `ip address' value. */
888static void route_match_mac_address_free(void *rule)
889{
890 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
891}
892
893/* Route map commands for mac address matching. */
364deb04
DL
894static const struct route_map_rule_cmd route_match_mac_address_cmd = {
895 "mac address",
896 route_match_mac_address,
897 route_match_mac_address_compile,
898 route_match_mac_address_free
899};
d37ba549 900
82b692c0
LK
901/*
902 * Match function returns:
903 * ...RMAP_MATCH if match is found.
904 * ...RMAP_NOMATCH if match is not found.
905 * ...RMAP_NOOP to ignore this match check.
906 */
b68885f9 907static enum route_map_cmd_result_t
1782514f 908route_match_vni(void *rule, const struct prefix *prefix, void *object)
16f7ce2b
MK
909{
910 vni_t vni = 0;
82b692c0 911 unsigned int label_cnt = 0;
9b6d8fcf 912 struct bgp_path_info *path = NULL;
82b692c0 913 struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
16f7ce2b 914
1782514f
DS
915 vni = *((vni_t *)rule);
916 path = (struct bgp_path_info *)object;
16f7ce2b 917
1782514f
DS
918 /*
919 * This rmap filter is valid for vxlan tunnel type only.
920 * For any other tunnel type, return noop to ignore
921 * this check.
922 */
923 if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
924 return RMAP_NOOP;
82b692c0 925
1782514f
DS
926 /*
927 * Apply filter to type 1, 2, 5 routes only.
928 * Other route types do not have vni label.
929 */
930 if (evp
931 && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE
932 && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
933 && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
934 return RMAP_NOOP;
82b692c0 935
1782514f
DS
936 if (path->extra == NULL)
937 return RMAP_NOMATCH;
80ced710 938
1782514f
DS
939 for (;
940 label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
941 label_cnt++) {
942 if (vni == label2vni(&path->extra->label[label_cnt]))
943 return RMAP_MATCH;
16f7ce2b
MK
944 }
945
946 return RMAP_NOMATCH;
947}
948
949/* Route map `vni' match statement. */
950static void *route_match_vni_compile(const char *arg)
951{
952 vni_t *vni = NULL;
953 char *end = NULL;
954
955 vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
16f7ce2b
MK
956
957 *vni = strtoul(arg, &end, 10);
0af35d90
RW
958 if (*end != '\0') {
959 XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
16f7ce2b 960 return NULL;
0af35d90 961 }
16f7ce2b
MK
962
963 return vni;
964}
965
966/* Free route map's compiled `vni' value. */
967static void route_match_vni_free(void *rule)
968{
969 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
970}
971
972/* Route map commands for vni matching. */
364deb04
DL
973static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
974 "evpn vni",
975 route_match_vni,
976 route_match_vni_compile,
977 route_match_vni_free
978};
16f7ce2b 979
33c2ff62
MK
980/* `match evpn route-type' */
981
982/* Match function should return 1 if match is success else return
983 zero. */
b68885f9 984static enum route_map_cmd_result_t
1782514f 985route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object)
33c2ff62 986{
d7c0a89a 987 uint8_t route_type = 0;
33c2ff62 988
1782514f 989 route_type = *((uint8_t *)rule);
33c2ff62 990
1782514f
DS
991 if (route_type == pfx->u.prefix_evpn.route_type)
992 return RMAP_MATCH;
33c2ff62
MK
993
994 return RMAP_NOMATCH;
995}
996
997/* Route map `route-type' match statement. */
998static void *route_match_evpn_route_type_compile(const char *arg)
999{
d7c0a89a 1000 uint8_t *route_type = NULL;
33c2ff62 1001
d7c0a89a 1002 route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
33c2ff62
MK
1003
1004 if (strncmp(arg, "ma", 2) == 0)
1005 *route_type = BGP_EVPN_MAC_IP_ROUTE;
1006 else if (strncmp(arg, "mu", 2) == 0)
1007 *route_type = BGP_EVPN_IMET_ROUTE;
1008 else
1009 *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
1010
1011 return route_type;
1012}
1013
1014/* Free route map's compiled `route-type' value. */
1015static void route_match_evpn_route_type_free(void *rule)
1016{
1017 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1018}
1019
1020/* Route map commands for evpn route-type matching. */
364deb04
DL
1021static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
1022 "evpn route-type",
1023 route_match_evpn_route_type,
1024 route_match_evpn_route_type_compile,
1025 route_match_evpn_route_type_free
1026};
33c2ff62 1027
196c6b09
LK
1028/* `match rd' */
1029
1030/* Match function should return 1 if match is success else return zero. */
1031static enum route_map_cmd_result_t
1782514f 1032route_match_rd(void *rule, const struct prefix *prefix, void *object)
196c6b09
LK
1033{
1034 struct prefix_rd *prd_rule = NULL;
b54892e0 1035 const struct prefix_rd *prd_route = NULL;
196c6b09
LK
1036 struct bgp_path_info *path = NULL;
1037
1782514f
DS
1038 if (prefix->family != AF_EVPN)
1039 return RMAP_NOMATCH;
196c6b09 1040
1782514f
DS
1041 prd_rule = (struct prefix_rd *)rule;
1042 path = (struct bgp_path_info *)object;
196c6b09 1043
1782514f
DS
1044 if (path->net == NULL || path->net->pdest == NULL)
1045 return RMAP_NOMATCH;
196c6b09 1046
1782514f
DS
1047 prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest);
1048 if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
1049 return RMAP_MATCH;
196c6b09
LK
1050
1051 return RMAP_NOMATCH;
1052}
1053
1054/* Route map `rd' match statement. */
1055static void *route_match_rd_compile(const char *arg)
1056{
1057 struct prefix_rd *prd;
1058 int ret;
1059
1060 prd = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct prefix_rd));
1061
1062 ret = str2prefix_rd(arg, prd);
1063 if (!ret) {
1064 XFREE(MTYPE_ROUTE_MAP_COMPILED, prd);
1065 return NULL;
1066 }
1067
1068 return prd;
1069}
1070
1071/* Free route map's compiled `rd' value. */
1072static void route_match_rd_free(void *rule)
1073{
1074 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1075}
1076
1077/* Route map commands for rd matching. */
364deb04
DL
1078static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
1079 "evpn rd",
1080 route_match_rd,
1081 route_match_rd_compile,
1082 route_match_rd_free
1083};
196c6b09 1084
1dcc9e5b 1085/* Route map commands for VRF route leak with source vrf matching */
b68885f9 1086static enum route_map_cmd_result_t
c3935045 1087route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
1782514f 1088 void *object)
1dcc9e5b
CS
1089{
1090 struct bgp_path_info *path;
1091 char *vrf_name;
1092
1782514f
DS
1093 vrf_name = rule;
1094 path = (struct bgp_path_info *)object;
1dcc9e5b 1095
1782514f
DS
1096 if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
1097 return RMAP_NOMATCH;
1dcc9e5b 1098
1782514f
DS
1099 if (path->extra == NULL)
1100 return RMAP_NOMATCH;
1dcc9e5b 1101
1782514f
DS
1102 if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
1103 VRF_NAMSIZ)
1104 == 0)
1105 return RMAP_MATCH;
1dcc9e5b
CS
1106
1107 return RMAP_NOMATCH;
1108}
1109
1110static void *route_match_vrl_source_vrf_compile(const char *arg)
1111{
1112 uint8_t *vrf_name = NULL;
1113
1114 vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1115
1116 return vrf_name;
1117}
1118
1119/* Free route map's compiled `route-type' value. */
1120static void route_match_vrl_source_vrf_free(void *rule)
1121{
1122 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1123}
1124
364deb04
DL
1125static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
1126 "source-vrf",
1127 route_match_vrl_source_vrf,
1dcc9e5b 1128 route_match_vrl_source_vrf_compile,
364deb04
DL
1129 route_match_vrl_source_vrf_free
1130};
1dcc9e5b 1131
af291c15
DS
1132/* `match local-preference LOCAL-PREF' */
1133
1134/* Match function return 1 if match is success else return zero. */
b68885f9 1135static enum route_map_cmd_result_t
1782514f 1136route_match_local_pref(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1137{
d7c0a89a 1138 uint32_t *local_pref;
9b6d8fcf 1139 struct bgp_path_info *path;
d62a17ae 1140
1782514f
DS
1141 local_pref = rule;
1142 path = object;
d62a17ae 1143
1782514f
DS
1144 if (path->attr->local_pref == *local_pref)
1145 return RMAP_MATCH;
1146 else
1147 return RMAP_NOMATCH;
af291c15
DS
1148}
1149
196c6b09
LK
1150/*
1151 * Route map `match local-preference' match statement.
1152 * `arg' is local-pref value
1153 */
d62a17ae 1154static void *route_match_local_pref_compile(const char *arg)
af291c15 1155{
d7c0a89a 1156 uint32_t *local_pref;
d62a17ae 1157 char *endptr = NULL;
1158 unsigned long tmpval;
af291c15 1159
d62a17ae 1160 /* Locpref value shoud be integer. */
1161 if (!all_digit(arg))
1162 return NULL;
af291c15 1163
d62a17ae 1164 errno = 0;
1165 tmpval = strtoul(arg, &endptr, 10);
1166 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1167 return NULL;
af291c15 1168
d7c0a89a 1169 local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
af291c15 1170
d62a17ae 1171 *local_pref = tmpval;
1172 return local_pref;
af291c15
DS
1173}
1174
1175/* Free route map's compiled `match local-preference' value. */
d62a17ae 1176static void route_match_local_pref_free(void *rule)
af291c15 1177{
d62a17ae 1178 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
af291c15
DS
1179}
1180
1181/* Route map commands for metric matching. */
364deb04
DL
1182static const struct route_map_rule_cmd route_match_local_pref_cmd = {
1183 "local-preference",
1184 route_match_local_pref,
1185 route_match_local_pref_compile,
1186 route_match_local_pref_free
1187};
af291c15 1188
718e3744 1189/* `match metric METRIC' */
1190
1191/* Match function return 1 if match is success else return zero. */
b68885f9 1192static enum route_map_cmd_result_t
1782514f 1193route_match_metric(void *rule, const struct prefix *prefix, void *object)
718e3744 1194{
d62a17ae 1195 struct rmap_value *rv;
9b6d8fcf 1196 struct bgp_path_info *path;
718e3744 1197
1782514f
DS
1198 rv = rule;
1199 path = object;
1200 return route_value_match(rv, path->attr->med);
718e3744 1201}
1202
718e3744 1203/* Route map commands for metric matching. */
364deb04
DL
1204static const struct route_map_rule_cmd route_match_metric_cmd = {
1205 "metric",
1206 route_match_metric,
1207 route_value_compile,
1208 route_value_free,
718e3744 1209};
6b0655a2 1210
718e3744 1211/* `match as-path ASPATH' */
1212
1213/* Match function for as-path match. I assume given object is */
b68885f9 1214static enum route_map_cmd_result_t
1782514f 1215route_match_aspath(void *rule, const struct prefix *prefix, void *object)
718e3744 1216{
e52702f2 1217
d62a17ae 1218 struct as_list *as_list;
9b6d8fcf 1219 struct bgp_path_info *path;
718e3744 1220
1782514f
DS
1221 as_list = as_list_lookup((char *)rule);
1222 if (as_list == NULL)
1223 return RMAP_NOMATCH;
518f0eb1 1224
1782514f 1225 path = object;
518f0eb1 1226
1782514f
DS
1227 /* Perform match. */
1228 return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY)
1229 ? RMAP_NOMATCH
1230 : RMAP_MATCH);
718e3744 1231}
1232
1233/* Compile function for as-path match. */
d62a17ae 1234static void *route_match_aspath_compile(const char *arg)
718e3744 1235{
d62a17ae 1236 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 1237}
1238
1239/* Compile function for as-path match. */
d62a17ae 1240static void route_match_aspath_free(void *rule)
718e3744 1241{
d62a17ae 1242 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1243}
1244
1245/* Route map commands for aspath matching. */
364deb04
DL
1246static const struct route_map_rule_cmd route_match_aspath_cmd = {
1247 "as-path",
1248 route_match_aspath,
1249 route_match_aspath_compile,
1250 route_match_aspath_free
1251};
6b0655a2 1252
718e3744 1253/* `match community COMMUNIY' */
d62a17ae 1254struct rmap_community {
1255 char *name;
e237b0d2 1256 uint32_t name_hash;
d62a17ae 1257 int exact;
718e3744 1258};
1259
1260/* Match function for community match. */
b68885f9 1261static enum route_map_cmd_result_t
1782514f 1262route_match_community(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1263{
1264 struct community_list *list;
9b6d8fcf 1265 struct bgp_path_info *path;
e9a223ac 1266 struct rmap_community *rcom = rule;
d62a17ae 1267
1782514f
DS
1268 path = object;
1269 rcom = rule;
d62a17ae 1270
1782514f
DS
1271 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1272 COMMUNITY_LIST_MASTER);
1273 if (!list)
1274 return RMAP_NOMATCH;
d62a17ae 1275
1782514f
DS
1276 if (rcom->exact) {
1277 if (community_list_exact_match(path->attr->community, list))
1278 return RMAP_MATCH;
1279 } else {
1280 if (community_list_match(path->attr->community, list))
1281 return RMAP_MATCH;
718e3744 1282 }
1782514f 1283
d62a17ae 1284 return RMAP_NOMATCH;
718e3744 1285}
1286
1287/* Compile function for community match. */
d62a17ae 1288static void *route_match_community_compile(const char *arg)
1289{
1290 struct rmap_community *rcom;
1291 int len;
1292 char *p;
1293
1294 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1295
1296 p = strchr(arg, ' ');
1297 if (p) {
1298 len = p - arg;
1299 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1300 memcpy(rcom->name, arg, len);
1301 rcom->exact = 1;
1302 } else {
1303 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1304 rcom->exact = 0;
1305 }
e237b0d2
DS
1306
1307 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1308 return rcom;
718e3744 1309}
1310
1311/* Compile function for community match. */
d62a17ae 1312static void route_match_community_free(void *rule)
718e3744 1313{
d62a17ae 1314 struct rmap_community *rcom = rule;
718e3744 1315
d62a17ae 1316 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1317 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 1318}
1319
909f3d56 1320/*
1321 * In routemap processing there is a need to add the
1322 * name as a rule_key in the dependency table. Routemap
1323 * lib is unaware of rule_key when exact-match clause
1324 * is in use. routemap lib uses the compiled output to
1325 * get the rule_key value.
1326 */
1327static void *route_match_get_community_key(void *rule)
1328{
1329 struct rmap_community *rcom;
1330
1331 rcom = rule;
1332 return rcom->name;
1333}
1334
1335
718e3744 1336/* Route map commands for community matching. */
364deb04
DL
1337static const struct route_map_rule_cmd route_match_community_cmd = {
1338 "community",
1339 route_match_community,
1340 route_match_community_compile,
1341 route_match_community_free,
1342 route_match_get_community_key
1343};
6b0655a2 1344
57d187bc 1345/* Match function for lcommunity match. */
b68885f9 1346static enum route_map_cmd_result_t
1782514f 1347route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1348{
1349 struct community_list *list;
9b6d8fcf 1350 struct bgp_path_info *path;
e9a223ac 1351 struct rmap_community *rcom = rule;
d62a17ae 1352
1782514f 1353 path = object;
d62a17ae 1354
1782514f
DS
1355 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1356 LARGE_COMMUNITY_LIST_MASTER);
1357 if (!list)
1358 return RMAP_NOMATCH;
d62a17ae 1359
1782514f
DS
1360 if (rcom->exact) {
1361 if (lcommunity_list_exact_match(path->attr->lcommunity, list))
1362 return RMAP_MATCH;
1363 } else {
1364 if (lcommunity_list_match(path->attr->lcommunity, list))
1365 return RMAP_MATCH;
d62a17ae 1366 }
1782514f 1367
d62a17ae 1368 return RMAP_NOMATCH;
57d187bc
JS
1369}
1370
1371/* Compile function for community match. */
d62a17ae 1372static void *route_match_lcommunity_compile(const char *arg)
1373{
1374 struct rmap_community *rcom;
1375 int len;
1376 char *p;
1377
1378 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1379
1380 p = strchr(arg, ' ');
1381 if (p) {
1382 len = p - arg;
1383 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1384 memcpy(rcom->name, arg, len);
03ff9a14 1385 rcom->exact = 1;
d62a17ae 1386 } else {
1387 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1388 rcom->exact = 0;
1389 }
e237b0d2
DS
1390
1391 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1392 return rcom;
57d187bc
JS
1393}
1394
1395/* Compile function for community match. */
d62a17ae 1396static void route_match_lcommunity_free(void *rule)
57d187bc 1397{
d62a17ae 1398 struct rmap_community *rcom = rule;
57d187bc 1399
d62a17ae 1400 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1401 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
1402}
1403
1404/* Route map commands for community matching. */
364deb04
DL
1405static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
1406 "large-community",
1407 route_match_lcommunity,
1408 route_match_lcommunity_compile,
1409 route_match_lcommunity_free,
1410 route_match_get_community_key
1411};
57d187bc
JS
1412
1413
73ffb25b 1414/* Match function for extcommunity match. */
b68885f9 1415static enum route_map_cmd_result_t
1782514f 1416route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
73ffb25b 1417{
d62a17ae 1418 struct community_list *list;
9b6d8fcf 1419 struct bgp_path_info *path;
e9a223ac 1420 struct rmap_community *rcom = rule;
73ffb25b 1421
1782514f 1422 path = object;
e52702f2 1423
1782514f
DS
1424 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1425 EXTCOMMUNITY_LIST_MASTER);
1426 if (!list)
1427 return RMAP_NOMATCH;
1428
1429 if (ecommunity_list_match(path->attr->ecommunity, list))
1430 return RMAP_MATCH;
73ffb25b 1431
d62a17ae 1432 return RMAP_NOMATCH;
73ffb25b 1433}
1434
1435/* Compile function for extcommunity match. */
d62a17ae 1436static void *route_match_ecommunity_compile(const char *arg)
73ffb25b 1437{
e9a223ac
DS
1438 struct rmap_community *rcom;
1439
1440 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1441 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
e237b0d2 1442 rcom->name_hash = bgp_clist_hash_key(rcom->name);
e9a223ac
DS
1443
1444 return rcom;
73ffb25b 1445}
1446
1447/* Compile function for extcommunity match. */
d62a17ae 1448static void route_match_ecommunity_free(void *rule)
73ffb25b 1449{
e9a223ac
DS
1450 struct rmap_community *rcom = rule;
1451
1452 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1453 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
73ffb25b 1454}
1455
1456/* Route map commands for community matching. */
364deb04
DL
1457static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
1458 "extcommunity",
1459 route_match_ecommunity,
1460 route_match_ecommunity_compile,
1461 route_match_ecommunity_free
1462};
6b0655a2 1463
718e3744 1464/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1465 and `address-family vpnv4'. */
6b0655a2 1466
718e3744 1467/* `match origin' */
b68885f9 1468static enum route_map_cmd_result_t
1782514f 1469route_match_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 1470{
d7c0a89a 1471 uint8_t *origin;
9b6d8fcf 1472 struct bgp_path_info *path;
718e3744 1473
1782514f
DS
1474 origin = rule;
1475 path = object;
e52702f2 1476
1782514f
DS
1477 if (path->attr->origin == *origin)
1478 return RMAP_MATCH;
718e3744 1479
d62a17ae 1480 return RMAP_NOMATCH;
718e3744 1481}
1482
d62a17ae 1483static void *route_match_origin_compile(const char *arg)
718e3744 1484{
d7c0a89a 1485 uint8_t *origin;
718e3744 1486
d7c0a89a 1487 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 1488
d62a17ae 1489 if (strcmp(arg, "igp") == 0)
1490 *origin = 0;
1491 else if (strcmp(arg, "egp") == 0)
1492 *origin = 1;
1493 else
1494 *origin = 2;
718e3744 1495
d62a17ae 1496 return origin;
718e3744 1497}
1498
1499/* Free route map's compiled `ip address' value. */
d62a17ae 1500static void route_match_origin_free(void *rule)
718e3744 1501{
d62a17ae 1502 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1503}
1504
1505/* Route map commands for origin matching. */
364deb04
DL
1506static const struct route_map_rule_cmd route_match_origin_cmd = {
1507 "origin",
1508 route_match_origin,
1509 route_match_origin_compile,
1510 route_match_origin_free
1511};
1add115a
VT
1512
1513/* match probability { */
1514
b68885f9 1515static enum route_map_cmd_result_t
1782514f 1516route_match_probability(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1517{
5920b3eb 1518 long r = frr_weak_random();
d62a17ae 1519
1520 switch (*(long *)rule) {
1521 case 0:
1522 break;
1523 case RAND_MAX:
1524 return RMAP_MATCH;
1525 default:
1526 if (r < *(long *)rule) {
1527 return RMAP_MATCH;
1528 }
1529 }
1add115a 1530
d62a17ae 1531 return RMAP_NOMATCH;
1add115a
VT
1532}
1533
d62a17ae 1534static void *route_match_probability_compile(const char *arg)
1add115a 1535{
d62a17ae 1536 long *lobule;
1537 unsigned perc;
1add115a 1538
d62a17ae 1539 perc = atoi(arg);
1540 lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1add115a 1541
d62a17ae 1542 switch (perc) {
1543 case 0:
1544 *lobule = 0;
1545 break;
1546 case 100:
1547 *lobule = RAND_MAX;
1548 break;
1549 default:
1550 *lobule = RAND_MAX / 100 * perc;
1551 }
1add115a 1552
d62a17ae 1553 return lobule;
1add115a
VT
1554}
1555
d62a17ae 1556static void route_match_probability_free(void *rule)
1add115a 1557{
d62a17ae 1558 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1add115a
VT
1559}
1560
364deb04
DL
1561static const struct route_map_rule_cmd route_match_probability_cmd = {
1562 "probability",
1563 route_match_probability,
1564 route_match_probability_compile,
1565 route_match_probability_free
1566};
1add115a 1567
bc413143
DS
1568/* `match interface IFNAME' */
1569/* Match function should return 1 if match is success else return
1570 zero. */
b68885f9 1571static enum route_map_cmd_result_t
1782514f 1572route_match_interface(void *rule, const struct prefix *prefix, void *object)
bc413143 1573{
d62a17ae 1574 struct interface *ifp;
40381db7 1575 struct bgp_path_info *path;
bc413143 1576
1782514f 1577 path = object;
bc413143 1578
1782514f
DS
1579 if (!path)
1580 return RMAP_NOMATCH;
bc413143 1581
1782514f 1582 ifp = if_lookup_by_name_all_vrf((char *)rule);
bc413143 1583
1782514f
DS
1584 if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
1585 return RMAP_NOMATCH;
bc413143 1586
1782514f 1587 return RMAP_MATCH;
bc413143
DS
1588}
1589
1590/* Route map `interface' match statement. `arg' should be
1591 interface name. */
d62a17ae 1592static void *route_match_interface_compile(const char *arg)
bc413143 1593{
d62a17ae 1594 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
bc413143
DS
1595}
1596
1597/* Free route map's compiled `interface' value. */
d62a17ae 1598static void route_match_interface_free(void *rule)
bc413143 1599{
d62a17ae 1600 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
bc413143
DS
1601}
1602
1603/* Route map commands for ip address matching. */
364deb04
DL
1604static const struct route_map_rule_cmd route_match_interface_cmd = {
1605 "interface",
1606 route_match_interface,
1607 route_match_interface_compile,
1608 route_match_interface_free
1609};
bc413143 1610
1add115a
VT
1611/* } */
1612
718e3744 1613/* `set ip next-hop IP_ADDRESS' */
1614
0d9551dc 1615/* Match function return 1 if match is success else return zero. */
b68885f9 1616static enum route_map_cmd_result_t
1782514f 1617route_match_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 1618{
d62a17ae 1619 route_tag_t *tag;
9b6d8fcf 1620 struct bgp_path_info *path;
0d9551dc 1621
1782514f
DS
1622 tag = rule;
1623 path = object;
0d9551dc 1624
1782514f 1625 return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
0d9551dc
DS
1626}
1627
1628
0d9551dc 1629/* Route map commands for tag matching. */
364deb04
DL
1630static const struct route_map_rule_cmd route_match_tag_cmd = {
1631 "tag",
1632 route_match_tag,
1633 route_map_rule_tag_compile,
d62a17ae 1634 route_map_rule_tag_free,
0d9551dc
DS
1635};
1636
ef3e0d04 1637static enum route_map_cmd_result_t
1782514f 1638route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
ef3e0d04
SM
1639{
1640 uint32_t *srte_color = rule;
1641 struct bgp_path_info *path;
1642
ef3e0d04
SM
1643 path = object;
1644
1645 path->attr->srte_color = *srte_color;
1646 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
1647
1648 return RMAP_OKAY;
1649}
1650
1651/* Route map `sr-te color' compile function */
1652static void *route_set_srte_color_compile(const char *arg)
1653{
1654 uint32_t *color;
1655
1656 color = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1657 *color = atoi(arg);
1658
1659 return color;
1660}
1661
1662/* Free route map's compiled `sr-te color' value. */
1663static void route_set_srte_color_free(void *rule)
1664{
1665 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1666}
1667
1668/* Route map commands for sr-te color set. */
1669struct route_map_rule_cmd route_set_srte_color_cmd = {
1670 "sr-te color", route_set_srte_color, route_set_srte_color_compile,
1671 route_set_srte_color_free};
0d9551dc 1672
718e3744 1673/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 1674struct rmap_ip_nexthop_set {
1675 struct in_addr *address;
1676 int peer_address;
1677 int unchanged;
ac41b2a2 1678};
1679
b68885f9 1680static enum route_map_cmd_result_t
1782514f 1681route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1682{
1683 struct rmap_ip_nexthop_set *rins = rule;
9b6d8fcf 1684 struct bgp_path_info *path;
d62a17ae 1685 struct peer *peer;
1686
77f4dfb9
DS
1687 if (prefix->family == AF_INET6)
1688 return RMAP_OKAY;
1689
2b67b6f1
DS
1690 path = object;
1691 peer = path->peer;
1692
1693 if (rins->unchanged) {
1694 SET_FLAG(path->attr->rmap_change_flags,
1695 BATTR_RMAP_NEXTHOP_UNCHANGED);
1696 } else if (rins->peer_address) {
1697 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1698 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1699 && peer->su_remote
1700 && sockunion_family(peer->su_remote) == AF_INET) {
1701 path->attr->nexthop.s_addr =
1702 sockunion2ip(peer->su_remote);
9b6d8fcf 1703 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
2b67b6f1
DS
1704 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
1705 /* The next hop value will be set as part of
1706 * packet rewrite. Set the flags here to indicate
1707 * that rewrite needs to be done.
1708 * Also, clear the value.
1709 */
9b6d8fcf 1710 SET_FLAG(path->attr->rmap_change_flags,
2b67b6f1 1711 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
975a328e 1712 path->attr->nexthop.s_addr = INADDR_ANY;
d62a17ae 1713 }
2b67b6f1
DS
1714 } else {
1715 /* Set next hop value. */
1716 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1717 path->attr->nexthop = *rins->address;
1718 SET_FLAG(path->attr->rmap_change_flags,
1719 BATTR_RMAP_IPV4_NHOP_CHANGED);
1720 /* case for MP-BGP : MPLS VPN */
1721 path->attr->mp_nexthop_global_in = *rins->address;
1722 path->attr->mp_nexthop_len = sizeof(*rins->address);
ac41b2a2 1723 }
718e3744 1724
d62a17ae 1725 return RMAP_OKAY;
718e3744 1726}
1727
1728/* Route map `ip nexthop' compile function. Given string is converted
1729 to struct in_addr structure. */
d62a17ae 1730static void *route_set_ip_nexthop_compile(const char *arg)
1731{
1732 struct rmap_ip_nexthop_set *rins;
1733 struct in_addr *address = NULL;
1734 int peer_address = 0;
1735 int unchanged = 0;
1736 int ret;
1737
1738 if (strcmp(arg, "peer-address") == 0)
1739 peer_address = 1;
1740 else if (strcmp(arg, "unchanged") == 0)
1741 unchanged = 1;
1742 else {
1743 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
1744 sizeof(struct in_addr));
1745 ret = inet_aton(arg, address);
1746
1747 if (ret == 0) {
1748 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
1749 return NULL;
1750 }
ac41b2a2 1751 }
718e3744 1752
d62a17ae 1753 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
1754 sizeof(struct rmap_ip_nexthop_set));
ac41b2a2 1755
d62a17ae 1756 rins->address = address;
1757 rins->peer_address = peer_address;
1758 rins->unchanged = unchanged;
ac41b2a2 1759
d62a17ae 1760 return rins;
718e3744 1761}
1762
1763/* Free route map's compiled `ip nexthop' value. */
d62a17ae 1764static void route_set_ip_nexthop_free(void *rule)
718e3744 1765{
d62a17ae 1766 struct rmap_ip_nexthop_set *rins = rule;
ac41b2a2 1767
0a22ddfb 1768 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
e52702f2 1769
d62a17ae 1770 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
718e3744 1771}
1772
1773/* Route map commands for ip nexthop set. */
364deb04
DL
1774static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
1775 "ip next-hop",
1776 route_set_ip_nexthop,
1777 route_set_ip_nexthop_compile,
1778 route_set_ip_nexthop_free
1779};
6b0655a2 1780
718e3744 1781/* `set local-preference LOCAL_PREF' */
1782
1783/* Set local preference. */
b68885f9 1784static enum route_map_cmd_result_t
1782514f 1785route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1786{
1787 struct rmap_value *rv;
9b6d8fcf 1788 struct bgp_path_info *path;
d7c0a89a 1789 uint32_t locpref = 0;
d62a17ae 1790
1782514f
DS
1791 /* Fetch routemap's rule information. */
1792 rv = rule;
1793 path = object;
d62a17ae 1794
1782514f
DS
1795 /* Set local preference value. */
1796 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1797 locpref = path->attr->local_pref;
d62a17ae 1798
1782514f
DS
1799 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1800 path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
718e3744 1801
d62a17ae 1802 return RMAP_OKAY;
718e3744 1803}
1804
718e3744 1805/* Set local preference rule structure. */
364deb04
DL
1806static const struct route_map_rule_cmd route_set_local_pref_cmd = {
1807 "local-preference",
1808 route_set_local_pref,
1809 route_value_compile,
d62a17ae 1810 route_value_free,
718e3744 1811};
6b0655a2 1812
718e3744 1813/* `set weight WEIGHT' */
1814
1815/* Set weight. */
b68885f9 1816static enum route_map_cmd_result_t
1782514f 1817route_set_weight(void *rule, const struct prefix *prefix, void *object)
718e3744 1818{
d62a17ae 1819 struct rmap_value *rv;
9b6d8fcf 1820 struct bgp_path_info *path;
718e3744 1821
1782514f
DS
1822 /* Fetch routemap's rule information. */
1823 rv = rule;
1824 path = object;
e52702f2 1825
1782514f
DS
1826 /* Set weight value. */
1827 path->attr->weight = route_value_adjust(rv, 0, path->peer);
718e3744 1828
d62a17ae 1829 return RMAP_OKAY;
718e3744 1830}
1831
718e3744 1832/* Set local preference rule structure. */
364deb04
DL
1833static const struct route_map_rule_cmd route_set_weight_cmd = {
1834 "weight",
1835 route_set_weight,
1836 route_value_compile,
1837 route_value_free,
718e3744 1838};
6b0655a2 1839
7b7d48e5
DS
1840/* `set distance DISTANCE */
1841static enum route_map_cmd_result_t
1782514f 1842route_set_distance(void *rule, const struct prefix *prefix, void *object)
7b7d48e5
DS
1843{
1844 struct bgp_path_info *path = object;
1845 struct rmap_value *rv = rule;
1846
7b7d48e5
DS
1847 path->attr->distance = rv->value;
1848
1849 return RMAP_OKAY;
1850}
1851
1852/* set distance rule structure */
364deb04 1853static const struct route_map_rule_cmd route_set_distance_cmd = {
7b7d48e5
DS
1854 "distance",
1855 route_set_distance,
1856 route_value_compile,
1857 route_value_free,
1858};
1859
718e3744 1860/* `set metric METRIC' */
1861
1862/* Set metric to attribute. */
b68885f9 1863static enum route_map_cmd_result_t
1782514f 1864route_set_metric(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1865{
1866 struct rmap_value *rv;
9b6d8fcf 1867 struct bgp_path_info *path;
d7c0a89a 1868 uint32_t med = 0;
d62a17ae 1869
1782514f
DS
1870 /* Fetch routemap's rule information. */
1871 rv = rule;
1872 path = object;
d62a17ae 1873
1782514f
DS
1874 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
1875 med = path->attr->med;
1876
1877 path->attr->med = route_value_adjust(rv, med, path->peer);
1878 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
d62a17ae 1879
d62a17ae 1880 return RMAP_OKAY;
718e3744 1881}
1882
718e3744 1883/* Set metric rule structure. */
364deb04
DL
1884static const struct route_map_rule_cmd route_set_metric_cmd = {
1885 "metric",
1886 route_set_metric,
1887 route_value_compile,
1888 route_value_free,
718e3744 1889};
6b0655a2 1890
951745bd
PG
1891/* `set table (1-4294967295)' */
1892
1782514f
DS
1893static enum route_map_cmd_result_t
1894route_set_table_id(void *rule, const struct prefix *prefix,
1895
1896 void *object)
951745bd
PG
1897{
1898 struct rmap_value *rv;
1899 struct bgp_path_info *path;
1900
1782514f
DS
1901 /* Fetch routemap's rule information. */
1902 rv = rule;
1903 path = object;
1904
1905 path->attr->rmap_table_id = rv->value;
951745bd 1906
951745bd
PG
1907 return RMAP_OKAY;
1908}
1909
1910/* Set table_id rule structure. */
364deb04
DL
1911static const struct route_map_rule_cmd route_set_table_id_cmd = {
1912 "table",
1913 route_set_table_id,
1914 route_value_compile,
1915 route_value_free
951745bd
PG
1916};
1917
718e3744 1918/* `set as-path prepend ASPATH' */
1919
1920/* For AS path prepend mechanism. */
b68885f9 1921static enum route_map_cmd_result_t
1782514f 1922route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1923{
1924 struct aspath *aspath;
1925 struct aspath *new;
9b6d8fcf 1926 struct bgp_path_info *path;
d62a17ae 1927
1782514f 1928 path = object;
d62a17ae 1929
1782514f
DS
1930 if (path->attr->aspath->refcnt)
1931 new = aspath_dup(path->attr->aspath);
1932 else
1933 new = path->attr->aspath;
bc3dd427 1934
1782514f
DS
1935 if ((uintptr_t)rule > 10) {
1936 aspath = rule;
1937 aspath_prepend(aspath, new);
1938 } else {
1939 as_t as = aspath_leftmost(new);
1940 if (!as)
1941 as = path->peer->as;
1942 new = aspath_add_seq_n(new, as, (uintptr_t)rule);
d62a17ae 1943 }
718e3744 1944
1782514f
DS
1945 path->attr->aspath = new;
1946
d62a17ae 1947 return RMAP_OKAY;
718e3744 1948}
1949
d62a17ae 1950static void *route_set_aspath_prepend_compile(const char *arg)
bc3dd427 1951{
d62a17ae 1952 unsigned int num;
bc3dd427 1953
d62a17ae 1954 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
1955 return (void *)(uintptr_t)num;
bc3dd427 1956
d62a17ae 1957 return route_aspath_compile(arg);
bc3dd427
DW
1958}
1959
d62a17ae 1960static void route_set_aspath_prepend_free(void *rule)
bc3dd427 1961{
d62a17ae 1962 if ((uintptr_t)rule > 10)
1963 route_aspath_free(rule);
bc3dd427
DW
1964}
1965
1966
515e500c 1967/* Set as-path prepend rule structure. */
364deb04
DL
1968static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
1969 "as-path prepend",
1970 route_set_aspath_prepend,
1971 route_set_aspath_prepend_compile,
1972 route_set_aspath_prepend_free,
718e3744 1973};
6b0655a2 1974
841f7a57
DO
1975/* `set as-path exclude ASn' */
1976
1977/* For ASN exclude mechanism.
d62a17ae 1978 * Iterate over ASns requested and filter them from the given AS_PATH one by
1979 * one.
841f7a57
DO
1980 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1981 */
b68885f9 1982static enum route_map_cmd_result_t
1782514f 1983route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
d62a17ae 1984{
1985 struct aspath *new_path, *exclude_path;
9b6d8fcf 1986 struct bgp_path_info *path;
d62a17ae 1987
1782514f
DS
1988 exclude_path = rule;
1989 path = object;
1990 if (path->attr->aspath->refcnt)
1991 new_path = aspath_dup(path->attr->aspath);
1992 else
1993 new_path = path->attr->aspath;
1994 path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
1995
d62a17ae 1996 return RMAP_OKAY;
841f7a57
DO
1997}
1998
841f7a57 1999/* Set ASn exlude rule structure. */
364deb04
DL
2000static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2001 "as-path exclude",
2002 route_set_aspath_exclude,
2003 route_aspath_compile,
d62a17ae 2004 route_aspath_free,
841f7a57 2005};
6b0655a2 2006
718e3744 2007/* `set community COMMUNITY' */
d62a17ae 2008struct rmap_com_set {
2009 struct community *com;
2010 int additive;
2011 int none;
718e3744 2012};
2013
2014/* For community set mechanism. */
b68885f9 2015static enum route_map_cmd_result_t
1782514f 2016route_set_community(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2017{
2018 struct rmap_com_set *rcs;
9b6d8fcf 2019 struct bgp_path_info *path;
d62a17ae 2020 struct attr *attr;
2021 struct community *new = NULL;
2022 struct community *old;
2023 struct community *merge;
2024
1782514f
DS
2025 rcs = rule;
2026 path = object;
2027 attr = path->attr;
2028 old = attr->community;
2029
2030 /* "none" case. */
2031 if (rcs->none) {
2032 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
2033 attr->community = NULL;
2034 /* See the longer comment down below. */
2035 if (old && old->refcnt == 0)
2036 community_free(&old);
2037 return RMAP_OKAY;
2038 }
718e3744 2039
1782514f
DS
2040 /* "additive" case. */
2041 if (rcs->additive && old) {
2042 merge = community_merge(community_dup(old), rcs->com);
d62a17ae 2043
1782514f
DS
2044 new = community_uniq_sort(merge);
2045 community_free(&merge);
2046 } else
2047 new = community_dup(rcs->com);
d62a17ae 2048
1782514f
DS
2049 /* HACK: if the old community is not intern'd,
2050 * we should free it here, or all reference to it may be
2051 * lost.
2052 * Really need to cleanup attribute caching sometime.
2053 */
2054 if (old && old->refcnt == 0)
2055 community_free(&old);
f24804f4 2056
1782514f
DS
2057 /* will be interned by caller if required */
2058 attr->community = new;
d62a17ae 2059
1782514f 2060 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
718e3744 2061
d62a17ae 2062 return RMAP_OKAY;
718e3744 2063}
2064
2065/* Compile function for set community. */
d62a17ae 2066static void *route_set_community_compile(const char *arg)
2067{
2068 struct rmap_com_set *rcs;
2069 struct community *com = NULL;
2070 char *sp;
2071 int additive = 0;
2072 int none = 0;
2073
2074 if (strcmp(arg, "none") == 0)
2075 none = 1;
2076 else {
2077 sp = strstr(arg, "additive");
2078
2079 if (sp && sp > arg) {
770817b4 2080 /* "additive" keyword is included. */
d62a17ae 2081 additive = 1;
2082 *(sp - 1) = '\0';
2083 }
718e3744 2084
d62a17ae 2085 com = community_str2com(arg);
718e3744 2086
d62a17ae 2087 if (additive)
2088 *(sp - 1) = ' ';
718e3744 2089
d62a17ae 2090 if (!com)
2091 return NULL;
2092 }
e52702f2 2093
d62a17ae 2094 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2095 rcs->com = com;
2096 rcs->additive = additive;
2097 rcs->none = none;
e52702f2 2098
d62a17ae 2099 return rcs;
718e3744 2100}
2101
2102/* Free function for set community. */
d62a17ae 2103static void route_set_community_free(void *rule)
718e3744 2104{
d62a17ae 2105 struct rmap_com_set *rcs = rule;
718e3744 2106
d62a17ae 2107 if (rcs->com)
3c1f53de 2108 community_free(&rcs->com);
d62a17ae 2109 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2110}
2111
2112/* Set community rule structure. */
364deb04
DL
2113static const struct route_map_rule_cmd route_set_community_cmd = {
2114 "community",
2115 route_set_community,
2116 route_set_community_compile,
d62a17ae 2117 route_set_community_free,
718e3744 2118};
6b0655a2 2119
57d187bc 2120/* `set community COMMUNITY' */
d62a17ae 2121struct rmap_lcom_set {
2122 struct lcommunity *lcom;
2123 int additive;
2124 int none;
57d187bc
JS
2125};
2126
2127
2128/* For lcommunity set mechanism. */
b68885f9 2129static enum route_map_cmd_result_t
1782514f 2130route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2131{
2132 struct rmap_lcom_set *rcs;
9b6d8fcf 2133 struct bgp_path_info *path;
d62a17ae 2134 struct attr *attr;
2135 struct lcommunity *new = NULL;
2136 struct lcommunity *old;
2137 struct lcommunity *merge;
2138
1782514f
DS
2139 rcs = rule;
2140 path = object;
2141 attr = path->attr;
2142 old = attr->lcommunity;
d62a17ae 2143
1782514f
DS
2144 /* "none" case. */
2145 if (rcs->none) {
2146 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
2147 attr->lcommunity = NULL;
d62a17ae 2148
1782514f 2149 /* See the longer comment down below. */
4265a53e
NK
2150 if (old && old->refcnt == 0)
2151 lcommunity_free(&old);
1782514f
DS
2152 return RMAP_OKAY;
2153 }
4265a53e 2154
1782514f
DS
2155 if (rcs->additive && old) {
2156 merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
d62a17ae 2157
1782514f
DS
2158 new = lcommunity_uniq_sort(merge);
2159 lcommunity_free(&merge);
2160 } else
2161 new = lcommunity_dup(rcs->lcom);
2162
2163 /* HACK: if the old large-community is not intern'd,
2164 * we should free it here, or all reference to it may be
2165 * lost.
2166 * Really need to cleanup attribute caching sometime.
2167 */
2168 if (old && old->refcnt == 0)
2169 lcommunity_free(&old);
2170
2171 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2172 attr->lcommunity = new;
2173
2174 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
57d187bc 2175
d62a17ae 2176 return RMAP_OKAY;
2177}
57d187bc 2178
d62a17ae 2179/* Compile function for set community. */
2180static void *route_set_lcommunity_compile(const char *arg)
2181{
2182 struct rmap_lcom_set *rcs;
2183 struct lcommunity *lcom = NULL;
2184 char *sp;
2185 int additive = 0;
2186 int none = 0;
2187
2188 if (strcmp(arg, "none") == 0)
2189 none = 1;
2190 else {
2191 sp = strstr(arg, "additive");
2192
2193 if (sp && sp > arg) {
2194 /* "additive" keyworkd is included. */
2195 additive = 1;
2196 *(sp - 1) = '\0';
2197 }
57d187bc 2198
d62a17ae 2199 lcom = lcommunity_str2com(arg);
57d187bc 2200
d62a17ae 2201 if (additive)
2202 *(sp - 1) = ' ';
57d187bc 2203
d62a17ae 2204 if (!lcom)
2205 return NULL;
2206 }
57d187bc 2207
d62a17ae 2208 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2209 rcs->lcom = lcom;
2210 rcs->additive = additive;
2211 rcs->none = none;
57d187bc 2212
d62a17ae 2213 return rcs;
57d187bc
JS
2214}
2215
2216/* Free function for set lcommunity. */
d62a17ae 2217static void route_set_lcommunity_free(void *rule)
57d187bc 2218{
d62a17ae 2219 struct rmap_lcom_set *rcs = rule;
57d187bc 2220
d62a17ae 2221 if (rcs->lcom) {
2222 lcommunity_free(&rcs->lcom);
2223 }
2224 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
57d187bc
JS
2225}
2226
2227/* Set community rule structure. */
364deb04
DL
2228static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2229 "large-community",
2230 route_set_lcommunity,
2231 route_set_lcommunity_compile,
d62a17ae 2232 route_set_lcommunity_free,
57d187bc
JS
2233};
2234
2235/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2236
2237/* For large community set mechanism. */
b68885f9 2238static enum route_map_cmd_result_t
1782514f 2239route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
d62a17ae 2240{
2241 struct community_list *list;
2242 struct lcommunity *merge;
2243 struct lcommunity *new;
2244 struct lcommunity *old;
9b6d8fcf 2245 struct bgp_path_info *path;
e9a223ac 2246 struct rmap_community *rcom = rule;
d62a17ae 2247
1782514f
DS
2248 if (!rcom)
2249 return RMAP_OKAY;
d62a17ae 2250
1782514f
DS
2251 path = object;
2252 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2253 LARGE_COMMUNITY_LIST_MASTER);
2254 old = path->attr->lcommunity;
2255
2256 if (list && old) {
2257 merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
2258 new = lcommunity_uniq_sort(merge);
2259 lcommunity_free(&merge);
2260
2261 /* HACK: if the old community is not intern'd,
2262 * we should free it here, or all reference to it may be
2263 * lost.
2264 * Really need to cleanup attribute caching sometime.
2265 */
2266 if (old->refcnt == 0)
2267 lcommunity_free(&old);
2268
2269 if (new->size == 0) {
2270 path->attr->lcommunity = NULL;
2271 path->attr->flag &=
2272 ~ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
2273 lcommunity_free(&new);
2274 } else {
2275 path->attr->lcommunity = new;
2276 path->attr->flag |=
2277 ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
d62a17ae 2278 }
2279 }
2280
2281 return RMAP_OKAY;
57d187bc
JS
2282}
2283
2284/* Compile function for set lcommunity. */
d62a17ae 2285static void *route_set_lcommunity_delete_compile(const char *arg)
57d187bc 2286{
e9a223ac 2287 struct rmap_community *rcom;
caa5af30
DA
2288 char **splits;
2289 int num;
57d187bc 2290
caa5af30 2291 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2292
caa5af30
DA
2293 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2294 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2295 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2296
caa5af30
DA
2297 for (int i = 0; i < num; i++)
2298 XFREE(MTYPE_TMP, splits[i]);
2299 XFREE(MTYPE_TMP, splits);
2300
e9a223ac 2301 return rcom;
57d187bc
JS
2302}
2303
2304/* Free function for set lcommunity. */
d62a17ae 2305static void route_set_lcommunity_delete_free(void *rule)
57d187bc 2306{
e9a223ac
DS
2307 struct rmap_community *rcom = rule;
2308
2309 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2310 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
2311}
2312
2313/* Set lcommunity rule structure. */
364deb04
DL
2314static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2315 "large-comm-list",
2316 route_set_lcommunity_delete,
2317 route_set_lcommunity_delete_compile,
2318 route_set_lcommunity_delete_free,
57d187bc
JS
2319};
2320
2321
fee6e4e4 2322/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 2323
2324/* For community set mechanism. */
b68885f9
LK
2325static enum route_map_cmd_result_t
2326route_set_community_delete(void *rule, const struct prefix *prefix,
1782514f 2327 void *object)
d62a17ae 2328{
2329 struct community_list *list;
2330 struct community *merge;
2331 struct community *new;
2332 struct community *old;
9b6d8fcf 2333 struct bgp_path_info *path;
e9a223ac 2334 struct rmap_community *rcom = rule;
d62a17ae 2335
1782514f
DS
2336 if (!rcom)
2337 return RMAP_OKAY;
d62a17ae 2338
1782514f
DS
2339 path = object;
2340 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2341 COMMUNITY_LIST_MASTER);
2342 old = path->attr->community;
2343
2344 if (list && old) {
2345 merge = community_list_match_delete(community_dup(old), list);
2346 new = community_uniq_sort(merge);
2347 community_free(&merge);
2348
2349 /* HACK: if the old community is not intern'd,
2350 * we should free it here, or all reference to it may be
2351 * lost.
2352 * Really need to cleanup attribute caching sometime.
2353 */
2354 if (old->refcnt == 0)
2355 community_free(&old);
2356
2357 if (new->size == 0) {
2358 path->attr->community = NULL;
2359 path->attr->flag &=
2360 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
2361 community_free(&new);
2362 } else {
2363 path->attr->community = new;
2364 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
d62a17ae 2365 }
718e3744 2366 }
718e3744 2367
d62a17ae 2368 return RMAP_OKAY;
718e3744 2369}
2370
2371/* Compile function for set community. */
d62a17ae 2372static void *route_set_community_delete_compile(const char *arg)
718e3744 2373{
e9a223ac 2374 struct rmap_community *rcom;
60762f8f
DA
2375 char **splits;
2376 int num;
718e3744 2377
60762f8f 2378 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2379
60762f8f
DA
2380 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2381 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2382 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2383
60762f8f
DA
2384 for (int i = 0; i < num; i++)
2385 XFREE(MTYPE_TMP, splits[i]);
2386 XFREE(MTYPE_TMP, splits);
2387
e9a223ac 2388 return rcom;
718e3744 2389}
2390
2391/* Free function for set community. */
d62a17ae 2392static void route_set_community_delete_free(void *rule)
718e3744 2393{
e9a223ac
DS
2394 struct rmap_community *rcom = rule;
2395
2396 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2397 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 2398}
2399
2400/* Set community rule structure. */
364deb04
DL
2401static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2402 "comm-list",
2403 route_set_community_delete,
2404 route_set_community_delete_compile,
2405 route_set_community_delete_free,
718e3744 2406};
6b0655a2 2407
718e3744 2408/* `set extcommunity rt COMMUNITY' */
2409
73d78ea0 2410/* For community set mechanism. Used by _rt and _soo. */
b68885f9 2411static enum route_map_cmd_result_t
1782514f 2412route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2413{
2414 struct ecommunity *ecom;
2415 struct ecommunity *new_ecom;
2416 struct ecommunity *old_ecom;
9b6d8fcf 2417 struct bgp_path_info *path;
d62a17ae 2418
1782514f
DS
2419 ecom = rule;
2420 path = object;
d62a17ae 2421
1782514f
DS
2422 if (!ecom)
2423 return RMAP_OKAY;
d62a17ae 2424
1782514f
DS
2425 /* We assume additive for Extended Community. */
2426 old_ecom = path->attr->ecommunity;
2427
2428 if (old_ecom) {
2429 new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), ecom);
d62a17ae 2430
1782514f
DS
2431 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2432 * bgp_update_receive()
2433 * ->refcnt = 0 => set by a previous route-map
2434 * statement */
2435 if (!old_ecom->refcnt)
2436 ecommunity_free(&old_ecom);
2437 } else
2438 new_ecom = ecommunity_dup(ecom);
d62a17ae 2439
1782514f
DS
2440 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2441 path->attr->ecommunity = new_ecom;
d62a17ae 2442
1782514f 2443 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
d62a17ae 2444
d62a17ae 2445 return RMAP_OKAY;
718e3744 2446}
2447
2448/* Compile function for set community. */
d62a17ae 2449static void *route_set_ecommunity_rt_compile(const char *arg)
718e3744 2450{
d62a17ae 2451 struct ecommunity *ecom;
718e3744 2452
d62a17ae 2453 ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2454 if (!ecom)
2455 return NULL;
2456 return ecommunity_intern(ecom);
718e3744 2457}
2458
73d78ea0 2459/* Free function for set community. Used by _rt and _soo */
d62a17ae 2460static void route_set_ecommunity_free(void *rule)
718e3744 2461{
d62a17ae 2462 struct ecommunity *ecom = rule;
2463 ecommunity_unintern(&ecom);
718e3744 2464}
2465
2466/* Set community rule structure. */
364deb04
DL
2467static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2468 "extcommunity rt",
2469 route_set_ecommunity,
2470 route_set_ecommunity_rt_compile,
2471 route_set_ecommunity_free,
718e3744 2472};
2473
2474/* `set extcommunity soo COMMUNITY' */
2475
718e3744 2476/* Compile function for set community. */
d62a17ae 2477static void *route_set_ecommunity_soo_compile(const char *arg)
718e3744 2478{
d62a17ae 2479 struct ecommunity *ecom;
718e3744 2480
d62a17ae 2481 ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2482 if (!ecom)
2483 return NULL;
e52702f2 2484
d62a17ae 2485 return ecommunity_intern(ecom);
718e3744 2486}
2487
718e3744 2488/* Set community rule structure. */
364deb04
DL
2489static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2490 "extcommunity soo",
2491 route_set_ecommunity,
2492 route_set_ecommunity_soo_compile,
2493 route_set_ecommunity_free,
718e3744 2494};
6b0655a2 2495
ca9ac3ef 2496/* `set extcommunity bandwidth' */
2497
2498struct rmap_ecomm_lb_set {
2499 uint8_t lb_type;
2500#define RMAP_ECOMM_LB_SET_VALUE 1
2501#define RMAP_ECOMM_LB_SET_CUMUL 2
2502#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2503 bool non_trans;
2504 uint32_t bw;
2505};
2506
2507static enum route_map_cmd_result_t
1782514f 2508route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
ca9ac3ef 2509{
2510 struct rmap_ecomm_lb_set *rels = rule;
2511 struct bgp_path_info *path;
2512 struct peer *peer;
2513 struct ecommunity ecom_lb = {0};
2514 struct ecommunity_val lb_eval;
2515 uint32_t bw_bytes = 0;
b1875e65 2516 uint16_t mpath_count = 0;
ca9ac3ef 2517 struct ecommunity *new_ecom;
2518 struct ecommunity *old_ecom;
2519 as_t as;
2520
ca9ac3ef 2521 path = object;
2522 peer = path->peer;
2523 if (!peer || !peer->bgp)
2524 return RMAP_ERROR;
2525
2526 /* Build link bandwidth extended community */
2527 as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
b1875e65 2528 if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
87b42e3b 2529 bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
b1875e65 2530 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2531 /* process this only for the best path. */
2532 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2533 return RMAP_OKAY;
2534
2535 bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2536 if (!bw_bytes)
2537 return RMAP_OKAY;
2538
2539 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2540
2541 /* process this only for the best path. */
2542 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2543 return RMAP_OKAY;
2544
87b42e3b 2545 bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
b1875e65 2546 mpath_count = bgp_path_info_mpath_count(path) + 1;
2547 bw_bytes *= mpath_count;
2548 }
ca9ac3ef 2549
2550 encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval);
ca9ac3ef 2551
2552 /* add to route or merge with existing */
2553 old_ecom = path->attr->ecommunity;
2554 if (old_ecom) {
f6ca545a 2555 new_ecom = ecommunity_dup(old_ecom);
2556 ecommunity_add_val(new_ecom, &lb_eval, true, true);
ca9ac3ef 2557 if (!old_ecom->refcnt)
2558 ecommunity_free(&old_ecom);
f6ca545a 2559 } else {
2560 ecom_lb.size = 1;
7659ad68 2561 ecom_lb.unit_size = ECOMMUNITY_SIZE;
f6ca545a 2562 ecom_lb.val = (uint8_t *)lb_eval.val;
ca9ac3ef 2563 new_ecom = ecommunity_dup(&ecom_lb);
f6ca545a 2564 }
ca9ac3ef 2565
2566 /* new_ecom will be intern()'d or attr_flush()'d in call stack */
2567 path->attr->ecommunity = new_ecom;
2568 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
2569
7b651a32 2570 /* Mark that route-map has set link bandwidth; used in attribute
2571 * setting decisions.
2572 */
2573 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
ca9ac3ef 2574
2575 return RMAP_OKAY;
2576}
2577
2578static void *route_set_ecommunity_lb_compile(const char *arg)
2579{
2580 struct rmap_ecomm_lb_set *rels;
2581 uint8_t lb_type;
2582 uint32_t bw = 0;
4c13ffe4 2583 char bw_str[40] = {0};
2584 char *p, *str;
2585 bool non_trans = false;
ca9ac3ef 2586
4c13ffe4 2587 str = (char *)arg;
2588 p = strchr(arg, ' ');
2589 if (p) {
2590 int len;
2591
2592 len = p - arg;
2593 memcpy(bw_str, arg, len);
2594 non_trans = true;
2595 str = bw_str;
2596 }
2597
2598 if (strcmp(str, "cumulative") == 0)
ca9ac3ef 2599 lb_type = RMAP_ECOMM_LB_SET_CUMUL;
4c13ffe4 2600 else if (strcmp(str, "num-multipaths") == 0)
ca9ac3ef 2601 lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
2602 else {
2603 char *end = NULL;
2604
4c13ffe4 2605 bw = strtoul(str, &end, 10);
ca9ac3ef 2606 if (*end != '\0')
2607 return NULL;
2608 lb_type = RMAP_ECOMM_LB_SET_VALUE;
2609 }
2610
2611 rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2612 sizeof(struct rmap_ecomm_lb_set));
2613 rels->lb_type = lb_type;
2614 rels->bw = bw;
4c13ffe4 2615 rels->non_trans = non_trans;
ca9ac3ef 2616
2617 return rels;
2618}
2619
2620static void route_set_ecommunity_lb_free(void *rule)
2621{
2622 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2623}
2624
2625/* Set community rule structure. */
2626struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
2627 "extcommunity bandwidth",
2628 route_set_ecommunity_lb,
2629 route_set_ecommunity_lb_compile,
2630 route_set_ecommunity_lb_free,
2631};
2632
718e3744 2633/* `set origin ORIGIN' */
2634
2635/* For origin set. */
b68885f9 2636static enum route_map_cmd_result_t
1782514f 2637route_set_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 2638{
d7c0a89a 2639 uint8_t *origin;
9b6d8fcf 2640 struct bgp_path_info *path;
718e3744 2641
1782514f
DS
2642 origin = rule;
2643 path = object;
e52702f2 2644
1782514f 2645 path->attr->origin = *origin;
718e3744 2646
d62a17ae 2647 return RMAP_OKAY;
718e3744 2648}
2649
2650/* Compile function for origin set. */
d62a17ae 2651static void *route_set_origin_compile(const char *arg)
718e3744 2652{
d7c0a89a 2653 uint8_t *origin;
718e3744 2654
d7c0a89a 2655 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 2656
d62a17ae 2657 if (strcmp(arg, "igp") == 0)
2658 *origin = 0;
2659 else if (strcmp(arg, "egp") == 0)
2660 *origin = 1;
2661 else
2662 *origin = 2;
718e3744 2663
d62a17ae 2664 return origin;
718e3744 2665}
2666
2667/* Compile function for origin set. */
d62a17ae 2668static void route_set_origin_free(void *rule)
718e3744 2669{
d62a17ae 2670 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2671}
2672
515e500c 2673/* Set origin rule structure. */
364deb04
DL
2674static const struct route_map_rule_cmd route_set_origin_cmd = {
2675 "origin",
2676 route_set_origin,
2677 route_set_origin_compile,
d62a17ae 2678 route_set_origin_free,
718e3744 2679};
6b0655a2 2680
718e3744 2681/* `set atomic-aggregate' */
2682
2683/* For atomic aggregate set. */
b68885f9 2684static enum route_map_cmd_result_t
1782514f 2685route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
718e3744 2686{
9b6d8fcf 2687 struct bgp_path_info *path;
718e3744 2688
1782514f
DS
2689 path = object;
2690 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
718e3744 2691
d62a17ae 2692 return RMAP_OKAY;
718e3744 2693}
2694
2695/* Compile function for atomic aggregate. */
d62a17ae 2696static void *route_set_atomic_aggregate_compile(const char *arg)
718e3744 2697{
d62a17ae 2698 return (void *)1;
718e3744 2699}
2700
2701/* Compile function for atomic aggregate. */
d62a17ae 2702static void route_set_atomic_aggregate_free(void *rule)
718e3744 2703{
d62a17ae 2704 return;
718e3744 2705}
2706
2707/* Set atomic aggregate rule structure. */
364deb04
DL
2708static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
2709 "atomic-aggregate",
2710 route_set_atomic_aggregate,
2711 route_set_atomic_aggregate_compile,
2712 route_set_atomic_aggregate_free,
718e3744 2713};
6b0655a2 2714
718e3744 2715/* `set aggregator as AS A.B.C.D' */
d62a17ae 2716struct aggregator {
2717 as_t as;
2718 struct in_addr address;
718e3744 2719};
2720
b68885f9 2721static enum route_map_cmd_result_t
1782514f 2722route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
718e3744 2723{
9b6d8fcf 2724 struct bgp_path_info *path;
d62a17ae 2725 struct aggregator *aggregator;
718e3744 2726
1782514f
DS
2727 path = object;
2728 aggregator = rule;
e52702f2 2729
1782514f
DS
2730 path->attr->aggregator_as = aggregator->as;
2731 path->attr->aggregator_addr = aggregator->address;
2732 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
718e3744 2733
d62a17ae 2734 return RMAP_OKAY;
718e3744 2735}
2736
d62a17ae 2737static void *route_set_aggregator_as_compile(const char *arg)
718e3744 2738{
d62a17ae 2739 struct aggregator *aggregator;
2740 char as[10];
2741 char address[20];
2742 int ret;
718e3744 2743
d62a17ae 2744 aggregator =
2745 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
116e176d
DS
2746 if (sscanf(arg, "%s %s", as, address) != 2) {
2747 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2748 return NULL;
2749 }
718e3744 2750
d62a17ae 2751 aggregator->as = strtoul(as, NULL, 10);
2752 ret = inet_aton(address, &aggregator->address);
2753 if (ret == 0) {
2754 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2755 return NULL;
2756 }
2757 return aggregator;
718e3744 2758}
2759
d62a17ae 2760static void route_set_aggregator_as_free(void *rule)
718e3744 2761{
d62a17ae 2762 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2763}
2764
364deb04
DL
2765static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
2766 "aggregator as",
2767 route_set_aggregator_as,
2768 route_set_aggregator_as_compile,
2769 route_set_aggregator_as_free,
718e3744 2770};
6b0655a2 2771
4b7e6066 2772/* Set tag to object. object must be pointer to struct bgp_path_info */
b68885f9 2773static enum route_map_cmd_result_t
1782514f 2774route_set_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 2775{
d62a17ae 2776 route_tag_t *tag;
9b6d8fcf 2777 struct bgp_path_info *path;
0d9551dc 2778
1782514f
DS
2779 tag = rule;
2780 path = object;
0d9551dc 2781
1782514f
DS
2782 /* Set tag value */
2783 path->attr->tag = *tag;
0d9551dc 2784
d62a17ae 2785 return RMAP_OKAY;
0d9551dc
DS
2786}
2787
0d9551dc 2788/* Route map commands for tag set. */
364deb04
DL
2789static const struct route_map_rule_cmd route_set_tag_cmd = {
2790 "tag",
2791 route_set_tag,
2792 route_map_rule_tag_compile,
d62a17ae 2793 route_map_rule_tag_free,
0d9551dc
DS
2794};
2795
4b7e6066 2796/* Set label-index to object. object must be pointer to struct bgp_path_info */
b68885f9 2797static enum route_map_cmd_result_t
1782514f 2798route_set_label_index(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2799{
2800 struct rmap_value *rv;
9b6d8fcf 2801 struct bgp_path_info *path;
d7c0a89a 2802 uint32_t label_index;
d62a17ae 2803
1782514f
DS
2804 /* Fetch routemap's rule information. */
2805 rv = rule;
2806 path = object;
d62a17ae 2807
1782514f
DS
2808 /* Set label-index value. */
2809 label_index = rv->value;
2810 if (label_index) {
2811 path->attr->label_index = label_index;
2812 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
d62a17ae 2813 }
d990e384 2814
d62a17ae 2815 return RMAP_OKAY;
d990e384
DS
2816}
2817
2818/* Route map commands for label-index set. */
364deb04
DL
2819static const struct route_map_rule_cmd route_set_label_index_cmd = {
2820 "label-index",
2821 route_set_label_index,
2822 route_value_compile,
d62a17ae 2823 route_value_free,
d990e384 2824};
0d9551dc 2825
718e3744 2826/* `match ipv6 address IP_ACCESS_LIST' */
2827
b68885f9 2828static enum route_map_cmd_result_t
1782514f 2829route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
718e3744 2830{
d62a17ae 2831 struct access_list *alist;
718e3744 2832
1782514f 2833 if (prefix->family == AF_INET6) {
d62a17ae 2834 alist = access_list_lookup(AFI_IP6, (char *)rule);
2835 if (alist == NULL)
2836 return RMAP_NOMATCH;
e52702f2 2837
d62a17ae 2838 return (access_list_apply(alist, prefix) == FILTER_DENY
2839 ? RMAP_NOMATCH
2840 : RMAP_MATCH);
2841 }
2842 return RMAP_NOMATCH;
718e3744 2843}
2844
d62a17ae 2845static void *route_match_ipv6_address_compile(const char *arg)
718e3744 2846{
d62a17ae 2847 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2848}
2849
d62a17ae 2850static void route_match_ipv6_address_free(void *rule)
718e3744 2851{
d62a17ae 2852 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2853}
2854
2855/* Route map commands for ip address matching. */
364deb04
DL
2856static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
2857 "ipv6 address",
2858 route_match_ipv6_address,
2859 route_match_ipv6_address_compile,
2860 route_match_ipv6_address_free
2861};
6b0655a2 2862
718e3744 2863/* `match ipv6 next-hop IP_ADDRESS' */
2864
b68885f9 2865static enum route_map_cmd_result_t
1782514f 2866route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
718e3744 2867{
d62a17ae 2868 struct in6_addr *addr = rule;
9b6d8fcf 2869 struct bgp_path_info *path;
718e3744 2870
1782514f 2871 path = object;
718e3744 2872
1782514f
DS
2873 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
2874 return RMAP_MATCH;
718e3744 2875
1782514f
DS
2876 if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
2877 && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
2878 return RMAP_MATCH;
718e3744 2879
d62a17ae 2880 return RMAP_NOMATCH;
718e3744 2881}
2882
d62a17ae 2883static void *route_match_ipv6_next_hop_compile(const char *arg)
718e3744 2884{
d62a17ae 2885 struct in6_addr *address;
2886 int ret;
718e3744 2887
d62a17ae 2888 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2889
d62a17ae 2890 ret = inet_pton(AF_INET6, arg, address);
2891 if (!ret) {
2892 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2893 return NULL;
2894 }
718e3744 2895
d62a17ae 2896 return address;
718e3744 2897}
2898
d62a17ae 2899static void route_match_ipv6_next_hop_free(void *rule)
718e3744 2900{
d62a17ae 2901 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2902}
2903
364deb04
DL
2904static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
2905 "ipv6 next-hop",
2906 route_match_ipv6_next_hop,
2907 route_match_ipv6_next_hop_compile,
2908 route_match_ipv6_next_hop_free
2909};
6b0655a2 2910
be7735b3
PG
2911/* `match ip next-hop IP_ADDRESS' */
2912
2913static enum route_map_cmd_result_t
1782514f 2914route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
be7735b3
PG
2915{
2916 struct in_addr *addr = rule;
2917 struct bgp_path_info *path;
2918
1782514f 2919 path = object;
be7735b3 2920
1782514f
DS
2921 if (path->attr->nexthop.s_addr == addr->s_addr
2922 || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
2923 && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
2924 return RMAP_MATCH;
be7735b3
PG
2925
2926 return RMAP_NOMATCH;
2927}
2928
2929static void *route_match_ipv4_next_hop_compile(const char *arg)
2930{
2931 struct in_addr *address;
2932 int ret;
2933
2934 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
2935
2936 ret = inet_pton(AF_INET, arg, address);
2937 if (!ret) {
2938 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2939 return NULL;
2940 }
2941
2942 return address;
2943}
2944
2945static void route_match_ipv4_next_hop_free(void *rule)
2946{
2947 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2948}
2949
2950static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
2951 "ip next-hop address",
2952 route_match_ipv4_next_hop,
2953 route_match_ipv4_next_hop_compile,
2954 route_match_ipv4_next_hop_free
2955};
2956
718e3744 2957/* `match ipv6 address prefix-list PREFIX_LIST' */
2958
b68885f9 2959static enum route_map_cmd_result_t
123214ef 2960route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1782514f 2961 void *object)
718e3744 2962{
1782514f 2963 return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
718e3744 2964}
2965
d62a17ae 2966static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 2967{
d62a17ae 2968 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2969}
2970
d62a17ae 2971static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 2972{
d62a17ae 2973 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2974}
2975
364deb04
DL
2976static const struct route_map_rule_cmd
2977 route_match_ipv6_address_prefix_list_cmd = {
2978 "ipv6 address prefix-list",
2979 route_match_ipv6_address_prefix_list,
d62a17ae 2980 route_match_ipv6_address_prefix_list_compile,
364deb04
DL
2981 route_match_ipv6_address_prefix_list_free
2982};
6b0655a2 2983
61ad901e
DA
2984/* `match ipv6 next-hop type <TYPE>' */
2985
b68885f9 2986static enum route_map_cmd_result_t
61ad901e 2987route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1782514f 2988 void *object)
61ad901e 2989{
9b6d8fcf 2990 struct bgp_path_info *path;
61ad901e
DA
2991 struct in6_addr *addr = rule;
2992
1782514f 2993 if (prefix->family == AF_INET6) {
9b6d8fcf 2994 path = (struct bgp_path_info *)object;
05864da7 2995 if (!path)
b68885f9 2996 return RMAP_NOMATCH;
61ad901e 2997
9b6d8fcf
DS
2998 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
2999 && !path->attr->nh_ifindex)
61ad901e
DA
3000 return RMAP_MATCH;
3001 }
1782514f 3002
61ad901e
DA
3003 return RMAP_NOMATCH;
3004}
3005
3006static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3007{
3008 struct in6_addr *address;
3009 int ret;
3010
3011 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3012
3013 ret = inet_pton(AF_INET6, "::0", address);
3014 if (!ret) {
3015 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3016 return NULL;
3017 }
3018
3019 return address;
3020}
3021
3022static void route_match_ipv6_next_hop_type_free(void *rule)
3023{
3024 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3025}
3026
364deb04
DL
3027static const struct route_map_rule_cmd
3028 route_match_ipv6_next_hop_type_cmd = {
3029 "ipv6 next-hop type",
3030 route_match_ipv6_next_hop_type,
61ad901e 3031 route_match_ipv6_next_hop_type_compile,
364deb04
DL
3032 route_match_ipv6_next_hop_type_free
3033};
61ad901e 3034
718e3744 3035/* `set ipv6 nexthop global IP_ADDRESS' */
3036
3037/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9 3038static enum route_map_cmd_result_t
1782514f 3039route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
718e3744 3040{
d62a17ae 3041 struct in6_addr *address;
9b6d8fcf 3042 struct bgp_path_info *path;
718e3744 3043
1782514f
DS
3044 /* Fetch routemap's rule information. */
3045 address = rule;
3046 path = object;
e52702f2 3047
1782514f
DS
3048 /* Set next hop value. */
3049 path->attr->mp_nexthop_global = *address;
3f9c7369 3050
1782514f
DS
3051 /* Set nexthop length. */
3052 if (path->attr->mp_nexthop_len == 0)
3053 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 3054
1782514f
DS
3055 SET_FLAG(path->attr->rmap_change_flags,
3056 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
718e3744 3057
d62a17ae 3058 return RMAP_OKAY;
718e3744 3059}
3060
3061/* Route map `ip next-hop' compile function. Given string is converted
3062 to struct in_addr structure. */
d62a17ae 3063static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 3064{
d62a17ae 3065 int ret;
3066 struct in6_addr *address;
718e3744 3067
d62a17ae 3068 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3069
d62a17ae 3070 ret = inet_pton(AF_INET6, arg, address);
718e3744 3071
d62a17ae 3072 if (ret == 0) {
3073 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3074 return NULL;
3075 }
718e3744 3076
d62a17ae 3077 return address;
718e3744 3078}
3079
3080/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3081static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 3082{
d62a17ae 3083 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3084}
3085
3086/* Route map commands for ip nexthop set. */
364deb04
DL
3087static const struct route_map_rule_cmd
3088 route_set_ipv6_nexthop_global_cmd = {
3089 "ipv6 next-hop global",
3090 route_set_ipv6_nexthop_global,
d62a17ae 3091 route_set_ipv6_nexthop_global_compile,
364deb04
DL
3092 route_set_ipv6_nexthop_global_free
3093};
6b0655a2 3094
161995ea 3095/* Set next-hop preference value. */
b68885f9 3096static enum route_map_cmd_result_t
123214ef 3097route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
1782514f 3098 void *object)
d62a17ae 3099{
9b6d8fcf 3100 struct bgp_path_info *path;
d62a17ae 3101 struct peer *peer;
3102
1782514f
DS
3103 /* Fetch routemap's rule information. */
3104 path = object;
3105 peer = path->peer;
d62a17ae 3106
1782514f
DS
3107 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3108 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
3109 /* Set next hop preference to global */
3110 path->attr->mp_nexthop_prefer_global = true;
3111 SET_FLAG(path->attr->rmap_change_flags,
3112 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3113 } else {
3114 path->attr->mp_nexthop_prefer_global = false;
3115 SET_FLAG(path->attr->rmap_change_flags,
3116 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
161995ea 3117 }
1782514f 3118
d62a17ae 3119 return RMAP_OKAY;
161995ea
DS
3120}
3121
d62a17ae 3122static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 3123{
d62a17ae 3124 int *rins = NULL;
161995ea 3125
d62a17ae 3126 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3127 *rins = 1;
161995ea 3128
d62a17ae 3129 return rins;
161995ea
DS
3130}
3131
3132/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3133static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 3134{
d62a17ae 3135 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
3136}
3137
3138/* Route map commands for ip nexthop set preferred. */
364deb04
DL
3139static const struct route_map_rule_cmd
3140 route_set_ipv6_nexthop_prefer_global_cmd = {
3141 "ipv6 next-hop prefer-global",
3142 route_set_ipv6_nexthop_prefer_global,
d62a17ae 3143 route_set_ipv6_nexthop_prefer_global_compile,
364deb04
DL
3144 route_set_ipv6_nexthop_prefer_global_free
3145};
161995ea 3146
718e3744 3147/* `set ipv6 nexthop local IP_ADDRESS' */
3148
3149/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9 3150static enum route_map_cmd_result_t
1782514f 3151route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
d62a17ae 3152{
3153 struct in6_addr *address;
9b6d8fcf 3154 struct bgp_path_info *path;
d62a17ae 3155
1782514f
DS
3156 /* Fetch routemap's rule information. */
3157 address = rule;
3158 path = object;
d62a17ae 3159
1782514f
DS
3160 /* Set next hop value. */
3161 path->attr->mp_nexthop_local = *address;
d62a17ae 3162
1782514f
DS
3163 /* Set nexthop length. */
3164 if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3165 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 3166
1782514f
DS
3167 SET_FLAG(path->attr->rmap_change_flags,
3168 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 3169
d62a17ae 3170 return RMAP_OKAY;
718e3744 3171}
3172
3173/* Route map `ip nexthop' compile function. Given string is converted
3174 to struct in_addr structure. */
d62a17ae 3175static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 3176{
d62a17ae 3177 int ret;
3178 struct in6_addr *address;
718e3744 3179
d62a17ae 3180 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3181
d62a17ae 3182 ret = inet_pton(AF_INET6, arg, address);
718e3744 3183
d62a17ae 3184 if (ret == 0) {
3185 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3186 return NULL;
3187 }
718e3744 3188
d62a17ae 3189 return address;
718e3744 3190}
3191
3192/* Free route map's compiled `ip nexthop' value. */
d62a17ae 3193static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 3194{
d62a17ae 3195 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3196}
3197
3198/* Route map commands for ip nexthop set. */
364deb04
DL
3199static const struct route_map_rule_cmd
3200 route_set_ipv6_nexthop_local_cmd = {
3201 "ipv6 next-hop local",
3202 route_set_ipv6_nexthop_local,
d62a17ae 3203 route_set_ipv6_nexthop_local_compile,
364deb04
DL
3204 route_set_ipv6_nexthop_local_free
3205};
90916ac2
DS
3206
3207/* `set ipv6 nexthop peer-address' */
3208
3209/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9 3210static enum route_map_cmd_result_t
1782514f 3211route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
d62a17ae 3212{
3213 struct in6_addr peer_address;
9b6d8fcf 3214 struct bgp_path_info *path;
d62a17ae 3215 struct peer *peer;
3216
1782514f
DS
3217 /* Fetch routemap's rule information. */
3218 path = object;
3219 peer = path->peer;
d62a17ae 3220
1782514f
DS
3221 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3222 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3223 && peer->su_remote
3224 && sockunion_family(peer->su_remote) == AF_INET6) {
3225 peer_address = peer->su_remote->sin6.sin6_addr;
3226 /* Set next hop value and length in attribute. */
3227 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3228 path->attr->mp_nexthop_local = peer_address;
3229 if (path->attr->mp_nexthop_len
3230 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3231 path->attr->mp_nexthop_len =
3232 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3233 } else {
3234 path->attr->mp_nexthop_global = peer_address;
3235 if (path->attr->mp_nexthop_len == 0)
3236 path->attr->mp_nexthop_len =
3237 BGP_ATTR_NHLEN_IPV6_GLOBAL;
d62a17ae 3238 }
1782514f
DS
3239
3240 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3241 /* The next hop value will be set as part of packet
3242 * rewrite.
3243 * Set the flags here to indicate that rewrite needs to
3244 * be done.
3245 * Also, clear the value - we clear both global and
3246 * link-local
3247 * nexthops, whether we send one or both is determined
3248 * elsewhere.
3249 */
3250 SET_FLAG(path->attr->rmap_change_flags,
3251 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3252 /* clear next hop value. */
3253 memset(&(path->attr->mp_nexthop_global), 0,
3254 sizeof(struct in6_addr));
3255 memset(&(path->attr->mp_nexthop_local), 0,
3256 sizeof(struct in6_addr));
90916ac2 3257 }
90916ac2 3258
d62a17ae 3259 return RMAP_OKAY;
90916ac2
DS
3260}
3261
3262/* Route map `ip next-hop' compile function. Given string is converted
3263 to struct in_addr structure. */
d62a17ae 3264static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 3265{
d62a17ae 3266 int *rins = NULL;
90916ac2 3267
d62a17ae 3268 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3269 *rins = 1;
90916ac2 3270
d62a17ae 3271 return rins;
90916ac2
DS
3272}
3273
3274/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3275static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 3276{
d62a17ae 3277 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
3278}
3279
3280/* Route map commands for ip nexthop set. */
364deb04
DL
3281static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3282 "ipv6 next-hop peer-address",
3283 route_set_ipv6_nexthop_peer,
3284 route_set_ipv6_nexthop_peer_compile,
3285 route_set_ipv6_nexthop_peer_free
3286};
90916ac2 3287
69ba6dd7 3288/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 3289
b68885f9 3290static enum route_map_cmd_result_t
1782514f 3291route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
718e3744 3292{
d62a17ae 3293 struct in_addr *address;
9b6d8fcf 3294 struct bgp_path_info *path;
718e3744 3295
1782514f
DS
3296 /* Fetch routemap's rule information. */
3297 address = rule;
3298 path = object;
e52702f2 3299
1782514f
DS
3300 /* Set next hop value. */
3301 path->attr->mp_nexthop_global_in = *address;
3302 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
718e3744 3303
d62a17ae 3304 return RMAP_OKAY;
718e3744 3305}
3306
d62a17ae 3307static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 3308{
d62a17ae 3309 int ret;
3310 struct in_addr *address;
718e3744 3311
d62a17ae 3312 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3313
d62a17ae 3314 ret = inet_aton(arg, address);
718e3744 3315
d62a17ae 3316 if (ret == 0) {
3317 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3318 return NULL;
3319 }
718e3744 3320
d62a17ae 3321 return address;
718e3744 3322}
3323
69ba6dd7 3324/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 3325
b68885f9 3326static enum route_map_cmd_result_t
1782514f 3327route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
d6902373 3328{
d62a17ae 3329 struct in6_addr *address;
9b6d8fcf 3330 struct bgp_path_info *path;
d6902373 3331
1782514f
DS
3332 /* Fetch routemap's rule information. */
3333 address = rule;
3334 path = object;
d6902373 3335
1782514f
DS
3336 /* Set next hop value. */
3337 memcpy(&path->attr->mp_nexthop_global, address,
3338 sizeof(struct in6_addr));
3339 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
d6902373 3340
d62a17ae 3341 return RMAP_OKAY;
d6902373
PG
3342}
3343
d62a17ae 3344static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 3345{
d62a17ae 3346 int ret;
3347 struct in6_addr *address;
d6902373 3348
d62a17ae 3349 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3350 ret = inet_pton(AF_INET6, arg, address);
d6902373 3351
d62a17ae 3352 if (ret == 0) {
3353 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3354 return NULL;
3355 }
d6902373 3356
d62a17ae 3357 return address;
d6902373
PG
3358}
3359
d62a17ae 3360static void route_set_vpn_nexthop_free(void *rule)
718e3744 3361{
d62a17ae 3362 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3363}
3364
69ba6dd7 3365/* Route map commands for ipv4 next-hop set. */
364deb04
DL
3366static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3367 "ipv4 vpn next-hop",
3368 route_set_vpnv4_nexthop,
3369 route_set_vpnv4_nexthop_compile,
3370 route_set_vpn_nexthop_free
3371};
d6902373 3372
69ba6dd7 3373/* Route map commands for ipv6 next-hop set. */
364deb04
DL
3374static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3375 "ipv6 vpn next-hop",
3376 route_set_vpnv6_nexthop,
3377 route_set_vpnv6_nexthop_compile,
3378 route_set_vpn_nexthop_free
3379};
6b0655a2 3380
718e3744 3381/* `set originator-id' */
3382
3383/* For origin set. */
b68885f9 3384static enum route_map_cmd_result_t
1782514f 3385route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
718e3744 3386{
d62a17ae 3387 struct in_addr *address;
9b6d8fcf 3388 struct bgp_path_info *path;
718e3744 3389
1782514f
DS
3390 address = rule;
3391 path = object;
e52702f2 3392
1782514f
DS
3393 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3394 path->attr->originator_id = *address;
718e3744 3395
d62a17ae 3396 return RMAP_OKAY;
718e3744 3397}
3398
3399/* Compile function for originator-id set. */
d62a17ae 3400static void *route_set_originator_id_compile(const char *arg)
718e3744 3401{
d62a17ae 3402 int ret;
3403 struct in_addr *address;
718e3744 3404
d62a17ae 3405 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3406
d62a17ae 3407 ret = inet_aton(arg, address);
718e3744 3408
d62a17ae 3409 if (ret == 0) {
3410 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3411 return NULL;
3412 }
718e3744 3413
d62a17ae 3414 return address;
718e3744 3415}
3416
3417/* Compile function for originator_id set. */
d62a17ae 3418static void route_set_originator_id_free(void *rule)
718e3744 3419{
d62a17ae 3420 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3421}
3422
515e500c 3423/* Set originator-id rule structure. */
364deb04
DL
3424static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3425 "originator-id",
3426 route_set_originator_id,
3427 route_set_originator_id_compile,
3428 route_set_originator_id_free,
718e3744 3429};
6b0655a2 3430
718e3744 3431/* Add bgp route map rule. */
d62a17ae 3432static int bgp_route_match_add(struct vty *vty, const char *command,
3433 const char *arg, route_map_event_t type)
3434{
3435 VTY_DECLVAR_CONTEXT(route_map_index, index);
9ca25fed 3436 int retval = CMD_SUCCESS;
cda7187d 3437 enum rmap_compile_rets ret;
d62a17ae 3438
e2c8d6ce 3439 ret = route_map_add_match(index, command, arg, type);
9ca25fed
DS
3440 switch (ret) {
3441 case RMAP_RULE_MISSING:
3442 vty_out(vty, "%% BGP Can't find rule.\n");
3443 retval = CMD_WARNING_CONFIG_FAILED;
3444 break;
3445 case RMAP_COMPILE_ERROR:
3446 vty_out(vty, "%% BGP Argument is malformed.\n");
3447 retval = CMD_WARNING_CONFIG_FAILED;
3448 break;
3449 case RMAP_COMPILE_SUCCESS:
cda7187d
DS
3450 /*
3451 * Intentionally doing nothing here.
3452 */
3453 break;
718e3744 3454 }
518f0eb1 3455
9ca25fed 3456 return retval;
718e3744 3457}
3458
3459/* Delete bgp route map rule. */
d62a17ae 3460static int bgp_route_match_delete(struct vty *vty, const char *command,
3461 const char *arg, route_map_event_t type)
3462{
3463 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 3464 enum rmap_compile_rets ret;
9ca25fed 3465 int retval = CMD_SUCCESS;
d62a17ae 3466 char *dep_name = NULL;
3467 const char *tmpstr;
3468 char *rmap_name = NULL;
3469
3470 if (type != RMAP_EVENT_MATCH_DELETED) {
3471 /* ignore the mundane, the types without any dependency */
3472 if (arg == NULL) {
3473 if ((tmpstr = route_map_get_match_arg(index, command))
3474 != NULL)
3475 dep_name =
3476 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
3477 } else {
3478 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
3479 }
3480 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
ffd0c037 3481 }
d62a17ae 3482
909f3d56 3483 ret = route_map_delete_match(index, command, dep_name, type);
9ca25fed
DS
3484 switch (ret) {
3485 case RMAP_RULE_MISSING:
3486 vty_out(vty, "%% BGP Can't find rule.\n");
3487 retval = CMD_WARNING_CONFIG_FAILED;
3488 break;
3489 case RMAP_COMPILE_ERROR:
3490 vty_out(vty, "%% BGP Argument is malformed.\n");
3491 retval = CMD_WARNING_CONFIG_FAILED;
3492 break;
3493 case RMAP_COMPILE_SUCCESS:
cda7187d
DS
3494 /*
3495 * Nothing to do here
3496 */
3497 break;
718e3744 3498 }
518f0eb1 3499
0a22ddfb
QY
3500 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
3501 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
518f0eb1 3502
9ca25fed 3503 return retval;
718e3744 3504}
3505
518f0eb1 3506/*
2a3d5731 3507 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
3508 * modifications.
3509 */
d62a17ae 3510static void bgp_route_map_process_peer(const char *rmap_name,
3511 struct route_map *map, struct peer *peer,
3512 int afi, int safi, int route_update)
3513{
d62a17ae 3514 struct bgp_filter *filter;
3515
3516 if (!peer || !rmap_name)
3517 return;
3518
3519 filter = &peer->filter[afi][safi];
3520 /*
3521 * in is for non-route-server clients,
3522 * out is for all peers
3523 */
db77a501
DS
3524 if (filter->map[RMAP_IN].name
3525 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3526 filter->map[RMAP_IN].map = map;
d62a17ae 3527
db77a501 3528 if (route_update && peer->status == Established) {
d62a17ae 3529 if (CHECK_FLAG(peer->af_flags[afi][safi],
3530 PEER_FLAG_SOFT_RECONFIG)) {
3531 if (bgp_debug_update(peer, NULL, NULL, 1))
3532 zlog_debug(
db77a501 3533 "Processing route_map %s update on peer %s (inbound, soft-reconfig)",
d62a17ae 3534 rmap_name, peer->host);
3535
3536 bgp_soft_reconfig_in(peer, afi, safi);
3537 } else if (CHECK_FLAG(peer->cap,
3538 PEER_CAP_REFRESH_OLD_RCV)
3539 || CHECK_FLAG(peer->cap,
3540 PEER_CAP_REFRESH_NEW_RCV)) {
3541 if (bgp_debug_update(peer, NULL, NULL, 1))
3542 zlog_debug(
db77a501 3543 "Processing route_map %s update on peer %s (inbound, route-refresh)",
d62a17ae 3544 rmap_name, peer->host);
3545 bgp_route_refresh_send(peer, afi, safi, 0, 0,
3546 0);
3547 }
d62a17ae 3548 }
518f0eb1 3549 }
d62a17ae 3550
3551 /*
3552 * For outbound, unsuppress and default-originate map change (content or
3553 * map created), merely update the "config" here, the actual route
3554 * announcement happens at the group level.
3555 */
3556 if (filter->map[RMAP_OUT].name
3557 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3558 filter->map[RMAP_OUT].map = map;
3559
3560 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3561 filter->usmap.map = map;
3562
7f7940e6
MK
3563 if (filter->advmap.aname
3564 && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
3565 filter->advmap.amap = map;
7f7940e6
MK
3566 }
3567
3568 if (filter->advmap.cname
3569 && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
3570 filter->advmap.cmap = map;
7f7940e6
MK
3571 }
3572
d62a17ae 3573 if (peer->default_rmap[afi][safi].name
3574 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
3575 peer->default_rmap[afi][safi].map = map;
c5aec50b
MK
3576
3577 /* Notify BGP conditional advertisement scanner percess */
c385f82a 3578 peer->advmap_config_change[afi][safi] = true;
d62a17ae 3579}
3580
3581static void bgp_route_map_update_peer_group(const char *rmap_name,
3582 struct route_map *map,
3583 struct bgp *bgp)
3584{
3585 struct peer_group *group;
3586 struct listnode *node, *nnode;
3587 struct bgp_filter *filter;
3588 int afi, safi;
3589 int direct;
3590
3591 if (!bgp)
3592 return;
3593
3594 /* All the peers have been updated correctly already. This is
3595 * just updating the placeholder data. No real update required.
3596 */
05c7a1cc
QY
3597 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
3598 FOREACH_AFI_SAFI (afi, safi) {
3599 filter = &group->conf->filter[afi][safi];
3600
3601 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
3602 if ((filter->map[direct].name)
3603 && (strcmp(rmap_name,
3604 filter->map[direct].name)
d62a17ae 3605 == 0))
05c7a1cc 3606 filter->map[direct].map = map;
d62a17ae 3607 }
05c7a1cc
QY
3608
3609 if (filter->usmap.name
3610 && (strcmp(rmap_name, filter->usmap.name) == 0))
3611 filter->usmap.map = map;
3612 }
3613 }
518f0eb1
DS
3614}
3615
a6e0d253
DW
3616/*
3617 * Note that if an extreme number (tens of thousands) of route-maps are in use
3618 * and if bgp has an extreme number of peers, network statements, etc then this
3619 * function can consume a lot of cycles. This is due to this function being
3620 * called for each route-map and within this function we walk the list of peers,
3621 * network statements, etc looking to see if they use this route-map.
3622 */
d62a17ae 3623static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
3624 int route_update)
3625{
3626 int i;
4056a5f6 3627 bool matched;
d62a17ae 3628 afi_t afi;
3629 safi_t safi;
3630 struct peer *peer;
9bcb3eef 3631 struct bgp_dest *bn;
d62a17ae 3632 struct bgp_static *bgp_static;
20894f50 3633 struct bgp_aggregate *aggregate;
d62a17ae 3634 struct listnode *node, *nnode;
3635 struct route_map *map;
3636 char buf[INET6_ADDRSTRLEN];
3637
3638 map = route_map_lookup_by_name(rmap_name);
3639
3640 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
3641
3642 /* Ignore dummy peer-group structure */
3643 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3644 continue;
3645
05c7a1cc
QY
3646 FOREACH_AFI_SAFI (afi, safi) {
3647 /* process in/out/import/export/default-orig
3648 * route-maps */
3649 bgp_route_map_process_peer(rmap_name, map, peer, afi,
3650 safi, route_update);
3651 }
d62a17ae 3652 }
3653
3654 /* for outbound/default-orig route-maps, process for groups */
3655 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
3656 route_update, 0);
3657
3658 /* update peer-group config (template) */
3659 bgp_route_map_update_peer_group(rmap_name, map, bgp);
3660
05c7a1cc
QY
3661 FOREACH_AFI_SAFI (afi, safi) {
3662 /* For table route-map updates. */
3663 if (!bgp_fibupd_safi(safi))
3664 continue;
d62a17ae 3665
05c7a1cc
QY
3666 if (bgp->table_map[afi][safi].name
3667 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
3668 == 0)) {
b4897fa5 3669
3670 /* bgp->table_map[afi][safi].map is NULL.
3671 * i.e Route map creation event.
3672 * So update applied_counter.
3673 * If it is not NULL, i.e It may be routemap updation or
3674 * deletion. so no need to update the counter.
3675 */
3676 if (!bgp->table_map[afi][safi].map)
3677 route_map_counter_increment(map);
05c7a1cc
QY
3678 bgp->table_map[afi][safi].map = map;
3679
3680 if (BGP_DEBUG(zebra, ZEBRA))
3681 zlog_debug(
3efd0893 3682 "Processing route_map %s update on table map",
05c7a1cc
QY
3683 rmap_name);
3684 if (route_update)
3685 bgp_zebra_announce_table(bgp, afi, safi);
3686 }
d62a17ae 3687
05c7a1cc
QY
3688 /* For network route-map updates. */
3689 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
96f10e1e 3690 bn = bgp_route_next(bn)) {
9bcb3eef 3691 bgp_static = bgp_dest_get_bgp_static_info(bn);
c9837105
DS
3692 if (!bgp_static)
3693 continue;
3694
3695 if (!bgp_static->rmap.name
3696 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
3697 continue;
3698
b4897fa5 3699 if (!bgp_static->rmap.map)
3700 route_map_counter_increment(map);
3701
c9837105
DS
3702 bgp_static->rmap.map = map;
3703
3704 if (route_update && !bgp_static->backdoor) {
b54892e0 3705 const struct prefix *bn_p =
9bcb3eef 3706 bgp_dest_get_prefix(bn);
b54892e0
DS
3707
3708 if (bgp_debug_zebra(bn_p))
c9837105
DS
3709 zlog_debug(
3710 "Processing route_map %s update on static route %s",
3711 rmap_name,
b54892e0
DS
3712 inet_ntop(bn_p->family,
3713 &bn_p->u.prefix, buf,
c9837105 3714 INET6_ADDRSTRLEN));
b54892e0 3715 bgp_static_update(bgp, bn_p, bgp_static, afi,
c9837105 3716 safi);
05c7a1cc 3717 }
96f10e1e 3718 }
20894f50
DA
3719
3720 /* For aggregate-address route-map updates. */
3721 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
3722 bn = bgp_route_next(bn)) {
9bcb3eef 3723 aggregate = bgp_dest_get_bgp_aggregate_info(bn);
20894f50
DA
3724 if (!aggregate)
3725 continue;
3726
4056a5f6 3727 matched = false;
20894f50 3728
365ab2e7
RZ
3729 /* Update suppress map pointer. */
3730 if (aggregate->suppress_map_name
3731 && strmatch(aggregate->suppress_map_name,
3732 rmap_name)) {
4056a5f6 3733 if (aggregate->rmap.map == NULL)
365ab2e7 3734 route_map_counter_increment(map);
20894f50 3735
365ab2e7 3736 aggregate->suppress_map = map;
4056a5f6
RZ
3737
3738 bgp_aggregate_toggle_suppressed(
3739 aggregate, bgp, bgp_dest_get_prefix(bn),
3740 afi, safi, false);
3741
3742 matched = true;
365ab2e7
RZ
3743 }
3744
4056a5f6
RZ
3745 if (aggregate->rmap.name
3746 && strmatch(rmap_name, aggregate->rmap.name)) {
3747 if (aggregate->rmap.map == NULL)
3748 route_map_counter_increment(map);
20894f50 3749
4056a5f6 3750 aggregate->rmap.map = map;
20894f50 3751
4056a5f6
RZ
3752 matched = true;
3753 }
20894f50 3754
4056a5f6 3755 if (matched && route_update) {
b54892e0 3756 const struct prefix *bn_p =
9bcb3eef 3757 bgp_dest_get_prefix(bn);
b54892e0
DS
3758
3759 if (bgp_debug_zebra(bn_p))
20894f50
DA
3760 zlog_debug(
3761 "Processing route_map %s update on aggregate-address route %s",
3762 rmap_name,
b54892e0
DS
3763 inet_ntop(bn_p->family,
3764 &bn_p->u.prefix, buf,
20894f50 3765 INET6_ADDRSTRLEN));
b54892e0 3766 bgp_aggregate_route(bgp, bn_p, afi, safi,
20894f50
DA
3767 aggregate);
3768 }
3769 }
05c7a1cc 3770 }
d62a17ae 3771
3772 /* For redistribute route-map updates. */
3773 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3774 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3775 struct list *red_list;
d62a17ae 3776 struct bgp_redist *red;
3777
3778 red_list = bgp->redist[afi][i];
3779 if (!red_list)
3780 continue;
3781
3782 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
c9837105
DS
3783 if (!red->rmap.name
3784 || (strcmp(rmap_name, red->rmap.name) != 0))
3785 continue;
3786
b4897fa5 3787 if (!red->rmap.map)
3788 route_map_counter_increment(map);
3789
c9837105
DS
3790 red->rmap.map = map;
3791
3792 if (!route_update)
3793 continue;
3794
3795 if (BGP_DEBUG(zebra, ZEBRA))
3796 zlog_debug(
3797 "Processing route_map %s update on redistributed routes",
3798 rmap_name);
3799
3800 bgp_redistribute_resend(bgp, afi, i,
d62a17ae 3801 red->instance);
d62a17ae 3802 }
3803 }
53c84f78
MK
3804
3805 /* for type5 command route-maps */
3806 FOREACH_AFI_SAFI (afi, safi) {
c9837105
DS
3807 if (!bgp->adv_cmd_rmap[afi][safi].name
3808 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
3809 != 0)
3810 continue;
3811
2686df6a
NS
3812 /* Make sure the route-map is populated here if not already done */
3813 bgp->adv_cmd_rmap[afi][safi].map = map;
3814
c9837105
DS
3815 if (BGP_DEBUG(zebra, ZEBRA))
3816 zlog_debug(
3817 "Processing route_map %s update on advertise type5 route command",
3818 rmap_name);
2686df6a 3819
456a4697 3820 if (route_update && advertise_type5_routes(bgp, afi)) {
2686df6a
NS
3821 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
3822 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
3823 }
53c84f78 3824 }
d62a17ae 3825}
3826
46a69f10 3827static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 3828{
3829 struct listnode *node, *nnode;
3830 struct bgp *bgp;
3831
ddb5b488 3832 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
d62a17ae 3833 bgp_route_map_process_update(bgp, rmap_name, 1);
5fe9f963 3834
49e5a4a0 3835#ifdef ENABLE_BGP_VNC
ddb5b488
PZ
3836 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3837 vnc_routemap_update(bgp, __func__);
65efcfce 3838#endif
ddb5b488
PZ
3839 }
3840
3841 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
3842}
3843
d62a17ae 3844int bgp_route_map_update_timer(struct thread *thread)
518f0eb1 3845{
d62a17ae 3846 bm->t_rmap_update = NULL;
518f0eb1 3847
d62a17ae 3848 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 3849
95f7965d 3850 return 0;
518f0eb1
DS
3851}
3852
d62a17ae 3853static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 3854{
47c8fa1f
NT
3855 struct listnode *node, *nnode;
3856 struct bgp *bgp;
3857
3858 /* If new update is received before the current timer timed out,
3859 * turn it off and start a new timer.
3860 */
28ef0ee1 3861 THREAD_OFF(bm->t_rmap_update);
47c8fa1f
NT
3862
3863 /* rmap_update_timer of 0 means don't do route updates */
3864 if (bm->rmap_update_timer) {
3865 thread_add_timer(bm->master, bgp_route_map_update_timer,
3866 NULL, bm->rmap_update_timer,
3867 &bm->t_rmap_update);
3868
3869 /* Signal the groups that a route-map update event has
3870 * started */
3871 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3872 update_group_policy_update(bgp,
3873 BGP_POLICY_ROUTE_MAP,
3874 rmap_name, 1, 1);
3875 } else {
3876 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3877 bgp_route_map_process_update(bgp, rmap_name, 0);
49e5a4a0 3878#ifdef ENABLE_BGP_VNC
47c8fa1f
NT
3879 zlog_debug("%s: calling vnc_routemap_update", __func__);
3880 vnc_routemap_update(bgp, __func__);
65efcfce 3881#endif
d62a17ae 3882 }
718e3744 3883}
6b0655a2 3884
d62a17ae 3885static void bgp_route_map_add(const char *rmap_name)
73ac8160 3886{
7096e938 3887 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3888 bgp_route_map_mark_update(rmap_name);
73ac8160 3889
d62a17ae 3890 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 3891}
518f0eb1 3892
d62a17ae 3893static void bgp_route_map_delete(const char *rmap_name)
73ac8160 3894{
7096e938 3895 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3896 bgp_route_map_mark_update(rmap_name);
73ac8160 3897
d62a17ae 3898 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 3899}
518f0eb1 3900
097b5973 3901static void bgp_route_map_event(const char *rmap_name)
73ac8160 3902{
7096e938 3903 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3904 bgp_route_map_mark_update(rmap_name);
518f0eb1 3905
d62a17ae 3906 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
3907}
3908
d37ba549
MK
3909DEFUN (match_mac_address,
3910 match_mac_address_cmd,
3911 "match mac address WORD",
3912 MATCH_STR
3913 "mac address\n"
3914 "Match address of route\n"
3915 "MAC Access-list name\n")
3916{
3917 return bgp_route_match_add(vty, "mac address", argv[3]->arg,
3918 RMAP_EVENT_FILTER_ADDED);
3919}
3920
3921DEFUN (no_match_mac_address,
3922 no_match_mac_address_cmd,
646050e5 3923 "no match mac address WORD",
d37ba549
MK
3924 NO_STR
3925 MATCH_STR
3926 "mac\n"
646050e5
MK
3927 "Match address of route\n"
3928 "MAC acess-list name\n")
d37ba549 3929{
d37ba549
MK
3930 return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
3931 RMAP_EVENT_FILTER_DELETED);
3932}
73ac8160 3933
38677473
SW
3934/*
3935 * Helper to handle the case of the user passing in a number or type string
3936 */
3937static const char *parse_evpn_rt_type(const char *num_rt_type)
3938{
3939 switch (num_rt_type[0]) {
3940 case '1':
3941 return "ead";
3942 case '2':
3943 return "macip";
3944 case '3':
3945 return "multicast";
3946 case '4':
3947 return "es";
3948 case '5':
3949 return "prefix";
3950 default:
3951 break;
3952 }
3953
3954 /* Was already full type string */
3955 return num_rt_type;
3956}
3957
33c2ff62
MK
3958DEFUN (match_evpn_route_type,
3959 match_evpn_route_type_cmd,
38677473 3960 "match evpn route-type <macip|2|multicast|3|prefix|5>",
33c2ff62
MK
3961 MATCH_STR
3962 EVPN_HELP_STR
38677473
SW
3963 EVPN_TYPE_HELP_STR
3964 EVPN_TYPE_2_HELP_STR
3965 EVPN_TYPE_2_HELP_STR
3966 EVPN_TYPE_3_HELP_STR
3967 EVPN_TYPE_3_HELP_STR
3968 EVPN_TYPE_5_HELP_STR
3969 EVPN_TYPE_5_HELP_STR)
3970{
3971 return bgp_route_match_add(vty, "evpn route-type",
3972 parse_evpn_rt_type(argv[3]->arg),
33c2ff62
MK
3973 RMAP_EVENT_MATCH_ADDED);
3974}
3975
3976DEFUN (no_match_evpn_route_type,
3977 no_match_evpn_route_type_cmd,
38677473 3978 "no match evpn route-type <macip|2|multicast|3|prefix|5>",
33c2ff62
MK
3979 NO_STR
3980 MATCH_STR
3981 EVPN_HELP_STR
38677473
SW
3982 EVPN_TYPE_HELP_STR
3983 EVPN_TYPE_2_HELP_STR
3984 EVPN_TYPE_2_HELP_STR
3985 EVPN_TYPE_3_HELP_STR
3986 EVPN_TYPE_3_HELP_STR
3987 EVPN_TYPE_5_HELP_STR
3988 EVPN_TYPE_5_HELP_STR)
3989{
3990 return bgp_route_match_delete(vty, "evpn route-type",
3991 parse_evpn_rt_type(argv[4]->arg),
33c2ff62
MK
3992 RMAP_EVENT_MATCH_DELETED);
3993}
3994
3995
16f7ce2b
MK
3996DEFUN (match_evpn_vni,
3997 match_evpn_vni_cmd,
093e3f23 3998 "match evpn vni " CMD_VNI_RANGE,
16f7ce2b 3999 MATCH_STR
62982d5a 4000 EVPN_HELP_STR
16f7ce2b
MK
4001 "Match VNI\n"
4002 "VNI ID\n")
4003{
646050e5 4004 return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
16f7ce2b
MK
4005 RMAP_EVENT_MATCH_ADDED);
4006}
4007
4008DEFUN (no_match_evpn_vni,
4009 no_match_evpn_vni_cmd,
093e3f23 4010 "no match evpn vni " CMD_VNI_RANGE,
16f7ce2b
MK
4011 NO_STR
4012 MATCH_STR
62982d5a 4013 EVPN_HELP_STR
16f7ce2b
MK
4014 "Match VNI\n"
4015 "VNI ID\n")
4016{
646050e5 4017 return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
16f7ce2b
MK
4018 RMAP_EVENT_MATCH_DELETED);
4019}
4020
6fb219da
MK
4021DEFUN (match_evpn_default_route,
4022 match_evpn_default_route_cmd,
4023 "match evpn default-route",
4024 MATCH_STR
4025 EVPN_HELP_STR
4026 "default EVPN type-5 route\n")
4027{
4028 return bgp_route_match_add(vty, "evpn default-route", NULL,
4029 RMAP_EVENT_MATCH_ADDED);
4030}
4031
4032DEFUN (no_match_evpn_default_route,
4033 no_match_evpn_default_route_cmd,
4034 "no match evpn default-route",
4035 NO_STR
4036 MATCH_STR
4037 EVPN_HELP_STR
4038 "default EVPN type-5 route\n")
4039{
4040 return bgp_route_match_delete(vty, "evpn default-route", NULL,
4041 RMAP_EVENT_MATCH_DELETED);
4042}
4043
196c6b09
LK
4044DEFUN (match_evpn_rd,
4045 match_evpn_rd_cmd,
4046 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4047 MATCH_STR
4048 EVPN_HELP_STR
4049 "Route Distinguisher\n"
4050 "ASN:XX or A.B.C.D:XX\n")
4051{
4052 return bgp_route_match_add(vty, "evpn rd", argv[3]->arg,
4053 RMAP_EVENT_MATCH_ADDED);
4054}
4055
4056DEFUN (no_match_evpn_rd,
4057 no_match_evpn_rd_cmd,
4058 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4059 NO_STR
4060 MATCH_STR
4061 EVPN_HELP_STR
4062 "Route Distinguisher\n"
4063 "ASN:XX or A.B.C.D:XX\n")
4064{
4065 return bgp_route_match_delete(vty, "evpn rd", argv[4]->arg,
4066 RMAP_EVENT_MATCH_DELETED);
4067}
4068
1dcc9e5b
CS
4069DEFPY(match_vrl_source_vrf,
4070 match_vrl_source_vrf_cmd,
4071 "match source-vrf NAME$vrf_name",
4072 MATCH_STR
4073 "source vrf\n"
4074 "The VRF name\n")
4075{
4076 return bgp_route_match_add(vty, "source-vrf", vrf_name,
4077 RMAP_EVENT_MATCH_ADDED);
4078}
4079
4080DEFPY(no_match_vrl_source_vrf,
4081 no_match_vrl_source_vrf_cmd,
4082 "no match source-vrf NAME$vrf_name",
4083 NO_STR
4084 MATCH_STR
4085 "source vrf\n"
4086 "The VRF name\n")
4087{
4088 return bgp_route_match_delete(vty, "source-vrf", vrf_name,
4089 RMAP_EVENT_MATCH_DELETED);
4090}
4091
fee0f4c6 4092DEFUN (match_peer,
4093 match_peer_cmd,
8c3433e4 4094 "match peer <A.B.C.D|X:X::X:X|WORD>",
fee0f4c6 4095 MATCH_STR
4096 "Match peer address\n"
6e13ed4a 4097 "IP address of peer\n"
8c3433e4
DS
4098 "IPv6 address of peer\n"
4099 "Interface name of peer\n")
fee0f4c6 4100{
d62a17ae 4101 int idx_ip = 2;
4102 return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
4103 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 4104}
4105
4106DEFUN (match_peer_local,
f412b39a 4107 match_peer_local_cmd,
fee0f4c6 4108 "match peer local",
4109 MATCH_STR
4110 "Match peer address\n"
4111 "Static or Redistributed routes\n")
4112{
d62a17ae 4113 return bgp_route_match_add(vty, "peer", "local",
4114 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 4115}
4116
4117DEFUN (no_match_peer,
4118 no_match_peer_cmd,
8c3433e4 4119 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
fee0f4c6 4120 NO_STR
4121 MATCH_STR
4c9bd275
DW
4122 "Match peer address\n"
4123 "Static or Redistributed routes\n"
4124 "IP address of peer\n"
8c3433e4
DS
4125 "IPv6 address of peer\n"
4126 "Interface name of peer\n")
fee0f4c6 4127{
d62a17ae 4128 int idx_peer = 3;
4c9bd275 4129
d62a17ae 4130 if (argc <= idx_peer)
4131 return bgp_route_match_delete(vty, "peer", NULL,
4132 RMAP_EVENT_MATCH_DELETED);
4133 return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
4134 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 4135}
4136
1d7c7ace 4137#if defined(HAVE_LUA)
b4becb06
QY
4138DEFUN (match_script,
4139 match_script_cmd,
4140 "[no] match script WORD",
1d7c7ace
DS
4141 NO_STR
4142 MATCH_STR
b4becb06
QY
4143 "Execute script to determine match\n"
4144 "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
1d7c7ace 4145{
b4becb06
QY
4146 bool no = strmatch(argv[0]->text, "no");
4147 int i = 0;
4148 argv_find(argv, argc, "WORD", &i);
4149 const char *script = argv[i]->arg;
4150
4151 if (no) {
4152 return bgp_route_match_delete(vty, "script", script,
4153 RMAP_EVENT_FILTER_DELETED);
4154 } else {
4155 return bgp_route_match_add(vty, "script", script,
4156 RMAP_EVENT_FILTER_ADDED);
4157 }
1d7c7ace
DS
4158}
4159#endif
fee0f4c6 4160
4c9bd275 4161/* match probability */
1add115a
VT
4162DEFUN (match_probability,
4163 match_probability_cmd,
6147e2c6 4164 "match probability (0-100)",
1add115a
VT
4165 MATCH_STR
4166 "Match portion of routes defined by percentage value\n"
4167 "Percentage of routes\n")
4168{
d62a17ae 4169 int idx_number = 2;
4170 return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
4171 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
4172}
4173
4c9bd275 4174
1add115a
VT
4175DEFUN (no_match_probability,
4176 no_match_probability_cmd,
4c9bd275 4177 "no match probability [(1-99)]",
1add115a
VT
4178 NO_STR
4179 MATCH_STR
4c9bd275
DW
4180 "Match portion of routes defined by percentage value\n"
4181 "Percentage of routes\n")
1add115a 4182{
d62a17ae 4183 int idx_number = 3;
4184 if (argc <= idx_number)
4185 return bgp_route_match_delete(vty, "probability", NULL,
4186 RMAP_EVENT_MATCH_DELETED);
4187 return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
4188 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
4189}
4190
1add115a 4191
f412b39a 4192DEFUN (match_ip_route_source,
c1643bb7 4193 match_ip_route_source_cmd,
6147e2c6 4194 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 4195 MATCH_STR
4196 IP_STR
4197 "Match advertising source address of route\n"
4198 "IP access-list number\n"
4199 "IP access-list number (expanded range)\n"
4200 "IP standard access-list name\n")
4201{
d62a17ae 4202 int idx_acl = 3;
4203 return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
4204 RMAP_EVENT_FILTER_ADDED);
c1643bb7 4205}
4206
4c9bd275 4207
c1643bb7 4208DEFUN (no_match_ip_route_source,
4209 no_match_ip_route_source_cmd,
6de69f83 4210 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 4211 NO_STR
4212 MATCH_STR
4213 IP_STR
4c9bd275
DW
4214 "Match advertising source address of route\n"
4215 "IP access-list number\n"
4216 "IP access-list number (expanded range)\n"
4217 "IP standard access-list name\n")
c1643bb7 4218{
d62a17ae 4219 int idx_number = 4;
4220 if (argc <= idx_number)
4221 return bgp_route_match_delete(vty, "ip route-source", NULL,
4222 RMAP_EVENT_FILTER_DELETED);
4223 return bgp_route_match_delete(vty, "ip route-source",
4224 argv[idx_number]->arg,
4225 RMAP_EVENT_FILTER_DELETED);
c1643bb7 4226}
4227
c1643bb7 4228
f412b39a 4229DEFUN (match_ip_route_source_prefix_list,
c1643bb7 4230 match_ip_route_source_prefix_list_cmd,
4231 "match ip route-source prefix-list WORD",
4232 MATCH_STR
4233 IP_STR
4234 "Match advertising source address of route\n"
4235 "Match entries of prefix-lists\n"
4236 "IP prefix-list name\n")
4237{
d62a17ae 4238 int idx_word = 4;
4239 return bgp_route_match_add(vty, "ip route-source prefix-list",
4240 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 4241}
4242
4c9bd275 4243
c1643bb7 4244DEFUN (no_match_ip_route_source_prefix_list,
4245 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 4246 "no match ip route-source prefix-list [WORD]",
c1643bb7 4247 NO_STR
4248 MATCH_STR
4249 IP_STR
4250 "Match advertising source address of route\n"
4c9bd275
DW
4251 "Match entries of prefix-lists\n"
4252 "IP prefix-list name\n")
c1643bb7 4253{
d62a17ae 4254 int idx_word = 5;
4255 if (argc <= idx_word)
4256 return bgp_route_match_delete(vty,
4257 "ip route-source prefix-list",
4258 NULL, RMAP_EVENT_PLIST_DELETED);
4259 return bgp_route_match_delete(vty, "ip route-source prefix-list",
4260 argv[idx_word]->arg,
4261 RMAP_EVENT_PLIST_DELETED);
c1643bb7 4262}
4263
c1643bb7 4264
af291c15
DS
4265DEFUN (match_local_pref,
4266 match_local_pref_cmd,
6147e2c6 4267 "match local-preference (0-4294967295)",
af291c15
DS
4268 MATCH_STR
4269 "Match local-preference of route\n"
4270 "Metric value\n")
4271{
d62a17ae 4272 int idx_number = 2;
4273 return bgp_route_match_add(vty, "local-preference",
4274 argv[idx_number]->arg,
4275 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
4276}
4277
4c9bd275 4278
af291c15
DS
4279DEFUN (no_match_local_pref,
4280 no_match_local_pref_cmd,
4c9bd275 4281 "no match local-preference [(0-4294967295)]",
af291c15
DS
4282 NO_STR
4283 MATCH_STR
4c9bd275
DW
4284 "Match local preference of route\n"
4285 "Local preference value\n")
af291c15 4286{
d62a17ae 4287 int idx_localpref = 3;
4288 if (argc <= idx_localpref)
4289 return bgp_route_match_delete(vty, "local-preference", NULL,
4290 RMAP_EVENT_MATCH_DELETED);
4291 return bgp_route_match_delete(vty, "local-preference",
4292 argv[idx_localpref]->arg,
4293 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
4294}
4295
af291c15 4296
f412b39a 4297DEFUN (match_community,
718e3744 4298 match_community_cmd,
0d702986 4299 "match community <(1-99)|(100-500)|WORD> [exact-match]",
718e3744 4300 MATCH_STR
4301 "Match BGP community list\n"
4302 "Community-list number (standard)\n"
4303 "Community-list number (expanded)\n"
4304 "Community-list name\n"
4305 "Do exact matching of communities\n")
4306{
d62a17ae 4307 int idx_comm_list = 2;
4308 int ret;
4309 char *argstr;
718e3744 4310
d62a17ae 4311 if (argc == 4) {
4312 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4313 strlen(argv[idx_comm_list]->arg)
4314 + strlen("exact-match") + 2);
718e3744 4315
d62a17ae 4316 sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
4317 } else
4318 argstr = argv[idx_comm_list]->arg;
718e3744 4319
d62a17ae 4320 ret = bgp_route_match_add(vty, "community", argstr,
4321 RMAP_EVENT_CLIST_ADDED);
718e3744 4322
d62a17ae 4323 if (argstr != argv[idx_comm_list]->arg)
4324 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4325
d62a17ae 4326 return ret;
718e3744 4327}
4328
4329DEFUN (no_match_community,
4330 no_match_community_cmd,
4c9bd275 4331 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 4332 NO_STR
4333 MATCH_STR
4c9bd275
DW
4334 "Match BGP community list\n"
4335 "Community-list number (standard)\n"
4336 "Community-list number (expanded)\n"
4337 "Community-list name\n"
4338 "Do exact matching of communities\n")
718e3744 4339{
d62a17ae 4340 return bgp_route_match_delete(vty, "community", NULL,
4341 RMAP_EVENT_CLIST_DELETED);
718e3744 4342}
4343
57d187bc
JS
4344DEFUN (match_lcommunity,
4345 match_lcommunity_cmd,
03ff9a14 4346 "match large-community <(1-99)|(100-500)|WORD> [exact-match]",
57d187bc
JS
4347 MATCH_STR
4348 "Match BGP large community list\n"
4349 "Large Community-list number (standard)\n"
4350 "Large Community-list number (expanded)\n"
03ff9a14 4351 "Large Community-list name\n"
4352 "Do exact matching of communities\n")
57d187bc 4353{
03ff9a14 4354 int idx_lcomm_list = 2;
4355 int ret;
4356 char *argstr;
4357
4358 if (argc == 4) {
4359 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4360 strlen(argv[idx_lcomm_list]->arg)
4361 + strlen("exact-match") + 2);
4362
4363 sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
4364 } else
4365 argstr = argv[idx_lcomm_list]->arg;
4366
4367 ret = bgp_route_match_add(vty, "large-community", argstr,
d62a17ae 4368 RMAP_EVENT_LLIST_ADDED);
03ff9a14 4369 if (argstr != argv[idx_lcomm_list]->arg)
4370 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
4371
4372 return ret;
57d187bc 4373}
718e3744 4374
57d187bc
JS
4375DEFUN (no_match_lcommunity,
4376 no_match_lcommunity_cmd,
03ff9a14 4377 "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]",
57d187bc
JS
4378 NO_STR
4379 MATCH_STR
4380 "Match BGP large community list\n"
4381 "Large Community-list number (standard)\n"
4382 "Large Community-list number (expanded)\n"
03ff9a14 4383 "Large Community-list name\n"
4384 "Do exact matching of communities\n")
57d187bc 4385{
d62a17ae 4386 return bgp_route_match_delete(vty, "large-community", NULL,
4387 RMAP_EVENT_LLIST_DELETED);
57d187bc 4388}
718e3744 4389
f412b39a 4390DEFUN (match_ecommunity,
73ffb25b 4391 match_ecommunity_cmd,
6147e2c6 4392 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 4393 MATCH_STR
4394 "Match BGP/VPN extended community list\n"
4395 "Extended community-list number (standard)\n"
4396 "Extended community-list number (expanded)\n"
4397 "Extended community-list name\n")
4398{
d62a17ae 4399 int idx_comm_list = 2;
4400 return bgp_route_match_add(vty, "extcommunity",
4401 argv[idx_comm_list]->arg,
4402 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 4403}
4404
4c9bd275 4405
73ffb25b 4406DEFUN (no_match_ecommunity,
4407 no_match_ecommunity_cmd,
4c9bd275 4408 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 4409 NO_STR
4410 MATCH_STR
4c9bd275
DW
4411 "Match BGP/VPN extended community list\n"
4412 "Extended community-list number (standard)\n"
4413 "Extended community-list number (expanded)\n"
4414 "Extended community-list name\n")
73ffb25b 4415{
d62a17ae 4416 return bgp_route_match_delete(vty, "extcommunity", NULL,
4417 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 4418}
4419
73ffb25b 4420
718e3744 4421DEFUN (match_aspath,
4422 match_aspath_cmd,
4423 "match as-path WORD",
4424 MATCH_STR
4425 "Match BGP AS path list\n"
4426 "AS path access-list name\n")
4427{
d62a17ae 4428 int idx_word = 2;
4429 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
4430 RMAP_EVENT_ASLIST_ADDED);
718e3744 4431}
4432
4c9bd275 4433
718e3744 4434DEFUN (no_match_aspath,
4435 no_match_aspath_cmd,
4c9bd275 4436 "no match as-path [WORD]",
718e3744 4437 NO_STR
4438 MATCH_STR
4c9bd275
DW
4439 "Match BGP AS path list\n"
4440 "AS path access-list name\n")
718e3744 4441{
d62a17ae 4442 return bgp_route_match_delete(vty, "as-path", NULL,
4443 RMAP_EVENT_ASLIST_DELETED);
718e3744 4444}
4445
718e3744 4446
4447DEFUN (match_origin,
4448 match_origin_cmd,
6147e2c6 4449 "match origin <egp|igp|incomplete>",
718e3744 4450 MATCH_STR
4451 "BGP origin code\n"
4452 "remote EGP\n"
4453 "local IGP\n"
4454 "unknown heritage\n")
4455{
d62a17ae 4456 int idx_origin = 2;
4457 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4458 return bgp_route_match_add(vty, "origin", "igp",
4459 RMAP_EVENT_MATCH_ADDED);
4460 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4461 return bgp_route_match_add(vty, "origin", "egp",
4462 RMAP_EVENT_MATCH_ADDED);
4463 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4464 return bgp_route_match_add(vty, "origin", "incomplete",
4465 RMAP_EVENT_MATCH_ADDED);
718e3744 4466
d62a17ae 4467 vty_out(vty, "%% Invalid match origin type\n");
4468 return CMD_WARNING_CONFIG_FAILED;
718e3744 4469}
4470
4c9bd275 4471
718e3744 4472DEFUN (no_match_origin,
4473 no_match_origin_cmd,
4c9bd275 4474 "no match origin [<egp|igp|incomplete>]",
718e3744 4475 NO_STR
4476 MATCH_STR
4c9bd275
DW
4477 "BGP origin code\n"
4478 "remote EGP\n"
4479 "local IGP\n"
4480 "unknown heritage\n")
718e3744 4481{
d62a17ae 4482 return bgp_route_match_delete(vty, "origin", NULL,
4483 RMAP_EVENT_MATCH_DELETED);
718e3744 4484}
4485
951745bd
PG
4486DEFUN (set_table_id,
4487 set_table_id_cmd,
4488 "set table (1-4294967295)",
4489 SET_STR
4490 "export route to non-main kernel table\n"
4491 "Kernel routing table id\n")
4492{
4493 int idx_id = 2;
4494
4495 VTY_DECLVAR_CONTEXT(route_map_index, index);
4496
4497 return generic_set_add(vty, index, "table", argv[idx_id]->arg);
4498}
4499
4500DEFUN (no_set_table_id,
4501 no_set_table_id_cmd,
4502 "no set table",
4503 NO_STR
4504 SET_STR
4505 "export route to non-main kernel table\n")
4506{
4507 VTY_DECLVAR_CONTEXT(route_map_index, index);
4508
4509 return generic_set_delete(vty, index, "table", NULL);
4510}
4511
af5cd0a5 4512DEFUN (set_ip_nexthop_peer,
4513 set_ip_nexthop_peer_cmd,
89602edb
QY
4514 "[no] set ip next-hop peer-address",
4515 NO_STR
af5cd0a5 4516 SET_STR
4517 IP_STR
4518 "Next hop address\n"
4519 "Use peer address (for BGP only)\n")
4520{
89602edb 4521 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
4522 const char *) = strmatch(argv[0]->text, "no")
4523 ? generic_set_delete
4524 : generic_set_add;
89602edb
QY
4525
4526 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
4527 "peer-address");
af5cd0a5 4528}
4529
316e074d
DS
4530DEFUN (set_ip_nexthop_unchanged,
4531 set_ip_nexthop_unchanged_cmd,
cca30ba8
QY
4532 "[no] set ip next-hop unchanged",
4533 NO_STR
316e074d
DS
4534 SET_STR
4535 IP_STR
4536 "Next hop address\n"
4537 "Don't modify existing Next hop address\n")
4538{
cca30ba8 4539 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
4540 const char *) = strmatch(argv[0]->text, "no")
4541 ? generic_set_delete
4542 : generic_set_add;
cca30ba8
QY
4543
4544 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
4545 "unchanged");
718e3744 4546}
4547
7b7d48e5
DS
4548DEFUN (set_distance,
4549 set_distance_cmd,
4550 "set distance (0-255)",
4551 SET_STR
4552 "BGP Administrative Distance to use\n"
4553 "Distance value\n")
4554{
4555 int idx_number = 2;
4556
4557 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4558 "distance", argv[idx_number]->arg);
4559}
4560
4561DEFUN (no_set_distance,
4562 no_set_distance_cmd,
4563 "no set distance [(0-255)]",
4564 NO_STR SET_STR
4565 "BGP Administrative Distance to use\n"
4566 "Distance value\n")
4567{
4568 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4569 "distance", NULL);
4570}
718e3744 4571
4572DEFUN (set_local_pref,
4573 set_local_pref_cmd,
3684eb43 4574 "set local-preference WORD",
718e3744 4575 SET_STR
4576 "BGP local preference path attribute\n"
3684eb43 4577 "Preference value (0-4294967295)\n")
718e3744 4578{
d62a17ae 4579 int idx_number = 2;
4580 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4581 "local-preference", argv[idx_number]->arg);
718e3744 4582}
4583
4c9bd275 4584
718e3744 4585DEFUN (no_set_local_pref,
4586 no_set_local_pref_cmd,
3684eb43 4587 "no set local-preference [WORD]",
718e3744 4588 NO_STR
4589 SET_STR
4c9bd275 4590 "BGP local preference path attribute\n"
3684eb43 4591 "Preference value (0-4294967295)\n")
718e3744 4592{
d62a17ae 4593 int idx_localpref = 3;
4594 if (argc <= idx_localpref)
4595 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4596 "local-preference", NULL);
4597 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4598 "local-preference", argv[idx_localpref]->arg);
718e3744 4599}
4600
718e3744 4601
4602DEFUN (set_weight,
4603 set_weight_cmd,
6147e2c6 4604 "set weight (0-4294967295)",
718e3744 4605 SET_STR
4606 "BGP weight for routing table\n"
4607 "Weight value\n")
4608{
d62a17ae 4609 int idx_number = 2;
4610 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
4611 argv[idx_number]->arg);
718e3744 4612}
4613
4c9bd275 4614
718e3744 4615DEFUN (no_set_weight,
4616 no_set_weight_cmd,
4c9bd275 4617 "no set weight [(0-4294967295)]",
718e3744 4618 NO_STR
4619 SET_STR
4c9bd275
DW
4620 "BGP weight for routing table\n"
4621 "Weight value\n")
718e3744 4622{
d62a17ae 4623 int idx_weight = 3;
4624 if (argc <= idx_weight)
4625 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4626 "weight", NULL);
4627 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4628 "weight", argv[idx_weight]->arg);
718e3744 4629}
4630
d990e384
DS
4631DEFUN (set_label_index,
4632 set_label_index_cmd,
8b81993e 4633 "set label-index (0-1048560)",
d990e384
DS
4634 SET_STR
4635 "Label index to associate with the prefix\n"
4636 "Label index value\n")
4637{
d62a17ae 4638 int idx_number = 2;
4639 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4640 "label-index", argv[idx_number]->arg);
d990e384
DS
4641}
4642
4643DEFUN (no_set_label_index,
4644 no_set_label_index_cmd,
8b81993e 4645 "no set label-index [(0-1048560)]",
d990e384
DS
4646 NO_STR
4647 SET_STR
4648 "Label index to associate with the prefix\n"
4649 "Label index value\n")
4650{
d62a17ae 4651 int idx_label_index = 3;
4652 if (argc <= idx_label_index)
4653 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4654 "label-index", NULL);
4655 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4656 "label-index", argv[idx_label_index]->arg);
d990e384 4657}
718e3744 4658
12dcf78e
QY
4659DEFUN (set_aspath_prepend_asn,
4660 set_aspath_prepend_asn_cmd,
4661 "set as-path prepend (1-4294967295)...",
718e3744 4662 SET_STR
841f7a57 4663 "Transform BGP AS_PATH attribute\n"
718e3744 4664 "Prepend to the as-path\n"
12dcf78e 4665 "AS number\n")
718e3744 4666{
d62a17ae 4667 int idx_asn = 3;
4668 int ret;
4669 char *str;
718e3744 4670
d62a17ae 4671 str = argv_concat(argv, argc, idx_asn);
4672 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4673 "as-path prepend", str);
4674 XFREE(MTYPE_TMP, str);
718e3744 4675
d62a17ae 4676 return ret;
718e3744 4677}
4678
12dcf78e
QY
4679DEFUN (set_aspath_prepend_lastas,
4680 set_aspath_prepend_lastas_cmd,
b6ab2929 4681 "set as-path prepend last-as (1-10)",
12dcf78e
QY
4682 SET_STR
4683 "Transform BGP AS_PATH attribute\n"
4684 "Prepend to the as-path\n"
4685 "Use the peer's AS-number\n"
b6ab2929 4686 "Number of times to insert\n")
12dcf78e 4687{
d62a17ae 4688 return set_aspath_prepend_asn(self, vty, argc, argv);
12dcf78e 4689}
bc3dd427 4690
718e3744 4691DEFUN (no_set_aspath_prepend,
4692 no_set_aspath_prepend_cmd,
a4b2b610 4693 "no set as-path prepend [(1-4294967295)]",
718e3744 4694 NO_STR
4695 SET_STR
841f7a57 4696 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
4697 "Prepend to the as-path\n"
4698 "AS number\n")
718e3744 4699{
d62a17ae 4700 int idx_asn = 4;
4701 int ret;
4702 char *str;
a7f93f3e 4703
d62a17ae 4704 str = argv_concat(argv, argc, idx_asn);
4705 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4706 "as-path prepend", str);
4707 XFREE(MTYPE_TMP, str);
4708 return ret;
718e3744 4709}
4710
9131e6e8
DS
4711DEFUN (no_set_aspath_prepend_lastas,
4712 no_set_aspath_prepend_lastas_cmd,
4713 "no set as-path prepend last-as [(1-10)]",
4714 NO_STR
4715 SET_STR
4716 "Transform BGP AS_PATH attribute\n"
4717 "Prepend to the as-path\n"
4718 "Use the peers AS-number\n"
4719 "Number of times to insert\n")
4720{
4721 return no_set_aspath_prepend(self, vty, argc, argv);
4722}
718e3744 4723
841f7a57
DO
4724DEFUN (set_aspath_exclude,
4725 set_aspath_exclude_cmd,
a4b2b610 4726 "set as-path exclude (1-4294967295)...",
841f7a57
DO
4727 SET_STR
4728 "Transform BGP AS-path attribute\n"
4729 "Exclude from the as-path\n"
4730 "AS number\n")
4731{
d62a17ae 4732 int idx_asn = 3;
4733 int ret;
4734 char *str;
841f7a57 4735
d62a17ae 4736 str = argv_concat(argv, argc, idx_asn);
4737 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4738 "as-path exclude", str);
4739 XFREE(MTYPE_TMP, str);
4740 return ret;
841f7a57
DO
4741}
4742
4743DEFUN (no_set_aspath_exclude,
4744 no_set_aspath_exclude_cmd,
a4b2b610 4745 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
4746 NO_STR
4747 SET_STR
4748 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
4749 "Exclude from the as-path\n"
4750 "AS number\n")
841f7a57 4751{
d62a17ae 4752 int idx_asn = 4;
4753 int ret;
4754 char *str;
841f7a57 4755
d62a17ae 4756 str = argv_concat(argv, argc, idx_asn);
4757 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4758 "as-path exclude", str);
4759 XFREE(MTYPE_TMP, str);
4760 return ret;
841f7a57
DO
4761}
4762
499ceb3d
DA
4763ALIAS(no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
4764 "no set as-path exclude",
4765 NO_STR SET_STR
4766 "Transform BGP AS_PATH attribute\n"
4767 "Exclude from the as-path\n")
841f7a57 4768
718e3744 4769DEFUN (set_community,
4770 set_community_cmd,
e961923c 4771 "set community AA:NN...",
718e3744 4772 SET_STR
4773 "BGP community attribute\n"
859d388e 4774 COMMUNITY_VAL_STR)
718e3744 4775{
d62a17ae 4776 int idx_aa_nn = 2;
4777 int i;
4778 int first = 0;
4779 int additive = 0;
4780 struct buffer *b;
4781 struct community *com = NULL;
4782 char *str;
4783 char *argstr;
4784 int ret;
4785
4786 b = buffer_new(1024);
4787
4788 for (i = idx_aa_nn; i < argc; i++) {
4789 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
4790 == 0) {
4791 additive = 1;
4792 continue;
4793 }
4794
4795 if (first)
4796 buffer_putc(b, ' ');
4797 else
4798 first = 1;
4799
4800 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
4801 == 0) {
4802 buffer_putstr(b, "internet");
4803 continue;
4804 }
4805 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
4806 == 0) {
4807 buffer_putstr(b, "local-AS");
4808 continue;
4809 }
4810 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
4811 && strncmp(argv[i]->arg, "no-advertise",
4812 strlen(argv[i]->arg))
4813 == 0) {
4814 buffer_putstr(b, "no-advertise");
4815 continue;
4816 }
4817 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
4818 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
4819 == 0) {
4820 buffer_putstr(b, "no-export");
4821 continue;
4822 }
a4d82a8a
PZ
4823 if (strncmp(argv[i]->arg, "graceful-shutdown",
4824 strlen(argv[i]->arg))
7f323236
DW
4825 == 0) {
4826 buffer_putstr(b, "graceful-shutdown");
4827 continue;
4828 }
d62a17ae 4829 buffer_putstr(b, argv[i]->arg);
4830 }
4831 buffer_putc(b, '\0');
4832
4833 /* Fetch result string then compile it to communities attribute. */
4834 str = buffer_getstr(b);
4835 buffer_free(b);
4836
4837 if (str) {
4838 com = community_str2com(str);
4839 XFREE(MTYPE_TMP, str);
4840 }
4841
4842 /* Can't compile user input into communities attribute. */
4843 if (!com) {
4844 vty_out(vty, "%% Malformed communities attribute\n");
4845 return CMD_WARNING_CONFIG_FAILED;
4846 }
4847
4848 /* Set communites attribute string. */
a69ea8ae 4849 str = community_str(com, false);
d62a17ae 4850
4851 if (additive) {
552d6491
QY
4852 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
4853 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
4854 strlcpy(argstr, str, argstr_sz);
4855 strlcat(argstr, " additive", argstr_sz);
d62a17ae 4856 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4857 "community", argstr);
4858 XFREE(MTYPE_TMP, argstr);
4859 } else
4860 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4861 "community", str);
4862
3c1f53de 4863 community_free(&com);
d62a17ae 4864
4865 return ret;
718e3744 4866}
4867
4868DEFUN (set_community_none,
4869 set_community_none_cmd,
4870 "set community none",
4871 SET_STR
4872 "BGP community attribute\n"
4873 "No community attribute\n")
4874{
d62a17ae 4875 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4876 "community", "none");
718e3744 4877}
4878
4879DEFUN (no_set_community,
4880 no_set_community_cmd,
a4b2b610 4881 "no set community AA:NN...",
718e3744 4882 NO_STR
4883 SET_STR
d7fa34c1
QY
4884 "BGP community attribute\n"
4885 COMMUNITY_VAL_STR)
718e3744 4886{
d62a17ae 4887 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4888 "community", NULL);
718e3744 4889}
4890
2929de9e
DS
4891ALIAS (no_set_community,
4892 no_set_community_short_cmd,
4893 "no set community",
4894 NO_STR
4895 SET_STR
4896 "BGP community attribute\n")
4897
718e3744 4898
718e3744 4899DEFUN (set_community_delete,
4900 set_community_delete_cmd,
6147e2c6 4901 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 4902 SET_STR
4903 "set BGP community list (for deletion)\n"
4904 "Community-list number (standard)\n"
5e3edbf5 4905 "Community-list number (expanded)\n"
718e3744 4906 "Community-list name\n"
4907 "Delete matching communities\n")
4908{
d62a17ae 4909 int idx_comm_list = 2;
4cae2269 4910 char *args;
718e3744 4911
4cae2269 4912 args = argv_concat(argv, argc, idx_comm_list);
d62a17ae 4913 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
4cae2269
DA
4914 args);
4915 XFREE(MTYPE_TMP, args);
718e3744 4916
d62a17ae 4917 return CMD_SUCCESS;
718e3744 4918}
4919
4920DEFUN (no_set_community_delete,
4921 no_set_community_delete_cmd,
a4b2b610 4922 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 4923 NO_STR
4924 SET_STR
d7fa34c1
QY
4925 "set BGP community list (for deletion)\n"
4926 "Community-list number (standard)\n"
4927 "Community-list number (expanded)\n"
4928 "Community-list name\n"
4929 "Delete matching communities\n")
718e3744 4930{
d62a17ae 4931 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4932 "comm-list", NULL);
718e3744 4933}
4934
57d187bc
JS
4935DEFUN (set_lcommunity,
4936 set_lcommunity_cmd,
4937 "set large-community AA:BB:CC...",
4938 SET_STR
4939 "BGP large community attribute\n"
4940 "Large Community number in aa:bb:cc format or additive\n")
4941{
d62a17ae 4942 int ret;
4943 char *str;
57d187bc 4944
d62a17ae 4945 str = argv_concat(argv, argc, 2);
4946 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4947 "large-community", str);
4948 XFREE(MTYPE_TMP, str);
57d187bc 4949
d62a17ae 4950 return ret;
57d187bc
JS
4951}
4952
4953DEFUN (set_lcommunity_none,
4954 set_lcommunity_none_cmd,
4955 "set large-community none",
4956 SET_STR
4957 "BGP large community attribute\n"
4958 "No large community attribute\n")
4959{
d62a17ae 4960 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4961 "large-community", "none");
57d187bc
JS
4962}
4963
4964DEFUN (no_set_lcommunity,
4965 no_set_lcommunity_cmd,
52951b63 4966 "no set large-community none",
57d187bc
JS
4967 NO_STR
4968 SET_STR
4969 "BGP large community attribute\n"
52951b63 4970 "No community attribute\n")
57d187bc 4971{
d62a17ae 4972 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4973 "large-community", NULL);
57d187bc
JS
4974}
4975
52951b63
DS
4976DEFUN (no_set_lcommunity1,
4977 no_set_lcommunity1_cmd,
4978 "no set large-community AA:BB:CC...",
4979 NO_STR
4980 SET_STR
4981 "BGP large community attribute\n"
4982 "Large community in AA:BB:CC... format or additive\n")
4983{
d62a17ae 4984 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4985 "large-community", NULL);
52951b63 4986}
57d187bc 4987
76a20aa9
DS
4988ALIAS (no_set_lcommunity1,
4989 no_set_lcommunity1_short_cmd,
4990 "no set large-community",
4991 NO_STR
4992 SET_STR
4993 "BGP large community attribute\n")
4994
57d187bc
JS
4995DEFUN (set_lcommunity_delete,
4996 set_lcommunity_delete_cmd,
4997 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4998 SET_STR
4999 "set BGP large community list (for deletion)\n"
5000 "Large Community-list number (standard)\n"
5001 "Large Communitly-list number (expanded)\n"
5002 "Large Community-list name\n"
5003 "Delete matching large communities\n")
5004{
4cae2269
DA
5005 int idx_lcomm_list = 2;
5006 char *args;
5007
5008 args = argv_concat(argv, argc, idx_lcomm_list);
d62a17ae 5009 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4cae2269
DA
5010 "large-comm-list", args);
5011 XFREE(MTYPE_TMP, args);
57d187bc 5012
d62a17ae 5013 return CMD_SUCCESS;
57d187bc
JS
5014}
5015
5016DEFUN (no_set_lcommunity_delete,
5017 no_set_lcommunity_delete_cmd,
db4f7086 5018 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
57d187bc
JS
5019 NO_STR
5020 SET_STR
5021 "set BGP large community list (for deletion)\n"
5022 "Large Community-list number (standard)\n"
5023 "Large Communitly-list number (expanded)\n"
5024 "Large Community-list name\n"
5025 "Delete matching large communities\n")
5026{
d62a17ae 5027 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5028 "large-comm-list", NULL);
57d187bc 5029}
718e3744 5030
76a20aa9
DS
5031ALIAS (no_set_lcommunity_delete,
5032 no_set_lcommunity_delete_short_cmd,
5033 "no set large-comm-list",
5034 NO_STR
5035 SET_STR
5036 "set BGP large community list (for deletion)\n")
5037
718e3744 5038DEFUN (set_ecommunity_rt,
5039 set_ecommunity_rt_cmd,
d114b977 5040 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5041 SET_STR
5042 "BGP extended community attribute\n"
e6b6a564 5043 "Route Target extended community\n"
718e3744 5044 "VPN extended community\n")
5045{
d62a17ae 5046 int idx_asn_nn = 3;
5047 int ret;
5048 char *str;
718e3744 5049
d62a17ae 5050 str = argv_concat(argv, argc, idx_asn_nn);
5051 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5052 "extcommunity rt", str);
5053 XFREE(MTYPE_TMP, str);
718e3744 5054
d62a17ae 5055 return ret;
718e3744 5056}
5057
5058DEFUN (no_set_ecommunity_rt,
5059 no_set_ecommunity_rt_cmd,
d114b977 5060 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5061 NO_STR
5062 SET_STR
5063 "BGP extended community attribute\n"
3a2d747c
QY
5064 "Route Target extended community\n"
5065 "VPN extended community\n")
718e3744 5066{
d62a17ae 5067 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5068 "extcommunity rt", NULL);
718e3744 5069}
5070
4db5ee8e
DS
5071ALIAS (no_set_ecommunity_rt,
5072 no_set_ecommunity_rt_short_cmd,
5073 "no set extcommunity rt",
5074 NO_STR
5075 SET_STR
5076 "BGP extended community attribute\n"
5077 "Route Target extended community\n")
718e3744 5078
5079DEFUN (set_ecommunity_soo,
5080 set_ecommunity_soo_cmd,
d114b977 5081 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5082 SET_STR
5083 "BGP extended community attribute\n"
5084 "Site-of-Origin extended community\n"
5085 "VPN extended community\n")
5086{
d62a17ae 5087 int idx_asn_nn = 3;
5088 int ret;
5089 char *str;
718e3744 5090
d62a17ae 5091 str = argv_concat(argv, argc, idx_asn_nn);
5092 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5093 "extcommunity soo", str);
5094 XFREE(MTYPE_TMP, str);
5095 return ret;
718e3744 5096}
5097
a4b2b610 5098
718e3744 5099DEFUN (no_set_ecommunity_soo,
5100 no_set_ecommunity_soo_cmd,
d114b977 5101 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5102 NO_STR
5103 SET_STR
5104 "BGP extended community attribute\n"
3a2d747c
QY
5105 "Site-of-Origin extended community\n"
5106 "VPN extended community\n")
718e3744 5107{
d62a17ae 5108 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5109 "extcommunity soo", NULL);
718e3744 5110}
5111
4db5ee8e
DS
5112ALIAS (no_set_ecommunity_soo,
5113 no_set_ecommunity_soo_short_cmd,
5114 "no set extcommunity soo",
5115 NO_STR
5116 SET_STR
5117 "GP extended community attribute\n"
5118 "Site-of-Origin extended community\n")
718e3744 5119
ca9ac3ef 5120DEFUN (set_ecommunity_lb,
5121 set_ecommunity_lb_cmd,
5122 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
5123 SET_STR
5124 "BGP extended community attribute\n"
5125 "Link bandwidth extended community\n"
5126 "Bandwidth value in Mbps\n"
5127 "Cumulative bandwidth of all multipaths (outbound-only)\n"
5128 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
5129 "Attribute is set as non-transitive\n")
5130{
5131 int idx_lb = 3;
5132 int ret;
5133 char *str;
5134
5135 str = argv_concat(argv, argc, idx_lb);
5136 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5137 "extcommunity bandwidth", str);
5138 XFREE(MTYPE_TMP, str);
5139 return ret;
5140}
5141
5142
5143DEFUN (no_set_ecommunity_lb,
5144 no_set_ecommunity_lb_cmd,
5145 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
5146 NO_STR
5147 SET_STR
5148 "BGP extended community attribute\n"
5149 "Link bandwidth extended community\n"
5150 "Bandwidth value in Mbps\n"
5151 "Cumulative bandwidth of all multipaths (outbound-only)\n"
5152 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
5153 "Attribute is set as non-transitive\n")
5154{
5155 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5156 "extcommunity bandwidth", NULL);
5157}
5158
5159ALIAS (no_set_ecommunity_lb,
5160 no_set_ecommunity_lb_short_cmd,
5161 "no set extcommunity bandwidth",
5162 NO_STR
5163 SET_STR
5164 "BGP extended community attribute\n"
5165 "Link bandwidth extended community\n")
5166
718e3744 5167DEFUN (set_origin,
5168 set_origin_cmd,
6147e2c6 5169 "set origin <egp|igp|incomplete>",
718e3744 5170 SET_STR
5171 "BGP origin code\n"
5172 "remote EGP\n"
5173 "local IGP\n"
5174 "unknown heritage\n")
5175{
d62a17ae 5176 int idx_origin = 2;
5177 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
5178 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5179 "origin", "igp");
5180 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5181 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5182 "origin", "egp");
5183 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5184 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5185 "origin", "incomplete");
718e3744 5186
d62a17ae 5187 vty_out(vty, "%% Invalid set origin type\n");
5188 return CMD_WARNING_CONFIG_FAILED;
718e3744 5189}
5190
a4b2b610 5191
718e3744 5192DEFUN (no_set_origin,
5193 no_set_origin_cmd,
a4b2b610 5194 "no set origin [<egp|igp|incomplete>]",
718e3744 5195 NO_STR
5196 SET_STR
d7fa34c1
QY
5197 "BGP origin code\n"
5198 "remote EGP\n"
5199 "local IGP\n"
5200 "unknown heritage\n")
718e3744 5201{
d62a17ae 5202 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5203 "origin", NULL);
718e3744 5204}
5205
718e3744 5206
5207DEFUN (set_atomic_aggregate,
5208 set_atomic_aggregate_cmd,
5209 "set atomic-aggregate",
5210 SET_STR
5211 "BGP atomic aggregate attribute\n" )
5212{
d62a17ae 5213 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5214 "atomic-aggregate", NULL);
718e3744 5215}
5216
5217DEFUN (no_set_atomic_aggregate,
5218 no_set_atomic_aggregate_cmd,
5219 "no set atomic-aggregate",
5220 NO_STR
5221 SET_STR
5222 "BGP atomic aggregate attribute\n" )
5223{
d62a17ae 5224 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5225 "atomic-aggregate", NULL);
718e3744 5226}
5227
5228DEFUN (set_aggregator_as,
5229 set_aggregator_as_cmd,
9ccf14f7 5230 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 5231 SET_STR
5232 "BGP aggregator attribute\n"
5233 "AS number of aggregator\n"
5234 "AS number\n"
5235 "IP address of aggregator\n")
5236{
d62a17ae 5237 int idx_number = 3;
5238 int idx_ipv4 = 4;
5239 int ret;
5240 struct in_addr address;
5241 char *argstr;
e52702f2 5242
d62a17ae 5243 ret = inet_aton(argv[idx_ipv4]->arg, &address);
5244 if (ret == 0) {
5245 vty_out(vty, "Aggregator IP address is invalid\n");
5246 return CMD_WARNING_CONFIG_FAILED;
5247 }
718e3744 5248
d62a17ae 5249 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
5250 strlen(argv[idx_number]->arg)
5251 + strlen(argv[idx_ipv4]->arg) + 2);
718e3744 5252
d62a17ae 5253 sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 5254
d62a17ae 5255 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5256 "aggregator as", argstr);
718e3744 5257
d62a17ae 5258 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 5259
d62a17ae 5260 return ret;
718e3744 5261}
5262
a4b2b610 5263
718e3744 5264DEFUN (no_set_aggregator_as,
5265 no_set_aggregator_as_cmd,
a4b2b610 5266 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 5267 NO_STR
5268 SET_STR
5269 "BGP aggregator attribute\n"
a4b2b610
DW
5270 "AS number of aggregator\n"
5271 "AS number\n"
5272 "IP address of aggregator\n")
718e3744 5273{
d62a17ae 5274 int idx_asn = 4;
5275 int idx_ip = 5;
5276 int ret;
5277 struct in_addr address;
5278 char *argstr;
718e3744 5279
d62a17ae 5280 if (argc <= idx_asn)
5281 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5282 "aggregator as", NULL);
e52702f2 5283
d62a17ae 5284 ret = inet_aton(argv[idx_ip]->arg, &address);
5285 if (ret == 0) {
5286 vty_out(vty, "Aggregator IP address is invalid\n");
5287 return CMD_WARNING_CONFIG_FAILED;
5288 }
718e3744 5289
d62a17ae 5290 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
5291 strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
5292 + 2);
718e3744 5293
d62a17ae 5294 sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 5295
d62a17ae 5296 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5297 "aggregator as", argstr);
718e3744 5298
d62a17ae 5299 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 5300
d62a17ae 5301 return ret;
718e3744 5302}
5303
f412b39a 5304DEFUN (match_ipv6_next_hop,
718e3744 5305 match_ipv6_next_hop_cmd,
5306 "match ipv6 next-hop X:X::X:X",
5307 MATCH_STR
5308 IPV6_STR
5309 "Match IPv6 next-hop address of route\n"
5310 "IPv6 address of next hop\n")
5311{
d62a17ae 5312 int idx_ipv6 = 3;
5313 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
5314 RMAP_EVENT_MATCH_ADDED);
718e3744 5315}
5316
5317DEFUN (no_match_ipv6_next_hop,
5318 no_match_ipv6_next_hop_cmd,
5319 "no match ipv6 next-hop X:X::X:X",
5320 NO_STR
5321 MATCH_STR
5322 IPV6_STR
5323 "Match IPv6 next-hop address of route\n"
5324 "IPv6 address of next hop\n")
5325{
d62a17ae 5326 int idx_ipv6 = 4;
5327 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
5328 RMAP_EVENT_MATCH_DELETED);
718e3744 5329}
5330
be7735b3
PG
5331DEFPY (match_ipv4_next_hop,
5332 match_ipv4_next_hop_cmd,
17ac51eb 5333 "match ip next-hop address A.B.C.D",
be7735b3
PG
5334 MATCH_STR
5335 IP_STR
5336 "Match IP next-hop address of route\n"
5337 "IP address\n"
5338 "IP address of next-hop\n")
5339{
5340 int idx_ipv4 = 4;
5341
17ac51eb
DS
5342 return bgp_route_match_add(vty, "ip next-hop address",
5343 argv[idx_ipv4]->arg, RMAP_EVENT_MATCH_ADDED);
5344}
be7735b3 5345
17ac51eb
DS
5346DEFPY (no_match_ipv4_next_hop,
5347 no_match_ipv4_next_hop_cmd,
5348 "no match ip next-hop address [A.B.C.D]",
5349 NO_STR
5350 MATCH_STR
5351 IP_STR
5352 "Match IP next-hop address of route\n"
5353 "IP address\n"
5354 "IP address of next-hop\n")
5355{
5356 return bgp_route_match_delete(vty, "ip next-hop address", NULL,
5357 RMAP_EVENT_MATCH_DELETED);
be7735b3 5358}
718e3744 5359
90916ac2
DS
5360DEFUN (set_ipv6_nexthop_peer,
5361 set_ipv6_nexthop_peer_cmd,
5362 "set ipv6 next-hop peer-address",
5363 SET_STR
5364 IPV6_STR
5365 "Next hop address\n"
5366 "Use peer address (for BGP only)\n")
5367{
d62a17ae 5368 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5369 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
5370}
5371
5372DEFUN (no_set_ipv6_nexthop_peer,
5373 no_set_ipv6_nexthop_peer_cmd,
5374 "no set ipv6 next-hop peer-address",
5375 NO_STR
5376 SET_STR
5377 IPV6_STR
5378 "IPv6 next-hop address\n"
161995ea 5379 "Use peer address (for BGP only)\n")
90916ac2 5380{
d62a17ae 5381 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5382 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
5383}
5384
161995ea
DS
5385DEFUN (set_ipv6_nexthop_prefer_global,
5386 set_ipv6_nexthop_prefer_global_cmd,
5387 "set ipv6 next-hop prefer-global",
5388 SET_STR
5389 IPV6_STR
5390 "IPv6 next-hop address\n"
5391 "Prefer global over link-local if both exist\n")
5392{
d62a17ae 5393 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5394 "ipv6 next-hop prefer-global", NULL);
5395 ;
161995ea
DS
5396}
5397
5398DEFUN (no_set_ipv6_nexthop_prefer_global,
5399 no_set_ipv6_nexthop_prefer_global_cmd,
5400 "no set ipv6 next-hop prefer-global",
5401 NO_STR
5402 SET_STR
5403 IPV6_STR
5404 "IPv6 next-hop address\n"
5405 "Prefer global over link-local if both exist\n")
5406{
d62a17ae 5407 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5408 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
5409}
5410
718e3744 5411DEFUN (set_ipv6_nexthop_global,
5412 set_ipv6_nexthop_global_cmd,
5413 "set ipv6 next-hop global X:X::X:X",
5414 SET_STR
5415 IPV6_STR
5416 "IPv6 next-hop address\n"
5417 "IPv6 global address\n"
5418 "IPv6 address of next hop\n")
5419{
d62a17ae 5420 int idx_ipv6 = 4;
5421 struct in6_addr addr;
5422 int ret;
bf8b3d27 5423
d62a17ae 5424 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
5425 if (!ret) {
5426 vty_out(vty, "%% Malformed nexthop address\n");
5427 return CMD_WARNING_CONFIG_FAILED;
5428 }
5429 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
5430 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
5431 vty_out(vty, "%% Invalid global nexthop address\n");
5432 return CMD_WARNING_CONFIG_FAILED;
5433 }
bf8b3d27 5434
d62a17ae 5435 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5436 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 5437}
5438
a4b2b610 5439
718e3744 5440DEFUN (no_set_ipv6_nexthop_global,
5441 no_set_ipv6_nexthop_global_cmd,
a4b2b610 5442 "no set ipv6 next-hop global X:X::X:X",
718e3744 5443 NO_STR
5444 SET_STR
5445 IPV6_STR
5446 "IPv6 next-hop address\n"
a4b2b610
DW
5447 "IPv6 global address\n"
5448 "IPv6 address of next hop\n")
718e3744 5449{
d62a17ae 5450 int idx_ipv6 = 5;
5451 if (argc <= idx_ipv6)
5452 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5453 "ipv6 next-hop global", NULL);
5454 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5455 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 5456}
718e3744 5457
d6902373
PG
5458#ifdef KEEP_OLD_VPN_COMMANDS
5459DEFUN (set_vpn_nexthop,
5460 set_vpn_nexthop_cmd,
a13c883e 5461 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 5462 SET_STR
5463 "VPNv4 information\n"
d6902373
PG
5464 "VPN next-hop address\n"
5465 "IP address of next hop\n"
a13c883e
QY
5466 "VPNv6 information\n"
5467 "VPN next-hop address\n"
d6902373 5468 "IPv6 address of next hop\n")
718e3744 5469{
d62a17ae 5470 int idx_ip = 3;
5471 afi_t afi;
5472 int idx = 0;
5473
5474 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
5475 if (afi == AFI_IP)
5476 return generic_set_add(
5477 vty, VTY_GET_CONTEXT(route_map_index),
5478 "ipv4 vpn next-hop", argv[idx_ip]->arg);
5479 else
5480 return generic_set_add(
5481 vty, VTY_GET_CONTEXT(route_map_index),
5482 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5483 }
5484 return CMD_SUCCESS;
d6902373 5485}
a4b2b610 5486
d6902373
PG
5487DEFUN (no_set_vpn_nexthop,
5488 no_set_vpn_nexthop_cmd,
a13c883e 5489 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 5490 NO_STR
5491 SET_STR
a13c883e 5492 "VPNv4 information\n"
d6902373
PG
5493 "VPN next-hop address\n"
5494 "IP address of next hop\n"
a13c883e
QY
5495 "VPNv6 information\n"
5496 "VPN next-hop address\n"
d6902373 5497 "IPv6 address of next hop\n")
718e3744 5498{
d62a17ae 5499 int idx_ip = 4;
5500 char *arg;
5501 afi_t afi;
5502 int idx = 0;
5503
5504 if (argc <= idx_ip)
5505 arg = NULL;
5506 else
5507 arg = argv[idx_ip]->arg;
5508 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
5509 if (afi == AFI_IP)
5510 return generic_set_delete(
5511 vty, VTY_GET_CONTEXT(route_map_index),
5512 "ipv4 vpn next-hop", arg);
5513 else
5514 return generic_set_delete(
5515 vty, VTY_GET_CONTEXT(route_map_index),
5516 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5517 }
5518 return CMD_SUCCESS;
d6902373
PG
5519}
5520#endif /* KEEP_OLD_VPN_COMMANDS */
5521
5522DEFUN (set_ipx_vpn_nexthop,
5523 set_ipx_vpn_nexthop_cmd,
0d702986 5524 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
d6902373
PG
5525 SET_STR
5526 "IPv4 information\n"
5527 "IPv6 information\n"
5528 "VPN information\n"
5529 "VPN next-hop address\n"
5530 "IP address of next hop\n"
5531 "IPv6 address of next hop\n")
5532{
d62a17ae 5533 int idx_ip = 4;
5534 afi_t afi;
5535 int idx = 0;
5536
5537 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
5538 if (afi == AFI_IP)
5539 return generic_set_add(
5540 vty, VTY_GET_CONTEXT(route_map_index),
5541 "ipv4 vpn next-hop", argv[idx_ip]->arg);
5542 else
5543 return generic_set_add(
5544 vty, VTY_GET_CONTEXT(route_map_index),
5545 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5546 }
5547 return CMD_SUCCESS;
718e3744 5548}
5549
d6902373
PG
5550DEFUN (no_set_ipx_vpn_nexthop,
5551 no_set_ipx_vpn_nexthop_cmd,
9fa4d336 5552 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
d6902373
PG
5553 NO_STR
5554 SET_STR
5555 "IPv4 information\n"
5556 "IPv6 information\n"
5557 "VPN information\n"
5558 "VPN next-hop address\n"
5559 "IP address of next hop\n"
5560 "IPv6 address of next hop\n")
5561{
d62a17ae 5562 int idx_ip = 5;
5563 char *arg;
5564 afi_t afi;
5565 int idx = 0;
5566
5567 if (argc <= idx_ip)
5568 arg = NULL;
5569 else
5570 arg = argv[idx_ip]->arg;
5571 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
5572 if (afi == AFI_IP)
5573 return generic_set_delete(
5574 vty, VTY_GET_CONTEXT(route_map_index),
5575 "ipv4 vpn next-hop", arg);
5576 else
5577 return generic_set_delete(
5578 vty, VTY_GET_CONTEXT(route_map_index),
5579 "ipv6 vpn next-hop", arg);
5580 }
5581 return CMD_SUCCESS;
d6902373 5582}
718e3744 5583
5584DEFUN (set_originator_id,
5585 set_originator_id_cmd,
5586 "set originator-id A.B.C.D",
5587 SET_STR
5588 "BGP originator ID attribute\n"
5589 "IP address of originator\n")
5590{
d62a17ae 5591 int idx_ipv4 = 2;
5592 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5593 "originator-id", argv[idx_ipv4]->arg);
718e3744 5594}
5595
4c9bd275 5596
718e3744 5597DEFUN (no_set_originator_id,
5598 no_set_originator_id_cmd,
4c9bd275 5599 "no set originator-id [A.B.C.D]",
718e3744 5600 NO_STR
5601 SET_STR
4c9bd275
DW
5602 "BGP originator ID attribute\n"
5603 "IP address of originator\n")
718e3744 5604{
d62a17ae 5605 int idx = 0;
5606 char *arg =
5607 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
0d702986 5608
d62a17ae 5609 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5610 "originator-id", arg);
718e3744 5611}
5612
718e3744 5613
718e3744 5614/* Initialization of route map. */
d62a17ae 5615void bgp_route_map_init(void)
5616{
5617 route_map_init();
5618
5619 route_map_add_hook(bgp_route_map_add);
5620 route_map_delete_hook(bgp_route_map_delete);
5621 route_map_event_hook(bgp_route_map_event);
5622
5623 route_map_match_interface_hook(generic_match_add);
5624 route_map_no_match_interface_hook(generic_match_delete);
5625
5626 route_map_match_ip_address_hook(generic_match_add);
5627 route_map_no_match_ip_address_hook(generic_match_delete);
5628
5629 route_map_match_ip_address_prefix_list_hook(generic_match_add);
5630 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
5631
5632 route_map_match_ip_next_hop_hook(generic_match_add);
5633 route_map_no_match_ip_next_hop_hook(generic_match_delete);
5634
5635 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
5636 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
5637
61ad901e
DA
5638 route_map_match_ip_next_hop_type_hook(generic_match_add);
5639 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
5640
d62a17ae 5641 route_map_match_ipv6_address_hook(generic_match_add);
5642 route_map_no_match_ipv6_address_hook(generic_match_delete);
5643
5644 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
5645 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
5646
61ad901e
DA
5647 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
5648 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
5649
d62a17ae 5650 route_map_match_metric_hook(generic_match_add);
5651 route_map_no_match_metric_hook(generic_match_delete);
5652
5653 route_map_match_tag_hook(generic_match_add);
5654 route_map_no_match_tag_hook(generic_match_delete);
5655
ef3e0d04
SM
5656 route_map_set_srte_color_hook(generic_set_add);
5657 route_map_no_set_srte_color_hook(generic_set_delete);
5658
d62a17ae 5659 route_map_set_ip_nexthop_hook(generic_set_add);
5660 route_map_no_set_ip_nexthop_hook(generic_set_delete);
5661
5662 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
5663 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
5664
5665 route_map_set_metric_hook(generic_set_add);
5666 route_map_no_set_metric_hook(generic_set_delete);
5667
5668 route_map_set_tag_hook(generic_set_add);
5669 route_map_no_set_tag_hook(generic_set_delete);
5670
5671 route_map_install_match(&route_match_peer_cmd);
5672 route_map_install_match(&route_match_local_pref_cmd);
1d7c7ace 5673#if defined(HAVE_LUA)
b4becb06 5674 route_map_install_match(&route_match_script_cmd);
1d7c7ace 5675#endif
d62a17ae 5676 route_map_install_match(&route_match_ip_address_cmd);
5677 route_map_install_match(&route_match_ip_next_hop_cmd);
5678 route_map_install_match(&route_match_ip_route_source_cmd);
5679 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
5680 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 5681 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 5682 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
5683 route_map_install_match(&route_match_aspath_cmd);
5684 route_map_install_match(&route_match_community_cmd);
5685 route_map_install_match(&route_match_lcommunity_cmd);
5686 route_map_install_match(&route_match_ecommunity_cmd);
5687 route_map_install_match(&route_match_local_pref_cmd);
5688 route_map_install_match(&route_match_metric_cmd);
5689 route_map_install_match(&route_match_origin_cmd);
5690 route_map_install_match(&route_match_probability_cmd);
5691 route_map_install_match(&route_match_interface_cmd);
5692 route_map_install_match(&route_match_tag_cmd);
d37ba549 5693 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 5694 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 5695 route_map_install_match(&route_match_evpn_route_type_cmd);
196c6b09 5696 route_map_install_match(&route_match_evpn_rd_cmd);
6fb219da 5697 route_map_install_match(&route_match_evpn_default_route_cmd);
1dcc9e5b 5698 route_map_install_match(&route_match_vrl_source_vrf_cmd);
d62a17ae 5699
951745bd 5700 route_map_install_set(&route_set_table_id_cmd);
ef3e0d04 5701 route_map_install_set(&route_set_srte_color_cmd);
d62a17ae 5702 route_map_install_set(&route_set_ip_nexthop_cmd);
5703 route_map_install_set(&route_set_local_pref_cmd);
5704 route_map_install_set(&route_set_weight_cmd);
5705 route_map_install_set(&route_set_label_index_cmd);
5706 route_map_install_set(&route_set_metric_cmd);
7b7d48e5 5707 route_map_install_set(&route_set_distance_cmd);
d62a17ae 5708 route_map_install_set(&route_set_aspath_prepend_cmd);
5709 route_map_install_set(&route_set_aspath_exclude_cmd);
5710 route_map_install_set(&route_set_origin_cmd);
5711 route_map_install_set(&route_set_atomic_aggregate_cmd);
5712 route_map_install_set(&route_set_aggregator_as_cmd);
5713 route_map_install_set(&route_set_community_cmd);
5714 route_map_install_set(&route_set_community_delete_cmd);
5715 route_map_install_set(&route_set_lcommunity_cmd);
5716 route_map_install_set(&route_set_lcommunity_delete_cmd);
5717 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
5718 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
5719 route_map_install_set(&route_set_originator_id_cmd);
5720 route_map_install_set(&route_set_ecommunity_rt_cmd);
5721 route_map_install_set(&route_set_ecommunity_soo_cmd);
ca9ac3ef 5722 route_map_install_set(&route_set_ecommunity_lb_cmd);
d62a17ae 5723 route_map_install_set(&route_set_tag_cmd);
5724 route_map_install_set(&route_set_label_index_cmd);
5725
5726 install_element(RMAP_NODE, &match_peer_cmd);
5727 install_element(RMAP_NODE, &match_peer_local_cmd);
5728 install_element(RMAP_NODE, &no_match_peer_cmd);
5729 install_element(RMAP_NODE, &match_ip_route_source_cmd);
5730 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
5731 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
5732 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
5733 install_element(RMAP_NODE, &match_mac_address_cmd);
5734 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
5735 install_element(RMAP_NODE, &match_evpn_vni_cmd);
5736 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
5737 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
5738 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
196c6b09
LK
5739 install_element(RMAP_NODE, &match_evpn_rd_cmd);
5740 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
6fb219da
MK
5741 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
5742 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
1dcc9e5b
CS
5743 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
5744 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
d62a17ae 5745
5746 install_element(RMAP_NODE, &match_aspath_cmd);
5747 install_element(RMAP_NODE, &no_match_aspath_cmd);
5748 install_element(RMAP_NODE, &match_local_pref_cmd);
5749 install_element(RMAP_NODE, &no_match_local_pref_cmd);
5750 install_element(RMAP_NODE, &match_community_cmd);
5751 install_element(RMAP_NODE, &no_match_community_cmd);
5752 install_element(RMAP_NODE, &match_lcommunity_cmd);
5753 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
5754 install_element(RMAP_NODE, &match_ecommunity_cmd);
5755 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
5756 install_element(RMAP_NODE, &match_origin_cmd);
5757 install_element(RMAP_NODE, &no_match_origin_cmd);
5758 install_element(RMAP_NODE, &match_probability_cmd);
5759 install_element(RMAP_NODE, &no_match_probability_cmd);
5760
951745bd
PG
5761 install_element(RMAP_NODE, &no_set_table_id_cmd);
5762 install_element(RMAP_NODE, &set_table_id_cmd);
d62a17ae 5763 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
5764 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
5765 install_element(RMAP_NODE, &set_local_pref_cmd);
7b7d48e5
DS
5766 install_element(RMAP_NODE, &set_distance_cmd);
5767 install_element(RMAP_NODE, &no_set_distance_cmd);
d62a17ae 5768 install_element(RMAP_NODE, &no_set_local_pref_cmd);
5769 install_element(RMAP_NODE, &set_weight_cmd);
5770 install_element(RMAP_NODE, &set_label_index_cmd);
5771 install_element(RMAP_NODE, &no_set_weight_cmd);
5772 install_element(RMAP_NODE, &no_set_label_index_cmd);
5773 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
5774 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
5775 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
5776 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
9131e6e8 5777 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
d62a17ae 5778 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
499ceb3d 5779 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
d62a17ae 5780 install_element(RMAP_NODE, &set_origin_cmd);
5781 install_element(RMAP_NODE, &no_set_origin_cmd);
5782 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
5783 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
5784 install_element(RMAP_NODE, &set_aggregator_as_cmd);
5785 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
5786 install_element(RMAP_NODE, &set_community_cmd);
5787 install_element(RMAP_NODE, &set_community_none_cmd);
5788 install_element(RMAP_NODE, &no_set_community_cmd);
2929de9e 5789 install_element(RMAP_NODE, &no_set_community_short_cmd);
d62a17ae 5790 install_element(RMAP_NODE, &set_community_delete_cmd);
5791 install_element(RMAP_NODE, &no_set_community_delete_cmd);
5792 install_element(RMAP_NODE, &set_lcommunity_cmd);
5793 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
5794 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
5795 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
76a20aa9 5796 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
d62a17ae 5797 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
5798 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
76a20aa9 5799 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
d62a17ae 5800 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
5801 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4db5ee8e 5802 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
d62a17ae 5803 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
5804 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4db5ee8e 5805 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
ca9ac3ef 5806 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
5807 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
5808 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
d6902373 5809#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 5810 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
5811 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 5812#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 5813 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
5814 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
5815 install_element(RMAP_NODE, &set_originator_id_cmd);
5816 install_element(RMAP_NODE, &no_set_originator_id_cmd);
5817
5818 route_map_install_match(&route_match_ipv6_address_cmd);
5819 route_map_install_match(&route_match_ipv6_next_hop_cmd);
be7735b3 5820 route_map_install_match(&route_match_ipv4_next_hop_cmd);
d62a17ae 5821 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 5822 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 5823 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
5824 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
5825 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
5826 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
5827
5828 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
5829 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
be7735b3 5830 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
17ac51eb 5831 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
d62a17ae 5832 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
5833 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
5834 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
5835 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
5836 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
5837 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
1d7c7ace 5838#if defined(HAVE_LUA)
b4becb06 5839 install_element(RMAP_NODE, &match_script_cmd);
1d7c7ace 5840#endif
d62a17ae 5841}
5842
5843void bgp_route_map_terminate(void)
5844{
5845 /* ToDo: Cleanup all the used memory */
d62a17ae 5846 route_map_finish();
518f0eb1 5847}