]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Merge pull request #13455 from sri-mohan1/srib-ldpd
[mirror_frr.git] / bgpd / bgp_routemap.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* Route map function of bgpd.
896014f4 3 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
896014f4 4 */
718e3744 5
6#include <zebra.h>
7
8#include "prefix.h"
9#include "filter.h"
10#include "routemap.h"
11#include "command.h"
12#include "linklist.h"
13#include "plist.h"
14#include "memory.h"
15#include "log.h"
5dbb0a7b 16#include "frrlua.h"
fa2bb2e8 17#include "frrscript.h"
061f5d1c
DA
18#ifdef HAVE_LIBPCRE2_POSIX
19#ifndef _FRR_PCRE2_POSIX
20#define _FRR_PCRE2_POSIX
21#include <pcre2posix.h>
22#endif /* _FRR_PCRE2_POSIX */
23#elif defined(HAVE_LIBPCREPOSIX)
d62a17ae 24#include <pcreposix.h>
718e3744 25#else
d62a17ae 26#include <regex.h>
061f5d1c 27#endif /* HAVE_LIBPCRE2_POSIX */
718e3744 28#include "buffer.h"
29#include "sockunion.h"
518f0eb1 30#include "hash.h"
3f9c7369 31#include "queue.h"
5d5ba018 32#include "frrstr.h"
5920b3eb 33#include "network.h"
48cb7ea9 34#include "lib/northbound_cli.h"
718e3744 35
36#include "bgpd/bgpd.h"
37#include "bgpd/bgp_table.h"
38#include "bgpd/bgp_attr.h"
39#include "bgpd/bgp_aspath.h"
518f0eb1 40#include "bgpd/bgp_packet.h"
718e3744 41#include "bgpd/bgp_route.h"
73ac8160 42#include "bgpd/bgp_zebra.h"
718e3744 43#include "bgpd/bgp_regex.h"
44#include "bgpd/bgp_community.h"
2690f18c 45#include "bgpd/bgp_community_alias.h"
718e3744 46#include "bgpd/bgp_clist.h"
47#include "bgpd/bgp_filter.h"
48#include "bgpd/bgp_mplsvpn.h"
49#include "bgpd/bgp_ecommunity.h"
57d187bc 50#include "bgpd/bgp_lcommunity.h"
320da874 51#include "bgpd/bgp_vty.h"
73ac8160 52#include "bgpd/bgp_debug.h"
d37ba549
MK
53#include "bgpd/bgp_evpn.h"
54#include "bgpd/bgp_evpn_private.h"
62982d5a 55#include "bgpd/bgp_evpn_vty.h"
ddb5b488 56#include "bgpd/bgp_mplsvpn.h"
2e59405f
DS
57#include "bgpd/bgp_pbr.h"
58#include "bgpd/bgp_flowspec_util.h"
82b692c0 59#include "bgpd/bgp_encap_types.h"
b1875e65 60#include "bgpd/bgp_mpath.h"
b4becb06 61#include "bgpd/bgp_script.h"
718e3744 62
49e5a4a0 63#ifdef ENABLE_BGP_VNC
d62a17ae 64#include "bgpd/rfapi/bgp_rfapi_cfg.h"
65efcfce 65#endif
518f0eb1 66
1dcc9e5b 67#include "bgpd/bgp_routemap_clippy.c"
1dcc9e5b 68
718e3744 69/* Memo of route-map commands.
70
71o Cisco route-map
72
73 match as-path : Done
74 community : Done
bc413143 75 interface : Done
718e3744 76 ip address : Done
77 ip next-hop : Done
c1643bb7 78 ip route-source : Done
718e3744 79 ip prefix-list : Done
80 ipv6 address : Done
81 ipv6 next-hop : Done
82 ipv6 route-source: (This will not be implemented by bgpd)
83 ipv6 prefix-list : Done
84 length : (This will not be implemented by bgpd)
85 metric : Done
86 route-type : (This will not be implemented by bgpd)
0d9551dc 87 tag : Done
af291c15 88 local-preference : Done
718e3744 89
90 set as-path prepend : Done
91 as-path tag : Not yet
92 automatic-tag : (This will not be implemented by bgpd)
93 community : Done
57d187bc
JS
94 large-community : Done
95 large-comm-list : Done
718e3744 96 comm-list : Not yet
97 dampning : Not yet
98 default : (This will not be implemented by bgpd)
99 interface : (This will not be implemented by bgpd)
100 ip default : (This will not be implemented by bgpd)
101 ip next-hop : Done
102 ip precedence : (This will not be implemented by bgpd)
103 ip tos : (This will not be implemented by bgpd)
104 level : (This will not be implemented by bgpd)
105 local-preference : Done
106 metric : Done
107 metric-type : Not yet
108 origin : Done
0d9551dc 109 tag : Done
718e3744 110 weight : Done
951745bd 111 table : Done
718e3744 112
515e500c 113o Local extensions
718e3744 114
115 set ipv6 next-hop global: Done
161995ea 116 set ipv6 next-hop prefer-global: Done
718e3744 117 set ipv6 next-hop local : Done
841f7a57 118 set as-path exclude : Done
718e3744 119
e52702f2 120*/
6b0655a2 121
d62a17ae 122/* generic value manipulation to be shared in multiple rules */
76759f4f
TT
123
124#define RMAP_VALUE_SET 0
125#define RMAP_VALUE_ADD 1
126#define RMAP_VALUE_SUB 2
127
d62a17ae 128struct rmap_value {
d7c0a89a
QY
129 uint8_t action;
130 uint8_t variable;
131 uint32_t value;
76759f4f
TT
132};
133
d7c0a89a 134static int route_value_match(struct rmap_value *rv, uint32_t value)
d62a17ae 135{
136 if (rv->variable == 0 && value == rv->value)
137 return RMAP_MATCH;
76759f4f 138
d62a17ae 139 return RMAP_NOMATCH;
76759f4f
TT
140}
141
d7c0a89a
QY
142static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
143 struct peer *peer)
76759f4f 144{
d7c0a89a 145 uint32_t value;
baa376fc 146
d62a17ae 147 switch (rv->variable) {
148 case 1:
149 value = peer->rtt;
150 break;
151 default:
152 value = rv->value;
153 break;
154 }
76759f4f 155
d62a17ae 156 switch (rv->action) {
157 case RMAP_VALUE_ADD:
158 if (current > UINT32_MAX - value)
159 return UINT32_MAX;
160 return current + value;
161 case RMAP_VALUE_SUB:
162 if (current <= value)
163 return 0;
164 return current - value;
165 default:
166 return value;
167 }
76759f4f
TT
168}
169
d62a17ae 170static void *route_value_compile(const char *arg)
76759f4f 171{
d7c0a89a 172 uint8_t action = RMAP_VALUE_SET, var = 0;
d62a17ae 173 unsigned long larg = 0;
174 char *endptr = NULL;
175 struct rmap_value *rv;
76759f4f 176
d62a17ae 177 if (arg[0] == '+') {
178 action = RMAP_VALUE_ADD;
179 arg++;
180 } else if (arg[0] == '-') {
181 action = RMAP_VALUE_SUB;
182 arg++;
183 }
76759f4f 184
d62a17ae 185 if (all_digit(arg)) {
186 errno = 0;
187 larg = strtoul(arg, &endptr, 10);
188 if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
189 return NULL;
190 } else {
191 if (strcmp(arg, "rtt") == 0)
192 var = 1;
193 else
194 return NULL;
195 }
76759f4f 196
d62a17ae 197 rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
76759f4f 198
d62a17ae 199 rv->action = action;
200 rv->variable = var;
201 rv->value = larg;
202 return rv;
76759f4f
TT
203}
204
d62a17ae 205static void route_value_free(void *rule)
76759f4f 206{
d62a17ae 207 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
76759f4f
TT
208}
209
d62a17ae 210/* generic as path object to be shared in multiple rules */
374f12f9 211
d62a17ae 212static void *route_aspath_compile(const char *arg)
374f12f9 213{
d62a17ae 214 struct aspath *aspath;
374f12f9 215
17571c4a 216 aspath = aspath_str2aspath(arg, bgp_get_asnotation(NULL));
d62a17ae 217 if (!aspath)
218 return NULL;
219 return aspath;
374f12f9
TT
220}
221
d62a17ae 222static void route_aspath_free(void *rule)
374f12f9 223{
d62a17ae 224 struct aspath *aspath = rule;
225 aspath_free(aspath);
374f12f9
TT
226}
227
8c3433e4
DS
228struct bgp_match_peer_compiled {
229 char *interface;
230 union sockunion su;
231};
232
233/* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
fee0f4c6 234
235/* Compares the peer specified in the 'match peer' clause with the peer
18ee8310 236 received in bgp_path_info->peer. If it is the same, or if the peer structure
fee0f4c6 237 received is a peer_group containing it, returns RMAP_MATCH. */
b68885f9 238static enum route_map_cmd_result_t
1782514f 239route_match_peer(void *rule, const struct prefix *prefix, void *object)
d62a17ae 240{
8c3433e4 241 struct bgp_match_peer_compiled *pc;
d62a17ae 242 union sockunion *su;
243 union sockunion su_def = {
244 .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
245 struct peer_group *group;
246 struct peer *peer;
247 struct listnode *node, *nnode;
248
1782514f
DS
249 pc = rule;
250 su = &pc->su;
251 peer = ((struct bgp_path_info *)object)->peer;
d62a17ae 252
1782514f 253 if (pc->interface) {
1bb1c0cf 254 if (!peer->conf_if || !peer->group)
1782514f 255 return RMAP_NOMATCH;
8c3433e4 256
1bb1c0cf
DS
257 if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
258 return RMAP_MATCH;
259
260 if (peer->group &&
261 strcmp(peer->group->name, pc->interface) == 0)
1782514f 262 return RMAP_MATCH;
8c3433e4 263
1782514f
DS
264 return RMAP_NOMATCH;
265 }
8c3433e4 266
1782514f
DS
267 /* If su='0.0.0.0' (command 'match peer local'), and it's a
268 NETWORK,
269 REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
270 => return RMAP_MATCH
271 */
272 if (sockunion_same(su, &su_def)) {
273 int ret;
274 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
275 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE)
276 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE)
277 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
278 ret = RMAP_MATCH;
279 else
280 ret = RMAP_NOMATCH;
281 return ret;
282 }
283
284 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
285 if (sockunion_same(su, &peer->su))
286 return RMAP_MATCH;
d62a17ae 287
1782514f
DS
288 return RMAP_NOMATCH;
289 } else {
290 group = peer->group;
291 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
d62a17ae 292 if (sockunion_same(su, &peer->su))
293 return RMAP_MATCH;
d62a17ae 294 }
1782514f 295 return RMAP_NOMATCH;
d62a17ae 296 }
1782514f 297
d62a17ae 298 return RMAP_NOMATCH;
299}
300
301static void *route_match_peer_compile(const char *arg)
302{
8c3433e4 303 struct bgp_match_peer_compiled *pc;
d62a17ae 304 int ret;
305
a633d869 306 pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
8c3433e4 307 sizeof(struct bgp_match_peer_compiled));
d62a17ae 308
8c3433e4 309 ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
d62a17ae 310 if (ret < 0) {
8c3433e4
DS
311 pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
312 return pc;
d62a17ae 313 }
314
8c3433e4 315 return pc;
fee0f4c6 316}
317
318/* Free route map's compiled `ip address' value. */
d62a17ae 319static void route_match_peer_free(void *rule)
fee0f4c6 320{
8c3433e4
DS
321 struct bgp_match_peer_compiled *pc = rule;
322
0a22ddfb 323 XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
8c3433e4 324
d62a17ae 325 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
fee0f4c6 326}
327
328/* Route map commands for ip address matching. */
364deb04
DL
329static const struct route_map_rule_cmd route_match_peer_cmd = {
330 "peer",
331 route_match_peer,
332 route_match_peer_compile,
333 route_match_peer_free
334};
fee0f4c6 335
fa22080d 336#ifdef HAVE_SCRIPTING
1d7c7ace 337
0fe6a43d 338enum frrlua_rm_status {
1d7c7ace 339 /*
b4becb06 340 * Script function run failure. This will translate into a deny
1d7c7ace 341 */
0fe6a43d 342 LUA_RM_FAILURE = 0,
1d7c7ace 343 /*
0fe6a43d 344 * No Match was found for the route map function
1d7c7ace 345 */
0fe6a43d 346 LUA_RM_NOMATCH,
1d7c7ace 347 /*
b4becb06 348 * Match was found but no changes were made to the incoming data.
1d7c7ace 349 */
0fe6a43d
QY
350 LUA_RM_MATCH,
351 /*
b4becb06 352 * Match was found and data was modified, so figure out what changed
0fe6a43d
QY
353 */
354 LUA_RM_MATCH_AND_CHANGE,
355};
356
b4becb06
QY
357static enum route_map_cmd_result_t
358route_match_script(void *rule, const struct prefix *prefix, void *object)
0fe6a43d 359{
b4becb06 360 const char *scriptname = rule;
0972af95 361 const char *routematch_function = "route_match";
b4becb06
QY
362 struct bgp_path_info *path = (struct bgp_path_info *)object;
363
bf938fdb 364 struct frrscript *fs = frrscript_new(scriptname);
0fe6a43d 365
0972af95 366 if (frrscript_load(fs, routematch_function, NULL)) {
bf938fdb 367 zlog_err(
bca62fe0 368 "Issue loading script or function; defaulting to no match");
b4becb06 369 return RMAP_NOMATCH;
0fe6a43d
QY
370 }
371
b16a58fc
DL
372 struct attr newattr = *path->attr;
373
fa2bb2e8 374 int result = frrscript_call(
62435f8c
DL
375 fs, routematch_function, ("prefix", prefix),
376 ("attributes", &newattr), ("peer", path->peer),
59a35b66
DL
377 ("RM_FAILURE", LUA_RM_FAILURE), ("RM_NOMATCH", LUA_RM_NOMATCH),
378 ("RM_MATCH", LUA_RM_MATCH),
379 ("RM_MATCH_AND_CHANGE", LUA_RM_MATCH_AND_CHANGE));
b4becb06
QY
380
381 if (result) {
382 zlog_err("Issue running script rule; defaulting to no match");
383 return RMAP_NOMATCH;
384 }
0fe6a43d 385
2ce634e2
DL
386 long long *action = frrscript_get_result(fs, routematch_function,
387 "action", lua_tointegerp);
0972af95 388
b4becb06 389 int status = RMAP_NOMATCH;
1d7c7ace 390
0972af95 391 switch (*action) {
1d7c7ace 392 case LUA_RM_FAILURE:
b4becb06
QY
393 zlog_err(
394 "Executing route-map match script '%s' failed; defaulting to no match",
395 scriptname);
396 status = RMAP_NOMATCH;
1d7c7ace
DS
397 break;
398 case LUA_RM_NOMATCH:
b4becb06 399 status = RMAP_NOMATCH;
1d7c7ace
DS
400 break;
401 case LUA_RM_MATCH_AND_CHANGE:
b4becb06
QY
402 status = RMAP_MATCH;
403 zlog_debug("Updating attribute based on script's values");
404
405 uint32_t locpref = 0;
b4becb06 406
b16a58fc 407 path->attr->med = newattr.med;
b4becb06 408
40381db7
DS
409 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
410 locpref = path->attr->local_pref;
b16a58fc 411 if (locpref != newattr.local_pref) {
b4becb06
QY
412 SET_FLAG(path->attr->flag,
413 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
b16a58fc 414 path->attr->local_pref = newattr.local_pref;
1d7c7ace 415 }
1d7c7ace
DS
416 break;
417 case LUA_RM_MATCH:
1d7c7ace
DS
418 status = RMAP_MATCH;
419 break;
420 }
b4becb06 421
78f1ac25 422 XFREE(MTYPE_SCRIPT_RES, action);
0972af95 423
64d457d7 424 frrscript_delete(fs);
b4becb06 425
1d7c7ace
DS
426 return status;
427}
428
b4becb06 429static void *route_match_script_compile(const char *arg)
1d7c7ace 430{
b4becb06
QY
431 char *scriptname;
432
433 scriptname = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1d7c7ace 434
b4becb06 435 return scriptname;
1d7c7ace
DS
436}
437
b4becb06 438static void route_match_script_free(void *rule)
1d7c7ace
DS
439{
440 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
441}
442
b4becb06
QY
443static const struct route_map_rule_cmd route_match_script_cmd = {
444 "script",
445 route_match_script,
446 route_match_script_compile,
447 route_match_script_free
1d7c7ace 448};
fa22080d
QY
449
450#endif /* HAVE_SCRIPTING */
1d7c7ace 451
718e3744 452/* `match ip address IP_ACCESS_LIST' */
453
454/* Match function should return 1 if match is success else return
455 zero. */
b68885f9 456static enum route_map_cmd_result_t
1782514f 457route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
d62a17ae 458{
459 struct access_list *alist;
d62a17ae 460
1782514f 461 if (prefix->family == AF_INET) {
d62a17ae 462 alist = access_list_lookup(AFI_IP, (char *)rule);
819547b2 463 if (alist == NULL) {
cc09ba45
DS
464 if (unlikely(CHECK_FLAG(rmap_debug,
465 DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
466 zlog_debug(
467 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
468 __func__, (char *)rule);
d62a17ae 469 return RMAP_NOMATCH;
819547b2 470 }
d62a17ae 471
472 return (access_list_apply(alist, prefix) == FILTER_DENY
473 ? RMAP_NOMATCH
474 : RMAP_MATCH);
475 }
718e3744 476 return RMAP_NOMATCH;
718e3744 477}
478
479/* Route map `ip address' match statement. `arg' should be
480 access-list name. */
d62a17ae 481static void *route_match_ip_address_compile(const char *arg)
718e3744 482{
b7d234f2
DS
483 struct access_list *alist;
484
485 alist = access_list_lookup(AFI_IP, arg);
486 if (!alist)
487 zlog_warn(
488 "Access List specified %s does not exist yet, default will be NO_MATCH until it is created",
489 arg);
d62a17ae 490 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 491}
492
493/* Free route map's compiled `ip address' value. */
d62a17ae 494static void route_match_ip_address_free(void *rule)
718e3744 495{
d62a17ae 496 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 497}
498
499/* Route map commands for ip address matching. */
364deb04
DL
500static const struct route_map_rule_cmd route_match_ip_address_cmd = {
501 "ip address",
502 route_match_ip_address,
503 route_match_ip_address_compile,
504 route_match_ip_address_free
505};
6b0655a2 506
b7d234f2 507/* `match ip next-hop <IP_ADDRESS_ACCESS_LIST_NAME>' */
718e3744 508
509/* Match function return 1 if match is success else return zero. */
b68885f9 510static enum route_map_cmd_result_t
1782514f 511route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
d62a17ae 512{
513 struct access_list *alist;
9b6d8fcf 514 struct bgp_path_info *path;
d62a17ae 515 struct prefix_ipv4 p;
516
1782514f 517 if (prefix->family == AF_INET) {
9b6d8fcf 518 path = object;
d62a17ae 519 p.family = AF_INET;
9b6d8fcf 520 p.prefix = path->attr->nexthop;
d62a17ae 521 p.prefixlen = IPV4_MAX_BITLEN;
522
523 alist = access_list_lookup(AFI_IP, (char *)rule);
819547b2 524 if (alist == NULL) {
cc09ba45
DS
525 if (unlikely(CHECK_FLAG(rmap_debug,
526 DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
527 zlog_debug(
528 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
529 __func__, (char *)rule);
530
d62a17ae 531 return RMAP_NOMATCH;
819547b2 532 }
d62a17ae 533
534 return (access_list_apply(alist, &p) == FILTER_DENY
535 ? RMAP_NOMATCH
536 : RMAP_MATCH);
537 }
718e3744 538 return RMAP_NOMATCH;
718e3744 539}
540
541/* Route map `ip next-hop' match statement. `arg' is
542 access-list name. */
d62a17ae 543static void *route_match_ip_next_hop_compile(const char *arg)
718e3744 544{
d62a17ae 545 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 546}
547
548/* Free route map's compiled `ip address' value. */
d62a17ae 549static void route_match_ip_next_hop_free(void *rule)
718e3744 550{
d62a17ae 551 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 552}
553
554/* Route map commands for ip next-hop matching. */
364deb04
DL
555static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
556 "ip next-hop",
557 route_match_ip_next_hop,
558 route_match_ip_next_hop_compile,
559 route_match_ip_next_hop_free
560};
6b0655a2 561
c1643bb7 562/* `match ip route-source ACCESS-LIST' */
563
564/* Match function return 1 if match is success else return zero. */
b68885f9 565static enum route_map_cmd_result_t
1782514f 566route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
d62a17ae 567{
568 struct access_list *alist;
9b6d8fcf 569 struct bgp_path_info *path;
d62a17ae 570 struct peer *peer;
571 struct prefix_ipv4 p;
572
1782514f 573 if (pfx->family == AF_INET) {
9b6d8fcf
DS
574 path = object;
575 peer = path->peer;
d62a17ae 576
577 if (!peer || sockunion_family(&peer->su) != AF_INET)
578 return RMAP_NOMATCH;
579
580 p.family = AF_INET;
581 p.prefix = peer->su.sin.sin_addr;
582 p.prefixlen = IPV4_MAX_BITLEN;
583
584 alist = access_list_lookup(AFI_IP, (char *)rule);
819547b2 585 if (alist == NULL) {
cc09ba45
DS
586 if (unlikely(CHECK_FLAG(rmap_debug,
587 DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
588 zlog_debug(
589 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
590 __func__, (char *)rule);
591
d62a17ae 592 return RMAP_NOMATCH;
819547b2 593 }
d62a17ae 594
595 return (access_list_apply(alist, &p) == FILTER_DENY
596 ? RMAP_NOMATCH
597 : RMAP_MATCH);
598 }
c1643bb7 599 return RMAP_NOMATCH;
c1643bb7 600}
601
602/* Route map `ip route-source' match statement. `arg' is
603 access-list name. */
d62a17ae 604static void *route_match_ip_route_source_compile(const char *arg)
c1643bb7 605{
d62a17ae 606 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 607}
608
609/* Free route map's compiled `ip address' value. */
d62a17ae 610static void route_match_ip_route_source_free(void *rule)
c1643bb7 611{
d62a17ae 612 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 613}
614
615/* Route map commands for ip route-source matching. */
364deb04
DL
616static const struct route_map_rule_cmd route_match_ip_route_source_cmd = {
617 "ip route-source",
618 route_match_ip_route_source,
619 route_match_ip_route_source_compile,
620 route_match_ip_route_source_free
621};
6b0655a2 622
b68885f9
LK
623static enum route_map_cmd_result_t
624route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
625 const struct prefix *p)
2e59405f
DS
626{
627 int ret;
628 struct bgp_pbr_entry_main api;
629
630 memset(&api, 0, sizeof(api));
631
1840384b
PG
632 if (family2afi(p->u.prefix_flowspec.family) != afi)
633 return RMAP_NOMATCH;
634
2e59405f
DS
635 /* extract match from flowspec entries */
636 ret = bgp_flowspec_match_rules_fill(
637 (uint8_t *)p->u.prefix_flowspec.ptr,
1840384b
PG
638 p->u.prefix_flowspec.prefixlen, &api,
639 afi);
2e59405f
DS
640 if (ret < 0)
641 return RMAP_NOMATCH;
642 if (api.match_bitmask & PREFIX_DST_PRESENT ||
643 api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
644 if (family2afi((&api.dst_prefix)->family) != afi)
645 return RMAP_NOMATCH;
646 return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
647 ? RMAP_NOMATCH
648 : RMAP_MATCH;
649 } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
650 api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
651 if (family2afi((&api.src_prefix)->family) != afi)
652 return RMAP_NOMATCH;
653 return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
654 ? RMAP_NOMATCH
655 : RMAP_MATCH);
656 }
657 return RMAP_NOMATCH;
658}
718e3744 659
6eb83505
SW
660static enum route_map_cmd_result_t
661route_match_prefix_list_evpn(afi_t afi, struct prefix_list *plist,
662 const struct prefix *p)
663{
664 /* Convert to match a general plist */
665 struct prefix new;
666
667 if (evpn_prefix2prefix(p, &new))
668 return RMAP_NOMATCH;
669
670 return (prefix_list_apply(plist, &new) == PREFIX_DENY ? RMAP_NOMATCH
671 : RMAP_MATCH);
672}
673
b68885f9 674static enum route_map_cmd_result_t
2e59405f 675route_match_address_prefix_list(void *rule, afi_t afi,
1782514f 676 const struct prefix *prefix, void *object)
718e3744 677{
d62a17ae 678 struct prefix_list *plist;
718e3744 679
2e59405f 680 plist = prefix_list_lookup(afi, (char *)rule);
2a3ffbb2 681 if (plist == NULL) {
cc09ba45 682 if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
2a3ffbb2
DS
683 zlog_debug(
684 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
685 __func__, (char *)rule);
2e59405f 686 return RMAP_NOMATCH;
2a3ffbb2 687 }
2e59405f
DS
688
689 if (prefix->family == AF_FLOWSPEC)
690 return route_match_prefix_list_flowspec(afi, plist,
691 prefix);
6eb83505
SW
692
693 else if (prefix->family == AF_EVPN)
694 return route_match_prefix_list_evpn(afi, plist, prefix);
695
2e59405f
DS
696 return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
697 : RMAP_MATCH);
698}
699
b68885f9 700static enum route_map_cmd_result_t
2e59405f 701route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1782514f 702 void *object)
2e59405f 703{
1782514f 704 return route_match_address_prefix_list(rule, AFI_IP, prefix, object);
718e3744 705}
706
d62a17ae 707static void *route_match_ip_address_prefix_list_compile(const char *arg)
718e3744 708{
d62a17ae 709 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 710}
711
d62a17ae 712static void route_match_ip_address_prefix_list_free(void *rule)
718e3744 713{
d62a17ae 714 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 715}
716
364deb04
DL
717static const struct route_map_rule_cmd
718 route_match_ip_address_prefix_list_cmd = {
719 "ip address prefix-list",
720 route_match_ip_address_prefix_list,
d62a17ae 721 route_match_ip_address_prefix_list_compile,
364deb04
DL
722 route_match_ip_address_prefix_list_free
723};
6b0655a2 724
718e3744 725/* `match ip next-hop prefix-list PREFIX_LIST' */
726
b68885f9 727static enum route_map_cmd_result_t
123214ef 728route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
1782514f 729 void *object)
718e3744 730{
d62a17ae 731 struct prefix_list *plist;
9b6d8fcf 732 struct bgp_path_info *path;
d62a17ae 733 struct prefix_ipv4 p;
718e3744 734
1782514f 735 if (prefix->family == AF_INET) {
9b6d8fcf 736 path = object;
d62a17ae 737 p.family = AF_INET;
9b6d8fcf 738 p.prefix = path->attr->nexthop;
d62a17ae 739 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 740
d62a17ae 741 plist = prefix_list_lookup(AFI_IP, (char *)rule);
2a3ffbb2 742 if (plist == NULL) {
cc09ba45
DS
743 if (unlikely(CHECK_FLAG(rmap_debug,
744 DEBUG_ROUTEMAP_DETAIL)))
2a3ffbb2
DS
745 zlog_debug(
746 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
747 __func__, (char *)rule);
d62a17ae 748 return RMAP_NOMATCH;
2a3ffbb2 749 }
718e3744 750
d62a17ae 751 return (prefix_list_apply(plist, &p) == PREFIX_DENY
752 ? RMAP_NOMATCH
753 : RMAP_MATCH);
754 }
755 return RMAP_NOMATCH;
718e3744 756}
757
d62a17ae 758static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
718e3744 759{
d62a17ae 760 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 761}
762
d62a17ae 763static void route_match_ip_next_hop_prefix_list_free(void *rule)
718e3744 764{
d62a17ae 765 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 766}
767
364deb04
DL
768static const struct route_map_rule_cmd
769 route_match_ip_next_hop_prefix_list_cmd = {
770 "ip next-hop prefix-list",
771 route_match_ip_next_hop_prefix_list,
d62a17ae 772 route_match_ip_next_hop_prefix_list_compile,
364deb04
DL
773 route_match_ip_next_hop_prefix_list_free
774};
6b0655a2 775
82f191a2
DA
776/* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
777static enum route_map_cmd_result_t
778route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
779 void *object)
780{
781 struct prefix_list *plist;
782 struct bgp_path_info *path;
783 struct prefix_ipv6 p;
784
785 if (prefix->family == AF_INET6) {
786 path = object;
787 p.family = AF_INET6;
788 p.prefix = path->attr->mp_nexthop_global;
789 p.prefixlen = IPV6_MAX_BITLEN;
790
791 plist = prefix_list_lookup(AFI_IP6, (char *)rule);
2a3ffbb2 792 if (!plist) {
cc09ba45
DS
793 if (unlikely(CHECK_FLAG(rmap_debug,
794 DEBUG_ROUTEMAP_DETAIL)))
2a3ffbb2
DS
795 zlog_debug(
796 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
797 __func__, (char *)rule);
82f191a2 798 return RMAP_NOMATCH;
2a3ffbb2 799 }
82f191a2
DA
800
801 if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
802 return RMAP_MATCH;
803
804 if (path->attr->mp_nexthop_len
805 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
806 p.prefix = path->attr->mp_nexthop_local;
807 if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
808 return RMAP_MATCH;
809 }
810 }
811
812 return RMAP_NOMATCH;
813}
814
815static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
816{
817 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
818}
819
820static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
821{
822 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
823}
824
825static const struct route_map_rule_cmd
826 route_match_ipv6_next_hop_prefix_list_cmd = {
827 "ipv6 next-hop prefix-list",
828 route_match_ipv6_next_hop_prefix_list,
829 route_match_ipv6_next_hop_prefix_list_compile,
830 route_match_ipv6_next_hop_prefix_list_free
831};
832
61ad901e
DA
833/* `match ip next-hop type <blackhole>' */
834
b68885f9 835static enum route_map_cmd_result_t
61ad901e 836route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
1782514f 837 void *object)
61ad901e 838{
9b6d8fcf 839 struct bgp_path_info *path;
61ad901e 840
1782514f 841 if (prefix->family == AF_INET) {
9b6d8fcf 842 path = (struct bgp_path_info *)object;
05864da7 843 if (!path)
b68885f9 844 return RMAP_NOMATCH;
61ad901e
DA
845
846 /* If nexthop interface's index can't be resolved and nexthop is
847 set to any address then mark it as type `blackhole`.
848 This logic works for matching kernel/static routes like:
849 `ip route add blackhole 10.0.0.1`. */
9b6d8fcf
DS
850 if (path->attr->nexthop.s_addr == INADDR_ANY
851 && !path->attr->nh_ifindex)
61ad901e
DA
852 return RMAP_MATCH;
853 }
854 return RMAP_NOMATCH;
855}
856
857static void *route_match_ip_next_hop_type_compile(const char *arg)
858{
859 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
860}
861
862static void route_match_ip_next_hop_type_free(void *rule)
863{
864 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
865}
866
364deb04
DL
867static const struct route_map_rule_cmd
868 route_match_ip_next_hop_type_cmd = {
869 "ip next-hop type",
870 route_match_ip_next_hop_type,
61ad901e 871 route_match_ip_next_hop_type_compile,
364deb04
DL
872 route_match_ip_next_hop_type_free
873};
61ad901e 874
c1643bb7 875/* `match ip route-source prefix-list PREFIX_LIST' */
876
b68885f9 877static enum route_map_cmd_result_t
1782514f
DS
878route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
879 void *object)
c1643bb7 880{
d62a17ae 881 struct prefix_list *plist;
9b6d8fcf 882 struct bgp_path_info *path;
d62a17ae 883 struct peer *peer;
884 struct prefix_ipv4 p;
c1643bb7 885
1782514f 886 if (prefix->family == AF_INET) {
9b6d8fcf
DS
887 path = object;
888 peer = path->peer;
c1643bb7 889
d62a17ae 890 if (!peer || sockunion_family(&peer->su) != AF_INET)
891 return RMAP_NOMATCH;
c1643bb7 892
d62a17ae 893 p.family = AF_INET;
894 p.prefix = peer->su.sin.sin_addr;
895 p.prefixlen = IPV4_MAX_BITLEN;
c1643bb7 896
d62a17ae 897 plist = prefix_list_lookup(AFI_IP, (char *)rule);
2a3ffbb2 898 if (plist == NULL) {
cc09ba45
DS
899 if (unlikely(CHECK_FLAG(rmap_debug,
900 DEBUG_ROUTEMAP_DETAIL)))
2a3ffbb2
DS
901 zlog_debug(
902 "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
903 __func__, (char *)rule);
d62a17ae 904 return RMAP_NOMATCH;
2a3ffbb2 905 }
c1643bb7 906
d62a17ae 907 return (prefix_list_apply(plist, &p) == PREFIX_DENY
908 ? RMAP_NOMATCH
909 : RMAP_MATCH);
910 }
911 return RMAP_NOMATCH;
c1643bb7 912}
913
d62a17ae 914static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
c1643bb7 915{
d62a17ae 916 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 917}
918
d62a17ae 919static void route_match_ip_route_source_prefix_list_free(void *rule)
c1643bb7 920{
d62a17ae 921 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 922}
923
364deb04
DL
924static const struct route_map_rule_cmd
925 route_match_ip_route_source_prefix_list_cmd = {
926 "ip route-source prefix-list",
927 route_match_ip_route_source_prefix_list,
d62a17ae 928 route_match_ip_route_source_prefix_list_compile,
364deb04
DL
929 route_match_ip_route_source_prefix_list_free
930};
6b0655a2 931
6fb219da
MK
932/* `match evpn default-route' */
933
934/* Match function should return 1 if match is success else 0 */
b68885f9 935static enum route_map_cmd_result_t
1782514f 936route_match_evpn_default_route(void *rule, const struct prefix *p, void *object)
6fb219da 937{
1782514f 938 if (is_evpn_prefix_default(p))
6fb219da
MK
939 return RMAP_MATCH;
940
941 return RMAP_NOMATCH;
942}
943
944/* Route map commands for default-route matching. */
364deb04
DL
945static const struct route_map_rule_cmd
946 route_match_evpn_default_route_cmd = {
947 "evpn default-route",
948 route_match_evpn_default_route,
949 NULL,
950 NULL
951};
6fb219da 952
d37ba549
MK
953/* `match mac address MAC_ACCESS_LIST' */
954
955/* Match function should return 1 if match is success else return
956 zero. */
b68885f9 957static enum route_map_cmd_result_t
1782514f 958route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
d37ba549
MK
959{
960 struct access_list *alist;
0f6476cc 961 struct prefix p;
d37ba549 962
1782514f 963 alist = access_list_lookup(AFI_L2VPN, (char *)rule);
819547b2 964 if (alist == NULL) {
cc09ba45 965 if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
966 zlog_debug(
967 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
968 __func__, (char *)rule);
d37ba549 969
1782514f 970 return RMAP_NOMATCH;
819547b2
DS
971 }
972 if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE) {
cc09ba45 973 if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
974 zlog_debug(
975 "%s: Prefix %pFX is not a EVPN MAC IP ROUTE defaulting to NO_MATCH",
976 __func__, prefix);
977 return RMAP_NOMATCH;
978 }
d37ba549 979
1782514f
DS
980 p.family = AF_ETHERNET;
981 p.prefixlen = ETH_ALEN * 8;
982 p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
0f6476cc 983
1782514f
DS
984 return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
985 : RMAP_MATCH);
d37ba549
MK
986}
987
988/* Route map `mac address' match statement. `arg' should be
989 access-list name. */
990static void *route_match_mac_address_compile(const char *arg)
991{
992 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
993}
994
995/* Free route map's compiled `ip address' value. */
996static void route_match_mac_address_free(void *rule)
997{
998 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
999}
1000
1001/* Route map commands for mac address matching. */
364deb04
DL
1002static const struct route_map_rule_cmd route_match_mac_address_cmd = {
1003 "mac address",
1004 route_match_mac_address,
1005 route_match_mac_address_compile,
1006 route_match_mac_address_free
1007};
d37ba549 1008
82b692c0
LK
1009/*
1010 * Match function returns:
1011 * ...RMAP_MATCH if match is found.
1012 * ...RMAP_NOMATCH if match is not found.
1013 * ...RMAP_NOOP to ignore this match check.
1014 */
b68885f9 1015static enum route_map_cmd_result_t
1782514f 1016route_match_vni(void *rule, const struct prefix *prefix, void *object)
16f7ce2b
MK
1017{
1018 vni_t vni = 0;
82b692c0 1019 unsigned int label_cnt = 0;
9b6d8fcf 1020 struct bgp_path_info *path = NULL;
82b692c0 1021 struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
16f7ce2b 1022
1782514f
DS
1023 vni = *((vni_t *)rule);
1024 path = (struct bgp_path_info *)object;
16f7ce2b 1025
1782514f
DS
1026 /*
1027 * This rmap filter is valid for vxlan tunnel type only.
1028 * For any other tunnel type, return noop to ignore
1029 * this check.
1030 */
1031 if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
1032 return RMAP_NOOP;
82b692c0 1033
1782514f
DS
1034 /*
1035 * Apply filter to type 1, 2, 5 routes only.
1036 * Other route types do not have vni label.
1037 */
1038 if (evp
1039 && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE
1040 && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
1041 && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
1042 return RMAP_NOOP;
82b692c0 1043
1782514f
DS
1044 if (path->extra == NULL)
1045 return RMAP_NOMATCH;
80ced710 1046
1782514f
DS
1047 for (;
1048 label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
1049 label_cnt++) {
1050 if (vni == label2vni(&path->extra->label[label_cnt]))
1051 return RMAP_MATCH;
16f7ce2b
MK
1052 }
1053
1054 return RMAP_NOMATCH;
1055}
1056
1057/* Route map `vni' match statement. */
1058static void *route_match_vni_compile(const char *arg)
1059{
1060 vni_t *vni = NULL;
1061 char *end = NULL;
1062
1063 vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
16f7ce2b
MK
1064
1065 *vni = strtoul(arg, &end, 10);
0af35d90
RW
1066 if (*end != '\0') {
1067 XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
16f7ce2b 1068 return NULL;
0af35d90 1069 }
16f7ce2b
MK
1070
1071 return vni;
1072}
1073
1074/* Free route map's compiled `vni' value. */
1075static void route_match_vni_free(void *rule)
1076{
1077 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1078}
1079
1080/* Route map commands for vni matching. */
364deb04
DL
1081static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
1082 "evpn vni",
1083 route_match_vni,
1084 route_match_vni_compile,
1085 route_match_vni_free
1086};
16f7ce2b 1087
33c2ff62
MK
1088/* `match evpn route-type' */
1089
1090/* Match function should return 1 if match is success else return
1091 zero. */
b68885f9 1092static enum route_map_cmd_result_t
1782514f 1093route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object)
33c2ff62 1094{
d7c0a89a 1095 uint8_t route_type = 0;
33c2ff62 1096
1782514f 1097 route_type = *((uint8_t *)rule);
33c2ff62 1098
1782514f
DS
1099 if (route_type == pfx->u.prefix_evpn.route_type)
1100 return RMAP_MATCH;
33c2ff62
MK
1101
1102 return RMAP_NOMATCH;
1103}
1104
1105/* Route map `route-type' match statement. */
1106static void *route_match_evpn_route_type_compile(const char *arg)
1107{
d7c0a89a 1108 uint8_t *route_type = NULL;
33c2ff62 1109
d7c0a89a 1110 route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
33c2ff62 1111
bd44ab08
CS
1112 if (strncmp(arg, "ea", 2) == 0)
1113 *route_type = BGP_EVPN_AD_ROUTE;
1114 else if (strncmp(arg, "ma", 2) == 0)
33c2ff62
MK
1115 *route_type = BGP_EVPN_MAC_IP_ROUTE;
1116 else if (strncmp(arg, "mu", 2) == 0)
1117 *route_type = BGP_EVPN_IMET_ROUTE;
2514d231
CS
1118 else if (strncmp(arg, "es", 2) == 0)
1119 *route_type = BGP_EVPN_ES_ROUTE;
33c2ff62
MK
1120 else
1121 *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
1122
1123 return route_type;
1124}
1125
1126/* Free route map's compiled `route-type' value. */
1127static void route_match_evpn_route_type_free(void *rule)
1128{
1129 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1130}
1131
1132/* Route map commands for evpn route-type matching. */
364deb04
DL
1133static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
1134 "evpn route-type",
1135 route_match_evpn_route_type,
1136 route_match_evpn_route_type_compile,
1137 route_match_evpn_route_type_free
1138};
33c2ff62 1139
196c6b09
LK
1140/* `match rd' */
1141
1142/* Match function should return 1 if match is success else return zero. */
1143static enum route_map_cmd_result_t
1782514f 1144route_match_rd(void *rule, const struct prefix *prefix, void *object)
196c6b09
LK
1145{
1146 struct prefix_rd *prd_rule = NULL;
b54892e0 1147 const struct prefix_rd *prd_route = NULL;
196c6b09
LK
1148 struct bgp_path_info *path = NULL;
1149
1782514f
DS
1150 if (prefix->family != AF_EVPN)
1151 return RMAP_NOMATCH;
196c6b09 1152
1782514f
DS
1153 prd_rule = (struct prefix_rd *)rule;
1154 path = (struct bgp_path_info *)object;
196c6b09 1155
1782514f
DS
1156 if (path->net == NULL || path->net->pdest == NULL)
1157 return RMAP_NOMATCH;
196c6b09 1158
1782514f
DS
1159 prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest);
1160 if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
1161 return RMAP_MATCH;
196c6b09
LK
1162
1163 return RMAP_NOMATCH;
1164}
1165
1166/* Route map `rd' match statement. */
1167static void *route_match_rd_compile(const char *arg)
1168{
1169 struct prefix_rd *prd;
1170 int ret;
1171
1172 prd = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct prefix_rd));
1173
1174 ret = str2prefix_rd(arg, prd);
1175 if (!ret) {
1176 XFREE(MTYPE_ROUTE_MAP_COMPILED, prd);
1177 return NULL;
1178 }
1179
1180 return prd;
1181}
1182
1183/* Free route map's compiled `rd' value. */
1184static void route_match_rd_free(void *rule)
1185{
1186 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1187}
1188
1189/* Route map commands for rd matching. */
364deb04
DL
1190static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
1191 "evpn rd",
1192 route_match_rd,
1193 route_match_rd_compile,
1194 route_match_rd_free
1195};
196c6b09 1196
d0a4ee60
AD
1197static enum route_map_cmd_result_t
1198route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
1199{
1200 struct ipaddr *gw_ip = rule;
1201 struct bgp_path_info *path;
1202 struct prefix_evpn *evp;
1203
1204 if (prefix->family != AF_EVPN)
1205 return RMAP_OKAY;
1206
1207 evp = (struct prefix_evpn *)prefix;
1208 if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
1209 return RMAP_OKAY;
1210
1211 if ((is_evpn_prefix_ipaddr_v4(evp) && IPADDRSZ(gw_ip) != 4)
1212 || (is_evpn_prefix_ipaddr_v6(evp) && IPADDRSZ(gw_ip) != 16))
1213 return RMAP_OKAY;
1214
1215 path = object;
1216
1217 /* Set gateway-ip value. */
1218 path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
1219 memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr,
1220 IPADDRSZ(gw_ip));
1221
1222 return RMAP_OKAY;
1223}
1224
1225/*
1226 * Route map `evpn gateway-ip' compile function.
1227 * Given string is converted to struct ipaddr structure
1228 */
1229static void *route_set_evpn_gateway_ip_compile(const char *arg)
1230{
1231 struct ipaddr *gw_ip = NULL;
1232 int ret;
1233
1234 gw_ip = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct ipaddr));
1235
1236 ret = str2ipaddr(arg, gw_ip);
1237 if (ret < 0) {
1238 XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
1239 return NULL;
1240 }
1241 return gw_ip;
1242}
1243
1244/* Free route map's compiled `evpn gateway_ip' value. */
1245static void route_set_evpn_gateway_ip_free(void *rule)
1246{
1247 struct ipaddr *gw_ip = rule;
1248
1249 XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
1250}
1251
1252/* Route map commands for set evpn gateway-ip ipv4. */
1253struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv4_cmd = {
1254 "evpn gateway-ip ipv4", route_set_evpn_gateway_ip,
1255 route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
1256
1257/* Route map commands for set evpn gateway-ip ipv6. */
1258struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv6_cmd = {
1259 "evpn gateway-ip ipv6", route_set_evpn_gateway_ip,
1260 route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
1261
1dcc9e5b 1262/* Route map commands for VRF route leak with source vrf matching */
b68885f9 1263static enum route_map_cmd_result_t
c3935045 1264route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
1782514f 1265 void *object)
1dcc9e5b
CS
1266{
1267 struct bgp_path_info *path;
1268 char *vrf_name;
1269
1782514f
DS
1270 vrf_name = rule;
1271 path = (struct bgp_path_info *)object;
1dcc9e5b 1272
1782514f
DS
1273 if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
1274 return RMAP_NOMATCH;
1dcc9e5b 1275
89c3ebe6 1276 if (path->extra == NULL || path->extra->bgp_orig == NULL)
1782514f 1277 return RMAP_NOMATCH;
1dcc9e5b 1278
1782514f
DS
1279 if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
1280 VRF_NAMSIZ)
1281 == 0)
1282 return RMAP_MATCH;
1dcc9e5b
CS
1283
1284 return RMAP_NOMATCH;
1285}
1286
1287static void *route_match_vrl_source_vrf_compile(const char *arg)
1288{
1289 uint8_t *vrf_name = NULL;
1290
1291 vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1292
1293 return vrf_name;
1294}
1295
1296/* Free route map's compiled `route-type' value. */
1297static void route_match_vrl_source_vrf_free(void *rule)
1298{
1299 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1300}
1301
364deb04
DL
1302static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
1303 "source-vrf",
1304 route_match_vrl_source_vrf,
1dcc9e5b 1305 route_match_vrl_source_vrf_compile,
364deb04
DL
1306 route_match_vrl_source_vrf_free
1307};
1dcc9e5b 1308
2690f18c
DA
1309/* `match alias` */
1310static enum route_map_cmd_result_t
1311route_match_alias(void *rule, const struct prefix *prefix, void *object)
1312{
1313 char *alias = rule;
1314 struct bgp_path_info *path = object;
1315 char **communities;
1316 int num;
1ca0a0bc 1317 bool found;
2690f18c 1318
9a706b42 1319 if (bgp_attr_get_community(path->attr)) {
1ca0a0bc 1320 found = false;
9a706b42
DA
1321 frrstr_split(bgp_attr_get_community(path->attr)->str, " ",
1322 &communities, &num);
2690f18c
DA
1323 for (int i = 0; i < num; i++) {
1324 const char *com2alias =
1325 bgp_community2alias(communities[i]);
1ca0a0bc
IR
1326 if (!found && strcmp(alias, com2alias) == 0)
1327 found = true;
1328 XFREE(MTYPE_TMP, communities[i]);
2690f18c 1329 }
1ca0a0bc
IR
1330 XFREE(MTYPE_TMP, communities);
1331 if (found)
1332 return RMAP_MATCH;
2690f18c
DA
1333 }
1334
1bcf3a96 1335 if (bgp_attr_get_lcommunity(path->attr)) {
1ca0a0bc 1336 found = false;
1bcf3a96
DA
1337 frrstr_split(bgp_attr_get_lcommunity(path->attr)->str, " ",
1338 &communities, &num);
2690f18c
DA
1339 for (int i = 0; i < num; i++) {
1340 const char *com2alias =
1341 bgp_community2alias(communities[i]);
1ca0a0bc 1342 if (!found && strcmp(alias, com2alias) == 0)
bd67b727 1343 found = true;
1ca0a0bc 1344 XFREE(MTYPE_TMP, communities[i]);
2690f18c 1345 }
1ca0a0bc
IR
1346 XFREE(MTYPE_TMP, communities);
1347 if (found)
1348 return RMAP_MATCH;
2690f18c
DA
1349 }
1350
1351 return RMAP_NOMATCH;
1352}
1353
1354static void *route_match_alias_compile(const char *arg)
1355{
1356
1357 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1358}
1359
1360static void route_match_alias_free(void *rule)
1361{
1362 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1363}
1364
1365static const struct route_map_rule_cmd route_match_alias_cmd = {
1366 "alias", route_match_alias, route_match_alias_compile,
1367 route_match_alias_free};
1368
af291c15
DS
1369/* `match local-preference LOCAL-PREF' */
1370
1371/* Match function return 1 if match is success else return zero. */
b68885f9 1372static enum route_map_cmd_result_t
1782514f 1373route_match_local_pref(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1374{
d7c0a89a 1375 uint32_t *local_pref;
9b6d8fcf 1376 struct bgp_path_info *path;
d62a17ae 1377
1782514f
DS
1378 local_pref = rule;
1379 path = object;
d62a17ae 1380
1782514f
DS
1381 if (path->attr->local_pref == *local_pref)
1382 return RMAP_MATCH;
1383 else
1384 return RMAP_NOMATCH;
af291c15
DS
1385}
1386
196c6b09
LK
1387/*
1388 * Route map `match local-preference' match statement.
1389 * `arg' is local-pref value
1390 */
d62a17ae 1391static void *route_match_local_pref_compile(const char *arg)
af291c15 1392{
d7c0a89a 1393 uint32_t *local_pref;
d62a17ae 1394 char *endptr = NULL;
1395 unsigned long tmpval;
af291c15 1396
d62a17ae 1397 errno = 0;
1398 tmpval = strtoul(arg, &endptr, 10);
1399 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1400 return NULL;
af291c15 1401
d7c0a89a 1402 local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
af291c15 1403
d62a17ae 1404 *local_pref = tmpval;
1405 return local_pref;
af291c15
DS
1406}
1407
1408/* Free route map's compiled `match local-preference' value. */
d62a17ae 1409static void route_match_local_pref_free(void *rule)
af291c15 1410{
d62a17ae 1411 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
af291c15
DS
1412}
1413
1414/* Route map commands for metric matching. */
364deb04
DL
1415static const struct route_map_rule_cmd route_match_local_pref_cmd = {
1416 "local-preference",
1417 route_match_local_pref,
1418 route_match_local_pref_compile,
1419 route_match_local_pref_free
1420};
af291c15 1421
718e3744 1422/* `match metric METRIC' */
1423
1424/* Match function return 1 if match is success else return zero. */
b68885f9 1425static enum route_map_cmd_result_t
1782514f 1426route_match_metric(void *rule, const struct prefix *prefix, void *object)
718e3744 1427{
d62a17ae 1428 struct rmap_value *rv;
9b6d8fcf 1429 struct bgp_path_info *path;
718e3744 1430
1782514f
DS
1431 rv = rule;
1432 path = object;
1433 return route_value_match(rv, path->attr->med);
718e3744 1434}
1435
718e3744 1436/* Route map commands for metric matching. */
364deb04
DL
1437static const struct route_map_rule_cmd route_match_metric_cmd = {
1438 "metric",
1439 route_match_metric,
1440 route_value_compile,
1441 route_value_free,
718e3744 1442};
6b0655a2 1443
718e3744 1444/* `match as-path ASPATH' */
1445
1446/* Match function for as-path match. I assume given object is */
b68885f9 1447static enum route_map_cmd_result_t
1782514f 1448route_match_aspath(void *rule, const struct prefix *prefix, void *object)
718e3744 1449{
e52702f2 1450
d62a17ae 1451 struct as_list *as_list;
9b6d8fcf 1452 struct bgp_path_info *path;
718e3744 1453
1782514f
DS
1454 as_list = as_list_lookup((char *)rule);
1455 if (as_list == NULL)
1456 return RMAP_NOMATCH;
518f0eb1 1457
1782514f 1458 path = object;
518f0eb1 1459
1782514f
DS
1460 /* Perform match. */
1461 return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY)
1462 ? RMAP_NOMATCH
1463 : RMAP_MATCH);
718e3744 1464}
1465
1466/* Compile function for as-path match. */
d62a17ae 1467static void *route_match_aspath_compile(const char *arg)
718e3744 1468{
d62a17ae 1469 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 1470}
1471
1472/* Compile function for as-path match. */
d62a17ae 1473static void route_match_aspath_free(void *rule)
718e3744 1474{
d62a17ae 1475 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1476}
1477
1478/* Route map commands for aspath matching. */
364deb04
DL
1479static const struct route_map_rule_cmd route_match_aspath_cmd = {
1480 "as-path",
1481 route_match_aspath,
1482 route_match_aspath_compile,
1483 route_match_aspath_free
1484};
6b0655a2 1485
718e3744 1486/* `match community COMMUNIY' */
d62a17ae 1487struct rmap_community {
1488 char *name;
e237b0d2 1489 uint32_t name_hash;
d62a17ae 1490 int exact;
718e3744 1491};
1492
1493/* Match function for community match. */
b68885f9 1494static enum route_map_cmd_result_t
1782514f 1495route_match_community(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1496{
1497 struct community_list *list;
9b6d8fcf 1498 struct bgp_path_info *path;
e9a223ac 1499 struct rmap_community *rcom = rule;
d62a17ae 1500
1782514f
DS
1501 path = object;
1502 rcom = rule;
d62a17ae 1503
1782514f
DS
1504 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1505 COMMUNITY_LIST_MASTER);
1506 if (!list)
1507 return RMAP_NOMATCH;
d62a17ae 1508
1782514f 1509 if (rcom->exact) {
9a706b42
DA
1510 if (community_list_exact_match(
1511 bgp_attr_get_community(path->attr), list))
1782514f
DS
1512 return RMAP_MATCH;
1513 } else {
9a706b42
DA
1514 if (community_list_match(bgp_attr_get_community(path->attr),
1515 list))
1782514f 1516 return RMAP_MATCH;
718e3744 1517 }
1782514f 1518
d62a17ae 1519 return RMAP_NOMATCH;
718e3744 1520}
1521
1522/* Compile function for community match. */
d62a17ae 1523static void *route_match_community_compile(const char *arg)
1524{
1525 struct rmap_community *rcom;
1526 int len;
1527 char *p;
1528
1529 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1530
1531 p = strchr(arg, ' ');
1532 if (p) {
1533 len = p - arg;
1534 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1535 memcpy(rcom->name, arg, len);
1536 rcom->exact = 1;
1537 } else {
1538 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1539 rcom->exact = 0;
1540 }
e237b0d2
DS
1541
1542 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1543 return rcom;
718e3744 1544}
1545
1546/* Compile function for community match. */
d62a17ae 1547static void route_match_community_free(void *rule)
718e3744 1548{
d62a17ae 1549 struct rmap_community *rcom = rule;
718e3744 1550
d62a17ae 1551 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1552 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 1553}
1554
909f3d56 1555/*
1556 * In routemap processing there is a need to add the
1557 * name as a rule_key in the dependency table. Routemap
1558 * lib is unaware of rule_key when exact-match clause
1559 * is in use. routemap lib uses the compiled output to
1560 * get the rule_key value.
1561 */
1562static void *route_match_get_community_key(void *rule)
1563{
1564 struct rmap_community *rcom;
1565
1566 rcom = rule;
1567 return rcom->name;
1568}
1569
1570
718e3744 1571/* Route map commands for community matching. */
364deb04
DL
1572static const struct route_map_rule_cmd route_match_community_cmd = {
1573 "community",
1574 route_match_community,
1575 route_match_community_compile,
1576 route_match_community_free,
1577 route_match_get_community_key
1578};
6b0655a2 1579
57d187bc 1580/* Match function for lcommunity match. */
b68885f9 1581static enum route_map_cmd_result_t
1782514f 1582route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1583{
1584 struct community_list *list;
9b6d8fcf 1585 struct bgp_path_info *path;
e9a223ac 1586 struct rmap_community *rcom = rule;
d62a17ae 1587
1782514f 1588 path = object;
d62a17ae 1589
1782514f
DS
1590 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1591 LARGE_COMMUNITY_LIST_MASTER);
1592 if (!list)
1593 return RMAP_NOMATCH;
d62a17ae 1594
1782514f 1595 if (rcom->exact) {
1bcf3a96
DA
1596 if (lcommunity_list_exact_match(
1597 bgp_attr_get_lcommunity(path->attr), list))
1782514f
DS
1598 return RMAP_MATCH;
1599 } else {
1bcf3a96
DA
1600 if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
1601 list))
1782514f 1602 return RMAP_MATCH;
d62a17ae 1603 }
1782514f 1604
d62a17ae 1605 return RMAP_NOMATCH;
57d187bc
JS
1606}
1607
1608/* Compile function for community match. */
d62a17ae 1609static void *route_match_lcommunity_compile(const char *arg)
1610{
1611 struct rmap_community *rcom;
1612 int len;
1613 char *p;
1614
1615 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1616
1617 p = strchr(arg, ' ');
1618 if (p) {
1619 len = p - arg;
1620 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1621 memcpy(rcom->name, arg, len);
03ff9a14 1622 rcom->exact = 1;
d62a17ae 1623 } else {
1624 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1625 rcom->exact = 0;
1626 }
e237b0d2
DS
1627
1628 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1629 return rcom;
57d187bc
JS
1630}
1631
1632/* Compile function for community match. */
d62a17ae 1633static void route_match_lcommunity_free(void *rule)
57d187bc 1634{
d62a17ae 1635 struct rmap_community *rcom = rule;
57d187bc 1636
d62a17ae 1637 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1638 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
1639}
1640
1641/* Route map commands for community matching. */
364deb04
DL
1642static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
1643 "large-community",
1644 route_match_lcommunity,
1645 route_match_lcommunity_compile,
1646 route_match_lcommunity_free,
1647 route_match_get_community_key
1648};
57d187bc
JS
1649
1650
73ffb25b 1651/* Match function for extcommunity match. */
b68885f9 1652static enum route_map_cmd_result_t
1782514f 1653route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
73ffb25b 1654{
d62a17ae 1655 struct community_list *list;
9b6d8fcf 1656 struct bgp_path_info *path;
e9a223ac 1657 struct rmap_community *rcom = rule;
73ffb25b 1658
1782514f 1659 path = object;
e52702f2 1660
1782514f
DS
1661 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1662 EXTCOMMUNITY_LIST_MASTER);
1663 if (!list)
1664 return RMAP_NOMATCH;
1665
b53e67a3 1666 if (ecommunity_list_match(bgp_attr_get_ecommunity(path->attr), list))
1782514f 1667 return RMAP_MATCH;
73ffb25b 1668
d62a17ae 1669 return RMAP_NOMATCH;
73ffb25b 1670}
1671
1672/* Compile function for extcommunity match. */
d62a17ae 1673static void *route_match_ecommunity_compile(const char *arg)
73ffb25b 1674{
e9a223ac
DS
1675 struct rmap_community *rcom;
1676
1677 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1678 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
e237b0d2 1679 rcom->name_hash = bgp_clist_hash_key(rcom->name);
e9a223ac
DS
1680
1681 return rcom;
73ffb25b 1682}
1683
1684/* Compile function for extcommunity match. */
d62a17ae 1685static void route_match_ecommunity_free(void *rule)
73ffb25b 1686{
e9a223ac
DS
1687 struct rmap_community *rcom = rule;
1688
1689 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1690 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
73ffb25b 1691}
1692
1693/* Route map commands for community matching. */
364deb04
DL
1694static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
1695 "extcommunity",
1696 route_match_ecommunity,
1697 route_match_ecommunity_compile,
1698 route_match_ecommunity_free
1699};
6b0655a2 1700
718e3744 1701/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1702 and `address-family vpnv4'. */
6b0655a2 1703
718e3744 1704/* `match origin' */
b68885f9 1705static enum route_map_cmd_result_t
1782514f 1706route_match_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 1707{
d7c0a89a 1708 uint8_t *origin;
9b6d8fcf 1709 struct bgp_path_info *path;
718e3744 1710
1782514f
DS
1711 origin = rule;
1712 path = object;
e52702f2 1713
1782514f
DS
1714 if (path->attr->origin == *origin)
1715 return RMAP_MATCH;
718e3744 1716
d62a17ae 1717 return RMAP_NOMATCH;
718e3744 1718}
1719
d62a17ae 1720static void *route_match_origin_compile(const char *arg)
718e3744 1721{
d7c0a89a 1722 uint8_t *origin;
718e3744 1723
d7c0a89a 1724 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 1725
d62a17ae 1726 if (strcmp(arg, "igp") == 0)
1727 *origin = 0;
1728 else if (strcmp(arg, "egp") == 0)
1729 *origin = 1;
1730 else
1731 *origin = 2;
718e3744 1732
d62a17ae 1733 return origin;
718e3744 1734}
1735
1736/* Free route map's compiled `ip address' value. */
d62a17ae 1737static void route_match_origin_free(void *rule)
718e3744 1738{
d62a17ae 1739 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1740}
1741
1742/* Route map commands for origin matching. */
364deb04
DL
1743static const struct route_map_rule_cmd route_match_origin_cmd = {
1744 "origin",
1745 route_match_origin,
1746 route_match_origin_compile,
1747 route_match_origin_free
1748};
1add115a
VT
1749
1750/* match probability { */
1751
b68885f9 1752static enum route_map_cmd_result_t
1782514f 1753route_match_probability(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1754{
5920b3eb 1755 long r = frr_weak_random();
d62a17ae 1756
1757 switch (*(long *)rule) {
1758 case 0:
1759 break;
1760 case RAND_MAX:
1761 return RMAP_MATCH;
1762 default:
1763 if (r < *(long *)rule) {
1764 return RMAP_MATCH;
1765 }
1766 }
1add115a 1767
d62a17ae 1768 return RMAP_NOMATCH;
1add115a
VT
1769}
1770
d62a17ae 1771static void *route_match_probability_compile(const char *arg)
1add115a 1772{
d62a17ae 1773 long *lobule;
1774 unsigned perc;
1add115a 1775
d62a17ae 1776 perc = atoi(arg);
1777 lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1add115a 1778
d62a17ae 1779 switch (perc) {
1780 case 0:
1781 *lobule = 0;
1782 break;
1783 case 100:
1784 *lobule = RAND_MAX;
1785 break;
1786 default:
1787 *lobule = RAND_MAX / 100 * perc;
1788 }
1add115a 1789
d62a17ae 1790 return lobule;
1add115a
VT
1791}
1792
d62a17ae 1793static void route_match_probability_free(void *rule)
1add115a 1794{
d62a17ae 1795 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1add115a
VT
1796}
1797
364deb04
DL
1798static const struct route_map_rule_cmd route_match_probability_cmd = {
1799 "probability",
1800 route_match_probability,
1801 route_match_probability_compile,
1802 route_match_probability_free
1803};
1add115a 1804
bc413143
DS
1805/* `match interface IFNAME' */
1806/* Match function should return 1 if match is success else return
1807 zero. */
b68885f9 1808static enum route_map_cmd_result_t
1782514f 1809route_match_interface(void *rule, const struct prefix *prefix, void *object)
bc413143 1810{
d62a17ae 1811 struct interface *ifp;
40381db7 1812 struct bgp_path_info *path;
bc413143 1813
1782514f 1814 path = object;
bc413143 1815
de4f1a66 1816 if (!path || !path->peer || !path->peer->bgp)
1782514f 1817 return RMAP_NOMATCH;
bc413143 1818
de4f1a66 1819 ifp = if_lookup_by_name((char *)rule, path->peer->bgp->vrf_id);
bc413143 1820
1782514f
DS
1821 if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
1822 return RMAP_NOMATCH;
bc413143 1823
1782514f 1824 return RMAP_MATCH;
bc413143
DS
1825}
1826
1827/* Route map `interface' match statement. `arg' should be
1828 interface name. */
d62a17ae 1829static void *route_match_interface_compile(const char *arg)
bc413143 1830{
d62a17ae 1831 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
bc413143
DS
1832}
1833
1834/* Free route map's compiled `interface' value. */
d62a17ae 1835static void route_match_interface_free(void *rule)
bc413143 1836{
d62a17ae 1837 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
bc413143
DS
1838}
1839
1840/* Route map commands for ip address matching. */
364deb04
DL
1841static const struct route_map_rule_cmd route_match_interface_cmd = {
1842 "interface",
1843 route_match_interface,
1844 route_match_interface_compile,
1845 route_match_interface_free
1846};
bc413143 1847
1add115a
VT
1848/* } */
1849
718e3744 1850/* `set ip next-hop IP_ADDRESS' */
1851
0d9551dc 1852/* Match function return 1 if match is success else return zero. */
b68885f9 1853static enum route_map_cmd_result_t
1782514f 1854route_match_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 1855{
d62a17ae 1856 route_tag_t *tag;
9b6d8fcf 1857 struct bgp_path_info *path;
0d9551dc 1858
1782514f
DS
1859 tag = rule;
1860 path = object;
0d9551dc 1861
1782514f 1862 return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
0d9551dc
DS
1863}
1864
1865
0d9551dc 1866/* Route map commands for tag matching. */
364deb04
DL
1867static const struct route_map_rule_cmd route_match_tag_cmd = {
1868 "tag",
1869 route_match_tag,
1870 route_map_rule_tag_compile,
d62a17ae 1871 route_map_rule_tag_free,
0d9551dc
DS
1872};
1873
ef3e0d04 1874static enum route_map_cmd_result_t
1782514f 1875route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
ef3e0d04
SM
1876{
1877 uint32_t *srte_color = rule;
1878 struct bgp_path_info *path;
1879
ef3e0d04
SM
1880 path = object;
1881
1882 path->attr->srte_color = *srte_color;
1883 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
1884
1885 return RMAP_OKAY;
1886}
1887
1888/* Route map `sr-te color' compile function */
1889static void *route_set_srte_color_compile(const char *arg)
1890{
1891 uint32_t *color;
1892
1893 color = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1894 *color = atoi(arg);
1895
1896 return color;
1897}
1898
1899/* Free route map's compiled `sr-te color' value. */
1900static void route_set_srte_color_free(void *rule)
1901{
1902 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1903}
1904
1905/* Route map commands for sr-te color set. */
1906struct route_map_rule_cmd route_set_srte_color_cmd = {
1907 "sr-te color", route_set_srte_color, route_set_srte_color_compile,
1908 route_set_srte_color_free};
0d9551dc 1909
581776fa 1910/* Set nexthop to object. object must be pointer to struct attr. */
d62a17ae 1911struct rmap_ip_nexthop_set {
1912 struct in_addr *address;
1913 int peer_address;
1914 int unchanged;
ac41b2a2 1915};
1916
b68885f9 1917static enum route_map_cmd_result_t
1782514f 1918route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1919{
1920 struct rmap_ip_nexthop_set *rins = rule;
9b6d8fcf 1921 struct bgp_path_info *path;
d62a17ae 1922 struct peer *peer;
1923
77f4dfb9
DS
1924 if (prefix->family == AF_INET6)
1925 return RMAP_OKAY;
1926
2b67b6f1
DS
1927 path = object;
1928 peer = path->peer;
1929
1930 if (rins->unchanged) {
1931 SET_FLAG(path->attr->rmap_change_flags,
1932 BATTR_RMAP_NEXTHOP_UNCHANGED);
1933 } else if (rins->peer_address) {
1934 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1935 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1936 && peer->su_remote
1937 && sockunion_family(peer->su_remote) == AF_INET) {
1938 path->attr->nexthop.s_addr =
1939 sockunion2ip(peer->su_remote);
9b6d8fcf 1940 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
2b67b6f1
DS
1941 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
1942 /* The next hop value will be set as part of
1943 * packet rewrite. Set the flags here to indicate
1944 * that rewrite needs to be done.
1945 * Also, clear the value.
1946 */
9b6d8fcf 1947 SET_FLAG(path->attr->rmap_change_flags,
2b67b6f1 1948 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
975a328e 1949 path->attr->nexthop.s_addr = INADDR_ANY;
d62a17ae 1950 }
2b67b6f1
DS
1951 } else {
1952 /* Set next hop value. */
1953 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1954 path->attr->nexthop = *rins->address;
1955 SET_FLAG(path->attr->rmap_change_flags,
1956 BATTR_RMAP_IPV4_NHOP_CHANGED);
1957 /* case for MP-BGP : MPLS VPN */
1958 path->attr->mp_nexthop_global_in = *rins->address;
1959 path->attr->mp_nexthop_len = sizeof(*rins->address);
ac41b2a2 1960 }
718e3744 1961
d62a17ae 1962 return RMAP_OKAY;
718e3744 1963}
1964
1965/* Route map `ip nexthop' compile function. Given string is converted
1966 to struct in_addr structure. */
d62a17ae 1967static void *route_set_ip_nexthop_compile(const char *arg)
1968{
1969 struct rmap_ip_nexthop_set *rins;
1970 struct in_addr *address = NULL;
1971 int peer_address = 0;
1972 int unchanged = 0;
1973 int ret;
1974
1975 if (strcmp(arg, "peer-address") == 0)
1976 peer_address = 1;
1977 else if (strcmp(arg, "unchanged") == 0)
1978 unchanged = 1;
1979 else {
1980 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
1981 sizeof(struct in_addr));
1982 ret = inet_aton(arg, address);
1983
1984 if (ret == 0) {
1985 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
1986 return NULL;
1987 }
ac41b2a2 1988 }
718e3744 1989
d62a17ae 1990 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
1991 sizeof(struct rmap_ip_nexthop_set));
ac41b2a2 1992
d62a17ae 1993 rins->address = address;
1994 rins->peer_address = peer_address;
1995 rins->unchanged = unchanged;
ac41b2a2 1996
d62a17ae 1997 return rins;
718e3744 1998}
1999
2000/* Free route map's compiled `ip nexthop' value. */
d62a17ae 2001static void route_set_ip_nexthop_free(void *rule)
718e3744 2002{
d62a17ae 2003 struct rmap_ip_nexthop_set *rins = rule;
ac41b2a2 2004
0a22ddfb 2005 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
e52702f2 2006
d62a17ae 2007 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
718e3744 2008}
2009
2010/* Route map commands for ip nexthop set. */
364deb04
DL
2011static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
2012 "ip next-hop",
2013 route_set_ip_nexthop,
2014 route_set_ip_nexthop_compile,
2015 route_set_ip_nexthop_free
2016};
6b0655a2 2017
1bb550b6
PG
2018/* `set l3vpn next-hop encapsulation l3vpn gre' */
2019
2020/* Set nexthop to object */
2021struct rmap_l3vpn_nexthop_encapsulation_set {
2022 uint8_t protocol;
2023};
2024
2025static enum route_map_cmd_result_t
2026route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,
2027 void *object)
2028{
2029 struct rmap_l3vpn_nexthop_encapsulation_set *rins = rule;
2030 struct bgp_path_info *path;
2031
2032 path = object;
2033
2034 if (rins->protocol != IPPROTO_GRE)
2035 return RMAP_OKAY;
2036
2037 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
2038 return RMAP_OKAY;
2039}
2040
2041/* Route map `l3vpn nexthop encapsulation' compile function. */
2042static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
2043{
2044 struct rmap_l3vpn_nexthop_encapsulation_set *rins;
2045
2046 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2047 sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));
2048
2049 /* XXX ALL GRE modes are accepted for now: gre or ip6gre */
2050 rins->protocol = IPPROTO_GRE;
2051
2052 return rins;
2053}
2054
2055/* Free route map's compiled `ip nexthop' value. */
2056static void route_set_l3vpn_nexthop_encapsulation_free(void *rule)
2057{
2058 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2059}
2060
2061/* Route map commands for l3vpn next-hop encapsulation set. */
2062static const struct route_map_rule_cmd
2063 route_set_l3vpn_nexthop_encapsulation_cmd = {
2064 "l3vpn next-hop encapsulation",
2065 route_set_l3vpn_nexthop_encapsulation,
2066 route_set_l3vpn_nexthop_encapsulation_compile,
2067 route_set_l3vpn_nexthop_encapsulation_free};
2068
718e3744 2069/* `set local-preference LOCAL_PREF' */
2070
2071/* Set local preference. */
b68885f9 2072static enum route_map_cmd_result_t
1782514f 2073route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2074{
2075 struct rmap_value *rv;
9b6d8fcf 2076 struct bgp_path_info *path;
d7c0a89a 2077 uint32_t locpref = 0;
d62a17ae 2078
1782514f
DS
2079 /* Fetch routemap's rule information. */
2080 rv = rule;
2081 path = object;
d62a17ae 2082
1782514f 2083 /* Set local preference value. */
0f05ea43 2084 if (path->attr->local_pref)
1782514f 2085 locpref = path->attr->local_pref;
d62a17ae 2086
1782514f
DS
2087 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2088 path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
718e3744 2089
d62a17ae 2090 return RMAP_OKAY;
718e3744 2091}
2092
718e3744 2093/* Set local preference rule structure. */
364deb04
DL
2094static const struct route_map_rule_cmd route_set_local_pref_cmd = {
2095 "local-preference",
2096 route_set_local_pref,
2097 route_value_compile,
d62a17ae 2098 route_value_free,
718e3744 2099};
6b0655a2 2100
718e3744 2101/* `set weight WEIGHT' */
2102
2103/* Set weight. */
b68885f9 2104static enum route_map_cmd_result_t
1782514f 2105route_set_weight(void *rule, const struct prefix *prefix, void *object)
718e3744 2106{
d62a17ae 2107 struct rmap_value *rv;
9b6d8fcf 2108 struct bgp_path_info *path;
718e3744 2109
1782514f
DS
2110 /* Fetch routemap's rule information. */
2111 rv = rule;
2112 path = object;
e52702f2 2113
1782514f
DS
2114 /* Set weight value. */
2115 path->attr->weight = route_value_adjust(rv, 0, path->peer);
718e3744 2116
d62a17ae 2117 return RMAP_OKAY;
718e3744 2118}
2119
718e3744 2120/* Set local preference rule structure. */
364deb04
DL
2121static const struct route_map_rule_cmd route_set_weight_cmd = {
2122 "weight",
2123 route_set_weight,
2124 route_value_compile,
2125 route_value_free,
718e3744 2126};
6b0655a2 2127
7b7d48e5
DS
2128/* `set distance DISTANCE */
2129static enum route_map_cmd_result_t
1782514f 2130route_set_distance(void *rule, const struct prefix *prefix, void *object)
7b7d48e5
DS
2131{
2132 struct bgp_path_info *path = object;
2133 struct rmap_value *rv = rule;
2134
7b7d48e5
DS
2135 path->attr->distance = rv->value;
2136
2137 return RMAP_OKAY;
2138}
2139
2140/* set distance rule structure */
364deb04 2141static const struct route_map_rule_cmd route_set_distance_cmd = {
7b7d48e5
DS
2142 "distance",
2143 route_set_distance,
2144 route_value_compile,
2145 route_value_free,
2146};
2147
718e3744 2148/* `set metric METRIC' */
2149
2150/* Set metric to attribute. */
b68885f9 2151static enum route_map_cmd_result_t
1782514f 2152route_set_metric(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2153{
2154 struct rmap_value *rv;
9b6d8fcf 2155 struct bgp_path_info *path;
d7c0a89a 2156 uint32_t med = 0;
d62a17ae 2157
1782514f
DS
2158 /* Fetch routemap's rule information. */
2159 rv = rule;
2160 path = object;
d62a17ae 2161
1782514f
DS
2162 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
2163 med = path->attr->med;
2164
2165 path->attr->med = route_value_adjust(rv, med, path->peer);
2166 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
d62a17ae 2167
d62a17ae 2168 return RMAP_OKAY;
718e3744 2169}
2170
718e3744 2171/* Set metric rule structure. */
364deb04
DL
2172static const struct route_map_rule_cmd route_set_metric_cmd = {
2173 "metric",
2174 route_set_metric,
2175 route_value_compile,
2176 route_value_free,
718e3744 2177};
6b0655a2 2178
951745bd
PG
2179/* `set table (1-4294967295)' */
2180
1782514f
DS
2181static enum route_map_cmd_result_t
2182route_set_table_id(void *rule, const struct prefix *prefix,
2183
2184 void *object)
951745bd
PG
2185{
2186 struct rmap_value *rv;
2187 struct bgp_path_info *path;
2188
1782514f
DS
2189 /* Fetch routemap's rule information. */
2190 rv = rule;
2191 path = object;
2192
2193 path->attr->rmap_table_id = rv->value;
951745bd 2194
951745bd
PG
2195 return RMAP_OKAY;
2196}
2197
2198/* Set table_id rule structure. */
364deb04
DL
2199static const struct route_map_rule_cmd route_set_table_id_cmd = {
2200 "table",
2201 route_set_table_id,
2202 route_value_compile,
2203 route_value_free
951745bd
PG
2204};
2205
718e3744 2206/* `set as-path prepend ASPATH' */
2207
2208/* For AS path prepend mechanism. */
b68885f9 2209static enum route_map_cmd_result_t
1782514f 2210route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2211{
2212 struct aspath *aspath;
2213 struct aspath *new;
9b6d8fcf 2214 struct bgp_path_info *path;
d62a17ae 2215
1782514f 2216 path = object;
d62a17ae 2217
1782514f
DS
2218 if (path->attr->aspath->refcnt)
2219 new = aspath_dup(path->attr->aspath);
2220 else
2221 new = path->attr->aspath;
bc3dd427 2222
1782514f
DS
2223 if ((uintptr_t)rule > 10) {
2224 aspath = rule;
2225 aspath_prepend(aspath, new);
2226 } else {
2227 as_t as = aspath_leftmost(new);
6ba0adac
DS
2228 if (as)
2229 new = aspath_add_seq_n(new, as, (uintptr_t)rule);
d62a17ae 2230 }
718e3744 2231
1782514f
DS
2232 path->attr->aspath = new;
2233
d62a17ae 2234 return RMAP_OKAY;
718e3744 2235}
2236
d62a17ae 2237static void *route_set_aspath_prepend_compile(const char *arg)
bc3dd427 2238{
d62a17ae 2239 unsigned int num;
bc3dd427 2240
d62a17ae 2241 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
2242 return (void *)(uintptr_t)num;
bc3dd427 2243
d62a17ae 2244 return route_aspath_compile(arg);
bc3dd427
DW
2245}
2246
d62a17ae 2247static void route_set_aspath_prepend_free(void *rule)
bc3dd427 2248{
d62a17ae 2249 if ((uintptr_t)rule > 10)
2250 route_aspath_free(rule);
bc3dd427
DW
2251}
2252
2253
515e500c 2254/* Set as-path prepend rule structure. */
364deb04
DL
2255static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
2256 "as-path prepend",
2257 route_set_aspath_prepend,
2258 route_set_aspath_prepend_compile,
2259 route_set_aspath_prepend_free,
718e3744 2260};
6b0655a2 2261
841f7a57
DO
2262/* `set as-path exclude ASn' */
2263
2264/* For ASN exclude mechanism.
d62a17ae 2265 * Iterate over ASns requested and filter them from the given AS_PATH one by
2266 * one.
841f7a57
DO
2267 * Make a deep copy of existing AS_PATH, but for the first ASn only.
2268 */
b68885f9 2269static enum route_map_cmd_result_t
1782514f 2270route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
d62a17ae 2271{
2272 struct aspath *new_path, *exclude_path;
9b6d8fcf 2273 struct bgp_path_info *path;
d62a17ae 2274
1782514f
DS
2275 exclude_path = rule;
2276 path = object;
2277 if (path->attr->aspath->refcnt)
2278 new_path = aspath_dup(path->attr->aspath);
2279 else
2280 new_path = path->attr->aspath;
2281 path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
2282
d62a17ae 2283 return RMAP_OKAY;
841f7a57
DO
2284}
2285
841f7a57 2286/* Set ASn exlude rule structure. */
364deb04
DL
2287static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2288 "as-path exclude",
2289 route_set_aspath_exclude,
2290 route_aspath_compile,
d62a17ae 2291 route_aspath_free,
841f7a57 2292};
6b0655a2 2293
77e3d821
DA
2294/* `set as-path replace AS-PATH` */
2295static void *route_aspath_replace_compile(const char *arg)
2296{
2297 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
2298}
2299
2300static void route_aspath_replace_free(void *rule)
2301{
2302 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2303}
2304
2305static enum route_map_cmd_result_t
2306route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
2307{
2308 struct aspath *aspath_new;
2309 const char *replace = rule;
2310 struct bgp_path_info *path = object;
2311 as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
2312 : path->peer->local_as;
2313
2314 if (path->peer->sort != BGP_PEER_EBGP) {
2315 zlog_warn(
2316 "`set as-path replace` is supported only for EBGP peers");
2317 return RMAP_NOOP;
2318 }
2319
2320 if (path->attr->aspath->refcnt)
2321 aspath_new = aspath_dup(path->attr->aspath);
2322 else
2323 aspath_new = path->attr->aspath;
2324
2325 if (strmatch(replace, "any")) {
2326 path->attr->aspath =
2327 aspath_replace_all_asn(aspath_new, own_asn);
2328 } else {
2329 as_t replace_asn = strtoul(replace, NULL, 10);
2330
2331 path->attr->aspath = aspath_replace_specific_asn(
2332 aspath_new, replace_asn, own_asn);
2333 }
2334
67a9da92
DA
2335 aspath_free(aspath_new);
2336
77e3d821
DA
2337 return RMAP_OKAY;
2338}
2339
2340static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
2341 "as-path replace",
2342 route_set_aspath_replace,
2343 route_aspath_replace_compile,
2344 route_aspath_replace_free,
2345};
2346
718e3744 2347/* `set community COMMUNITY' */
d62a17ae 2348struct rmap_com_set {
2349 struct community *com;
2350 int additive;
2351 int none;
718e3744 2352};
2353
2354/* For community set mechanism. */
b68885f9 2355static enum route_map_cmd_result_t
1782514f 2356route_set_community(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2357{
2358 struct rmap_com_set *rcs;
9b6d8fcf 2359 struct bgp_path_info *path;
d62a17ae 2360 struct attr *attr;
2361 struct community *new = NULL;
2362 struct community *old;
2363 struct community *merge;
2364
1782514f
DS
2365 rcs = rule;
2366 path = object;
2367 attr = path->attr;
9a706b42 2368 old = bgp_attr_get_community(attr);
1782514f
DS
2369
2370 /* "none" case. */
2371 if (rcs->none) {
9a706b42 2372 bgp_attr_set_community(attr, NULL);
1782514f
DS
2373 /* See the longer comment down below. */
2374 if (old && old->refcnt == 0)
2375 community_free(&old);
2376 return RMAP_OKAY;
2377 }
718e3744 2378
1782514f
DS
2379 /* "additive" case. */
2380 if (rcs->additive && old) {
2381 merge = community_merge(community_dup(old), rcs->com);
d62a17ae 2382
1782514f
DS
2383 new = community_uniq_sort(merge);
2384 community_free(&merge);
2385 } else
2386 new = community_dup(rcs->com);
d62a17ae 2387
1782514f
DS
2388 /* HACK: if the old community is not intern'd,
2389 * we should free it here, or all reference to it may be
2390 * lost.
2391 * Really need to cleanup attribute caching sometime.
2392 */
2393 if (old && old->refcnt == 0)
2394 community_free(&old);
f24804f4 2395
1782514f 2396 /* will be interned by caller if required */
9a706b42 2397 bgp_attr_set_community(attr, new);
d62a17ae 2398
d62a17ae 2399 return RMAP_OKAY;
718e3744 2400}
2401
2402/* Compile function for set community. */
d62a17ae 2403static void *route_set_community_compile(const char *arg)
2404{
2405 struct rmap_com_set *rcs;
2406 struct community *com = NULL;
2407 char *sp;
2408 int additive = 0;
2409 int none = 0;
2410
2411 if (strcmp(arg, "none") == 0)
2412 none = 1;
2413 else {
2414 sp = strstr(arg, "additive");
2415
2416 if (sp && sp > arg) {
770817b4 2417 /* "additive" keyword is included. */
d62a17ae 2418 additive = 1;
2419 *(sp - 1) = '\0';
2420 }
718e3744 2421
d62a17ae 2422 com = community_str2com(arg);
718e3744 2423
d62a17ae 2424 if (additive)
2425 *(sp - 1) = ' ';
718e3744 2426
d62a17ae 2427 if (!com)
2428 return NULL;
2429 }
e52702f2 2430
d62a17ae 2431 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2432 rcs->com = com;
2433 rcs->additive = additive;
2434 rcs->none = none;
e52702f2 2435
d62a17ae 2436 return rcs;
718e3744 2437}
2438
2439/* Free function for set community. */
d62a17ae 2440static void route_set_community_free(void *rule)
718e3744 2441{
d62a17ae 2442 struct rmap_com_set *rcs = rule;
718e3744 2443
d62a17ae 2444 if (rcs->com)
3c1f53de 2445 community_free(&rcs->com);
d62a17ae 2446 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2447}
2448
2449/* Set community rule structure. */
364deb04
DL
2450static const struct route_map_rule_cmd route_set_community_cmd = {
2451 "community",
2452 route_set_community,
2453 route_set_community_compile,
d62a17ae 2454 route_set_community_free,
718e3744 2455};
6b0655a2 2456
57d187bc 2457/* `set community COMMUNITY' */
d62a17ae 2458struct rmap_lcom_set {
2459 struct lcommunity *lcom;
2460 int additive;
2461 int none;
57d187bc
JS
2462};
2463
2464
2465/* For lcommunity set mechanism. */
b68885f9 2466static enum route_map_cmd_result_t
1782514f 2467route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2468{
2469 struct rmap_lcom_set *rcs;
9b6d8fcf 2470 struct bgp_path_info *path;
d62a17ae 2471 struct attr *attr;
2472 struct lcommunity *new = NULL;
2473 struct lcommunity *old;
2474 struct lcommunity *merge;
2475
1782514f
DS
2476 rcs = rule;
2477 path = object;
2478 attr = path->attr;
1bcf3a96 2479 old = bgp_attr_get_lcommunity(attr);
d62a17ae 2480
1782514f
DS
2481 /* "none" case. */
2482 if (rcs->none) {
1bcf3a96 2483 bgp_attr_set_lcommunity(attr, NULL);
d62a17ae 2484
1782514f 2485 /* See the longer comment down below. */
4265a53e
NK
2486 if (old && old->refcnt == 0)
2487 lcommunity_free(&old);
1782514f
DS
2488 return RMAP_OKAY;
2489 }
4265a53e 2490
1782514f
DS
2491 if (rcs->additive && old) {
2492 merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
d62a17ae 2493
1782514f
DS
2494 new = lcommunity_uniq_sort(merge);
2495 lcommunity_free(&merge);
2496 } else
2497 new = lcommunity_dup(rcs->lcom);
2498
2499 /* HACK: if the old large-community is not intern'd,
2500 * we should free it here, or all reference to it may be
2501 * lost.
2502 * Really need to cleanup attribute caching sometime.
2503 */
2504 if (old && old->refcnt == 0)
2505 lcommunity_free(&old);
2506
2507 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1bcf3a96 2508 bgp_attr_set_lcommunity(attr, new);
1782514f 2509
d62a17ae 2510 return RMAP_OKAY;
2511}
57d187bc 2512
d62a17ae 2513/* Compile function for set community. */
2514static void *route_set_lcommunity_compile(const char *arg)
2515{
2516 struct rmap_lcom_set *rcs;
2517 struct lcommunity *lcom = NULL;
2518 char *sp;
2519 int additive = 0;
2520 int none = 0;
2521
2522 if (strcmp(arg, "none") == 0)
2523 none = 1;
2524 else {
2525 sp = strstr(arg, "additive");
2526
2527 if (sp && sp > arg) {
2528 /* "additive" keyworkd is included. */
2529 additive = 1;
2530 *(sp - 1) = '\0';
2531 }
57d187bc 2532
d62a17ae 2533 lcom = lcommunity_str2com(arg);
57d187bc 2534
d62a17ae 2535 if (additive)
2536 *(sp - 1) = ' ';
57d187bc 2537
d62a17ae 2538 if (!lcom)
2539 return NULL;
2540 }
57d187bc 2541
d62a17ae 2542 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2543 rcs->lcom = lcom;
2544 rcs->additive = additive;
2545 rcs->none = none;
57d187bc 2546
d62a17ae 2547 return rcs;
57d187bc
JS
2548}
2549
2550/* Free function for set lcommunity. */
d62a17ae 2551static void route_set_lcommunity_free(void *rule)
57d187bc 2552{
d62a17ae 2553 struct rmap_lcom_set *rcs = rule;
57d187bc 2554
d62a17ae 2555 if (rcs->lcom) {
2556 lcommunity_free(&rcs->lcom);
2557 }
2558 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
57d187bc
JS
2559}
2560
2561/* Set community rule structure. */
364deb04
DL
2562static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2563 "large-community",
2564 route_set_lcommunity,
2565 route_set_lcommunity_compile,
d62a17ae 2566 route_set_lcommunity_free,
57d187bc
JS
2567};
2568
2569/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2570
2571/* For large community set mechanism. */
b68885f9 2572static enum route_map_cmd_result_t
1782514f 2573route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
d62a17ae 2574{
2575 struct community_list *list;
2576 struct lcommunity *merge;
2577 struct lcommunity *new;
2578 struct lcommunity *old;
9b6d8fcf 2579 struct bgp_path_info *path;
e9a223ac 2580 struct rmap_community *rcom = rule;
d62a17ae 2581
1782514f
DS
2582 if (!rcom)
2583 return RMAP_OKAY;
d62a17ae 2584
1782514f
DS
2585 path = object;
2586 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2587 LARGE_COMMUNITY_LIST_MASTER);
1bcf3a96 2588 old = bgp_attr_get_lcommunity(path->attr);
1782514f
DS
2589
2590 if (list && old) {
2591 merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
2592 new = lcommunity_uniq_sort(merge);
2593 lcommunity_free(&merge);
2594
2595 /* HACK: if the old community is not intern'd,
2596 * we should free it here, or all reference to it may be
2597 * lost.
2598 * Really need to cleanup attribute caching sometime.
2599 */
2600 if (old->refcnt == 0)
2601 lcommunity_free(&old);
2602
2603 if (new->size == 0) {
1bcf3a96 2604 bgp_attr_set_lcommunity(path->attr, NULL);
1782514f
DS
2605 lcommunity_free(&new);
2606 } else {
1bcf3a96 2607 bgp_attr_set_lcommunity(path->attr, new);
d62a17ae 2608 }
2609 }
2610
2611 return RMAP_OKAY;
57d187bc
JS
2612}
2613
2614/* Compile function for set lcommunity. */
d62a17ae 2615static void *route_set_lcommunity_delete_compile(const char *arg)
57d187bc 2616{
e9a223ac 2617 struct rmap_community *rcom;
caa5af30
DA
2618 char **splits;
2619 int num;
57d187bc 2620
caa5af30 2621 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2622
caa5af30
DA
2623 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2624 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2625 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2626
caa5af30
DA
2627 for (int i = 0; i < num; i++)
2628 XFREE(MTYPE_TMP, splits[i]);
2629 XFREE(MTYPE_TMP, splits);
2630
e9a223ac 2631 return rcom;
57d187bc
JS
2632}
2633
2634/* Free function for set lcommunity. */
d62a17ae 2635static void route_set_lcommunity_delete_free(void *rule)
57d187bc 2636{
e9a223ac
DS
2637 struct rmap_community *rcom = rule;
2638
2639 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2640 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
2641}
2642
2643/* Set lcommunity rule structure. */
364deb04
DL
2644static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2645 "large-comm-list",
2646 route_set_lcommunity_delete,
2647 route_set_lcommunity_delete_compile,
2648 route_set_lcommunity_delete_free,
57d187bc
JS
2649};
2650
2651
fee6e4e4 2652/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 2653
2654/* For community set mechanism. */
b68885f9
LK
2655static enum route_map_cmd_result_t
2656route_set_community_delete(void *rule, const struct prefix *prefix,
1782514f 2657 void *object)
d62a17ae 2658{
2659 struct community_list *list;
2660 struct community *merge;
2661 struct community *new;
2662 struct community *old;
9b6d8fcf 2663 struct bgp_path_info *path;
e9a223ac 2664 struct rmap_community *rcom = rule;
d62a17ae 2665
1782514f
DS
2666 if (!rcom)
2667 return RMAP_OKAY;
d62a17ae 2668
1782514f
DS
2669 path = object;
2670 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2671 COMMUNITY_LIST_MASTER);
9a706b42 2672 old = bgp_attr_get_community(path->attr);
1782514f
DS
2673
2674 if (list && old) {
2675 merge = community_list_match_delete(community_dup(old), list);
2676 new = community_uniq_sort(merge);
2677 community_free(&merge);
2678
2679 /* HACK: if the old community is not intern'd,
2680 * we should free it here, or all reference to it may be
2681 * lost.
2682 * Really need to cleanup attribute caching sometime.
2683 */
2684 if (old->refcnt == 0)
2685 community_free(&old);
2686
2687 if (new->size == 0) {
9a706b42 2688 bgp_attr_set_community(path->attr, NULL);
1782514f
DS
2689 community_free(&new);
2690 } else {
9a706b42 2691 bgp_attr_set_community(path->attr, new);
d62a17ae 2692 }
718e3744 2693 }
718e3744 2694
d62a17ae 2695 return RMAP_OKAY;
718e3744 2696}
2697
2698/* Compile function for set community. */
d62a17ae 2699static void *route_set_community_delete_compile(const char *arg)
718e3744 2700{
e9a223ac 2701 struct rmap_community *rcom;
60762f8f
DA
2702 char **splits;
2703 int num;
718e3744 2704
60762f8f 2705 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2706
60762f8f
DA
2707 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2708 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2709 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2710
60762f8f
DA
2711 for (int i = 0; i < num; i++)
2712 XFREE(MTYPE_TMP, splits[i]);
2713 XFREE(MTYPE_TMP, splits);
2714
e9a223ac 2715 return rcom;
718e3744 2716}
2717
2718/* Free function for set community. */
d62a17ae 2719static void route_set_community_delete_free(void *rule)
718e3744 2720{
e9a223ac
DS
2721 struct rmap_community *rcom = rule;
2722
2723 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2724 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 2725}
2726
2727/* Set community rule structure. */
364deb04
DL
2728static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2729 "comm-list",
2730 route_set_community_delete,
2731 route_set_community_delete_compile,
2732 route_set_community_delete_free,
718e3744 2733};
6b0655a2 2734
718e3744 2735/* `set extcommunity rt COMMUNITY' */
2736
bb4dcdd1
DA
2737struct rmap_ecom_set {
2738 struct ecommunity *ecom;
2739 bool none;
2740};
2741
73d78ea0 2742/* For community set mechanism. Used by _rt and _soo. */
b68885f9 2743static enum route_map_cmd_result_t
1782514f 2744route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2745{
bb4dcdd1 2746 struct rmap_ecom_set *rcs;
d62a17ae 2747 struct ecommunity *new_ecom;
2748 struct ecommunity *old_ecom;
9b6d8fcf 2749 struct bgp_path_info *path;
bb4dcdd1 2750 struct attr *attr;
d62a17ae 2751
bb4dcdd1 2752 rcs = rule;
1782514f 2753 path = object;
bb4dcdd1 2754 attr = path->attr;
d62a17ae 2755
bb4dcdd1 2756 if (rcs->none) {
b53e67a3 2757 bgp_attr_set_ecommunity(attr, NULL);
bb4dcdd1
DA
2758 return RMAP_OKAY;
2759 }
2760
2761 if (!rcs->ecom)
1782514f 2762 return RMAP_OKAY;
d62a17ae 2763
1782514f 2764 /* We assume additive for Extended Community. */
b53e67a3 2765 old_ecom = bgp_attr_get_ecommunity(path->attr);
1782514f
DS
2766
2767 if (old_ecom) {
bb4dcdd1
DA
2768 new_ecom =
2769 ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
d62a17ae 2770
1782514f
DS
2771 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2772 * bgp_update_receive()
2773 * ->refcnt = 0 => set by a previous route-map
2774 * statement */
2775 if (!old_ecom->refcnt)
2776 ecommunity_free(&old_ecom);
2777 } else
bb4dcdd1 2778 new_ecom = ecommunity_dup(rcs->ecom);
d62a17ae 2779
1782514f 2780 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
b53e67a3 2781 bgp_attr_set_ecommunity(path->attr, new_ecom);
d62a17ae 2782
d62a17ae 2783 return RMAP_OKAY;
718e3744 2784}
2785
bb4dcdd1
DA
2786static void *route_set_ecommunity_none_compile(const char *arg)
2787{
2788 struct rmap_ecom_set *rcs;
2789 bool none = false;
2790
2791 if (strncmp(arg, "none", 4) == 0)
2792 none = true;
2793
2794 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2795 rcs->ecom = NULL;
2796 rcs->none = none;
2797
2798 return rcs;
2799}
2800
d62a17ae 2801static void *route_set_ecommunity_rt_compile(const char *arg)
718e3744 2802{
bb4dcdd1 2803 struct rmap_ecom_set *rcs;
d62a17ae 2804 struct ecommunity *ecom;
718e3744 2805
d62a17ae 2806 ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2807 if (!ecom)
2808 return NULL;
bb4dcdd1
DA
2809
2810 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2811 rcs->ecom = ecommunity_intern(ecom);
2812 rcs->none = false;
2813
2814 return rcs;
718e3744 2815}
2816
73d78ea0 2817/* Free function for set community. Used by _rt and _soo */
d62a17ae 2818static void route_set_ecommunity_free(void *rule)
718e3744 2819{
bb4dcdd1
DA
2820 struct rmap_ecom_set *rcs = rule;
2821
2822 if (rcs->ecom)
2823 ecommunity_unintern(&rcs->ecom);
2824
2825 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2826}
2827
bb4dcdd1
DA
2828static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
2829 "extcommunity",
2830 route_set_ecommunity,
2831 route_set_ecommunity_none_compile,
2832 route_set_ecommunity_free,
2833};
2834
718e3744 2835/* Set community rule structure. */
364deb04
DL
2836static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2837 "extcommunity rt",
2838 route_set_ecommunity,
2839 route_set_ecommunity_rt_compile,
2840 route_set_ecommunity_free,
718e3744 2841};
2842
2843/* `set extcommunity soo COMMUNITY' */
2844
718e3744 2845/* Compile function for set community. */
d62a17ae 2846static void *route_set_ecommunity_soo_compile(const char *arg)
718e3744 2847{
bb4dcdd1 2848 struct rmap_ecom_set *rcs;
d62a17ae 2849 struct ecommunity *ecom;
718e3744 2850
d62a17ae 2851 ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2852 if (!ecom)
2853 return NULL;
e52702f2 2854
bb4dcdd1
DA
2855 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2856 rcs->ecom = ecommunity_intern(ecom);
2857 rcs->none = false;
2858
2859 return rcs;
718e3744 2860}
2861
718e3744 2862/* Set community rule structure. */
364deb04
DL
2863static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2864 "extcommunity soo",
2865 route_set_ecommunity,
2866 route_set_ecommunity_soo_compile,
2867 route_set_ecommunity_free,
718e3744 2868};
6b0655a2 2869
c9a25614
DA
2870static void *route_set_ecommunity_nt_compile(const char *arg)
2871{
2872 struct rmap_ecom_set *rcs;
2873 struct ecommunity *ecom;
2874
2875 ecom = ecommunity_str2com(arg, ECOMMUNITY_NODE_TARGET, 0);
2876 if (!ecom)
2877 return NULL;
2878
2879 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2880 rcs->ecom = ecommunity_intern(ecom);
2881 rcs->none = false;
2882
2883 return rcs;
2884}
2885
2886static const struct route_map_rule_cmd route_set_ecommunity_nt_cmd = {
2887 "extcommunity nt",
2888 route_set_ecommunity,
2889 route_set_ecommunity_nt_compile,
2890 route_set_ecommunity_free,
2891};
2892
ca9ac3ef 2893/* `set extcommunity bandwidth' */
2894
2895struct rmap_ecomm_lb_set {
2896 uint8_t lb_type;
2897#define RMAP_ECOMM_LB_SET_VALUE 1
2898#define RMAP_ECOMM_LB_SET_CUMUL 2
2899#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2900 bool non_trans;
2901 uint32_t bw;
2902};
2903
2904static enum route_map_cmd_result_t
1782514f 2905route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
ca9ac3ef 2906{
2907 struct rmap_ecomm_lb_set *rels = rule;
2908 struct bgp_path_info *path;
2909 struct peer *peer;
2910 struct ecommunity ecom_lb = {0};
2911 struct ecommunity_val lb_eval;
2912 uint32_t bw_bytes = 0;
b1875e65 2913 uint16_t mpath_count = 0;
ca9ac3ef 2914 struct ecommunity *new_ecom;
2915 struct ecommunity *old_ecom;
2916 as_t as;
2917
ca9ac3ef 2918 path = object;
2919 peer = path->peer;
2920 if (!peer || !peer->bgp)
2921 return RMAP_ERROR;
2922
2923 /* Build link bandwidth extended community */
2924 as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
b1875e65 2925 if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
87b42e3b 2926 bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
b1875e65 2927 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2928 /* process this only for the best path. */
2929 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2930 return RMAP_OKAY;
2931
2932 bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2933 if (!bw_bytes)
2934 return RMAP_OKAY;
2935
2936 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2937
2938 /* process this only for the best path. */
2939 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2940 return RMAP_OKAY;
2941
87b42e3b 2942 bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
b1875e65 2943 mpath_count = bgp_path_info_mpath_count(path) + 1;
2944 bw_bytes *= mpath_count;
2945 }
ca9ac3ef 2946
27aa23a4
DA
2947 encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
2948 CHECK_FLAG(peer->flags,
2949 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
ca9ac3ef 2950
2951 /* add to route or merge with existing */
b53e67a3 2952 old_ecom = bgp_attr_get_ecommunity(path->attr);
ca9ac3ef 2953 if (old_ecom) {
f6ca545a 2954 new_ecom = ecommunity_dup(old_ecom);
2955 ecommunity_add_val(new_ecom, &lb_eval, true, true);
ca9ac3ef 2956 if (!old_ecom->refcnt)
2957 ecommunity_free(&old_ecom);
f6ca545a 2958 } else {
2959 ecom_lb.size = 1;
7659ad68 2960 ecom_lb.unit_size = ECOMMUNITY_SIZE;
f6ca545a 2961 ecom_lb.val = (uint8_t *)lb_eval.val;
ca9ac3ef 2962 new_ecom = ecommunity_dup(&ecom_lb);
f6ca545a 2963 }
ca9ac3ef 2964
2965 /* new_ecom will be intern()'d or attr_flush()'d in call stack */
b53e67a3 2966 bgp_attr_set_ecommunity(path->attr, new_ecom);
ca9ac3ef 2967
7b651a32 2968 /* Mark that route-map has set link bandwidth; used in attribute
2969 * setting decisions.
2970 */
2971 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
ca9ac3ef 2972
2973 return RMAP_OKAY;
2974}
2975
2976static void *route_set_ecommunity_lb_compile(const char *arg)
2977{
2978 struct rmap_ecomm_lb_set *rels;
2979 uint8_t lb_type;
2980 uint32_t bw = 0;
4c13ffe4 2981 char bw_str[40] = {0};
2982 char *p, *str;
2983 bool non_trans = false;
ca9ac3ef 2984
4c13ffe4 2985 str = (char *)arg;
2986 p = strchr(arg, ' ');
2987 if (p) {
2988 int len;
2989
2990 len = p - arg;
2991 memcpy(bw_str, arg, len);
2992 non_trans = true;
2993 str = bw_str;
2994 }
2995
2996 if (strcmp(str, "cumulative") == 0)
ca9ac3ef 2997 lb_type = RMAP_ECOMM_LB_SET_CUMUL;
4c13ffe4 2998 else if (strcmp(str, "num-multipaths") == 0)
ca9ac3ef 2999 lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
3000 else {
3001 char *end = NULL;
3002
4c13ffe4 3003 bw = strtoul(str, &end, 10);
ca9ac3ef 3004 if (*end != '\0')
3005 return NULL;
3006 lb_type = RMAP_ECOMM_LB_SET_VALUE;
3007 }
3008
3009 rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
3010 sizeof(struct rmap_ecomm_lb_set));
3011 rels->lb_type = lb_type;
3012 rels->bw = bw;
4c13ffe4 3013 rels->non_trans = non_trans;
ca9ac3ef 3014
3015 return rels;
3016}
3017
3018static void route_set_ecommunity_lb_free(void *rule)
3019{
3020 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3021}
3022
3023/* Set community rule structure. */
3024struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
3025 "extcommunity bandwidth",
3026 route_set_ecommunity_lb,
3027 route_set_ecommunity_lb_compile,
3028 route_set_ecommunity_lb_free,
3029};
3030
718e3744 3031/* `set origin ORIGIN' */
3032
3033/* For origin set. */
b68885f9 3034static enum route_map_cmd_result_t
1782514f 3035route_set_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 3036{
d7c0a89a 3037 uint8_t *origin;
9b6d8fcf 3038 struct bgp_path_info *path;
718e3744 3039
1782514f
DS
3040 origin = rule;
3041 path = object;
e52702f2 3042
1782514f 3043 path->attr->origin = *origin;
718e3744 3044
d62a17ae 3045 return RMAP_OKAY;
718e3744 3046}
3047
3048/* Compile function for origin set. */
d62a17ae 3049static void *route_set_origin_compile(const char *arg)
718e3744 3050{
d7c0a89a 3051 uint8_t *origin;
718e3744 3052
d7c0a89a 3053 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 3054
d62a17ae 3055 if (strcmp(arg, "igp") == 0)
1aa8aef3 3056 *origin = BGP_ORIGIN_IGP;
d62a17ae 3057 else if (strcmp(arg, "egp") == 0)
1aa8aef3 3058 *origin = BGP_ORIGIN_EGP;
d62a17ae 3059 else
1aa8aef3 3060 *origin = BGP_ORIGIN_INCOMPLETE;
718e3744 3061
d62a17ae 3062 return origin;
718e3744 3063}
3064
3065/* Compile function for origin set. */
d62a17ae 3066static void route_set_origin_free(void *rule)
718e3744 3067{
d62a17ae 3068 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3069}
3070
515e500c 3071/* Set origin rule structure. */
364deb04
DL
3072static const struct route_map_rule_cmd route_set_origin_cmd = {
3073 "origin",
3074 route_set_origin,
3075 route_set_origin_compile,
d62a17ae 3076 route_set_origin_free,
718e3744 3077};
6b0655a2 3078
718e3744 3079/* `set atomic-aggregate' */
3080
3081/* For atomic aggregate set. */
b68885f9 3082static enum route_map_cmd_result_t
1782514f 3083route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
718e3744 3084{
9b6d8fcf 3085 struct bgp_path_info *path;
718e3744 3086
1782514f
DS
3087 path = object;
3088 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
718e3744 3089
d62a17ae 3090 return RMAP_OKAY;
718e3744 3091}
3092
3093/* Compile function for atomic aggregate. */
d62a17ae 3094static void *route_set_atomic_aggregate_compile(const char *arg)
718e3744 3095{
d62a17ae 3096 return (void *)1;
718e3744 3097}
3098
3099/* Compile function for atomic aggregate. */
d62a17ae 3100static void route_set_atomic_aggregate_free(void *rule)
718e3744 3101{
d62a17ae 3102 return;
718e3744 3103}
3104
3105/* Set atomic aggregate rule structure. */
364deb04
DL
3106static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
3107 "atomic-aggregate",
3108 route_set_atomic_aggregate,
3109 route_set_atomic_aggregate_compile,
3110 route_set_atomic_aggregate_free,
718e3744 3111};
6b0655a2 3112
97a52c82
DA
3113/* AIGP TLV Metric */
3114static enum route_map_cmd_result_t
3115route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
3116{
3117 const char *aigp_metric = rule;
3118 struct bgp_path_info *path = object;
3119 uint32_t aigp = 0;
3120
3121 if (strmatch(aigp_metric, "igp-metric")) {
3122 if (!path->nexthop)
3123 return RMAP_NOMATCH;
3124
3125 bgp_attr_set_aigp_metric(path->attr, path->nexthop->metric);
3126 } else {
3127 aigp = atoi(aigp_metric);
3128 bgp_attr_set_aigp_metric(path->attr, aigp);
3129 }
3130
3131 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP);
3132
3133 return RMAP_OKAY;
3134}
3135
3136static void *route_set_aigp_metric_compile(const char *arg)
3137{
3138 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3139}
3140
3141static void route_set_aigp_metric_free(void *rule)
3142{
3143 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3144}
3145
3146static const struct route_map_rule_cmd route_set_aigp_metric_cmd = {
3147 "aigp-metric",
3148 route_set_aigp_metric,
3149 route_set_aigp_metric_compile,
3150 route_set_aigp_metric_free,
3151};
3152
718e3744 3153/* `set aggregator as AS A.B.C.D' */
d62a17ae 3154struct aggregator {
3155 as_t as;
3156 struct in_addr address;
718e3744 3157};
3158
b68885f9 3159static enum route_map_cmd_result_t
1782514f 3160route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
718e3744 3161{
9b6d8fcf 3162 struct bgp_path_info *path;
d62a17ae 3163 struct aggregator *aggregator;
718e3744 3164
1782514f
DS
3165 path = object;
3166 aggregator = rule;
e52702f2 3167
1782514f
DS
3168 path->attr->aggregator_as = aggregator->as;
3169 path->attr->aggregator_addr = aggregator->address;
3170 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
718e3744 3171
d62a17ae 3172 return RMAP_OKAY;
718e3744 3173}
3174
d62a17ae 3175static void *route_set_aggregator_as_compile(const char *arg)
718e3744 3176{
d62a17ae 3177 struct aggregator *aggregator;
3178 char as[10];
3179 char address[20];
3180 int ret;
718e3744 3181
d62a17ae 3182 aggregator =
3183 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
116e176d
DS
3184 if (sscanf(arg, "%s %s", as, address) != 2) {
3185 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3186 return NULL;
3187 }
718e3744 3188
d62a17ae 3189 aggregator->as = strtoul(as, NULL, 10);
3190 ret = inet_aton(address, &aggregator->address);
3191 if (ret == 0) {
3192 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3193 return NULL;
3194 }
3195 return aggregator;
718e3744 3196}
3197
d62a17ae 3198static void route_set_aggregator_as_free(void *rule)
718e3744 3199{
d62a17ae 3200 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3201}
3202
364deb04
DL
3203static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
3204 "aggregator as",
3205 route_set_aggregator_as,
3206 route_set_aggregator_as_compile,
3207 route_set_aggregator_as_free,
718e3744 3208};
6b0655a2 3209
4b7e6066 3210/* Set tag to object. object must be pointer to struct bgp_path_info */
b68885f9 3211static enum route_map_cmd_result_t
1782514f 3212route_set_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 3213{
d62a17ae 3214 route_tag_t *tag;
9b6d8fcf 3215 struct bgp_path_info *path;
0d9551dc 3216
1782514f
DS
3217 tag = rule;
3218 path = object;
0d9551dc 3219
1782514f
DS
3220 /* Set tag value */
3221 path->attr->tag = *tag;
0d9551dc 3222
d62a17ae 3223 return RMAP_OKAY;
0d9551dc
DS
3224}
3225
0d9551dc 3226/* Route map commands for tag set. */
364deb04
DL
3227static const struct route_map_rule_cmd route_set_tag_cmd = {
3228 "tag",
3229 route_set_tag,
3230 route_map_rule_tag_compile,
d62a17ae 3231 route_map_rule_tag_free,
0d9551dc
DS
3232};
3233
4b7e6066 3234/* Set label-index to object. object must be pointer to struct bgp_path_info */
b68885f9 3235static enum route_map_cmd_result_t
1782514f 3236route_set_label_index(void *rule, const struct prefix *prefix, void *object)
d62a17ae 3237{
3238 struct rmap_value *rv;
9b6d8fcf 3239 struct bgp_path_info *path;
d7c0a89a 3240 uint32_t label_index;
d62a17ae 3241
1782514f
DS
3242 /* Fetch routemap's rule information. */
3243 rv = rule;
3244 path = object;
d62a17ae 3245
1782514f
DS
3246 /* Set label-index value. */
3247 label_index = rv->value;
3248 if (label_index) {
3249 path->attr->label_index = label_index;
3250 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
d62a17ae 3251 }
d990e384 3252
d62a17ae 3253 return RMAP_OKAY;
d990e384
DS
3254}
3255
3256/* Route map commands for label-index set. */
364deb04
DL
3257static const struct route_map_rule_cmd route_set_label_index_cmd = {
3258 "label-index",
3259 route_set_label_index,
3260 route_value_compile,
d62a17ae 3261 route_value_free,
d990e384 3262};
0d9551dc 3263
718e3744 3264/* `match ipv6 address IP_ACCESS_LIST' */
3265
b68885f9 3266static enum route_map_cmd_result_t
1782514f 3267route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
718e3744 3268{
d62a17ae 3269 struct access_list *alist;
718e3744 3270
1782514f 3271 if (prefix->family == AF_INET6) {
d62a17ae 3272 alist = access_list_lookup(AFI_IP6, (char *)rule);
819547b2 3273 if (alist == NULL) {
cc09ba45
DS
3274 if (unlikely(CHECK_FLAG(rmap_debug,
3275 DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
3276 zlog_debug(
3277 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
3278 __func__, (char *)rule);
3279
d62a17ae 3280 return RMAP_NOMATCH;
819547b2 3281 }
e52702f2 3282
d62a17ae 3283 return (access_list_apply(alist, prefix) == FILTER_DENY
3284 ? RMAP_NOMATCH
3285 : RMAP_MATCH);
3286 }
3287 return RMAP_NOMATCH;
718e3744 3288}
3289
d62a17ae 3290static void *route_match_ipv6_address_compile(const char *arg)
718e3744 3291{
b7d234f2
DS
3292 struct access_list *alist;
3293
3294 alist = access_list_lookup(AFI_IP6, arg);
3295 if (!alist)
3296 zlog_warn(
3297 "Access List specified %s does not exist yet, default will be NO_MATCH until it is created",
3298 arg);
3299
d62a17ae 3300 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3301}
3302
d62a17ae 3303static void route_match_ipv6_address_free(void *rule)
718e3744 3304{
d62a17ae 3305 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3306}
3307
3308/* Route map commands for ip address matching. */
364deb04
DL
3309static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
3310 "ipv6 address",
3311 route_match_ipv6_address,
3312 route_match_ipv6_address_compile,
3313 route_match_ipv6_address_free
3314};
6b0655a2 3315
bc63ba98
DA
3316/* `match ipv6 next-hop ACCESSLIST6_NAME' */
3317static enum route_map_cmd_result_t
3318route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
3319{
3320 struct bgp_path_info *path;
3321 struct access_list *alist;
3322 struct prefix_ipv6 p;
3323
3324 if (prefix->family == AF_INET6) {
3325 path = object;
3326 p.family = AF_INET6;
3327 p.prefix = path->attr->mp_nexthop_global;
3328 p.prefixlen = IPV6_MAX_BITLEN;
3329
3330 alist = access_list_lookup(AFI_IP6, (char *)rule);
819547b2 3331 if (!alist) {
cc09ba45
DS
3332 if (unlikely(CHECK_FLAG(rmap_debug,
3333 DEBUG_ROUTEMAP_DETAIL)))
819547b2
DS
3334 zlog_debug(
3335 "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
3336 __func__, (char *)rule);
3337
bc63ba98 3338 return RMAP_NOMATCH;
819547b2 3339 }
bc63ba98
DA
3340
3341 if (access_list_apply(alist, &p) == FILTER_PERMIT)
3342 return RMAP_MATCH;
3343
3344 if (path->attr->mp_nexthop_len
3345 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3346 p.prefix = path->attr->mp_nexthop_local;
3347 if (access_list_apply(alist, &p) == FILTER_PERMIT)
3348 return RMAP_MATCH;
3349 }
3350 }
3351
3352 return RMAP_NOMATCH;
3353}
3354
3355static void *route_match_ipv6_next_hop_compile(const char *arg)
3356{
3357 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3358}
3359
3360static void route_match_ipv6_next_hop_free(void *rule)
3361{
3362 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3363}
3364
3365static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
3366 "ipv6 next-hop",
3367 route_match_ipv6_next_hop,
3368 route_match_ipv6_next_hop_compile,
3369 route_match_ipv6_next_hop_free
3370};
3371
718e3744 3372/* `match ipv6 next-hop IP_ADDRESS' */
3373
b68885f9 3374static enum route_map_cmd_result_t
bc63ba98
DA
3375route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
3376 void *object)
718e3744 3377{
d62a17ae 3378 struct in6_addr *addr = rule;
9b6d8fcf 3379 struct bgp_path_info *path;
718e3744 3380
1782514f 3381 path = object;
718e3744 3382
1782514f
DS
3383 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
3384 return RMAP_MATCH;
718e3744 3385
1782514f
DS
3386 if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
3387 && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
3388 return RMAP_MATCH;
718e3744 3389
d62a17ae 3390 return RMAP_NOMATCH;
718e3744 3391}
3392
bc63ba98 3393static void *route_match_ipv6_next_hop_address_compile(const char *arg)
718e3744 3394{
d62a17ae 3395 struct in6_addr *address;
3396 int ret;
718e3744 3397
d62a17ae 3398 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3399
d62a17ae 3400 ret = inet_pton(AF_INET6, arg, address);
3401 if (!ret) {
3402 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3403 return NULL;
3404 }
718e3744 3405
d62a17ae 3406 return address;
718e3744 3407}
3408
bc63ba98 3409static void route_match_ipv6_next_hop_address_free(void *rule)
718e3744 3410{
d62a17ae 3411 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3412}
3413
bc63ba98 3414static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
03030106 3415 "ipv6 next-hop address",
bc63ba98
DA
3416 route_match_ipv6_next_hop_address,
3417 route_match_ipv6_next_hop_address_compile,
3418 route_match_ipv6_next_hop_address_free
364deb04 3419};
6b0655a2 3420
b7d234f2 3421/* `match ip next-hop address IP_ADDRESS' */
be7735b3
PG
3422
3423static enum route_map_cmd_result_t
1782514f 3424route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
be7735b3
PG
3425{
3426 struct in_addr *addr = rule;
3427 struct bgp_path_info *path;
3428
1782514f 3429 path = object;
be7735b3 3430
1782514f
DS
3431 if (path->attr->nexthop.s_addr == addr->s_addr
3432 || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
3433 && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
3434 return RMAP_MATCH;
be7735b3
PG
3435
3436 return RMAP_NOMATCH;
3437}
3438
3439static void *route_match_ipv4_next_hop_compile(const char *arg)
3440{
3441 struct in_addr *address;
3442 int ret;
3443
3444 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3445
3446 ret = inet_pton(AF_INET, arg, address);
3447 if (!ret) {
3448 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3449 return NULL;
3450 }
3451
3452 return address;
3453}
3454
3455static void route_match_ipv4_next_hop_free(void *rule)
3456{
3457 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3458}
3459
3460static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
3461 "ip next-hop address",
3462 route_match_ipv4_next_hop,
3463 route_match_ipv4_next_hop_compile,
3464 route_match_ipv4_next_hop_free
3465};
3466
718e3744 3467/* `match ipv6 address prefix-list PREFIX_LIST' */
3468
b68885f9 3469static enum route_map_cmd_result_t
123214ef 3470route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1782514f 3471 void *object)
718e3744 3472{
1782514f 3473 return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
718e3744 3474}
3475
d62a17ae 3476static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 3477{
d62a17ae 3478 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3479}
3480
d62a17ae 3481static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 3482{
d62a17ae 3483 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3484}
3485
364deb04
DL
3486static const struct route_map_rule_cmd
3487 route_match_ipv6_address_prefix_list_cmd = {
3488 "ipv6 address prefix-list",
3489 route_match_ipv6_address_prefix_list,
d62a17ae 3490 route_match_ipv6_address_prefix_list_compile,
364deb04
DL
3491 route_match_ipv6_address_prefix_list_free
3492};
6b0655a2 3493
61ad901e
DA
3494/* `match ipv6 next-hop type <TYPE>' */
3495
b68885f9 3496static enum route_map_cmd_result_t
61ad901e 3497route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1782514f 3498 void *object)
61ad901e 3499{
9b6d8fcf 3500 struct bgp_path_info *path;
61ad901e
DA
3501 struct in6_addr *addr = rule;
3502
1782514f 3503 if (prefix->family == AF_INET6) {
9b6d8fcf 3504 path = (struct bgp_path_info *)object;
05864da7 3505 if (!path)
b68885f9 3506 return RMAP_NOMATCH;
61ad901e 3507
9b6d8fcf
DS
3508 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
3509 && !path->attr->nh_ifindex)
61ad901e
DA
3510 return RMAP_MATCH;
3511 }
1782514f 3512
61ad901e
DA
3513 return RMAP_NOMATCH;
3514}
3515
3516static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3517{
3518 struct in6_addr *address;
3519 int ret;
3520
3521 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3522
3523 ret = inet_pton(AF_INET6, "::0", address);
3524 if (!ret) {
3525 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3526 return NULL;
3527 }
3528
3529 return address;
3530}
3531
3532static void route_match_ipv6_next_hop_type_free(void *rule)
3533{
3534 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3535}
3536
364deb04
DL
3537static const struct route_map_rule_cmd
3538 route_match_ipv6_next_hop_type_cmd = {
3539 "ipv6 next-hop type",
3540 route_match_ipv6_next_hop_type,
61ad901e 3541 route_match_ipv6_next_hop_type_compile,
364deb04
DL
3542 route_match_ipv6_next_hop_type_free
3543};
61ad901e 3544
718e3744 3545/* `set ipv6 nexthop global IP_ADDRESS' */
3546
581776fa 3547/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3548static enum route_map_cmd_result_t
1782514f 3549route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
718e3744 3550{
d62a17ae 3551 struct in6_addr *address;
9b6d8fcf 3552 struct bgp_path_info *path;
718e3744 3553
1782514f
DS
3554 /* Fetch routemap's rule information. */
3555 address = rule;
3556 path = object;
e52702f2 3557
1782514f
DS
3558 /* Set next hop value. */
3559 path->attr->mp_nexthop_global = *address;
3f9c7369 3560
1782514f
DS
3561 /* Set nexthop length. */
3562 if (path->attr->mp_nexthop_len == 0)
3563 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 3564
1782514f
DS
3565 SET_FLAG(path->attr->rmap_change_flags,
3566 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
718e3744 3567
d62a17ae 3568 return RMAP_OKAY;
718e3744 3569}
3570
3571/* Route map `ip next-hop' compile function. Given string is converted
3572 to struct in_addr structure. */
d62a17ae 3573static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 3574{
d62a17ae 3575 int ret;
3576 struct in6_addr *address;
718e3744 3577
d62a17ae 3578 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3579
d62a17ae 3580 ret = inet_pton(AF_INET6, arg, address);
718e3744 3581
d62a17ae 3582 if (ret == 0) {
3583 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3584 return NULL;
3585 }
718e3744 3586
d62a17ae 3587 return address;
718e3744 3588}
3589
3590/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3591static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 3592{
d62a17ae 3593 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3594}
3595
3596/* Route map commands for ip nexthop set. */
364deb04
DL
3597static const struct route_map_rule_cmd
3598 route_set_ipv6_nexthop_global_cmd = {
3599 "ipv6 next-hop global",
3600 route_set_ipv6_nexthop_global,
d62a17ae 3601 route_set_ipv6_nexthop_global_compile,
364deb04
DL
3602 route_set_ipv6_nexthop_global_free
3603};
6b0655a2 3604
161995ea 3605/* Set next-hop preference value. */
b68885f9 3606static enum route_map_cmd_result_t
123214ef 3607route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
1782514f 3608 void *object)
d62a17ae 3609{
9b6d8fcf 3610 struct bgp_path_info *path;
d62a17ae 3611 struct peer *peer;
3612
1782514f
DS
3613 /* Fetch routemap's rule information. */
3614 path = object;
3615 peer = path->peer;
d62a17ae 3616
1782514f
DS
3617 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3618 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
3619 /* Set next hop preference to global */
2bb8b49c 3620 path->attr->mp_nexthop_prefer_global = true;
1782514f
DS
3621 SET_FLAG(path->attr->rmap_change_flags,
3622 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3623 } else {
2bb8b49c 3624 path->attr->mp_nexthop_prefer_global = false;
1782514f
DS
3625 SET_FLAG(path->attr->rmap_change_flags,
3626 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
161995ea 3627 }
1782514f 3628
d62a17ae 3629 return RMAP_OKAY;
161995ea
DS
3630}
3631
d62a17ae 3632static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 3633{
d62a17ae 3634 int *rins = NULL;
161995ea 3635
d62a17ae 3636 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3637 *rins = 1;
161995ea 3638
d62a17ae 3639 return rins;
161995ea
DS
3640}
3641
3642/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3643static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 3644{
d62a17ae 3645 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
3646}
3647
3648/* Route map commands for ip nexthop set preferred. */
364deb04
DL
3649static const struct route_map_rule_cmd
3650 route_set_ipv6_nexthop_prefer_global_cmd = {
3651 "ipv6 next-hop prefer-global",
3652 route_set_ipv6_nexthop_prefer_global,
d62a17ae 3653 route_set_ipv6_nexthop_prefer_global_compile,
364deb04
DL
3654 route_set_ipv6_nexthop_prefer_global_free
3655};
161995ea 3656
718e3744 3657/* `set ipv6 nexthop local IP_ADDRESS' */
3658
581776fa 3659/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3660static enum route_map_cmd_result_t
1782514f 3661route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
d62a17ae 3662{
3663 struct in6_addr *address;
9b6d8fcf 3664 struct bgp_path_info *path;
5bbcc782
PG
3665 struct bgp_dest *dest;
3666 struct bgp_table *table = NULL;
d62a17ae 3667
1782514f
DS
3668 /* Fetch routemap's rule information. */
3669 address = rule;
3670 path = object;
5bbcc782
PG
3671 dest = path->net;
3672
3673 if (!dest)
3674 return RMAP_OKAY;
3675
3676 table = bgp_dest_table(dest);
3677 if (!table)
3678 return RMAP_OKAY;
d62a17ae 3679
1782514f
DS
3680 /* Set next hop value. */
3681 path->attr->mp_nexthop_local = *address;
d62a17ae 3682
1782514f 3683 /* Set nexthop length. */
5bbcc782
PG
3684 if (table->safi == SAFI_MPLS_VPN || table->safi == SAFI_ENCAP ||
3685 table->safi == SAFI_EVPN)
3686 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
3687 else
1782514f 3688 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 3689
1782514f
DS
3690 SET_FLAG(path->attr->rmap_change_flags,
3691 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 3692
d62a17ae 3693 return RMAP_OKAY;
718e3744 3694}
3695
3696/* Route map `ip nexthop' compile function. Given string is converted
3697 to struct in_addr structure. */
d62a17ae 3698static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 3699{
d62a17ae 3700 int ret;
3701 struct in6_addr *address;
718e3744 3702
d62a17ae 3703 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3704
d62a17ae 3705 ret = inet_pton(AF_INET6, arg, address);
718e3744 3706
d62a17ae 3707 if (ret == 0) {
3708 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3709 return NULL;
3710 }
718e3744 3711
d62a17ae 3712 return address;
718e3744 3713}
3714
3715/* Free route map's compiled `ip nexthop' value. */
d62a17ae 3716static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 3717{
d62a17ae 3718 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3719}
3720
3721/* Route map commands for ip nexthop set. */
364deb04
DL
3722static const struct route_map_rule_cmd
3723 route_set_ipv6_nexthop_local_cmd = {
3724 "ipv6 next-hop local",
3725 route_set_ipv6_nexthop_local,
d62a17ae 3726 route_set_ipv6_nexthop_local_compile,
364deb04
DL
3727 route_set_ipv6_nexthop_local_free
3728};
90916ac2
DS
3729
3730/* `set ipv6 nexthop peer-address' */
3731
581776fa 3732/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3733static enum route_map_cmd_result_t
1782514f 3734route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
d62a17ae 3735{
3736 struct in6_addr peer_address;
9b6d8fcf 3737 struct bgp_path_info *path;
d62a17ae 3738 struct peer *peer;
3739
1782514f
DS
3740 /* Fetch routemap's rule information. */
3741 path = object;
3742 peer = path->peer;
d62a17ae 3743
1782514f
DS
3744 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3745 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3746 && peer->su_remote
3747 && sockunion_family(peer->su_remote) == AF_INET6) {
3748 peer_address = peer->su_remote->sin6.sin6_addr;
3749 /* Set next hop value and length in attribute. */
3750 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3751 path->attr->mp_nexthop_local = peer_address;
3752 if (path->attr->mp_nexthop_len
3753 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3754 path->attr->mp_nexthop_len =
3755 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3756 } else {
3757 path->attr->mp_nexthop_global = peer_address;
3758 if (path->attr->mp_nexthop_len == 0)
3759 path->attr->mp_nexthop_len =
3760 BGP_ATTR_NHLEN_IPV6_GLOBAL;
d62a17ae 3761 }
1782514f
DS
3762
3763 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3764 /* The next hop value will be set as part of packet
3765 * rewrite.
3766 * Set the flags here to indicate that rewrite needs to
3767 * be done.
3768 * Also, clear the value - we clear both global and
3769 * link-local
3770 * nexthops, whether we send one or both is determined
3771 * elsewhere.
3772 */
3773 SET_FLAG(path->attr->rmap_change_flags,
3774 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3775 /* clear next hop value. */
3776 memset(&(path->attr->mp_nexthop_global), 0,
3777 sizeof(struct in6_addr));
3778 memset(&(path->attr->mp_nexthop_local), 0,
3779 sizeof(struct in6_addr));
90916ac2 3780 }
90916ac2 3781
d62a17ae 3782 return RMAP_OKAY;
90916ac2
DS
3783}
3784
3785/* Route map `ip next-hop' compile function. Given string is converted
3786 to struct in_addr structure. */
d62a17ae 3787static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 3788{
d62a17ae 3789 int *rins = NULL;
90916ac2 3790
d62a17ae 3791 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3792 *rins = 1;
90916ac2 3793
d62a17ae 3794 return rins;
90916ac2
DS
3795}
3796
3797/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3798static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 3799{
d62a17ae 3800 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
3801}
3802
3803/* Route map commands for ip nexthop set. */
364deb04
DL
3804static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3805 "ipv6 next-hop peer-address",
3806 route_set_ipv6_nexthop_peer,
3807 route_set_ipv6_nexthop_peer_compile,
3808 route_set_ipv6_nexthop_peer_free
3809};
90916ac2 3810
69ba6dd7 3811/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 3812
b68885f9 3813static enum route_map_cmd_result_t
1782514f 3814route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
718e3744 3815{
d62a17ae 3816 struct in_addr *address;
9b6d8fcf 3817 struct bgp_path_info *path;
718e3744 3818
1782514f
DS
3819 /* Fetch routemap's rule information. */
3820 address = rule;
3821 path = object;
e52702f2 3822
1782514f
DS
3823 /* Set next hop value. */
3824 path->attr->mp_nexthop_global_in = *address;
3825 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
718e3744 3826
6eeb9255
DA
3827 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_VPNV4_NHOP_CHANGED);
3828
d62a17ae 3829 return RMAP_OKAY;
718e3744 3830}
3831
d62a17ae 3832static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 3833{
d62a17ae 3834 int ret;
3835 struct in_addr *address;
718e3744 3836
d62a17ae 3837 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3838
d62a17ae 3839 ret = inet_aton(arg, address);
718e3744 3840
d62a17ae 3841 if (ret == 0) {
3842 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3843 return NULL;
3844 }
718e3744 3845
d62a17ae 3846 return address;
718e3744 3847}
3848
69ba6dd7 3849/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 3850
b68885f9 3851static enum route_map_cmd_result_t
1782514f 3852route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
d6902373 3853{
d62a17ae 3854 struct in6_addr *address;
9b6d8fcf 3855 struct bgp_path_info *path;
d6902373 3856
1782514f
DS
3857 /* Fetch routemap's rule information. */
3858 address = rule;
3859 path = object;
d6902373 3860
1782514f
DS
3861 /* Set next hop value. */
3862 memcpy(&path->attr->mp_nexthop_global, address,
3863 sizeof(struct in6_addr));
3864 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
d6902373 3865
6eeb9255
DA
3866 SET_FLAG(path->attr->rmap_change_flags,
3867 BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED);
3868
d62a17ae 3869 return RMAP_OKAY;
d6902373
PG
3870}
3871
d62a17ae 3872static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 3873{
d62a17ae 3874 int ret;
3875 struct in6_addr *address;
d6902373 3876
d62a17ae 3877 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3878 ret = inet_pton(AF_INET6, arg, address);
d6902373 3879
d62a17ae 3880 if (ret == 0) {
3881 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3882 return NULL;
3883 }
d6902373 3884
d62a17ae 3885 return address;
d6902373
PG
3886}
3887
d62a17ae 3888static void route_set_vpn_nexthop_free(void *rule)
718e3744 3889{
d62a17ae 3890 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3891}
3892
69ba6dd7 3893/* Route map commands for ipv4 next-hop set. */
364deb04
DL
3894static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3895 "ipv4 vpn next-hop",
3896 route_set_vpnv4_nexthop,
3897 route_set_vpnv4_nexthop_compile,
3898 route_set_vpn_nexthop_free
3899};
d6902373 3900
69ba6dd7 3901/* Route map commands for ipv6 next-hop set. */
364deb04
DL
3902static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3903 "ipv6 vpn next-hop",
3904 route_set_vpnv6_nexthop,
3905 route_set_vpnv6_nexthop_compile,
3906 route_set_vpn_nexthop_free
3907};
6b0655a2 3908
718e3744 3909/* `set originator-id' */
3910
3911/* For origin set. */
b68885f9 3912static enum route_map_cmd_result_t
1782514f 3913route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
718e3744 3914{
d62a17ae 3915 struct in_addr *address;
9b6d8fcf 3916 struct bgp_path_info *path;
718e3744 3917
1782514f
DS
3918 address = rule;
3919 path = object;
e52702f2 3920
1782514f
DS
3921 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3922 path->attr->originator_id = *address;
718e3744 3923
d62a17ae 3924 return RMAP_OKAY;
718e3744 3925}
3926
3927/* Compile function for originator-id set. */
d62a17ae 3928static void *route_set_originator_id_compile(const char *arg)
718e3744 3929{
d62a17ae 3930 int ret;
3931 struct in_addr *address;
718e3744 3932
d62a17ae 3933 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3934
d62a17ae 3935 ret = inet_aton(arg, address);
718e3744 3936
d62a17ae 3937 if (ret == 0) {
3938 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3939 return NULL;
3940 }
718e3744 3941
d62a17ae 3942 return address;
718e3744 3943}
3944
3945/* Compile function for originator_id set. */
d62a17ae 3946static void route_set_originator_id_free(void *rule)
718e3744 3947{
d62a17ae 3948 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3949}
3950
515e500c 3951/* Set originator-id rule structure. */
364deb04
DL
3952static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3953 "originator-id",
3954 route_set_originator_id,
3955 route_set_originator_id_compile,
3956 route_set_originator_id_free,
718e3744 3957};
6b0655a2 3958
324e8b1f
DA
3959static enum route_map_cmd_result_t
3960route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
3961 void *object)
3962{
3963 struct bgp_path_info *path;
3964 struct ecommunity *ecomm;
3965 struct ecommunity_val *ecomm_val;
3966 enum rpki_states *rpki_status = rule;
3967 enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
3968
3969 path = object;
3970
3971 ecomm = bgp_attr_get_ecommunity(path->attr);
3972 if (!ecomm)
3973 return RMAP_NOMATCH;
3974
3975 ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
3976 ECOMMUNITY_ORIGIN_VALIDATION_STATE);
3977 if (!ecomm_val)
3978 return RMAP_NOMATCH;
3979
3980 /* The Origin Validation State is encoded in the last octet of
3981 * the extended community.
3982 */
3983 switch (ecomm_val->val[7]) {
3984 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
3985 ecomm_rpki_status = RPKI_VALID;
3986 break;
3987 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
3988 ecomm_rpki_status = RPKI_NOTFOUND;
3989 break;
3990 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
3991 ecomm_rpki_status = RPKI_INVALID;
3992 break;
3993 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
3994 break;
3995 }
3996
3997 if (ecomm_rpki_status == *rpki_status)
3998 return RMAP_MATCH;
3999
4000 return RMAP_NOMATCH;
4001}
4002
4003static void *route_match_extcommunity_compile(const char *arg)
4004{
4005 int *rpki_status;
4006
4007 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
4008
4009 if (strcmp(arg, "valid") == 0)
4010 *rpki_status = RPKI_VALID;
4011 else if (strcmp(arg, "invalid") == 0)
4012 *rpki_status = RPKI_INVALID;
4013 else
4014 *rpki_status = RPKI_NOTFOUND;
4015
4016 return rpki_status;
4017}
4018
4019static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
4020 "rpki-extcommunity",
4021 route_match_rpki_extcommunity,
4022 route_match_extcommunity_compile,
4023 route_value_free
4024};
4025
518f0eb1 4026/*
2a3d5731 4027 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
4028 * modifications.
4029 */
d62a17ae 4030static void bgp_route_map_process_peer(const char *rmap_name,
4031 struct route_map *map, struct peer *peer,
4032 int afi, int safi, int route_update)
4033{
d62a17ae 4034 struct bgp_filter *filter;
4035
4036 if (!peer || !rmap_name)
4037 return;
4038
4039 filter = &peer->filter[afi][safi];
4040 /*
4041 * in is for non-route-server clients,
4042 * out is for all peers
4043 */
db77a501
DS
4044 if (filter->map[RMAP_IN].name
4045 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
4046 filter->map[RMAP_IN].map = map;
d62a17ae 4047
feb17238 4048 if (route_update && peer_established(peer)) {
d62a17ae 4049 if (CHECK_FLAG(peer->af_flags[afi][safi],
4050 PEER_FLAG_SOFT_RECONFIG)) {
4051 if (bgp_debug_update(peer, NULL, NULL, 1))
4052 zlog_debug(
11b228cd
DS
4053 "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
4054 rmap_name, afi2str(afi),
4055 safi2str(safi), peer->host);
d62a17ae 4056
4057 bgp_soft_reconfig_in(peer, afi, safi);
4058 } else if (CHECK_FLAG(peer->cap,
4059 PEER_CAP_REFRESH_OLD_RCV)
4060 || CHECK_FLAG(peer->cap,
4061 PEER_CAP_REFRESH_NEW_RCV)) {
4062 if (bgp_debug_update(peer, NULL, NULL, 1))
4063 zlog_debug(
11b228cd
DS
4064 "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
4065 rmap_name, afi2str(afi),
4066 safi2str(safi), peer->host);
9af52ccf
DA
4067 bgp_route_refresh_send(
4068 peer, afi, safi, 0, 0, 0,
4069 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 4070 }
d62a17ae 4071 }
518f0eb1 4072 }
d62a17ae 4073
4074 /*
4075 * For outbound, unsuppress and default-originate map change (content or
4076 * map created), merely update the "config" here, the actual route
4077 * announcement happens at the group level.
4078 */
4079 if (filter->map[RMAP_OUT].name
4080 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
4081 filter->map[RMAP_OUT].map = map;
4082
4083 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
4084 filter->usmap.map = map;
4085
7f7940e6
MK
4086 if (filter->advmap.aname
4087 && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
4088 filter->advmap.amap = map;
7f7940e6
MK
4089 }
4090
4091 if (filter->advmap.cname
4092 && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
4093 filter->advmap.cmap = map;
7f7940e6
MK
4094 }
4095
d62a17ae 4096 if (peer->default_rmap[afi][safi].name
4097 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
4098 peer->default_rmap[afi][safi].map = map;
c5aec50b
MK
4099
4100 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4101 peer->advmap_config_change[afi][safi] = true;
d62a17ae 4102}
4103
4104static void bgp_route_map_update_peer_group(const char *rmap_name,
4105 struct route_map *map,
4106 struct bgp *bgp)
4107{
4108 struct peer_group *group;
4109 struct listnode *node, *nnode;
4110 struct bgp_filter *filter;
4111 int afi, safi;
4112 int direct;
4113
4114 if (!bgp)
4115 return;
4116
4117 /* All the peers have been updated correctly already. This is
4118 * just updating the placeholder data. No real update required.
4119 */
05c7a1cc
QY
4120 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
4121 FOREACH_AFI_SAFI (afi, safi) {
4122 filter = &group->conf->filter[afi][safi];
4123
4124 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
4125 if ((filter->map[direct].name)
4126 && (strcmp(rmap_name,
4127 filter->map[direct].name)
d62a17ae 4128 == 0))
05c7a1cc 4129 filter->map[direct].map = map;
d62a17ae 4130 }
05c7a1cc
QY
4131
4132 if (filter->usmap.name
4133 && (strcmp(rmap_name, filter->usmap.name) == 0))
4134 filter->usmap.map = map;
9118301e
DA
4135
4136 if (filter->advmap.aname &&
4137 (strcmp(rmap_name, filter->advmap.aname) == 0))
4138 filter->advmap.amap = map;
4139
4140 if (filter->advmap.cname &&
4141 (strcmp(rmap_name, filter->advmap.cname) == 0))
4142 filter->advmap.cmap = map;
05c7a1cc
QY
4143 }
4144 }
518f0eb1
DS
4145}
4146
a6e0d253
DW
4147/*
4148 * Note that if an extreme number (tens of thousands) of route-maps are in use
4149 * and if bgp has an extreme number of peers, network statements, etc then this
4150 * function can consume a lot of cycles. This is due to this function being
4151 * called for each route-map and within this function we walk the list of peers,
4152 * network statements, etc looking to see if they use this route-map.
4153 */
d62a17ae 4154static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
f1aa4929 4155 bool route_update)
d62a17ae 4156{
4157 int i;
4056a5f6 4158 bool matched;
d62a17ae 4159 afi_t afi;
4160 safi_t safi;
4161 struct peer *peer;
9bcb3eef 4162 struct bgp_dest *bn;
d62a17ae 4163 struct bgp_static *bgp_static;
20894f50 4164 struct bgp_aggregate *aggregate;
d62a17ae 4165 struct listnode *node, *nnode;
4166 struct route_map *map;
4167 char buf[INET6_ADDRSTRLEN];
4168
4169 map = route_map_lookup_by_name(rmap_name);
4170
4171 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
4172
4173 /* Ignore dummy peer-group structure */
4174 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4175 continue;
4176
05c7a1cc
QY
4177 FOREACH_AFI_SAFI (afi, safi) {
4178 /* process in/out/import/export/default-orig
4179 * route-maps */
4180 bgp_route_map_process_peer(rmap_name, map, peer, afi,
4181 safi, route_update);
4182 }
d62a17ae 4183 }
4184
4185 /* for outbound/default-orig route-maps, process for groups */
4186 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
4187 route_update, 0);
4188
4189 /* update peer-group config (template) */
4190 bgp_route_map_update_peer_group(rmap_name, map, bgp);
4191
05c7a1cc
QY
4192 FOREACH_AFI_SAFI (afi, safi) {
4193 /* For table route-map updates. */
4194 if (!bgp_fibupd_safi(safi))
4195 continue;
d62a17ae 4196
05c7a1cc
QY
4197 if (bgp->table_map[afi][safi].name
4198 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
4199 == 0)) {
b4897fa5 4200
4201 /* bgp->table_map[afi][safi].map is NULL.
4202 * i.e Route map creation event.
4203 * So update applied_counter.
4204 * If it is not NULL, i.e It may be routemap updation or
4205 * deletion. so no need to update the counter.
4206 */
4207 if (!bgp->table_map[afi][safi].map)
4208 route_map_counter_increment(map);
05c7a1cc
QY
4209 bgp->table_map[afi][safi].map = map;
4210
4211 if (BGP_DEBUG(zebra, ZEBRA))
4212 zlog_debug(
11b228cd
DS
4213 "Processing route_map %s(%s:%s) update on table map",
4214 rmap_name, afi2str(afi),
4215 safi2str(safi));
05c7a1cc
QY
4216 if (route_update)
4217 bgp_zebra_announce_table(bgp, afi, safi);
4218 }
d62a17ae 4219
05c7a1cc
QY
4220 /* For network route-map updates. */
4221 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
96f10e1e 4222 bn = bgp_route_next(bn)) {
9bcb3eef 4223 bgp_static = bgp_dest_get_bgp_static_info(bn);
c9837105
DS
4224 if (!bgp_static)
4225 continue;
4226
4227 if (!bgp_static->rmap.name
4228 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
4229 continue;
4230
b4897fa5 4231 if (!bgp_static->rmap.map)
4232 route_map_counter_increment(map);
4233
c9837105
DS
4234 bgp_static->rmap.map = map;
4235
4236 if (route_update && !bgp_static->backdoor) {
b54892e0 4237 const struct prefix *bn_p =
9bcb3eef 4238 bgp_dest_get_prefix(bn);
b54892e0
DS
4239
4240 if (bgp_debug_zebra(bn_p))
c9837105 4241 zlog_debug(
11b228cd
DS
4242 "Processing route_map %s(%s:%s) update on static route %s",
4243 rmap_name, afi2str(afi),
4244 safi2str(safi),
b54892e0
DS
4245 inet_ntop(bn_p->family,
4246 &bn_p->u.prefix, buf,
07380148 4247 sizeof(buf)));
b54892e0 4248 bgp_static_update(bgp, bn_p, bgp_static, afi,
c9837105 4249 safi);
05c7a1cc 4250 }
96f10e1e 4251 }
20894f50
DA
4252
4253 /* For aggregate-address route-map updates. */
4254 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
4255 bn = bgp_route_next(bn)) {
9bcb3eef 4256 aggregate = bgp_dest_get_bgp_aggregate_info(bn);
20894f50
DA
4257 if (!aggregate)
4258 continue;
4259
4056a5f6 4260 matched = false;
20894f50 4261
365ab2e7
RZ
4262 /* Update suppress map pointer. */
4263 if (aggregate->suppress_map_name
4264 && strmatch(aggregate->suppress_map_name,
4265 rmap_name)) {
4056a5f6 4266 if (aggregate->rmap.map == NULL)
365ab2e7 4267 route_map_counter_increment(map);
20894f50 4268
365ab2e7 4269 aggregate->suppress_map = map;
4056a5f6
RZ
4270
4271 bgp_aggregate_toggle_suppressed(
4272 aggregate, bgp, bgp_dest_get_prefix(bn),
4273 afi, safi, false);
4274
4275 matched = true;
365ab2e7
RZ
4276 }
4277
4056a5f6
RZ
4278 if (aggregate->rmap.name
4279 && strmatch(rmap_name, aggregate->rmap.name)) {
4280 if (aggregate->rmap.map == NULL)
4281 route_map_counter_increment(map);
20894f50 4282
4056a5f6 4283 aggregate->rmap.map = map;
20894f50 4284
4056a5f6
RZ
4285 matched = true;
4286 }
20894f50 4287
4056a5f6 4288 if (matched && route_update) {
b54892e0 4289 const struct prefix *bn_p =
9bcb3eef 4290 bgp_dest_get_prefix(bn);
b54892e0
DS
4291
4292 if (bgp_debug_zebra(bn_p))
20894f50 4293 zlog_debug(
11b228cd
DS
4294 "Processing route_map %s(%s:%s) update on aggregate-address route %s",
4295 rmap_name, afi2str(afi),
4296 safi2str(safi),
b54892e0
DS
4297 inet_ntop(bn_p->family,
4298 &bn_p->u.prefix, buf,
07380148 4299 sizeof(buf)));
9bea1b4b
DA
4300 (void)bgp_aggregate_route(bgp, bn_p, afi, safi,
4301 aggregate);
20894f50
DA
4302 }
4303 }
05c7a1cc 4304 }
d62a17ae 4305
4306 /* For redistribute route-map updates. */
4307 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4308 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
4309 struct list *red_list;
d62a17ae 4310 struct bgp_redist *red;
4311
4312 red_list = bgp->redist[afi][i];
4313 if (!red_list)
4314 continue;
4315
4316 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
c9837105
DS
4317 if (!red->rmap.name
4318 || (strcmp(rmap_name, red->rmap.name) != 0))
4319 continue;
4320
b4897fa5 4321 if (!red->rmap.map)
4322 route_map_counter_increment(map);
4323
c9837105
DS
4324 red->rmap.map = map;
4325
4326 if (!route_update)
4327 continue;
4328
4329 if (BGP_DEBUG(zebra, ZEBRA))
4330 zlog_debug(
11b228cd
DS
4331 "Processing route_map %s(%s:%s) update on redistributed routes",
4332 rmap_name, afi2str(afi),
4333 safi2str(safi));
c9837105
DS
4334
4335 bgp_redistribute_resend(bgp, afi, i,
d62a17ae 4336 red->instance);
d62a17ae 4337 }
4338 }
53c84f78
MK
4339
4340 /* for type5 command route-maps */
4341 FOREACH_AFI_SAFI (afi, safi) {
c9837105
DS
4342 if (!bgp->adv_cmd_rmap[afi][safi].name
4343 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4344 != 0)
4345 continue;
4346
2686df6a
NS
4347 /* Make sure the route-map is populated here if not already done */
4348 bgp->adv_cmd_rmap[afi][safi].map = map;
4349
c9837105
DS
4350 if (BGP_DEBUG(zebra, ZEBRA))
4351 zlog_debug(
11b228cd
DS
4352 "Processing route_map %s(%s:%s) update on advertise type5 route command",
4353 rmap_name, afi2str(afi), safi2str(safi));
2686df6a 4354
456a4697 4355 if (route_update && advertise_type5_routes(bgp, afi)) {
2686df6a
NS
4356 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4357 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4358 }
53c84f78 4359 }
d62a17ae 4360}
4361
46a69f10 4362static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 4363{
4364 struct listnode *node, *nnode;
4365 struct bgp *bgp;
4366
ddb5b488 4367 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
f1aa4929 4368 bgp_route_map_process_update(bgp, rmap_name, true);
5fe9f963 4369
49e5a4a0 4370#ifdef ENABLE_BGP_VNC
ddb5b488 4371 vnc_routemap_update(bgp, __func__);
65efcfce 4372#endif
ddb5b488
PZ
4373 }
4374
4375 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
4376}
4377
e6685141 4378void bgp_route_map_update_timer(struct event *thread)
518f0eb1 4379{
d62a17ae 4380 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1
DS
4381}
4382
d62a17ae 4383static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 4384{
47c8fa1f
NT
4385 struct listnode *node, *nnode;
4386 struct bgp *bgp;
4387
4388 /* If new update is received before the current timer timed out,
4389 * turn it off and start a new timer.
4390 */
e16d030c 4391 EVENT_OFF(bm->t_rmap_update);
47c8fa1f
NT
4392
4393 /* rmap_update_timer of 0 means don't do route updates */
4394 if (bm->rmap_update_timer) {
907a2395
DS
4395 event_add_timer(bm->master, bgp_route_map_update_timer, NULL,
4396 bm->rmap_update_timer, &bm->t_rmap_update);
47c8fa1f
NT
4397
4398 /* Signal the groups that a route-map update event has
4399 * started */
4400 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
f1aa4929
DA
4401 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
4402 rmap_name, true, 1);
47c8fa1f 4403 } else {
f6e7507e 4404 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
f1aa4929 4405 bgp_route_map_process_update(bgp, rmap_name, false);
49e5a4a0 4406#ifdef ENABLE_BGP_VNC
f6e7507e 4407 vnc_routemap_update(bgp, __func__);
65efcfce 4408#endif
f6e7507e
IR
4409 }
4410
4411 vpn_policy_routemap_event(rmap_name);
d62a17ae 4412 }
718e3744 4413}
6b0655a2 4414
d62a17ae 4415static void bgp_route_map_add(const char *rmap_name)
73ac8160 4416{
7096e938 4417 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4418 bgp_route_map_mark_update(rmap_name);
73ac8160 4419
d62a17ae 4420 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 4421}
518f0eb1 4422
d62a17ae 4423static void bgp_route_map_delete(const char *rmap_name)
73ac8160 4424{
7096e938 4425 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4426 bgp_route_map_mark_update(rmap_name);
73ac8160 4427
d62a17ae 4428 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 4429}
518f0eb1 4430
097b5973 4431static void bgp_route_map_event(const char *rmap_name)
73ac8160 4432{
7096e938 4433 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4434 bgp_route_map_mark_update(rmap_name);
518f0eb1 4435
d62a17ae 4436 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
4437}
4438
48cb7ea9
SP
4439DEFUN_YANG (match_mac_address,
4440 match_mac_address_cmd,
c60dec36 4441 "match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4442 MATCH_STR
4443 "mac address\n"
4444 "Match address of route\n"
4445 "MAC Access-list name\n")
d37ba549 4446{
48cb7ea9
SP
4447 const char *xpath =
4448 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4449 char xpath_value[XPATH_MAXLEN];
4450
4451 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4452 snprintf(xpath_value, sizeof(xpath_value),
4453 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4454 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4455
4456 return nb_cli_apply_changes(vty, NULL);
d37ba549
MK
4457}
4458
48cb7ea9
SP
4459DEFUN_YANG (no_match_mac_address,
4460 no_match_mac_address_cmd,
c60dec36 4461 "no match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4462 NO_STR
4463 MATCH_STR
4464 "mac\n"
4465 "Match address of route\n"
4466 "MAC acess-list name\n")
d37ba549 4467{
48cb7ea9
SP
4468 const char *xpath =
4469 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4470
4471 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4472 return nb_cli_apply_changes(vty, NULL);
d37ba549 4473}
73ac8160 4474
38677473
SW
4475/*
4476 * Helper to handle the case of the user passing in a number or type string
4477 */
4478static const char *parse_evpn_rt_type(const char *num_rt_type)
4479{
4480 switch (num_rt_type[0]) {
4481 case '1':
4482 return "ead";
4483 case '2':
4484 return "macip";
4485 case '3':
4486 return "multicast";
4487 case '4':
4488 return "es";
4489 case '5':
4490 return "prefix";
4491 default:
4492 break;
4493 }
4494
4495 /* Was already full type string */
4496 return num_rt_type;
4497}
4498
48cb7ea9
SP
4499DEFUN_YANG (match_evpn_route_type,
4500 match_evpn_route_type_cmd,
2514d231 4501 "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4502 MATCH_STR
4503 EVPN_HELP_STR
4504 EVPN_TYPE_HELP_STR
bd44ab08
CS
4505 EVPN_TYPE_1_HELP_STR
4506 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4507 EVPN_TYPE_2_HELP_STR
4508 EVPN_TYPE_2_HELP_STR
4509 EVPN_TYPE_3_HELP_STR
4510 EVPN_TYPE_3_HELP_STR
2514d231
CS
4511 EVPN_TYPE_4_HELP_STR
4512 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4513 EVPN_TYPE_5_HELP_STR
4514 EVPN_TYPE_5_HELP_STR)
38677473 4515{
48cb7ea9
SP
4516 const char *xpath =
4517 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4518 char xpath_value[XPATH_MAXLEN];
33c2ff62 4519
48cb7ea9
SP
4520 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4521 snprintf(xpath_value, sizeof(xpath_value),
4522 "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4523 xpath);
4524 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4525 parse_evpn_rt_type(argv[3]->arg));
33c2ff62 4526
48cb7ea9
SP
4527 return nb_cli_apply_changes(vty, NULL);
4528}
4529
4530DEFUN_YANG (no_match_evpn_route_type,
4531 no_match_evpn_route_type_cmd,
2514d231 4532 "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4533 NO_STR
4534 MATCH_STR
4535 EVPN_HELP_STR
4536 EVPN_TYPE_HELP_STR
bd44ab08
CS
4537 EVPN_TYPE_1_HELP_STR
4538 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4539 EVPN_TYPE_2_HELP_STR
4540 EVPN_TYPE_2_HELP_STR
4541 EVPN_TYPE_3_HELP_STR
4542 EVPN_TYPE_3_HELP_STR
2514d231
CS
4543 EVPN_TYPE_4_HELP_STR
4544 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4545 EVPN_TYPE_5_HELP_STR
4546 EVPN_TYPE_5_HELP_STR)
16f7ce2b 4547{
48cb7ea9
SP
4548 const char *xpath =
4549 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4550
4551 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4552
4553 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4554}
4555
48cb7ea9
SP
4556
4557DEFUN_YANG (match_evpn_vni,
4558 match_evpn_vni_cmd,
4559 "match evpn vni " CMD_VNI_RANGE,
4560 MATCH_STR
4561 EVPN_HELP_STR
4562 "Match VNI\n"
4563 "VNI ID\n")
4564{
4565 const char *xpath =
4566 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4567 char xpath_value[XPATH_MAXLEN];
4568
4569 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4570 snprintf(xpath_value, sizeof(xpath_value),
4571 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4572 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4573
4574 return nb_cli_apply_changes(vty, NULL);
4575}
4576
4577DEFUN_YANG (no_match_evpn_vni,
4578 no_match_evpn_vni_cmd,
4579 "no match evpn vni " CMD_VNI_RANGE,
4580 NO_STR
4581 MATCH_STR
4582 EVPN_HELP_STR
4583 "Match VNI\n"
4584 "VNI ID\n")
16f7ce2b 4585{
48cb7ea9
SP
4586 const char *xpath =
4587 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4588 char xpath_value[XPATH_MAXLEN];
4589
4590 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4591 snprintf(xpath_value, sizeof(xpath_value),
4592 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4593 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4594
4595 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4596}
4597
48cb7ea9
SP
4598DEFUN_YANG (match_evpn_default_route,
4599 match_evpn_default_route_cmd,
4600 "match evpn default-route",
4601 MATCH_STR
4602 EVPN_HELP_STR
4603 "default EVPN type-5 route\n")
6fb219da 4604{
48cb7ea9
SP
4605 const char *xpath =
4606 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4607 char xpath_value[XPATH_MAXLEN];
4608
4609 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4610
4611 snprintf(xpath_value, sizeof(xpath_value),
4612 "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4613 xpath);
4614 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4615
4616 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4617}
4618
48cb7ea9
SP
4619DEFUN_YANG (no_match_evpn_default_route,
4620 no_match_evpn_default_route_cmd,
4621 "no match evpn default-route",
4622 NO_STR
4623 MATCH_STR
4624 EVPN_HELP_STR
4625 "default EVPN type-5 route\n")
6fb219da 4626{
48cb7ea9
SP
4627 const char *xpath =
4628 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4629
4630 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4631
4632 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4633}
4634
48cb7ea9
SP
4635DEFUN_YANG (match_evpn_rd,
4636 match_evpn_rd_cmd,
4637 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4638 MATCH_STR
4639 EVPN_HELP_STR
4640 "Route Distinguisher\n"
4641 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4642{
48cb7ea9
SP
4643 const char *xpath =
4644 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4645 char xpath_value[XPATH_MAXLEN];
4646
4647 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4648 snprintf(
4649 xpath_value, sizeof(xpath_value),
4650 "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4651 xpath);
4652 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4653
4654 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4655}
4656
48cb7ea9
SP
4657DEFUN_YANG (no_match_evpn_rd,
4658 no_match_evpn_rd_cmd,
4659 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4660 NO_STR
4661 MATCH_STR
4662 EVPN_HELP_STR
4663 "Route Distinguisher\n"
4664 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4665{
48cb7ea9
SP
4666 const char *xpath =
4667 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4668
4669 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4670 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4671}
4672
d0a4ee60
AD
4673DEFUN_YANG (set_evpn_gw_ip_ipv4,
4674 set_evpn_gw_ip_ipv4_cmd,
4675 "set evpn gateway-ip ipv4 A.B.C.D",
4676 SET_STR
4677 EVPN_HELP_STR
4678 "Set gateway IP for prefix advertisement route\n"
4679 "IPv4 address\n"
4680 "Gateway IP address in IPv4 format\n")
4681{
4682 int ret;
4683 union sockunion su;
4684 const char *xpath =
4685 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4686 char xpath_value[XPATH_MAXLEN];
4687
4688 ret = str2sockunion(argv[4]->arg, &su);
4689 if (ret < 0) {
4690 vty_out(vty, "%% Malformed gateway IP\n");
4691 return CMD_WARNING_CONFIG_FAILED;
4692 }
4693
e24a6977
DA
4694 if (su.sin.sin_addr.s_addr == 0 ||
4695 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4696 vty_out(vty,
4697 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4698 return CMD_WARNING_CONFIG_FAILED;
4699 }
4700
4701 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4702
4703 snprintf(xpath_value, sizeof(xpath_value),
4704 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4705 xpath);
4706
4707 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4708 return nb_cli_apply_changes(vty, NULL);
4709}
4710
4711DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4712 no_set_evpn_gw_ip_ipv4_cmd,
4713 "no set evpn gateway-ip ipv4 A.B.C.D",
4714 NO_STR
4715 SET_STR
4716 EVPN_HELP_STR
4717 "Set gateway IP for prefix advertisement route\n"
4718 "IPv4 address\n"
4719 "Gateway IP address in IPv4 format\n")
4720{
4721 int ret;
4722 union sockunion su;
4723 const char *xpath =
4724 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4725
4726 ret = str2sockunion(argv[5]->arg, &su);
4727 if (ret < 0) {
4728 vty_out(vty, "%% Malformed gateway IP\n");
4729 return CMD_WARNING_CONFIG_FAILED;
4730 }
4731
e24a6977
DA
4732 if (su.sin.sin_addr.s_addr == 0 ||
4733 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4734 vty_out(vty,
4735 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4736 return CMD_WARNING_CONFIG_FAILED;
4737 }
4738
4739 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4740
4741 return nb_cli_apply_changes(vty, NULL);
4742}
4743
4744DEFUN_YANG (set_evpn_gw_ip_ipv6,
4745 set_evpn_gw_ip_ipv6_cmd,
4746 "set evpn gateway-ip ipv6 X:X::X:X",
4747 SET_STR
4748 EVPN_HELP_STR
4749 "Set gateway IP for prefix advertisement route\n"
4750 "IPv6 address\n"
4751 "Gateway IP address in IPv6 format\n")
4752{
4753 int ret;
4754 union sockunion su;
4755 const char *xpath =
4756 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4757 char xpath_value[XPATH_MAXLEN];
4758
4759 ret = str2sockunion(argv[4]->arg, &su);
4760 if (ret < 0) {
4761 vty_out(vty, "%% Malformed gateway IP\n");
4762 return CMD_WARNING_CONFIG_FAILED;
4763 }
4764
4765 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4766 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4767 vty_out(vty,
4768 "%% Gateway IP cannot be a linklocal or multicast address\n");
4769 return CMD_WARNING_CONFIG_FAILED;
4770 }
4771
4772 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4773
4774 snprintf(xpath_value, sizeof(xpath_value),
4775 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4776 xpath);
4777
4778 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4779 return nb_cli_apply_changes(vty, NULL);
4780}
4781
4782DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4783 no_set_evpn_gw_ip_ipv6_cmd,
4784 "no set evpn gateway-ip ipv6 X:X::X:X",
4785 NO_STR
4786 SET_STR
4787 EVPN_HELP_STR
4788 "Set gateway IP for prefix advertisement route\n"
4789 "IPv4 address\n"
4790 "Gateway IP address in IPv4 format\n")
4791{
4792 int ret;
4793 union sockunion su;
4794 const char *xpath =
4795 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4796
4797 ret = str2sockunion(argv[5]->arg, &su);
4798 if (ret < 0) {
4799 vty_out(vty, "%% Malformed gateway IP\n");
4800 return CMD_WARNING_CONFIG_FAILED;
4801 }
4802
4803 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4804 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4805 vty_out(vty,
4806 "%% Gateway IP cannot be a linklocal or multicast address\n");
4807 return CMD_WARNING_CONFIG_FAILED;
4808 }
4809
4810 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4811
4812 return nb_cli_apply_changes(vty, NULL);
4813}
4814
48cb7ea9 4815DEFPY_YANG(match_vrl_source_vrf,
1dcc9e5b
CS
4816 match_vrl_source_vrf_cmd,
4817 "match source-vrf NAME$vrf_name",
4818 MATCH_STR
4819 "source vrf\n"
4820 "The VRF name\n")
4821{
48cb7ea9
SP
4822 const char *xpath =
4823 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4824 char xpath_value[XPATH_MAXLEN];
4825
4826 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4827 snprintf(xpath_value, sizeof(xpath_value),
4828 "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4829 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4830
4831 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4832}
4833
48cb7ea9 4834DEFPY_YANG(no_match_vrl_source_vrf,
1dcc9e5b
CS
4835 no_match_vrl_source_vrf_cmd,
4836 "no match source-vrf NAME$vrf_name",
48cb7ea9 4837 NO_STR MATCH_STR
1dcc9e5b
CS
4838 "source vrf\n"
4839 "The VRF name\n")
4840{
48cb7ea9
SP
4841 const char *xpath =
4842 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4843
4844 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4845 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4846}
4847
48cb7ea9 4848DEFPY_YANG (match_peer,
fee0f4c6 4849 match_peer_cmd,
48cb7ea9 4850 "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
fee0f4c6 4851 MATCH_STR
4852 "Match peer address\n"
6e13ed4a 4853 "IP address of peer\n"
8c3433e4 4854 "IPv6 address of peer\n"
1bb1c0cf 4855 "Interface name of peer or peer group name\n")
fee0f4c6 4856{
48cb7ea9
SP
4857 const char *xpath =
4858 "./match-condition[condition='frr-bgp-route-map:peer']";
4859 char xpath_value[XPATH_MAXLEN];
4860
4861 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4862
4863 if (addrv4_str) {
4864 snprintf(
4865 xpath_value, sizeof(xpath_value),
4866 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4867 xpath);
4868 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4869 addrv4_str);
4870 } else if (addrv6_str) {
4871 snprintf(
4872 xpath_value, sizeof(xpath_value),
4873 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4874 xpath);
4875 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4876 addrv6_str);
4877 } else {
4878 snprintf(
4879 xpath_value, sizeof(xpath_value),
4880 "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4881 xpath);
4882 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4883 }
4884
4885 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4886}
4887
48cb7ea9
SP
4888DEFUN_YANG (match_peer_local,
4889 match_peer_local_cmd,
4890 "match peer local",
4891 MATCH_STR
4892 "Match peer address\n"
4893 "Static or Redistributed routes\n")
fee0f4c6 4894{
48cb7ea9
SP
4895 const char *xpath =
4896 "./match-condition[condition='frr-bgp-route-map:peer']";
4897 char xpath_value[XPATH_MAXLEN];
4898
4899 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4900
4901 snprintf(xpath_value, sizeof(xpath_value),
4902 "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4903 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4904
4905 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4906}
4907
48cb7ea9
SP
4908DEFUN_YANG (no_match_peer,
4909 no_match_peer_cmd,
4910 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4911 NO_STR
4912 MATCH_STR
4913 "Match peer address\n"
4914 "Static or Redistributed routes\n"
4915 "IP address of peer\n"
4916 "IPv6 address of peer\n"
4917 "Interface name of peer\n")
fee0f4c6 4918{
48cb7ea9
SP
4919 const char *xpath =
4920 "./match-condition[condition='frr-bgp-route-map:peer']";
4921
4922 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4c9bd275 4923
48cb7ea9 4924 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4925}
4926
fa22080d 4927#ifdef HAVE_SCRIPTING
48cb7ea9
SP
4928DEFUN_YANG (match_script,
4929 match_script_cmd,
4930 "[no] match script WORD",
4931 NO_STR
4932 MATCH_STR
4933 "Execute script to determine match\n"
4934 "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
1d7c7ace 4935{
b4becb06
QY
4936 bool no = strmatch(argv[0]->text, "no");
4937 int i = 0;
4938 argv_find(argv, argc, "WORD", &i);
4939 const char *script = argv[i]->arg;
48cb7ea9
SP
4940 const char *xpath =
4941 "./match-condition[condition='frr-bgp-route-map:match-script']";
4942 char xpath_value[XPATH_MAXLEN];
b4becb06
QY
4943
4944 if (no) {
48cb7ea9
SP
4945 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4946 snprintf(xpath_value, sizeof(xpath_value),
4947 "%s/rmap-match-condition/frr-bgp-route-map:script",
4948 xpath);
4949 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4950 script);
4951
4952 return nb_cli_apply_changes(vty, NULL);
b4becb06 4953 }
48cb7ea9
SP
4954
4955 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4956 snprintf(xpath_value, sizeof(xpath_value),
4957 "%s/rmap-match-condition/frr-bgp-route-map:script",
4958 xpath);
4959 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4960 script);
4961
4962 return nb_cli_apply_changes(vty, NULL);
1d7c7ace 4963}
fa22080d 4964#endif /* HAVE_SCRIPTING */
fee0f4c6 4965
4c9bd275 4966/* match probability */
48cb7ea9
SP
4967DEFUN_YANG (match_probability,
4968 match_probability_cmd,
4969 "match probability (0-100)",
4970 MATCH_STR
4971 "Match portion of routes defined by percentage value\n"
4972 "Percentage of routes\n")
1add115a 4973{
d62a17ae 4974 int idx_number = 2;
48cb7ea9
SP
4975
4976 const char *xpath =
4977 "./match-condition[condition='frr-bgp-route-map:probability']";
4978 char xpath_value[XPATH_MAXLEN];
4979
4980 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4981 snprintf(xpath_value, sizeof(xpath_value),
4982 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4983 xpath);
4984 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4985 argv[idx_number]->arg);
4986
4987 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4988}
4989
4c9bd275 4990
48cb7ea9
SP
4991DEFUN_YANG (no_match_probability,
4992 no_match_probability_cmd,
4993 "no match probability [(1-99)]",
4994 NO_STR
4995 MATCH_STR
4996 "Match portion of routes defined by percentage value\n"
4997 "Percentage of routes\n")
1add115a 4998{
d62a17ae 4999 int idx_number = 3;
48cb7ea9
SP
5000 const char *xpath =
5001 "./match-condition[condition='frr-bgp-route-map:probability']";
5002 char xpath_value[XPATH_MAXLEN];
5003
5004 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5005
d62a17ae 5006 if (argc <= idx_number)
48cb7ea9
SP
5007 return nb_cli_apply_changes(vty, NULL);
5008
5009 snprintf(xpath_value, sizeof(xpath_value),
5010 "%s/rmap-match-condition/frr-bgp-route-map:probability",
5011 xpath);
5012 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5013 argv[idx_number]->arg);
5014
5015 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
5016}
5017
1add115a 5018
48cb7ea9 5019DEFPY_YANG (match_ip_route_source,
c1643bb7 5020 match_ip_route_source_cmd,
c60dec36 5021 "match ip route-source ACCESSLIST4_NAME",
c1643bb7 5022 MATCH_STR
5023 IP_STR
5024 "Match advertising source address of route\n"
7e869991 5025 "IP Access-list name\n")
c1643bb7 5026{
48cb7ea9
SP
5027 const char *xpath =
5028 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
5029 char xpath_value[XPATH_MAXLEN + 32];
d62a17ae 5030 int idx_acl = 3;
48cb7ea9
SP
5031
5032 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5033 snprintf(xpath_value, sizeof(xpath_value),
5034 "%s/rmap-match-condition/frr-bgp-route-map:list-name",
5035 xpath);
5036 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5037 argv[idx_acl]->arg);
5038
5039 return nb_cli_apply_changes(vty, NULL);
c1643bb7 5040}
5041
4c9bd275 5042
48cb7ea9
SP
5043DEFUN_YANG (no_match_ip_route_source,
5044 no_match_ip_route_source_cmd,
c60dec36 5045 "no match ip route-source [ACCESSLIST4_NAME]",
48cb7ea9
SP
5046 NO_STR
5047 MATCH_STR
5048 IP_STR
5049 "Match advertising source address of route\n"
7e869991 5050 "IP Access-list name\n")
c1643bb7 5051{
48cb7ea9
SP
5052 const char *xpath =
5053 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
c1643bb7 5054
48cb7ea9
SP
5055 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5056 return nb_cli_apply_changes(vty, NULL);
5057}
c1643bb7 5058
48cb7ea9
SP
5059DEFUN_YANG (match_ip_route_source_prefix_list,
5060 match_ip_route_source_prefix_list_cmd,
943224a1 5061 "match ip route-source prefix-list PREFIXLIST_NAME",
48cb7ea9
SP
5062 MATCH_STR
5063 IP_STR
5064 "Match advertising source address of route\n"
5065 "Match entries of prefix-lists\n"
5066 "IP prefix-list name\n")
c1643bb7 5067{
d62a17ae 5068 int idx_word = 4;
48cb7ea9
SP
5069 const char *xpath =
5070 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
5071 char xpath_value[XPATH_MAXLEN + 32];
5072
5073 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5074 snprintf(xpath_value, sizeof(xpath_value),
5075 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5076 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5077 argv[idx_word]->arg);
5078
5079 return nb_cli_apply_changes(vty, NULL);
c1643bb7 5080}
5081
4c9bd275 5082
48cb7ea9
SP
5083DEFUN_YANG (no_match_ip_route_source_prefix_list,
5084 no_match_ip_route_source_prefix_list_cmd,
943224a1 5085 "no match ip route-source prefix-list [PREFIXLIST_NAME]",
48cb7ea9
SP
5086 NO_STR
5087 MATCH_STR
5088 IP_STR
5089 "Match advertising source address of route\n"
5090 "Match entries of prefix-lists\n"
5091 "IP prefix-list name\n")
c1643bb7 5092{
48cb7ea9
SP
5093 const char *xpath =
5094 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
c1643bb7 5095
48cb7ea9
SP
5096 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5097 return nb_cli_apply_changes(vty, NULL);
5098}
c1643bb7 5099
48cb7ea9
SP
5100DEFUN_YANG (match_local_pref,
5101 match_local_pref_cmd,
5102 "match local-preference (0-4294967295)",
5103 MATCH_STR
5104 "Match local-preference of route\n"
5105 "Metric value\n")
af291c15 5106{
d62a17ae 5107 int idx_number = 2;
48cb7ea9
SP
5108
5109 const char *xpath =
5110 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5111 char xpath_value[XPATH_MAXLEN];
5112
5113 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5114 snprintf(xpath_value, sizeof(xpath_value),
5115 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5116 xpath);
5117 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5118 argv[idx_number]->arg);
5119
5120 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
5121}
5122
4c9bd275 5123
48cb7ea9
SP
5124DEFUN_YANG (no_match_local_pref,
5125 no_match_local_pref_cmd,
5126 "no match local-preference [(0-4294967295)]",
5127 NO_STR
5128 MATCH_STR
5129 "Match local preference of route\n"
5130 "Local preference value\n")
af291c15 5131{
d62a17ae 5132 int idx_localpref = 3;
48cb7ea9
SP
5133 const char *xpath =
5134 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5135 char xpath_value[XPATH_MAXLEN];
5136
5137 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5138
d62a17ae 5139 if (argc <= idx_localpref)
48cb7ea9
SP
5140 return nb_cli_apply_changes(vty, NULL);
5141
5142 snprintf(xpath_value, sizeof(xpath_value),
5143 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5144 xpath);
5145 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5146 argv[idx_localpref]->arg);
5147
5148 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
5149}
5150
2690f18c
DA
5151DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
5152 MATCH_STR
5153 "Match BGP community alias name\n"
5154 "BGP community alias name\n")
5155{
5156 const char *alias = argv[2]->arg;
5157 struct community_alias ca1;
5158 struct community_alias *lookup_alias;
5159
5160 const char *xpath =
5161 "./match-condition[condition='frr-bgp-route-map:match-alias']";
5162 char xpath_value[XPATH_MAXLEN];
5163
5164 memset(&ca1, 0, sizeof(ca1));
5165 strlcpy(ca1.alias, alias, sizeof(ca1.alias));
5166 lookup_alias = bgp_ca_alias_lookup(&ca1);
5167 if (!lookup_alias) {
5168 vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
5169 return CMD_WARNING_CONFIG_FAILED;
5170 }
5171
5172 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5173 snprintf(xpath_value, sizeof(xpath_value),
5174 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5175 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
5176
5177 return nb_cli_apply_changes(vty, NULL);
5178}
5179
5180
5181DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
5182 NO_STR MATCH_STR
5183 "Match BGP community alias name\n"
5184 "BGP community alias name\n")
5185{
5186 int idx_alias = 3;
5187 const char *xpath =
5188 "./match-condition[condition='frr-bgp-route-map:match-alias']";
5189 char xpath_value[XPATH_MAXLEN];
5190
5191 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5192
5193 if (argc <= idx_alias)
5194 return nb_cli_apply_changes(vty, NULL);
5195
5196 snprintf(xpath_value, sizeof(xpath_value),
5197 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5198 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5199 argv[idx_alias]->arg);
5200
5201 return nb_cli_apply_changes(vty, NULL);
5202}
af291c15 5203
48cb7ea9 5204DEFPY_YANG (match_community,
718e3744 5205 match_community_cmd,
a2099c1d 5206 "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
718e3744 5207 MATCH_STR
5208 "Match BGP community list\n"
5209 "Community-list number (standard)\n"
5210 "Community-list number (expanded)\n"
5211 "Community-list name\n"
5212 "Do exact matching of communities\n")
5213{
48cb7ea9
SP
5214 const char *xpath =
5215 "./match-condition[condition='frr-bgp-route-map:match-community']";
5216 char xpath_value[XPATH_MAXLEN];
5217 char xpath_match[XPATH_MAXLEN];
d62a17ae 5218 int idx_comm_list = 2;
718e3744 5219
48cb7ea9 5220 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 5221
48cb7ea9
SP
5222 snprintf(
5223 xpath_value, sizeof(xpath_value),
5224 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5225 xpath);
5226 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
718e3744 5227
48cb7ea9
SP
5228 if (argc == 4) {
5229 snprintf(
5230 xpath_match, sizeof(xpath_match),
5231 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5232 xpath);
5233 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5234 "true");
5235 } else {
5236 snprintf(
5237 xpath_match, sizeof(xpath_match),
5238 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5239 xpath);
5240 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5241 "false");
5242 }
718e3744 5243
48cb7ea9
SP
5244 return nb_cli_apply_changes(vty, NULL);
5245}
5246
5247DEFUN_YANG (no_match_community,
5248 no_match_community_cmd,
a2099c1d 5249 "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
5250 NO_STR
5251 MATCH_STR
5252 "Match BGP community list\n"
5253 "Community-list number (standard)\n"
5254 "Community-list number (expanded)\n"
5255 "Community-list name\n"
5256 "Do exact matching of communities\n")
5257{
5258 const char *xpath =
5259 "./match-condition[condition='frr-bgp-route-map:match-community']";
5260
5261 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5262 return nb_cli_apply_changes(vty, NULL);
5263}
5264
5265DEFPY_YANG (match_lcommunity,
5266 match_lcommunity_cmd,
a2099c1d 5267 "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
48cb7ea9
SP
5268 MATCH_STR
5269 "Match BGP large community list\n"
5270 "Large Community-list number (standard)\n"
5271 "Large Community-list number (expanded)\n"
5272 "Large Community-list name\n"
5273 "Do exact matching of communities\n")
5274{
5275 const char *xpath =
5276 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5277 char xpath_value[XPATH_MAXLEN];
5278 char xpath_match[XPATH_MAXLEN];
03ff9a14 5279 int idx_lcomm_list = 2;
03ff9a14 5280
48cb7ea9 5281 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
03ff9a14 5282
48cb7ea9
SP
5283 snprintf(
5284 xpath_value, sizeof(xpath_value),
5285 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5286 xpath);
5287 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
03ff9a14 5288
48cb7ea9
SP
5289 if (argc == 4) {
5290 snprintf(
5291 xpath_match, sizeof(xpath_match),
5292 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5293 xpath);
5294 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5295 "true");
5296 } else {
5297 snprintf(
5298 xpath_match, sizeof(xpath_match),
5299 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5300 xpath);
5301 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5302 "false");
5303 }
03ff9a14 5304
48cb7ea9 5305 return nb_cli_apply_changes(vty, NULL);
57d187bc 5306}
718e3744 5307
48cb7ea9
SP
5308DEFUN_YANG (no_match_lcommunity,
5309 no_match_lcommunity_cmd,
a2099c1d 5310 "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
5311 NO_STR
5312 MATCH_STR
5313 "Match BGP large community list\n"
5314 "Large Community-list number (standard)\n"
5315 "Large Community-list number (expanded)\n"
5316 "Large Community-list name\n"
5317 "Do exact matching of communities\n")
57d187bc 5318{
48cb7ea9
SP
5319 const char *xpath =
5320 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5321
5322 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5323 return nb_cli_apply_changes(vty, NULL);
57d187bc 5324}
718e3744 5325
48cb7ea9
SP
5326DEFPY_YANG (match_ecommunity,
5327 match_ecommunity_cmd,
a2099c1d 5328 "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
48cb7ea9
SP
5329 MATCH_STR
5330 "Match BGP/VPN extended community list\n"
5331 "Extended community-list number (standard)\n"
5332 "Extended community-list number (expanded)\n"
5333 "Extended community-list name\n")
73ffb25b 5334{
48cb7ea9
SP
5335 const char *xpath =
5336 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5337 char xpath_value[XPATH_MAXLEN];
d62a17ae 5338 int idx_comm_list = 2;
48cb7ea9
SP
5339
5340 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5341
5342 snprintf(
5343 xpath_value, sizeof(xpath_value),
5344 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5345 xpath);
5346 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5347
5348 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5349}
5350
4c9bd275 5351
48cb7ea9
SP
5352DEFUN_YANG (no_match_ecommunity,
5353 no_match_ecommunity_cmd,
a2099c1d 5354 "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
48cb7ea9
SP
5355 NO_STR
5356 MATCH_STR
5357 "Match BGP/VPN extended community list\n"
5358 "Extended community-list number (standard)\n"
5359 "Extended community-list number (expanded)\n"
5360 "Extended community-list name\n")
73ffb25b 5361{
48cb7ea9
SP
5362 const char *xpath =
5363 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5364
5365 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5366 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5367}
5368
73ffb25b 5369
48cb7ea9
SP
5370DEFUN_YANG (match_aspath,
5371 match_aspath_cmd,
2a342b35 5372 "match as-path AS_PATH_FILTER_NAME",
48cb7ea9
SP
5373 MATCH_STR
5374 "Match BGP AS path list\n"
5375 "AS path access-list name\n")
718e3744 5376{
d62a17ae 5377 int idx_word = 2;
48cb7ea9
SP
5378
5379 const char *xpath =
5380 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5381 char xpath_value[XPATH_MAXLEN];
5382
5383 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5384 snprintf(xpath_value, sizeof(xpath_value),
5385 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5386 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5387 argv[idx_word]->arg);
5388
5389 return nb_cli_apply_changes(vty, NULL);
718e3744 5390}
5391
4c9bd275 5392
48cb7ea9
SP
5393DEFUN_YANG (no_match_aspath,
5394 no_match_aspath_cmd,
2a342b35 5395 "no match as-path [AS_PATH_FILTER_NAME]",
48cb7ea9
SP
5396 NO_STR
5397 MATCH_STR
5398 "Match BGP AS path list\n"
5399 "AS path access-list name\n")
718e3744 5400{
48cb7ea9
SP
5401 const char *xpath =
5402 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
718e3744 5403
48cb7ea9 5404 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
718e3744 5405
48cb7ea9
SP
5406 return nb_cli_apply_changes(vty, NULL);
5407}
5408
5409DEFUN_YANG (match_origin,
5410 match_origin_cmd,
5411 "match origin <egp|igp|incomplete>",
5412 MATCH_STR
5413 "BGP origin code\n"
5414 "remote EGP\n"
5415 "local IGP\n"
5416 "unknown heritage\n")
718e3744 5417{
d62a17ae 5418 int idx_origin = 2;
48cb7ea9
SP
5419 const char *origin_type;
5420 const char *xpath =
5421 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5422 char xpath_value[XPATH_MAXLEN];
5423
d62a17ae 5424 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
48cb7ea9
SP
5425 origin_type = "igp";
5426 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5427 origin_type = "egp";
5428 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5429 origin_type = "incomplete";
5430 else {
5431 vty_out(vty, "%% Invalid match origin type\n");
5432 return CMD_WARNING_CONFIG_FAILED;
5433 }
5434
5435 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5436 snprintf(xpath_value, sizeof(xpath_value),
5437 "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5438 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
718e3744 5439
48cb7ea9 5440 return nb_cli_apply_changes(vty, NULL);
718e3744 5441}
5442
4c9bd275 5443
48cb7ea9
SP
5444DEFUN_YANG (no_match_origin,
5445 no_match_origin_cmd,
5446 "no match origin [<egp|igp|incomplete>]",
5447 NO_STR
5448 MATCH_STR
5449 "BGP origin code\n"
5450 "remote EGP\n"
5451 "local IGP\n"
5452 "unknown heritage\n")
718e3744 5453{
48cb7ea9
SP
5454 const char *xpath =
5455 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5456 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5457 return nb_cli_apply_changes(vty, NULL);
718e3744 5458}
5459
48cb7ea9
SP
5460DEFUN_YANG (set_table_id,
5461 set_table_id_cmd,
5462 "set table (1-4294967295)",
5463 SET_STR
5464 "export route to non-main kernel table\n"
5465 "Kernel routing table id\n")
951745bd 5466{
48cb7ea9
SP
5467 int idx_number = 2;
5468 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5469 char xpath_value[XPATH_MAXLEN];
5470
5471 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5472 snprintf(xpath_value, sizeof(xpath_value),
5473 "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5474 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5475 argv[idx_number]->arg);
5476 return nb_cli_apply_changes(vty, NULL);
5477}
5478
5479DEFUN_YANG (no_set_table_id,
5480 no_set_table_id_cmd,
5481 "no set table",
5482 NO_STR
5483 SET_STR
5484 "export route to non-main kernel table\n")
5485{
5486 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5487 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5488 return nb_cli_apply_changes(vty, NULL);
5489}
5490
5491DEFUN_YANG (set_ip_nexthop_peer,
5492 set_ip_nexthop_peer_cmd,
5493 "[no] set ip next-hop peer-address",
5494 NO_STR
5495 SET_STR
5496 IP_STR
5497 "Next hop address\n"
5498 "Use peer address (for BGP only)\n")
5499{
5500 char xpath_value[XPATH_MAXLEN];
5501 const char *xpath =
5502 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5503
5504 if (strmatch(argv[0]->text, "no"))
5505 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5506 else {
5507 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5508 snprintf(xpath_value, sizeof(xpath_value),
5509 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5510 xpath);
5511 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5512 "peer-address");
5513 }
5514 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5515}
5516
48cb7ea9
SP
5517DEFUN_YANG (set_ip_nexthop_unchanged,
5518 set_ip_nexthop_unchanged_cmd,
5519 "[no] set ip next-hop unchanged",
5520 NO_STR
5521 SET_STR
5522 IP_STR
5523 "Next hop address\n"
5524 "Don't modify existing Next hop address\n")
951745bd 5525{
48cb7ea9
SP
5526 char xpath_value[XPATH_MAXLEN];
5527 const char *xpath =
5528 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
951745bd 5529
48cb7ea9
SP
5530 if (strmatch(argv[0]->text, "no"))
5531 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5532 else {
5533 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5534 snprintf(xpath_value, sizeof(xpath_value),
5535 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5536 xpath);
5537 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5538 "unchanged");
5539 }
5540 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5541}
5542
48cb7ea9
SP
5543DEFUN_YANG (set_distance,
5544 set_distance_cmd,
d58e6dbc 5545 "set distance (1-255)",
48cb7ea9
SP
5546 SET_STR
5547 "BGP Administrative Distance to use\n"
5548 "Distance value\n")
af5cd0a5 5549{
48cb7ea9
SP
5550 int idx_number = 2;
5551 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5552 char xpath_value[XPATH_MAXLEN];
89602edb 5553
48cb7ea9
SP
5554 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5555 snprintf(xpath_value, sizeof(xpath_value),
5556 "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5557 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5558 argv[idx_number]->arg);
5559 return nb_cli_apply_changes(vty, NULL);
af5cd0a5 5560}
5561
48cb7ea9
SP
5562DEFUN_YANG (no_set_distance,
5563 no_set_distance_cmd,
d58e6dbc 5564 "no set distance [(1-255)]",
48cb7ea9
SP
5565 NO_STR SET_STR
5566 "BGP Administrative Distance to use\n"
5567 "Distance value\n")
316e074d 5568{
48cb7ea9 5569 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
cca30ba8 5570
48cb7ea9
SP
5571 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5572 return nb_cli_apply_changes(vty, NULL);
718e3744 5573}
5574
1bb550b6
PG
5575DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
5576 "[no] set l3vpn next-hop encapsulation gre",
5577 NO_STR SET_STR
5578 "L3VPN operations\n"
5579 "Next hop Information\n"
5580 "Encapsulation options (for BGP only)\n"
5581 "Accept L3VPN traffic over GRE encapsulation\n")
5582{
5583 const char *xpath =
5584 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
5585 const char *xpath_value =
5586 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
5587 enum nb_operation operation;
5588
5589 if (no)
5590 operation = NB_OP_DESTROY;
5591 else
5592 operation = NB_OP_CREATE;
5593
5594 nb_cli_enqueue_change(vty, xpath, operation, NULL);
5595 if (operation == NB_OP_DESTROY)
5596 return nb_cli_apply_changes(vty, NULL);
5597
5598 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
5599
5600 return nb_cli_apply_changes(vty, NULL);
5601}
5602
48cb7ea9
SP
5603DEFUN_YANG (set_local_pref,
5604 set_local_pref_cmd,
5605 "set local-preference WORD",
5606 SET_STR
5607 "BGP local preference path attribute\n"
5608 "Preference value (0-4294967295)\n")
7b7d48e5
DS
5609{
5610 int idx_number = 2;
48cb7ea9
SP
5611 const char *xpath =
5612 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5613 char xpath_value[XPATH_MAXLEN];
7b7d48e5 5614
48cb7ea9
SP
5615 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5616 snprintf(xpath_value, sizeof(xpath_value),
5617 "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5618 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5619 argv[idx_number]->arg);
5620 return nb_cli_apply_changes(vty, NULL);
7b7d48e5
DS
5621}
5622
48cb7ea9
SP
5623DEFUN_YANG (no_set_local_pref,
5624 no_set_local_pref_cmd,
5625 "no set local-preference [WORD]",
5626 NO_STR
5627 SET_STR
5628 "BGP local preference path attribute\n"
5629 "Preference value (0-4294967295)\n")
7b7d48e5 5630{
48cb7ea9
SP
5631 const char *xpath =
5632 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5633
5634 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5635 return nb_cli_apply_changes(vty, NULL);
7b7d48e5 5636}
718e3744 5637
48cb7ea9
SP
5638DEFUN_YANG (set_weight,
5639 set_weight_cmd,
5640 "set weight (0-4294967295)",
5641 SET_STR
5642 "BGP weight for routing table\n"
5643 "Weight value\n")
718e3744 5644{
d62a17ae 5645 int idx_number = 2;
48cb7ea9
SP
5646 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5647 char xpath_value[XPATH_MAXLEN];
4c9bd275 5648
48cb7ea9
SP
5649 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5650 snprintf(xpath_value, sizeof(xpath_value),
5651 "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5652 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5653 argv[idx_number]->arg);
5654 return nb_cli_apply_changes(vty, NULL);
718e3744 5655}
5656
48cb7ea9
SP
5657DEFUN_YANG (no_set_weight,
5658 no_set_weight_cmd,
5659 "no set weight [(0-4294967295)]",
5660 NO_STR
5661 SET_STR
5662 "BGP weight for routing table\n"
5663 "Weight value\n")
718e3744 5664{
48cb7ea9 5665 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
718e3744 5666
48cb7ea9
SP
5667 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5668 return nb_cli_apply_changes(vty, NULL);
718e3744 5669}
5670
48cb7ea9
SP
5671DEFUN_YANG (set_label_index,
5672 set_label_index_cmd,
5673 "set label-index (0-1048560)",
5674 SET_STR
5675 "Label index to associate with the prefix\n"
5676 "Label index value\n")
d990e384 5677{
d62a17ae 5678 int idx_number = 2;
48cb7ea9
SP
5679 const char *xpath =
5680 "./set-action[action='frr-bgp-route-map:label-index']";
5681 char xpath_value[XPATH_MAXLEN];
5682
5683 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5684 snprintf(xpath_value, sizeof(xpath_value),
5685 "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5686 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5687 argv[idx_number]->arg);
5688 return nb_cli_apply_changes(vty, NULL);
d990e384
DS
5689}
5690
48cb7ea9
SP
5691DEFUN_YANG (no_set_label_index,
5692 no_set_label_index_cmd,
5693 "no set label-index [(0-1048560)]",
5694 NO_STR
5695 SET_STR
5696 "Label index to associate with the prefix\n"
5697 "Label index value\n")
d990e384 5698{
48cb7ea9
SP
5699 const char *xpath =
5700 "./set-action[action='frr-bgp-route-map:label-index']";
5701
5702 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5703 return nb_cli_apply_changes(vty, NULL);
d990e384 5704}
718e3744 5705
48cb7ea9
SP
5706DEFUN_YANG (set_aspath_prepend_asn,
5707 set_aspath_prepend_asn_cmd,
8079a413 5708 "set as-path prepend ASNUM...",
48cb7ea9
SP
5709 SET_STR
5710 "Transform BGP AS_PATH attribute\n"
5711 "Prepend to the as-path\n"
8079a413 5712 AS_STR)
718e3744 5713{
d62a17ae 5714 int idx_asn = 3;
5715 int ret;
5716 char *str;
8079a413 5717 struct aspath *aspath;
718e3744 5718
d62a17ae 5719 str = argv_concat(argv, argc, idx_asn);
718e3744 5720
48cb7ea9
SP
5721 const char *xpath =
5722 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5723 char xpath_value[XPATH_MAXLEN];
5724
8079a413
PG
5725 aspath = route_aspath_compile(str);
5726 if (!aspath) {
5727 vty_out(vty, "%% Invalid AS path value %s\n", str);
5728 return CMD_WARNING_CONFIG_FAILED;
5729 }
5730 route_aspath_free(aspath);
48cb7ea9
SP
5731 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5732 snprintf(xpath_value, sizeof(xpath_value),
5733 "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5734 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5735 ret = nb_cli_apply_changes(vty, NULL);
5736 XFREE(MTYPE_TMP, str);
d62a17ae 5737 return ret;
718e3744 5738}
5739
48cb7ea9
SP
5740DEFUN_YANG (set_aspath_prepend_lastas,
5741 set_aspath_prepend_lastas_cmd,
5742 "set as-path prepend last-as (1-10)",
5743 SET_STR
5744 "Transform BGP AS_PATH attribute\n"
5745 "Prepend to the as-path\n"
6ba0adac 5746 "Use the last AS-number in the as-path\n"
48cb7ea9 5747 "Number of times to insert\n")
12dcf78e 5748{
48cb7ea9
SP
5749 int idx_num = 4;
5750
5751 const char *xpath =
5752 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5753 char xpath_value[XPATH_MAXLEN];
5754
5755 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5756 snprintf(xpath_value, sizeof(xpath_value),
5757 "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5758 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5759 argv[idx_num]->arg);
5760 return nb_cli_apply_changes(vty, NULL);
12dcf78e 5761}
bc3dd427 5762
77e3d821
DA
5763DEFPY_YANG (set_aspath_replace_asn,
5764 set_aspath_replace_asn_cmd,
8079a413 5765 "set as-path replace <any|ASNUM>$replace",
77e3d821
DA
5766 SET_STR
5767 "Transform BGP AS_PATH attribute\n"
5768 "Replace AS number to local AS number\n"
5769 "Replace any AS number to local AS number\n"
8079a413 5770 "Replace a specific AS number in plain or dotted format to local AS number\n")
77e3d821
DA
5771{
5772 const char *xpath =
5773 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5774 char xpath_value[XPATH_MAXLEN];
8079a413
PG
5775 as_t as_value;
5776
5777 if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) {
5778 vty_out(vty, "%% Invalid AS value %s\n", replace);
5779 return CMD_WARNING_CONFIG_FAILED;
5780 }
77e3d821
DA
5781
5782 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5783 snprintf(xpath_value, sizeof(xpath_value),
5784 "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5785 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5786 return nb_cli_apply_changes(vty, NULL);
5787}
5788
5789DEFPY_YANG (no_set_aspath_replace_asn,
5790 no_set_aspath_replace_asn_cmd,
8079a413 5791 "no set as-path replace [<any|ASNUM>]",
77e3d821
DA
5792 NO_STR
5793 SET_STR
5794 "Transform BGP AS_PATH attribute\n"
5795 "Replace AS number to local AS number\n"
5796 "Replace any AS number to local AS number\n"
8079a413 5797 "Replace a specific AS number in plain or dotted format to local AS number\n")
77e3d821
DA
5798{
5799 const char *xpath =
5800 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5801
5802 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5803 return nb_cli_apply_changes(vty, NULL);
5804}
5805
48cb7ea9
SP
5806DEFUN_YANG (no_set_aspath_prepend,
5807 no_set_aspath_prepend_cmd,
8079a413 5808 "no set as-path prepend [ASNUM]",
48cb7ea9
SP
5809 NO_STR
5810 SET_STR
5811 "Transform BGP AS_PATH attribute\n"
5812 "Prepend to the as-path\n"
8079a413 5813 AS_STR)
718e3744 5814{
48cb7ea9
SP
5815 const char *xpath =
5816 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
a7f93f3e 5817
48cb7ea9
SP
5818 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5819 return nb_cli_apply_changes(vty, NULL);
718e3744 5820}
5821
48cb7ea9
SP
5822DEFUN_YANG (no_set_aspath_prepend_lastas,
5823 no_set_aspath_prepend_lastas_cmd,
5824 "no set as-path prepend last-as [(1-10)]",
5825 NO_STR
5826 SET_STR
5827 "Transform BGP AS_PATH attribute\n"
5828 "Prepend to the as-path\n"
5829 "Use the peers AS-number\n"
5830 "Number of times to insert\n")
9131e6e8 5831{
48cb7ea9
SP
5832 const char *xpath =
5833 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5834
5835 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5836 return nb_cli_apply_changes(vty, NULL);
9131e6e8 5837}
718e3744 5838
48cb7ea9
SP
5839DEFUN_YANG (set_aspath_exclude,
5840 set_aspath_exclude_cmd,
8079a413 5841 "set as-path exclude ASNUM...",
48cb7ea9
SP
5842 SET_STR
5843 "Transform BGP AS-path attribute\n"
5844 "Exclude from the as-path\n"
8079a413 5845 AS_STR)
841f7a57 5846{
d62a17ae 5847 int idx_asn = 3;
5848 int ret;
5849 char *str;
8079a413 5850 struct aspath *aspath;
841f7a57 5851
d62a17ae 5852 str = argv_concat(argv, argc, idx_asn);
48cb7ea9
SP
5853
5854 const char *xpath =
5855 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5856 char xpath_value[XPATH_MAXLEN];
5857
8079a413
PG
5858 aspath = route_aspath_compile(str);
5859 if (!aspath) {
5860 vty_out(vty, "%% Invalid AS path value %s\n", str);
5861 return CMD_WARNING_CONFIG_FAILED;
5862 }
5863 route_aspath_free(aspath);
48cb7ea9
SP
5864 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5865 snprintf(xpath_value, sizeof(xpath_value),
5866 "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5867 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5868 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5869 XFREE(MTYPE_TMP, str);
5870 return ret;
841f7a57
DO
5871}
5872
48cb7ea9
SP
5873DEFUN_YANG (no_set_aspath_exclude,
5874 no_set_aspath_exclude_cmd,
8079a413 5875 "no set as-path exclude ASNUM...",
48cb7ea9
SP
5876 NO_STR
5877 SET_STR
5878 "Transform BGP AS_PATH attribute\n"
5879 "Exclude from the as-path\n"
5880 "AS number\n")
841f7a57 5881{
48cb7ea9
SP
5882 const char *xpath =
5883 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
841f7a57 5884
48cb7ea9
SP
5885 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5886 return nb_cli_apply_changes(vty, NULL);
841f7a57
DO
5887}
5888
48cb7ea9
SP
5889ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5890 "no set as-path exclude",
5891 NO_STR SET_STR
5892 "Transform BGP AS_PATH attribute\n"
5893 "Exclude from the as-path\n")
841f7a57 5894
48cb7ea9
SP
5895DEFUN_YANG (set_community,
5896 set_community_cmd,
5897 "set community AA:NN...",
5898 SET_STR
5899 "BGP community attribute\n"
5900 COMMUNITY_VAL_STR)
718e3744 5901{
d62a17ae 5902 int idx_aa_nn = 2;
5903 int i;
5904 int first = 0;
5905 int additive = 0;
5906 struct buffer *b;
5907 struct community *com = NULL;
5908 char *str;
48cb7ea9 5909 char *argstr = NULL;
d62a17ae 5910 int ret;
5911
48cb7ea9
SP
5912 const char *xpath =
5913 "./set-action[action='frr-bgp-route-map:set-community']";
5914 char xpath_value[XPATH_MAXLEN];
5915
5916 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5917 snprintf(xpath_value, sizeof(xpath_value),
5918 "%s/rmap-set-action/frr-bgp-route-map:community-string",
5919 xpath);
5920
d62a17ae 5921 b = buffer_new(1024);
5922
5923 for (i = idx_aa_nn; i < argc; i++) {
5924 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5925 == 0) {
5926 additive = 1;
5927 continue;
5928 }
5929
5930 if (first)
5931 buffer_putc(b, ' ');
5932 else
5933 first = 1;
5934
81a57d81
DA
5935#if CONFDATE > 20230801
5936CPP_NOTICE("Deprecate COMMUNITY_INTERNET BGP community")
5937#endif
d62a17ae 5938 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5939 == 0) {
5940 buffer_putstr(b, "internet");
81a57d81
DA
5941 vty_out(vty, "%% `internet` community is deprecated\n");
5942 zlog_warn("`internet` community is deprecated");
d62a17ae 5943 continue;
5944 }
5945 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5946 == 0) {
5947 buffer_putstr(b, "local-AS");
5948 continue;
5949 }
5950 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5951 && strncmp(argv[i]->arg, "no-advertise",
5952 strlen(argv[i]->arg))
5953 == 0) {
5954 buffer_putstr(b, "no-advertise");
5955 continue;
5956 }
5957 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5958 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5959 == 0) {
5960 buffer_putstr(b, "no-export");
5961 continue;
5962 }
2721dd61
DA
5963 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
5964 == 0) {
5965 buffer_putstr(b, "blackhole");
5966 continue;
5967 }
a4d82a8a
PZ
5968 if (strncmp(argv[i]->arg, "graceful-shutdown",
5969 strlen(argv[i]->arg))
7f323236
DW
5970 == 0) {
5971 buffer_putstr(b, "graceful-shutdown");
5972 continue;
5973 }
d62a17ae 5974 buffer_putstr(b, argv[i]->arg);
5975 }
5976 buffer_putc(b, '\0');
5977
5978 /* Fetch result string then compile it to communities attribute. */
5979 str = buffer_getstr(b);
5980 buffer_free(b);
5981
c0945b78 5982 if (str)
d62a17ae 5983 com = community_str2com(str);
d62a17ae 5984
5985 /* Can't compile user input into communities attribute. */
5986 if (!com) {
c0945b78
DA
5987 vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
5988 XFREE(MTYPE_TMP, str);
d62a17ae 5989 return CMD_WARNING_CONFIG_FAILED;
5990 }
c0945b78 5991 XFREE(MTYPE_TMP, str);
d62a17ae 5992
5993 /* Set communites attribute string. */
c0945b78 5994 str = community_str(com, false, false);
d62a17ae 5995
5996 if (additive) {
552d6491
QY
5997 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
5998 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
5999 strlcpy(argstr, str, argstr_sz);
6000 strlcat(argstr, " additive", argstr_sz);
48cb7ea9 6001 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
d62a17ae 6002 } else
48cb7ea9
SP
6003 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6004
6005 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 6006
48cb7ea9
SP
6007 if (argstr)
6008 XFREE(MTYPE_TMP, argstr);
3c1f53de 6009 community_free(&com);
d62a17ae 6010
6011 return ret;
718e3744 6012}
6013
48cb7ea9
SP
6014DEFUN_YANG (set_community_none,
6015 set_community_none_cmd,
6016 "set community none",
6017 SET_STR
6018 "BGP community attribute\n"
6019 "No community attribute\n")
718e3744 6020{
48cb7ea9
SP
6021 const char *xpath =
6022 "./set-action[action='frr-bgp-route-map:set-community']";
6023 char xpath_value[XPATH_MAXLEN];
6024
6025 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6026
6027 snprintf(xpath_value, sizeof(xpath_value),
6028 "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
6029 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6030 return nb_cli_apply_changes(vty, NULL);
718e3744 6031}
6032
48cb7ea9
SP
6033DEFUN_YANG (no_set_community,
6034 no_set_community_cmd,
6035 "no set community AA:NN...",
6036 NO_STR
6037 SET_STR
6038 "BGP community attribute\n"
6039 COMMUNITY_VAL_STR)
718e3744 6040{
48cb7ea9
SP
6041 const char *xpath =
6042 "./set-action[action='frr-bgp-route-map:set-community']";
718e3744 6043
48cb7ea9
SP
6044 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6045 return nb_cli_apply_changes(vty, NULL);
6046}
2929de9e 6047
48cb7ea9
SP
6048ALIAS_YANG (no_set_community,
6049 no_set_community_short_cmd,
6050 "no set community",
6051 NO_STR
6052 SET_STR
6053 "BGP community attribute\n")
718e3744 6054
48cb7ea9 6055DEFPY_YANG (set_community_delete,
718e3744 6056 set_community_delete_cmd,
a2099c1d 6057 "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
718e3744 6058 SET_STR
6059 "set BGP community list (for deletion)\n"
6060 "Community-list number (standard)\n"
5e3edbf5 6061 "Community-list number (expanded)\n"
718e3744 6062 "Community-list name\n"
6063 "Delete matching communities\n")
6064{
48cb7ea9
SP
6065 const char *xpath =
6066 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
6067 char xpath_value[XPATH_MAXLEN];
d62a17ae 6068 int idx_comm_list = 2;
718e3744 6069
48cb7ea9
SP
6070 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6071
6072 snprintf(xpath_value, sizeof(xpath_value),
6073 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6074 xpath);
6075 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6076 argv[idx_comm_list]->arg);
6077
6078 return nb_cli_apply_changes(vty, NULL);
718e3744 6079
718e3744 6080}
6081
48cb7ea9
SP
6082DEFUN_YANG (no_set_community_delete,
6083 no_set_community_delete_cmd,
a2099c1d 6084 "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
48cb7ea9
SP
6085 NO_STR
6086 SET_STR
6087 "set BGP community list (for deletion)\n"
6088 "Community-list number (standard)\n"
6089 "Community-list number (expanded)\n"
6090 "Community-list name\n"
6091 "Delete matching communities\n")
718e3744 6092{
48cb7ea9
SP
6093 const char *xpath =
6094 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
6095
6096 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6097 return nb_cli_apply_changes(vty, NULL);
718e3744 6098}
6099
48cb7ea9
SP
6100DEFUN_YANG (set_lcommunity,
6101 set_lcommunity_cmd,
6102 "set large-community AA:BB:CC...",
6103 SET_STR
6104 "BGP large community attribute\n"
6105 "Large Community number in aa:bb:cc format or additive\n")
57d187bc 6106{
d62a17ae 6107 char *str;
48cb7ea9
SP
6108 int ret;
6109 const char *xpath =
6110 "./set-action[action='frr-bgp-route-map:set-large-community']";
6111 char xpath_value[XPATH_MAXLEN];
6112
6113 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 6114
48cb7ea9
SP
6115 snprintf(xpath_value, sizeof(xpath_value),
6116 "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
6117 xpath);
d62a17ae 6118 str = argv_concat(argv, argc, 2);
48cb7ea9
SP
6119 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6120 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 6121 XFREE(MTYPE_TMP, str);
d62a17ae 6122 return ret;
57d187bc
JS
6123}
6124
48cb7ea9
SP
6125DEFUN_YANG (set_lcommunity_none,
6126 set_lcommunity_none_cmd,
6127 "set large-community none",
6128 SET_STR
6129 "BGP large community attribute\n"
6130 "No large community attribute\n")
57d187bc 6131{
48cb7ea9
SP
6132 const char *xpath =
6133 "./set-action[action='frr-bgp-route-map:set-large-community']";
6134 char xpath_value[XPATH_MAXLEN];
6135
6136 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6137
6138 snprintf(xpath_value, sizeof(xpath_value),
6139 "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
6140 xpath);
6141 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6142 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
6143}
6144
48cb7ea9
SP
6145DEFUN_YANG (no_set_lcommunity,
6146 no_set_lcommunity_cmd,
6147 "no set large-community none",
6148 NO_STR
6149 SET_STR
6150 "BGP large community attribute\n"
6151 "No community attribute\n")
57d187bc 6152{
48cb7ea9
SP
6153 const char *xpath =
6154 "./set-action[action='frr-bgp-route-map:set-large-community']";
6155
6156 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6157 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
6158}
6159
48cb7ea9
SP
6160DEFUN_YANG (no_set_lcommunity1,
6161 no_set_lcommunity1_cmd,
6162 "no set large-community AA:BB:CC...",
6163 NO_STR
6164 SET_STR
6165 "BGP large community attribute\n"
6166 "Large community in AA:BB:CC... format or additive\n")
52951b63 6167{
48cb7ea9
SP
6168 const char *xpath =
6169 "./set-action[action='frr-bgp-route-map:set-large-community']";
6170
6171 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6172 return nb_cli_apply_changes(vty, NULL);
52951b63 6173}
57d187bc 6174
48cb7ea9
SP
6175ALIAS_YANG (no_set_lcommunity1,
6176 no_set_lcommunity1_short_cmd,
6177 "no set large-community",
6178 NO_STR
6179 SET_STR
6180 "BGP large community attribute\n")
76a20aa9 6181
48cb7ea9 6182DEFPY_YANG (set_lcommunity_delete,
57d187bc 6183 set_lcommunity_delete_cmd,
a2099c1d 6184 "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
57d187bc
JS
6185 SET_STR
6186 "set BGP large community list (for deletion)\n"
6187 "Large Community-list number (standard)\n"
6188 "Large Communitly-list number (expanded)\n"
6189 "Large Community-list name\n"
6190 "Delete matching large communities\n")
6191{
48cb7ea9
SP
6192 const char *xpath =
6193 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6194 char xpath_value[XPATH_MAXLEN];
4cae2269 6195 int idx_lcomm_list = 2;
4cae2269 6196
48cb7ea9 6197 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 6198
48cb7ea9
SP
6199 snprintf(xpath_value, sizeof(xpath_value),
6200 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6201 xpath);
6202 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6203 argv[idx_lcomm_list]->arg);
6204
6205 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
6206}
6207
48cb7ea9
SP
6208DEFUN_YANG (no_set_lcommunity_delete,
6209 no_set_lcommunity_delete_cmd,
a2099c1d 6210 "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
48cb7ea9
SP
6211 NO_STR
6212 SET_STR
6213 "set BGP large community list (for deletion)\n"
6214 "Large Community-list number (standard)\n"
6215 "Large Communitly-list number (expanded)\n"
6216 "Large Community-list name\n"
6217 "Delete matching large communities\n")
57d187bc 6218{
48cb7ea9
SP
6219 const char *xpath =
6220 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6221
6222 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6223 return nb_cli_apply_changes(vty, NULL);
57d187bc 6224}
718e3744 6225
48cb7ea9
SP
6226ALIAS_YANG (no_set_lcommunity_delete,
6227 no_set_lcommunity_delete_short_cmd,
6228 "no set large-comm-list",
6229 NO_STR
6230 SET_STR
6231 "set BGP large community list (for deletion)\n")
76a20aa9 6232
48cb7ea9
SP
6233DEFUN_YANG (set_ecommunity_rt,
6234 set_ecommunity_rt_cmd,
6235 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6236 SET_STR
6237 "BGP extended community attribute\n"
6238 "Route Target extended community\n"
6239 "VPN extended community\n")
718e3744 6240{
d62a17ae 6241 int idx_asn_nn = 3;
d62a17ae 6242 char *str;
48cb7ea9
SP
6243 int ret;
6244 const char *xpath =
6245 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6246 char xpath_value[XPATH_MAXLEN];
6247
6248 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 6249
48cb7ea9
SP
6250 snprintf(xpath_value, sizeof(xpath_value),
6251 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
d62a17ae 6252 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
6253 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6254 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 6255 XFREE(MTYPE_TMP, str);
d62a17ae 6256 return ret;
718e3744 6257}
6258
48cb7ea9
SP
6259DEFUN_YANG (no_set_ecommunity_rt,
6260 no_set_ecommunity_rt_cmd,
6261 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6262 NO_STR
6263 SET_STR
6264 "BGP extended community attribute\n"
6265 "Route Target extended community\n"
6266 "VPN extended community\n")
6267{
6268 const char *xpath =
6269 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6270 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6271 return nb_cli_apply_changes(vty, NULL);
6272}
6273
6274ALIAS_YANG (no_set_ecommunity_rt,
6275 no_set_ecommunity_rt_short_cmd,
6276 "no set extcommunity rt",
6277 NO_STR
6278 SET_STR
6279 "BGP extended community attribute\n"
6280 "Route Target extended community\n")
6281
6282DEFUN_YANG (set_ecommunity_soo,
6283 set_ecommunity_soo_cmd,
6284 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6285 SET_STR
6286 "BGP extended community attribute\n"
6287 "Site-of-Origin extended community\n"
6288 "VPN extended community\n")
718e3744 6289{
d62a17ae 6290 int idx_asn_nn = 3;
d62a17ae 6291 char *str;
48cb7ea9
SP
6292 int ret;
6293 const char *xpath =
6294 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6295 char xpath_value[XPATH_MAXLEN];
718e3744 6296
48cb7ea9
SP
6297 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6298
6299 snprintf(xpath_value, sizeof(xpath_value),
6300 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
6301 xpath);
d62a17ae 6302 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
6303 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6304 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 6305 XFREE(MTYPE_TMP, str);
6306 return ret;
718e3744 6307}
6308
48cb7ea9
SP
6309DEFUN_YANG (no_set_ecommunity_soo,
6310 no_set_ecommunity_soo_cmd,
6311 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6312 NO_STR
6313 SET_STR
6314 "BGP extended community attribute\n"
6315 "Site-of-Origin extended community\n"
6316 "VPN extended community\n")
6317{
6318 const char *xpath =
6319 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6320 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6321 return nb_cli_apply_changes(vty, NULL);
6322}
6323
6324ALIAS_YANG (no_set_ecommunity_soo,
6325 no_set_ecommunity_soo_short_cmd,
6326 "no set extcommunity soo",
6327 NO_STR
6328 SET_STR
6329 "GP extended community attribute\n"
6330 "Site-of-Origin extended community\n")
6331
bb4dcdd1
DA
6332DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
6333 "set extcommunity none",
6334 SET_STR
6335 "BGP extended community attribute\n"
6336 "No extended community attribute\n")
6337{
6338 const char *xpath =
6339 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6340 char xpath_value[XPATH_MAXLEN];
6341
6342 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6343
6344 snprintf(xpath_value, sizeof(xpath_value),
6345 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6346 xpath);
6347 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6348 return nb_cli_apply_changes(vty, NULL);
6349}
6350
6351DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6352 "no set extcommunity none",
6353 NO_STR SET_STR
6354 "BGP extended community attribute\n"
6355 "No extended community attribute\n")
6356{
6357 const char *xpath =
6358 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6359 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6360 return nb_cli_apply_changes(vty, NULL);
6361}
6362
48cb7ea9
SP
6363DEFUN_YANG (set_ecommunity_lb,
6364 set_ecommunity_lb_cmd,
6365 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6366 SET_STR
6367 "BGP extended community attribute\n"
6368 "Link bandwidth extended community\n"
6369 "Bandwidth value in Mbps\n"
6370 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6371 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6372 "Attribute is set as non-transitive\n")
718e3744 6373{
48cb7ea9 6374 int idx_lb = 3;
3b225ee7 6375 int idx_non_transitive = 0;
48cb7ea9
SP
6376 const char *xpath =
6377 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6378 char xpath_lb_type[XPATH_MAXLEN];
6379 char xpath_bandwidth[XPATH_MAXLEN];
6380 char xpath_non_transitive[XPATH_MAXLEN];
6381
6382 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6383
6384 snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6385 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6386 xpath);
6387 snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6388 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6389 xpath);
6390 snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6391 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6392 xpath);
6393
6394 if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6395 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6396 "cumulative-bandwidth");
6397 else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6398 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6399 "computed-bandwidth");
6400 else {
6401 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6402 "explicit-bandwidth");
6403 nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6404 argv[idx_lb]->arg);
6405 }
718e3744 6406
3b225ee7 6407 if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
48cb7ea9
SP
6408 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6409 "true");
6410 else
6411 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6412 "false");
6413
6414 return nb_cli_apply_changes(vty, NULL);
6415}
6416
6417DEFUN_YANG (no_set_ecommunity_lb,
6418 no_set_ecommunity_lb_cmd,
6419 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6420 NO_STR
6421 SET_STR
6422 "BGP extended community attribute\n"
6423 "Link bandwidth extended community\n"
6424 "Bandwidth value in Mbps\n"
6425 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6426 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6427 "Attribute is set as non-transitive\n")
6428{
6429 const char *xpath =
6430 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6431
6432 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6433 return nb_cli_apply_changes(vty, NULL);
6434}
6435
6436ALIAS_YANG (no_set_ecommunity_lb,
6437 no_set_ecommunity_lb_short_cmd,
6438 "no set extcommunity bandwidth",
6439 NO_STR
6440 SET_STR
6441 "BGP extended community attribute\n"
6442 "Link bandwidth extended community\n")
6443
c9a25614
DA
6444DEFPY_YANG (set_ecommunity_nt,
6445 set_ecommunity_nt_cmd,
6446 "set extcommunity nt RTLIST...",
6447 SET_STR
6448 "BGP extended community attribute\n"
6449 "Node Target extended community\n"
6450 "Node Target ID\n")
6451{
6452 int idx_nt = 3;
6453 char *str;
6454 int ret;
6455 const char *xpath =
6456 "./set-action[action='frr-bgp-route-map:set-extcommunity-nt']";
6457 char xpath_value[XPATH_MAXLEN];
6458
6459 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6460
6461 snprintf(xpath_value, sizeof(xpath_value),
6462 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-nt", xpath);
6463 str = argv_concat(argv, argc, idx_nt);
6464 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6465 ret = nb_cli_apply_changes(vty, NULL);
6466 XFREE(MTYPE_TMP, str);
6467 return ret;
6468}
6469
6470DEFPY_YANG (no_set_ecommunity_nt,
6471 no_set_ecommunity_nt_cmd,
6472 "no set extcommunity nt RTLIST...",
6473 NO_STR
6474 SET_STR
6475 "BGP extended community attribute\n"
6476 "Node Target extended community\n"
6477 "Node Target ID\n")
6478{
6479 const char *xpath =
6480 "./set-action[action='frr-bgp-route-map:set-extcommunity-nt']";
6481 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6482 return nb_cli_apply_changes(vty, NULL);
6483}
6484
6485ALIAS_YANG (no_set_ecommunity_nt,
6486 no_set_ecommunity_nt_short_cmd,
6487 "no set extcommunity nt",
6488 NO_STR
6489 SET_STR
6490 "BGP extended community attribute\n"
6491 "Node Target extended community\n")
6492
48cb7ea9
SP
6493DEFUN_YANG (set_origin,
6494 set_origin_cmd,
6495 "set origin <egp|igp|incomplete>",
6496 SET_STR
6497 "BGP origin code\n"
6498 "remote EGP\n"
6499 "local IGP\n"
6500 "unknown heritage\n")
ca9ac3ef 6501{
48cb7ea9
SP
6502 int idx_origin = 2;
6503 const char *origin_type;
6504 const char *xpath =
6505 "./set-action[action='frr-bgp-route-map:set-origin']";
6506 char xpath_value[XPATH_MAXLEN];
ca9ac3ef 6507
48cb7ea9
SP
6508 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6509 origin_type = "igp";
6510 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6511 origin_type = "egp";
6512 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6513 origin_type = "incomplete";
6514 else {
6515 vty_out(vty, "%% Invalid match origin type\n");
6516 return CMD_WARNING_CONFIG_FAILED;
6517 }
ca9ac3ef 6518
48cb7ea9
SP
6519 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6520 snprintf(xpath_value, sizeof(xpath_value),
6521 "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6522 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
ca9ac3ef 6523
48cb7ea9 6524 return nb_cli_apply_changes(vty, NULL);
ca9ac3ef 6525}
6526
48cb7ea9
SP
6527DEFUN_YANG (no_set_origin,
6528 no_set_origin_cmd,
6529 "no set origin [<egp|igp|incomplete>]",
6530 NO_STR
6531 SET_STR
6532 "BGP origin code\n"
6533 "remote EGP\n"
6534 "local IGP\n"
6535 "unknown heritage\n")
718e3744 6536{
48cb7ea9
SP
6537 const char *xpath =
6538 "./set-action[action='frr-bgp-route-map:set-origin']";
718e3744 6539
48cb7ea9
SP
6540 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6541 return nb_cli_apply_changes(vty, NULL);
718e3744 6542}
6543
48cb7ea9
SP
6544DEFUN_YANG (set_atomic_aggregate,
6545 set_atomic_aggregate_cmd,
6546 "set atomic-aggregate",
6547 SET_STR
6548 "BGP atomic aggregate attribute\n" )
718e3744 6549{
48cb7ea9
SP
6550 const char *xpath =
6551 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6552 char xpath_value[XPATH_MAXLEN];
718e3744 6553
48cb7ea9
SP
6554 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6555 snprintf(xpath_value, sizeof(xpath_value),
6556 "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6557 xpath);
6558 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
718e3744 6559
48cb7ea9 6560 return nb_cli_apply_changes(vty, NULL);
718e3744 6561}
6562
48cb7ea9
SP
6563DEFUN_YANG (no_set_atomic_aggregate,
6564 no_set_atomic_aggregate_cmd,
6565 "no set atomic-aggregate",
6566 NO_STR
6567 SET_STR
6568 "BGP atomic aggregate attribute\n" )
718e3744 6569{
48cb7ea9
SP
6570 const char *xpath =
6571 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6572
6573 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6574 return nb_cli_apply_changes(vty, NULL);
718e3744 6575}
6576
97a52c82
DA
6577DEFPY_YANG (set_aigp_metric,
6578 set_aigp_metric_cmd,
6579 "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
6580 SET_STR
6581 "BGP AIGP attribute (AIGP Metric TLV)\n"
6582 "AIGP Metric value from IGP protocol\n"
6583 "Manual AIGP Metric value\n")
6584{
6585 const char *xpath =
6586 "./set-action[action='frr-bgp-route-map:aigp-metric']";
6587 char xpath_value[XPATH_MAXLEN];
6588
6589 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6590 snprintf(xpath_value, sizeof(xpath_value),
6591 "%s/rmap-set-action/frr-bgp-route-map:aigp-metric", xpath);
6592 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, aigp_metric);
6593
6594 return nb_cli_apply_changes(vty, NULL);
6595}
6596
6597DEFPY_YANG (no_set_aigp_metric,
6598 no_set_aigp_metric_cmd,
6599 "no set aigp-metric [<igp-metric|(1-4294967295)>]",
6600 NO_STR
6601 SET_STR
6602 "BGP AIGP attribute (AIGP Metric TLV)\n"
6603 "AIGP Metric value from IGP protocol\n"
6604 "Manual AIGP Metric value\n")
6605{
6606 const char *xpath =
6607 "./set-action[action='frr-bgp-route-map:aigp-metric']";
6608
6609 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6610 return nb_cli_apply_changes(vty, NULL);
6611}
6612
48cb7ea9
SP
6613DEFUN_YANG (set_aggregator_as,
6614 set_aggregator_as_cmd,
8079a413 6615 "set aggregator as ASNUM A.B.C.D",
48cb7ea9
SP
6616 SET_STR
6617 "BGP aggregator attribute\n"
6618 "AS number of aggregator\n"
8079a413 6619 AS_STR
48cb7ea9 6620 "IP address of aggregator\n")
718e3744 6621{
d62a17ae 6622 int idx_number = 3;
6623 int idx_ipv4 = 4;
48cb7ea9
SP
6624 char xpath_asn[XPATH_MAXLEN];
6625 char xpath_addr[XPATH_MAXLEN];
6626 const char *xpath =
6627 "./set-action[action='frr-bgp-route-map:aggregator']";
8079a413
PG
6628 as_t as_value;
6629
6630 if (!asn_str2asn(argv[idx_number]->arg, &as_value)) {
6631 vty_out(vty, "%% Invalid AS value %s\n", argv[idx_number]->arg);
6632 return CMD_WARNING_CONFIG_FAILED;
6633 }
e52702f2 6634
48cb7ea9 6635 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 6636
48cb7ea9
SP
6637 snprintf(
6638 xpath_asn, sizeof(xpath_asn),
6639 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6640 xpath);
6641 nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6642 argv[idx_number]->arg);
718e3744 6643
48cb7ea9
SP
6644 snprintf(
6645 xpath_addr, sizeof(xpath_addr),
6646 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6647 xpath);
6648 nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6649 argv[idx_ipv4]->arg);
718e3744 6650
48cb7ea9 6651 return nb_cli_apply_changes(vty, NULL);
718e3744 6652}
6653
48cb7ea9
SP
6654DEFUN_YANG (no_set_aggregator_as,
6655 no_set_aggregator_as_cmd,
8079a413 6656 "no set aggregator as [ASNUM A.B.C.D]",
48cb7ea9
SP
6657 NO_STR
6658 SET_STR
6659 "BGP aggregator attribute\n"
6660 "AS number of aggregator\n"
8079a413 6661 AS_STR
48cb7ea9 6662 "IP address of aggregator\n")
718e3744 6663{
48cb7ea9
SP
6664 const char *xpath =
6665 "./set-action[action='frr-bgp-route-map:aggregator']";
718e3744 6666
48cb7ea9
SP
6667 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6668 return nb_cli_apply_changes(vty, NULL);
6669}
718e3744 6670
48cb7ea9
SP
6671DEFUN_YANG (match_ipv6_next_hop,
6672 match_ipv6_next_hop_cmd,
bc63ba98
DA
6673 "match ipv6 next-hop ACCESSLIST6_NAME",
6674 MATCH_STR
6675 IPV6_STR
6676 "Match IPv6 next-hop address of route\n"
6677 "IPv6 access-list name\n")
6678{
6679 const char *xpath =
6680 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6681 char xpath_value[XPATH_MAXLEN];
6682
6683 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6684 snprintf(xpath_value, sizeof(xpath_value),
6685 "%s/rmap-match-condition/list-name", xpath);
6686 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6687 argv[argc - 1]->arg);
6688
6689 return nb_cli_apply_changes(vty, NULL);
6690}
6691
6692DEFUN_YANG (no_match_ipv6_next_hop,
6693 no_match_ipv6_next_hop_cmd,
6694 "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6695 NO_STR
6696 MATCH_STR
6697 IPV6_STR
6698 "Match IPv6 next-hop address of route\n"
6699 "IPv6 access-list name\n")
6700{
6701 const char *xpath =
6702 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6703
6704 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6705 return nb_cli_apply_changes(vty, NULL);
6706}
6707
6708DEFUN_YANG (match_ipv6_next_hop_address,
6709 match_ipv6_next_hop_address_cmd,
03030106 6710 "match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6711 MATCH_STR
6712 IPV6_STR
6713 "Match IPv6 next-hop address of route\n"
03030106 6714 "IPv6 address\n"
48cb7ea9
SP
6715 "IPv6 address of next hop\n")
6716{
6717 const char *xpath =
6718 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6719 char xpath_value[XPATH_MAXLEN];
718e3744 6720
48cb7ea9
SP
6721 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6722 snprintf(xpath_value, sizeof(xpath_value),
6723 "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6724 xpath);
bc63ba98
DA
6725 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6726 argv[argc - 1]->arg);
718e3744 6727
48cb7ea9 6728 return nb_cli_apply_changes(vty, NULL);
718e3744 6729}
6730
bc63ba98
DA
6731DEFUN_YANG (no_match_ipv6_next_hop_address,
6732 no_match_ipv6_next_hop_address_cmd,
03030106 6733 "no match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6734 NO_STR
6735 MATCH_STR
6736 IPV6_STR
6737 "Match IPv6 next-hop address of route\n"
03030106 6738 "IPv6 address\n"
48cb7ea9 6739 "IPv6 address of next hop\n")
718e3744 6740{
48cb7ea9
SP
6741 const char *xpath =
6742 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
718e3744 6743
48cb7ea9
SP
6744 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6745 return nb_cli_apply_changes(vty, NULL);
718e3744 6746}
6747
bc63ba98 6748ALIAS_HIDDEN (match_ipv6_next_hop_address,
03030106
IR
6749 match_ipv6_next_hop_old_cmd,
6750 "match ipv6 next-hop X:X::X:X",
6751 MATCH_STR
6752 IPV6_STR
6753 "Match IPv6 next-hop address of route\n"
6754 "IPv6 address of next hop\n")
6755
bc63ba98 6756ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
03030106
IR
6757 no_match_ipv6_next_hop_old_cmd,
6758 "no match ipv6 next-hop X:X::X:X",
6759 NO_STR
6760 MATCH_STR
6761 IPV6_STR
6762 "Match IPv6 next-hop address of route\n"
6763 "IPv6 address of next hop\n")
6764
82f191a2
DA
6765DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6766 match_ipv6_next_hop_prefix_list_cmd,
6767 "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6768 MATCH_STR
6769 IPV6_STR
6770 "Match IPv6 next-hop address of route\n"
6771 "Match entries by prefix-list\n"
6772 "IPv6 prefix-list name\n")
6773{
6774 const char *xpath =
6775 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6776 char xpath_value[XPATH_MAXLEN];
6777
6778 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6779 snprintf(xpath_value, sizeof(xpath_value),
6780 "%s/rmap-match-condition/list-name", xpath);
6781 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6782 argv[argc - 1]->arg);
6783
6784 return nb_cli_apply_changes(vty, NULL);
6785}
6786
6787DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6788 no_match_ipv6_next_hop_prefix_list_cmd,
6789 "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6790 NO_STR
6791 MATCH_STR
6792 IPV6_STR
6793 "Match IPv6 next-hop address of route\n"
6794 "Match entries by prefix-list\n"
6795 "IPv6 prefix-list name\n")
6796{
6797 const char *xpath =
6798 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6799
6800 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6801 return nb_cli_apply_changes(vty, NULL);
6802}
6803
48cb7ea9 6804DEFPY_YANG (match_ipv4_next_hop,
be7735b3 6805 match_ipv4_next_hop_cmd,
17ac51eb 6806 "match ip next-hop address A.B.C.D",
be7735b3
PG
6807 MATCH_STR
6808 IP_STR
6809 "Match IP next-hop address of route\n"
6810 "IP address\n"
6811 "IP address of next-hop\n")
6812{
48cb7ea9
SP
6813 const char *xpath =
6814 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6815 char xpath_value[XPATH_MAXLEN];
6816
6817 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6818 snprintf(xpath_value, sizeof(xpath_value),
6819 "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6820 xpath);
6821 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
be7735b3 6822
48cb7ea9 6823 return nb_cli_apply_changes(vty, NULL);
17ac51eb 6824}
be7735b3 6825
48cb7ea9 6826DEFPY_YANG (no_match_ipv4_next_hop,
17ac51eb
DS
6827 no_match_ipv4_next_hop_cmd,
6828 "no match ip next-hop address [A.B.C.D]",
6829 NO_STR
6830 MATCH_STR
6831 IP_STR
6832 "Match IP next-hop address of route\n"
6833 "IP address\n"
6834 "IP address of next-hop\n")
6835{
48cb7ea9
SP
6836 const char *xpath =
6837 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6838
6839 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6840 return nb_cli_apply_changes(vty, NULL);
be7735b3 6841}
718e3744 6842
48cb7ea9
SP
6843DEFUN_YANG (set_ipv6_nexthop_peer,
6844 set_ipv6_nexthop_peer_cmd,
6845 "set ipv6 next-hop peer-address",
6846 SET_STR
6847 IPV6_STR
6848 "Next hop address\n"
6849 "Use peer address (for BGP only)\n")
90916ac2 6850{
48cb7ea9
SP
6851 const char *xpath =
6852 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6853 char xpath_value[XPATH_MAXLEN];
6854
6855 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6856 snprintf(xpath_value, sizeof(xpath_value),
6857 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6858 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6859
6860 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6861}
6862
48cb7ea9
SP
6863DEFUN_YANG (no_set_ipv6_nexthop_peer,
6864 no_set_ipv6_nexthop_peer_cmd,
6865 "no set ipv6 next-hop peer-address",
6866 NO_STR
6867 SET_STR
6868 IPV6_STR
6869 "IPv6 next-hop address\n"
6870 "Use peer address (for BGP only)\n")
90916ac2 6871{
48cb7ea9
SP
6872 const char *xpath =
6873 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6874
6875 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6876 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6877}
6878
48cb7ea9
SP
6879DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6880 set_ipv6_nexthop_prefer_global_cmd,
6881 "set ipv6 next-hop prefer-global",
6882 SET_STR
6883 IPV6_STR
6884 "IPv6 next-hop address\n"
6885 "Prefer global over link-local if both exist\n")
161995ea 6886{
48cb7ea9
SP
6887 const char *xpath =
6888 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6889 char xpath_value[XPATH_MAXLEN];
6890
6891 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6892 snprintf(xpath_value, sizeof(xpath_value),
6893 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6894 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6895
6896 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6897}
6898
48cb7ea9
SP
6899DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6900 no_set_ipv6_nexthop_prefer_global_cmd,
6901 "no set ipv6 next-hop prefer-global",
6902 NO_STR
6903 SET_STR
6904 IPV6_STR
6905 "IPv6 next-hop address\n"
6906 "Prefer global over link-local if both exist\n")
161995ea 6907{
48cb7ea9
SP
6908 const char *xpath =
6909 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6910
6911 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6912 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6913}
6914
48cb7ea9
SP
6915DEFUN_YANG (set_ipv6_nexthop_global,
6916 set_ipv6_nexthop_global_cmd,
6917 "set ipv6 next-hop global X:X::X:X",
6918 SET_STR
6919 IPV6_STR
6920 "IPv6 next-hop address\n"
6921 "IPv6 global address\n"
6922 "IPv6 address of next hop\n")
718e3744 6923{
d62a17ae 6924 int idx_ipv6 = 4;
48cb7ea9
SP
6925 const char *xpath =
6926 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6927 char xpath_value[XPATH_MAXLEN];
bf8b3d27 6928
48cb7ea9
SP
6929 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6930 snprintf(xpath_value, sizeof(xpath_value),
6931 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6932 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6933 argv[idx_ipv6]->arg);
bf8b3d27 6934
48cb7ea9 6935 return nb_cli_apply_changes(vty, NULL);
718e3744 6936}
6937
48cb7ea9
SP
6938DEFUN_YANG (no_set_ipv6_nexthop_global,
6939 no_set_ipv6_nexthop_global_cmd,
6940 "no set ipv6 next-hop global X:X::X:X",
6941 NO_STR
6942 SET_STR
6943 IPV6_STR
6944 "IPv6 next-hop address\n"
6945 "IPv6 global address\n"
6946 "IPv6 address of next hop\n")
718e3744 6947{
48cb7ea9
SP
6948 const char *xpath =
6949 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6950
6951 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6952 return nb_cli_apply_changes(vty, NULL);
718e3744 6953}
718e3744 6954
d6902373 6955#ifdef KEEP_OLD_VPN_COMMANDS
48cb7ea9
SP
6956DEFUN_YANG (set_vpn_nexthop,
6957 set_vpn_nexthop_cmd,
6958 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6959 SET_STR
6960 "VPNv4 information\n"
6961 "VPN next-hop address\n"
6962 "IP address of next hop\n"
6963 "VPNv6 information\n"
6964 "VPN next-hop address\n"
6965 "IPv6 address of next hop\n")
718e3744 6966{
d62a17ae 6967 int idx_ip = 3;
6968 afi_t afi;
6969 int idx = 0;
4ad4ae64 6970 char xpath_value[XPATH_MAXLEN];
d62a17ae 6971
6972 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6973 if (afi == AFI_IP) {
6974 const char *xpath =
6975 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6976
6977 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6978 snprintf(
6979 xpath_value, sizeof(xpath_value),
6980 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6981 xpath);
6982 } else {
6983 const char *xpath =
6984 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6985
6986 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6987 snprintf(
6988 xpath_value, sizeof(xpath_value),
6989 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6990 xpath);
6991 }
6992
6993 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6994 argv[idx_ip]->arg);
6995
6996 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6997 }
48cb7ea9 6998
d62a17ae 6999 return CMD_SUCCESS;
d6902373 7000}
a4b2b610 7001
48cb7ea9
SP
7002DEFUN_YANG (no_set_vpn_nexthop,
7003 no_set_vpn_nexthop_cmd,
7004 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
7005 NO_STR
7006 SET_STR
7007 "VPNv4 information\n"
7008 "VPN next-hop address\n"
7009 "IP address of next hop\n"
7010 "VPNv6 information\n"
7011 "VPN next-hop address\n"
7012 "IPv6 address of next hop\n")
718e3744 7013{
d62a17ae 7014 afi_t afi;
7015 int idx = 0;
7016
d62a17ae 7017 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
7018 if (afi == AFI_IP) {
7019 const char *xpath =
7020 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7021 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7022 } else {
7023 const char *xpath =
7024 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7025 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7026 }
7027 return nb_cli_apply_changes(vty, NULL);
d62a17ae 7028 }
7029 return CMD_SUCCESS;
d6902373
PG
7030}
7031#endif /* KEEP_OLD_VPN_COMMANDS */
7032
7be9666f 7033DEFPY_YANG (set_ipx_vpn_nexthop,
48cb7ea9 7034 set_ipx_vpn_nexthop_cmd,
7be9666f 7035 "set <ipv4|ipv6> vpn next-hop <A.B.C.D$addrv4|X:X::X:X$addrv6>",
48cb7ea9
SP
7036 SET_STR
7037 "IPv4 information\n"
7038 "IPv6 information\n"
7039 "VPN information\n"
7040 "VPN next-hop address\n"
7041 "IP address of next hop\n"
7042 "IPv6 address of next hop\n")
d6902373 7043{
d62a17ae 7044 int idx_ip = 4;
7045 afi_t afi;
7046 int idx = 0;
48cb7ea9 7047 char xpath_value[XPATH_MAXLEN];
d62a17ae 7048
7049 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9 7050 if (afi == AFI_IP) {
7be9666f
DA
7051 if (addrv6_str) {
7052 vty_out(vty, "%% IPv4 next-hop expected\n");
7053 return CMD_WARNING_CONFIG_FAILED;
7054 }
7055
48cb7ea9
SP
7056 const char *xpath =
7057 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7058
7059 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7060 snprintf(
7061 xpath_value, sizeof(xpath_value),
7062 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
7063 xpath);
7064 } else {
7be9666f
DA
7065 if (addrv4_str) {
7066 vty_out(vty, "%% IPv6 next-hop expected\n");
7067 return CMD_WARNING_CONFIG_FAILED;
7068 }
7069
48cb7ea9
SP
7070 const char *xpath =
7071 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7072
7073 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7074 snprintf(
7075 xpath_value, sizeof(xpath_value),
7076 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
7077 xpath);
7078 }
7079 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7080 argv[idx_ip]->arg);
7081 return nb_cli_apply_changes(vty, NULL);
d62a17ae 7082 }
7083 return CMD_SUCCESS;
718e3744 7084}
7085
48cb7ea9
SP
7086DEFUN_YANG (no_set_ipx_vpn_nexthop,
7087 no_set_ipx_vpn_nexthop_cmd,
7088 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
7089 NO_STR
7090 SET_STR
7091 "IPv4 information\n"
7092 "IPv6 information\n"
7093 "VPN information\n"
7094 "VPN next-hop address\n"
7095 "IP address of next hop\n"
7096 "IPv6 address of next hop\n")
7097{
d62a17ae 7098 afi_t afi;
7099 int idx = 0;
7100
d62a17ae 7101 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9
SP
7102 if (afi == AFI_IP) {
7103 const char *xpath =
7104 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7105 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7106 } else {
7107 const char *xpath =
7108 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7109 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7110 }
7111 return nb_cli_apply_changes(vty, NULL);
d62a17ae 7112 }
7113 return CMD_SUCCESS;
d6902373 7114}
718e3744 7115
48cb7ea9
SP
7116DEFUN_YANG (set_originator_id,
7117 set_originator_id_cmd,
7118 "set originator-id A.B.C.D",
7119 SET_STR
7120 "BGP originator ID attribute\n"
7121 "IP address of originator\n")
718e3744 7122{
d62a17ae 7123 int idx_ipv4 = 2;
48cb7ea9
SP
7124 const char *xpath =
7125 "./set-action[action='frr-bgp-route-map:originator-id']";
7126 char xpath_value[XPATH_MAXLEN];
718e3744 7127
48cb7ea9
SP
7128 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7129 snprintf(xpath_value, sizeof(xpath_value),
7130 "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
7131 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7132 argv[idx_ipv4]->arg);
4c9bd275 7133
48cb7ea9
SP
7134 return nb_cli_apply_changes(vty, NULL);
7135}
7136
7137DEFUN_YANG (no_set_originator_id,
7138 no_set_originator_id_cmd,
7139 "no set originator-id [A.B.C.D]",
7140 NO_STR
7141 SET_STR
7142 "BGP originator ID attribute\n"
7143 "IP address of originator\n")
718e3744 7144{
48cb7ea9
SP
7145 const char *xpath =
7146 "./set-action[action='frr-bgp-route-map:originator-id']";
0d702986 7147
48cb7ea9
SP
7148 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7149 return nb_cli_apply_changes(vty, NULL);
718e3744 7150}
7151
324e8b1f
DA
7152DEFPY_YANG (match_rpki_extcommunity,
7153 match_rpki_extcommunity_cmd,
7154 "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
7155 NO_STR
7156 MATCH_STR
7157 "BGP RPKI (Origin Validation State) extended community attribute\n"
7158 "Valid prefix\n"
7159 "Invalid prefix\n"
7160 "Prefix not found\n")
7161{
7162 const char *xpath =
7163 "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
7164 char xpath_value[XPATH_MAXLEN];
7165
7166 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7167
7168 if (!no) {
7169 snprintf(
7170 xpath_value, sizeof(xpath_value),
7171 "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
7172 xpath);
7173 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7174 argv[2]->arg);
7175 }
7176
7177 return nb_cli_apply_changes(vty, NULL);
7178}
7179
718e3744 7180/* Initialization of route map. */
d62a17ae 7181void bgp_route_map_init(void)
7182{
7183 route_map_init();
7184
7185 route_map_add_hook(bgp_route_map_add);
7186 route_map_delete_hook(bgp_route_map_delete);
7187 route_map_event_hook(bgp_route_map_event);
7188
7189 route_map_match_interface_hook(generic_match_add);
7190 route_map_no_match_interface_hook(generic_match_delete);
7191
7192 route_map_match_ip_address_hook(generic_match_add);
7193 route_map_no_match_ip_address_hook(generic_match_delete);
7194
7195 route_map_match_ip_address_prefix_list_hook(generic_match_add);
7196 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
7197
7198 route_map_match_ip_next_hop_hook(generic_match_add);
7199 route_map_no_match_ip_next_hop_hook(generic_match_delete);
7200
bc63ba98
DA
7201 route_map_match_ipv6_next_hop_hook(generic_match_add);
7202 route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
7203
d62a17ae 7204 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
7205 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
7206
61ad901e
DA
7207 route_map_match_ip_next_hop_type_hook(generic_match_add);
7208 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
7209
d62a17ae 7210 route_map_match_ipv6_address_hook(generic_match_add);
7211 route_map_no_match_ipv6_address_hook(generic_match_delete);
7212
7213 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
7214 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
7215
61ad901e
DA
7216 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
7217 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
7218
82f191a2
DA
7219 route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
7220 route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
7221
d62a17ae 7222 route_map_match_metric_hook(generic_match_add);
7223 route_map_no_match_metric_hook(generic_match_delete);
7224
7225 route_map_match_tag_hook(generic_match_add);
7226 route_map_no_match_tag_hook(generic_match_delete);
7227
ef3e0d04
SM
7228 route_map_set_srte_color_hook(generic_set_add);
7229 route_map_no_set_srte_color_hook(generic_set_delete);
7230
d62a17ae 7231 route_map_set_ip_nexthop_hook(generic_set_add);
7232 route_map_no_set_ip_nexthop_hook(generic_set_delete);
7233
7234 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
7235 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
7236
7237 route_map_set_metric_hook(generic_set_add);
7238 route_map_no_set_metric_hook(generic_set_delete);
7239
7240 route_map_set_tag_hook(generic_set_add);
7241 route_map_no_set_tag_hook(generic_set_delete);
7242
7243 route_map_install_match(&route_match_peer_cmd);
2690f18c 7244 route_map_install_match(&route_match_alias_cmd);
d62a17ae 7245 route_map_install_match(&route_match_local_pref_cmd);
fa22080d 7246#ifdef HAVE_SCRIPTING
b4becb06 7247 route_map_install_match(&route_match_script_cmd);
1d7c7ace 7248#endif
d62a17ae 7249 route_map_install_match(&route_match_ip_address_cmd);
7250 route_map_install_match(&route_match_ip_next_hop_cmd);
7251 route_map_install_match(&route_match_ip_route_source_cmd);
7252 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
7253 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 7254 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 7255 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
7256 route_map_install_match(&route_match_aspath_cmd);
7257 route_map_install_match(&route_match_community_cmd);
7258 route_map_install_match(&route_match_lcommunity_cmd);
7259 route_map_install_match(&route_match_ecommunity_cmd);
7260 route_map_install_match(&route_match_local_pref_cmd);
7261 route_map_install_match(&route_match_metric_cmd);
7262 route_map_install_match(&route_match_origin_cmd);
7263 route_map_install_match(&route_match_probability_cmd);
7264 route_map_install_match(&route_match_interface_cmd);
7265 route_map_install_match(&route_match_tag_cmd);
d37ba549 7266 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 7267 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 7268 route_map_install_match(&route_match_evpn_route_type_cmd);
196c6b09 7269 route_map_install_match(&route_match_evpn_rd_cmd);
6fb219da 7270 route_map_install_match(&route_match_evpn_default_route_cmd);
1dcc9e5b 7271 route_map_install_match(&route_match_vrl_source_vrf_cmd);
d62a17ae 7272
d0a4ee60
AD
7273 route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
7274 route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
951745bd 7275 route_map_install_set(&route_set_table_id_cmd);
ef3e0d04 7276 route_map_install_set(&route_set_srte_color_cmd);
d62a17ae 7277 route_map_install_set(&route_set_ip_nexthop_cmd);
7278 route_map_install_set(&route_set_local_pref_cmd);
7279 route_map_install_set(&route_set_weight_cmd);
7280 route_map_install_set(&route_set_label_index_cmd);
7281 route_map_install_set(&route_set_metric_cmd);
7b7d48e5 7282 route_map_install_set(&route_set_distance_cmd);
d62a17ae 7283 route_map_install_set(&route_set_aspath_prepend_cmd);
7284 route_map_install_set(&route_set_aspath_exclude_cmd);
77e3d821 7285 route_map_install_set(&route_set_aspath_replace_cmd);
d62a17ae 7286 route_map_install_set(&route_set_origin_cmd);
7287 route_map_install_set(&route_set_atomic_aggregate_cmd);
97a52c82 7288 route_map_install_set(&route_set_aigp_metric_cmd);
d62a17ae 7289 route_map_install_set(&route_set_aggregator_as_cmd);
7290 route_map_install_set(&route_set_community_cmd);
7291 route_map_install_set(&route_set_community_delete_cmd);
7292 route_map_install_set(&route_set_lcommunity_cmd);
7293 route_map_install_set(&route_set_lcommunity_delete_cmd);
7294 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
7295 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
7296 route_map_install_set(&route_set_originator_id_cmd);
7297 route_map_install_set(&route_set_ecommunity_rt_cmd);
c9a25614 7298 route_map_install_set(&route_set_ecommunity_nt_cmd);
d62a17ae 7299 route_map_install_set(&route_set_ecommunity_soo_cmd);
ca9ac3ef 7300 route_map_install_set(&route_set_ecommunity_lb_cmd);
bb4dcdd1 7301 route_map_install_set(&route_set_ecommunity_none_cmd);
d62a17ae 7302 route_map_install_set(&route_set_tag_cmd);
7303 route_map_install_set(&route_set_label_index_cmd);
1bb550b6 7304 route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
d62a17ae 7305
7306 install_element(RMAP_NODE, &match_peer_cmd);
7307 install_element(RMAP_NODE, &match_peer_local_cmd);
7308 install_element(RMAP_NODE, &no_match_peer_cmd);
7309 install_element(RMAP_NODE, &match_ip_route_source_cmd);
7310 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
7311 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
7312 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
7313 install_element(RMAP_NODE, &match_mac_address_cmd);
7314 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
7315 install_element(RMAP_NODE, &match_evpn_vni_cmd);
7316 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
7317 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
7318 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
196c6b09
LK
7319 install_element(RMAP_NODE, &match_evpn_rd_cmd);
7320 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
6fb219da
MK
7321 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
7322 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
d0a4ee60
AD
7323 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
7324 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
7325 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
7326 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
1dcc9e5b
CS
7327 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
7328 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
d62a17ae 7329
7330 install_element(RMAP_NODE, &match_aspath_cmd);
7331 install_element(RMAP_NODE, &no_match_aspath_cmd);
7332 install_element(RMAP_NODE, &match_local_pref_cmd);
7333 install_element(RMAP_NODE, &no_match_local_pref_cmd);
2690f18c
DA
7334 install_element(RMAP_NODE, &match_alias_cmd);
7335 install_element(RMAP_NODE, &no_match_alias_cmd);
d62a17ae 7336 install_element(RMAP_NODE, &match_community_cmd);
7337 install_element(RMAP_NODE, &no_match_community_cmd);
7338 install_element(RMAP_NODE, &match_lcommunity_cmd);
7339 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
7340 install_element(RMAP_NODE, &match_ecommunity_cmd);
7341 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
7342 install_element(RMAP_NODE, &match_origin_cmd);
7343 install_element(RMAP_NODE, &no_match_origin_cmd);
7344 install_element(RMAP_NODE, &match_probability_cmd);
7345 install_element(RMAP_NODE, &no_match_probability_cmd);
7346
951745bd
PG
7347 install_element(RMAP_NODE, &no_set_table_id_cmd);
7348 install_element(RMAP_NODE, &set_table_id_cmd);
d62a17ae 7349 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
7350 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
7351 install_element(RMAP_NODE, &set_local_pref_cmd);
7b7d48e5
DS
7352 install_element(RMAP_NODE, &set_distance_cmd);
7353 install_element(RMAP_NODE, &no_set_distance_cmd);
d62a17ae 7354 install_element(RMAP_NODE, &no_set_local_pref_cmd);
7355 install_element(RMAP_NODE, &set_weight_cmd);
7356 install_element(RMAP_NODE, &set_label_index_cmd);
7357 install_element(RMAP_NODE, &no_set_weight_cmd);
7358 install_element(RMAP_NODE, &no_set_label_index_cmd);
7359 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
7360 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
7361 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
77e3d821 7362 install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
d62a17ae 7363 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
9131e6e8 7364 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
d62a17ae 7365 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
499ceb3d 7366 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
77e3d821 7367 install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
d62a17ae 7368 install_element(RMAP_NODE, &set_origin_cmd);
7369 install_element(RMAP_NODE, &no_set_origin_cmd);
7370 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
7371 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
97a52c82
DA
7372 install_element(RMAP_NODE, &set_aigp_metric_cmd);
7373 install_element(RMAP_NODE, &no_set_aigp_metric_cmd);
d62a17ae 7374 install_element(RMAP_NODE, &set_aggregator_as_cmd);
7375 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
7376 install_element(RMAP_NODE, &set_community_cmd);
7377 install_element(RMAP_NODE, &set_community_none_cmd);
7378 install_element(RMAP_NODE, &no_set_community_cmd);
2929de9e 7379 install_element(RMAP_NODE, &no_set_community_short_cmd);
d62a17ae 7380 install_element(RMAP_NODE, &set_community_delete_cmd);
7381 install_element(RMAP_NODE, &no_set_community_delete_cmd);
7382 install_element(RMAP_NODE, &set_lcommunity_cmd);
7383 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
7384 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
7385 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
76a20aa9 7386 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
d62a17ae 7387 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
7388 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
76a20aa9 7389 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
d62a17ae 7390 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
7391 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4db5ee8e 7392 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
d62a17ae 7393 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
7394 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4db5ee8e 7395 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
ca9ac3ef 7396 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
7397 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
7398 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
bb4dcdd1
DA
7399 install_element(RMAP_NODE, &set_ecommunity_none_cmd);
7400 install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
c9a25614
DA
7401 install_element(RMAP_NODE, &set_ecommunity_nt_cmd);
7402 install_element(RMAP_NODE, &no_set_ecommunity_nt_cmd);
7403 install_element(RMAP_NODE, &no_set_ecommunity_nt_short_cmd);
d6902373 7404#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 7405 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
7406 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 7407#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 7408 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
7409 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
7410 install_element(RMAP_NODE, &set_originator_id_cmd);
7411 install_element(RMAP_NODE, &no_set_originator_id_cmd);
1bb550b6 7412 install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
d62a17ae 7413
7414 route_map_install_match(&route_match_ipv6_address_cmd);
7415 route_map_install_match(&route_match_ipv6_next_hop_cmd);
bc63ba98 7416 route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
82f191a2 7417 route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
be7735b3 7418 route_map_install_match(&route_match_ipv4_next_hop_cmd);
d62a17ae 7419 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 7420 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 7421 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
7422 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
7423 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
7424 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
324e8b1f 7425 route_map_install_match(&route_match_rpki_extcommunity_cmd);
d62a17ae 7426
7427 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
bc63ba98 7428 install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
82f191a2 7429 install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
d62a17ae 7430 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
bc63ba98 7431 install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
82f191a2 7432 install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
03030106
IR
7433 install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
7434 install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
be7735b3 7435 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
17ac51eb 7436 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
d62a17ae 7437 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
7438 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
7439 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
7440 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
7441 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
7442 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
324e8b1f 7443 install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
fa22080d 7444#ifdef HAVE_SCRIPTING
b4becb06 7445 install_element(RMAP_NODE, &match_script_cmd);
1d7c7ace 7446#endif
d62a17ae 7447}
7448
7449void bgp_route_map_terminate(void)
7450{
7451 /* ToDo: Cleanup all the used memory */
d62a17ae 7452 route_map_finish();
518f0eb1 7453}