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