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