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