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