]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Merge pull request #12562 from opensourcerouting/fix/add_frrtrace_points_for_peer_loc...
[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 */
667a4e92 3534 SET_FLAG(path->attr->nh_flag, BGP_ATTR_NH_MP_PREFER_GLOBAL);
1782514f
DS
3535 SET_FLAG(path->attr->rmap_change_flags,
3536 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3537 } else {
667a4e92 3538 UNSET_FLAG(path->attr->nh_flag, BGP_ATTR_NH_MP_PREFER_GLOBAL);
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
DS
3587 /* Set nexthop length. */
3588 if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3589 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 3590
1782514f
DS
3591 SET_FLAG(path->attr->rmap_change_flags,
3592 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 3593
d62a17ae 3594 return RMAP_OKAY;
718e3744 3595}
3596
3597/* Route map `ip nexthop' compile function. Given string is converted
3598 to struct in_addr structure. */
d62a17ae 3599static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 3600{
d62a17ae 3601 int ret;
3602 struct in6_addr *address;
718e3744 3603
d62a17ae 3604 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3605
d62a17ae 3606 ret = inet_pton(AF_INET6, arg, address);
718e3744 3607
d62a17ae 3608 if (ret == 0) {
3609 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3610 return NULL;
3611 }
718e3744 3612
d62a17ae 3613 return address;
718e3744 3614}
3615
3616/* Free route map's compiled `ip nexthop' value. */
d62a17ae 3617static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 3618{
d62a17ae 3619 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3620}
3621
3622/* Route map commands for ip nexthop set. */
364deb04
DL
3623static const struct route_map_rule_cmd
3624 route_set_ipv6_nexthop_local_cmd = {
3625 "ipv6 next-hop local",
3626 route_set_ipv6_nexthop_local,
d62a17ae 3627 route_set_ipv6_nexthop_local_compile,
364deb04
DL
3628 route_set_ipv6_nexthop_local_free
3629};
90916ac2
DS
3630
3631/* `set ipv6 nexthop peer-address' */
3632
581776fa 3633/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3634static enum route_map_cmd_result_t
1782514f 3635route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
d62a17ae 3636{
3637 struct in6_addr peer_address;
9b6d8fcf 3638 struct bgp_path_info *path;
d62a17ae 3639 struct peer *peer;
3640
1782514f
DS
3641 /* Fetch routemap's rule information. */
3642 path = object;
3643 peer = path->peer;
d62a17ae 3644
1782514f
DS
3645 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3646 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3647 && peer->su_remote
3648 && sockunion_family(peer->su_remote) == AF_INET6) {
3649 peer_address = peer->su_remote->sin6.sin6_addr;
3650 /* Set next hop value and length in attribute. */
3651 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3652 path->attr->mp_nexthop_local = peer_address;
3653 if (path->attr->mp_nexthop_len
3654 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3655 path->attr->mp_nexthop_len =
3656 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3657 } else {
3658 path->attr->mp_nexthop_global = peer_address;
3659 if (path->attr->mp_nexthop_len == 0)
3660 path->attr->mp_nexthop_len =
3661 BGP_ATTR_NHLEN_IPV6_GLOBAL;
d62a17ae 3662 }
1782514f
DS
3663
3664 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3665 /* The next hop value will be set as part of packet
3666 * rewrite.
3667 * Set the flags here to indicate that rewrite needs to
3668 * be done.
3669 * Also, clear the value - we clear both global and
3670 * link-local
3671 * nexthops, whether we send one or both is determined
3672 * elsewhere.
3673 */
3674 SET_FLAG(path->attr->rmap_change_flags,
3675 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3676 /* clear next hop value. */
3677 memset(&(path->attr->mp_nexthop_global), 0,
3678 sizeof(struct in6_addr));
3679 memset(&(path->attr->mp_nexthop_local), 0,
3680 sizeof(struct in6_addr));
90916ac2 3681 }
90916ac2 3682
d62a17ae 3683 return RMAP_OKAY;
90916ac2
DS
3684}
3685
3686/* Route map `ip next-hop' compile function. Given string is converted
3687 to struct in_addr structure. */
d62a17ae 3688static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 3689{
d62a17ae 3690 int *rins = NULL;
90916ac2 3691
d62a17ae 3692 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3693 *rins = 1;
90916ac2 3694
d62a17ae 3695 return rins;
90916ac2
DS
3696}
3697
3698/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3699static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 3700{
d62a17ae 3701 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
3702}
3703
3704/* Route map commands for ip nexthop set. */
364deb04
DL
3705static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3706 "ipv6 next-hop peer-address",
3707 route_set_ipv6_nexthop_peer,
3708 route_set_ipv6_nexthop_peer_compile,
3709 route_set_ipv6_nexthop_peer_free
3710};
90916ac2 3711
69ba6dd7 3712/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 3713
b68885f9 3714static enum route_map_cmd_result_t
1782514f 3715route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
718e3744 3716{
d62a17ae 3717 struct in_addr *address;
9b6d8fcf 3718 struct bgp_path_info *path;
718e3744 3719
1782514f
DS
3720 /* Fetch routemap's rule information. */
3721 address = rule;
3722 path = object;
e52702f2 3723
1782514f
DS
3724 /* Set next hop value. */
3725 path->attr->mp_nexthop_global_in = *address;
3726 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
718e3744 3727
6eeb9255
DA
3728 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_VPNV4_NHOP_CHANGED);
3729
d62a17ae 3730 return RMAP_OKAY;
718e3744 3731}
3732
d62a17ae 3733static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 3734{
d62a17ae 3735 int ret;
3736 struct in_addr *address;
718e3744 3737
d62a17ae 3738 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3739
d62a17ae 3740 ret = inet_aton(arg, address);
718e3744 3741
d62a17ae 3742 if (ret == 0) {
3743 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3744 return NULL;
3745 }
718e3744 3746
d62a17ae 3747 return address;
718e3744 3748}
3749
69ba6dd7 3750/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 3751
b68885f9 3752static enum route_map_cmd_result_t
1782514f 3753route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
d6902373 3754{
d62a17ae 3755 struct in6_addr *address;
9b6d8fcf 3756 struct bgp_path_info *path;
d6902373 3757
1782514f
DS
3758 /* Fetch routemap's rule information. */
3759 address = rule;
3760 path = object;
d6902373 3761
1782514f
DS
3762 /* Set next hop value. */
3763 memcpy(&path->attr->mp_nexthop_global, address,
3764 sizeof(struct in6_addr));
3765 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
d6902373 3766
6eeb9255
DA
3767 SET_FLAG(path->attr->rmap_change_flags,
3768 BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED);
3769
d62a17ae 3770 return RMAP_OKAY;
d6902373
PG
3771}
3772
d62a17ae 3773static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 3774{
d62a17ae 3775 int ret;
3776 struct in6_addr *address;
d6902373 3777
d62a17ae 3778 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3779 ret = inet_pton(AF_INET6, arg, address);
d6902373 3780
d62a17ae 3781 if (ret == 0) {
3782 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3783 return NULL;
3784 }
d6902373 3785
d62a17ae 3786 return address;
d6902373
PG
3787}
3788
d62a17ae 3789static void route_set_vpn_nexthop_free(void *rule)
718e3744 3790{
d62a17ae 3791 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3792}
3793
69ba6dd7 3794/* Route map commands for ipv4 next-hop set. */
364deb04
DL
3795static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3796 "ipv4 vpn next-hop",
3797 route_set_vpnv4_nexthop,
3798 route_set_vpnv4_nexthop_compile,
3799 route_set_vpn_nexthop_free
3800};
d6902373 3801
69ba6dd7 3802/* Route map commands for ipv6 next-hop set. */
364deb04
DL
3803static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3804 "ipv6 vpn next-hop",
3805 route_set_vpnv6_nexthop,
3806 route_set_vpnv6_nexthop_compile,
3807 route_set_vpn_nexthop_free
3808};
6b0655a2 3809
718e3744 3810/* `set originator-id' */
3811
3812/* For origin set. */
b68885f9 3813static enum route_map_cmd_result_t
1782514f 3814route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
718e3744 3815{
d62a17ae 3816 struct in_addr *address;
9b6d8fcf 3817 struct bgp_path_info *path;
718e3744 3818
1782514f
DS
3819 address = rule;
3820 path = object;
e52702f2 3821
1782514f
DS
3822 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3823 path->attr->originator_id = *address;
718e3744 3824
d62a17ae 3825 return RMAP_OKAY;
718e3744 3826}
3827
3828/* Compile function for originator-id set. */
d62a17ae 3829static void *route_set_originator_id_compile(const char *arg)
718e3744 3830{
d62a17ae 3831 int ret;
3832 struct in_addr *address;
718e3744 3833
d62a17ae 3834 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3835
d62a17ae 3836 ret = inet_aton(arg, address);
718e3744 3837
d62a17ae 3838 if (ret == 0) {
3839 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3840 return NULL;
3841 }
718e3744 3842
d62a17ae 3843 return address;
718e3744 3844}
3845
3846/* Compile function for originator_id set. */
d62a17ae 3847static void route_set_originator_id_free(void *rule)
718e3744 3848{
d62a17ae 3849 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3850}
3851
515e500c 3852/* Set originator-id rule structure. */
364deb04
DL
3853static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3854 "originator-id",
3855 route_set_originator_id,
3856 route_set_originator_id_compile,
3857 route_set_originator_id_free,
718e3744 3858};
6b0655a2 3859
324e8b1f
DA
3860static enum route_map_cmd_result_t
3861route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
3862 void *object)
3863{
3864 struct bgp_path_info *path;
3865 struct ecommunity *ecomm;
3866 struct ecommunity_val *ecomm_val;
3867 enum rpki_states *rpki_status = rule;
3868 enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
3869
3870 path = object;
3871
3872 ecomm = bgp_attr_get_ecommunity(path->attr);
3873 if (!ecomm)
3874 return RMAP_NOMATCH;
3875
3876 ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
3877 ECOMMUNITY_ORIGIN_VALIDATION_STATE);
3878 if (!ecomm_val)
3879 return RMAP_NOMATCH;
3880
3881 /* The Origin Validation State is encoded in the last octet of
3882 * the extended community.
3883 */
3884 switch (ecomm_val->val[7]) {
3885 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
3886 ecomm_rpki_status = RPKI_VALID;
3887 break;
3888 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
3889 ecomm_rpki_status = RPKI_NOTFOUND;
3890 break;
3891 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
3892 ecomm_rpki_status = RPKI_INVALID;
3893 break;
3894 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
3895 break;
3896 }
3897
3898 if (ecomm_rpki_status == *rpki_status)
3899 return RMAP_MATCH;
3900
3901 return RMAP_NOMATCH;
3902}
3903
3904static void *route_match_extcommunity_compile(const char *arg)
3905{
3906 int *rpki_status;
3907
3908 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3909
3910 if (strcmp(arg, "valid") == 0)
3911 *rpki_status = RPKI_VALID;
3912 else if (strcmp(arg, "invalid") == 0)
3913 *rpki_status = RPKI_INVALID;
3914 else
3915 *rpki_status = RPKI_NOTFOUND;
3916
3917 return rpki_status;
3918}
3919
3920static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
3921 "rpki-extcommunity",
3922 route_match_rpki_extcommunity,
3923 route_match_extcommunity_compile,
3924 route_value_free
3925};
3926
518f0eb1 3927/*
2a3d5731 3928 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
3929 * modifications.
3930 */
d62a17ae 3931static void bgp_route_map_process_peer(const char *rmap_name,
3932 struct route_map *map, struct peer *peer,
3933 int afi, int safi, int route_update)
3934{
d62a17ae 3935 struct bgp_filter *filter;
3936
3937 if (!peer || !rmap_name)
3938 return;
3939
3940 filter = &peer->filter[afi][safi];
3941 /*
3942 * in is for non-route-server clients,
3943 * out is for all peers
3944 */
db77a501
DS
3945 if (filter->map[RMAP_IN].name
3946 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3947 filter->map[RMAP_IN].map = map;
d62a17ae 3948
feb17238 3949 if (route_update && peer_established(peer)) {
d62a17ae 3950 if (CHECK_FLAG(peer->af_flags[afi][safi],
3951 PEER_FLAG_SOFT_RECONFIG)) {
3952 if (bgp_debug_update(peer, NULL, NULL, 1))
3953 zlog_debug(
11b228cd
DS
3954 "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
3955 rmap_name, afi2str(afi),
3956 safi2str(safi), peer->host);
d62a17ae 3957
3958 bgp_soft_reconfig_in(peer, afi, safi);
3959 } else if (CHECK_FLAG(peer->cap,
3960 PEER_CAP_REFRESH_OLD_RCV)
3961 || CHECK_FLAG(peer->cap,
3962 PEER_CAP_REFRESH_NEW_RCV)) {
3963 if (bgp_debug_update(peer, NULL, NULL, 1))
3964 zlog_debug(
11b228cd
DS
3965 "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
3966 rmap_name, afi2str(afi),
3967 safi2str(safi), peer->host);
9af52ccf
DA
3968 bgp_route_refresh_send(
3969 peer, afi, safi, 0, 0, 0,
3970 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 3971 }
d62a17ae 3972 }
518f0eb1 3973 }
d62a17ae 3974
3975 /*
3976 * For outbound, unsuppress and default-originate map change (content or
3977 * map created), merely update the "config" here, the actual route
3978 * announcement happens at the group level.
3979 */
3980 if (filter->map[RMAP_OUT].name
3981 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3982 filter->map[RMAP_OUT].map = map;
3983
3984 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3985 filter->usmap.map = map;
3986
7f7940e6
MK
3987 if (filter->advmap.aname
3988 && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
3989 filter->advmap.amap = map;
7f7940e6
MK
3990 }
3991
3992 if (filter->advmap.cname
3993 && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
3994 filter->advmap.cmap = map;
7f7940e6
MK
3995 }
3996
d62a17ae 3997 if (peer->default_rmap[afi][safi].name
3998 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
3999 peer->default_rmap[afi][safi].map = map;
c5aec50b
MK
4000
4001 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4002 peer->advmap_config_change[afi][safi] = true;
d62a17ae 4003}
4004
4005static void bgp_route_map_update_peer_group(const char *rmap_name,
4006 struct route_map *map,
4007 struct bgp *bgp)
4008{
4009 struct peer_group *group;
4010 struct listnode *node, *nnode;
4011 struct bgp_filter *filter;
4012 int afi, safi;
4013 int direct;
4014
4015 if (!bgp)
4016 return;
4017
4018 /* All the peers have been updated correctly already. This is
4019 * just updating the placeholder data. No real update required.
4020 */
05c7a1cc
QY
4021 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
4022 FOREACH_AFI_SAFI (afi, safi) {
4023 filter = &group->conf->filter[afi][safi];
4024
4025 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
4026 if ((filter->map[direct].name)
4027 && (strcmp(rmap_name,
4028 filter->map[direct].name)
d62a17ae 4029 == 0))
05c7a1cc 4030 filter->map[direct].map = map;
d62a17ae 4031 }
05c7a1cc
QY
4032
4033 if (filter->usmap.name
4034 && (strcmp(rmap_name, filter->usmap.name) == 0))
4035 filter->usmap.map = map;
9118301e
DA
4036
4037 if (filter->advmap.aname &&
4038 (strcmp(rmap_name, filter->advmap.aname) == 0))
4039 filter->advmap.amap = map;
4040
4041 if (filter->advmap.cname &&
4042 (strcmp(rmap_name, filter->advmap.cname) == 0))
4043 filter->advmap.cmap = map;
05c7a1cc
QY
4044 }
4045 }
518f0eb1
DS
4046}
4047
a6e0d253
DW
4048/*
4049 * Note that if an extreme number (tens of thousands) of route-maps are in use
4050 * and if bgp has an extreme number of peers, network statements, etc then this
4051 * function can consume a lot of cycles. This is due to this function being
4052 * called for each route-map and within this function we walk the list of peers,
4053 * network statements, etc looking to see if they use this route-map.
4054 */
d62a17ae 4055static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
f1aa4929 4056 bool route_update)
d62a17ae 4057{
4058 int i;
4056a5f6 4059 bool matched;
d62a17ae 4060 afi_t afi;
4061 safi_t safi;
4062 struct peer *peer;
9bcb3eef 4063 struct bgp_dest *bn;
d62a17ae 4064 struct bgp_static *bgp_static;
20894f50 4065 struct bgp_aggregate *aggregate;
d62a17ae 4066 struct listnode *node, *nnode;
4067 struct route_map *map;
4068 char buf[INET6_ADDRSTRLEN];
4069
4070 map = route_map_lookup_by_name(rmap_name);
4071
4072 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
4073
4074 /* Ignore dummy peer-group structure */
4075 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4076 continue;
4077
05c7a1cc
QY
4078 FOREACH_AFI_SAFI (afi, safi) {
4079 /* process in/out/import/export/default-orig
4080 * route-maps */
4081 bgp_route_map_process_peer(rmap_name, map, peer, afi,
4082 safi, route_update);
4083 }
d62a17ae 4084 }
4085
4086 /* for outbound/default-orig route-maps, process for groups */
4087 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
4088 route_update, 0);
4089
4090 /* update peer-group config (template) */
4091 bgp_route_map_update_peer_group(rmap_name, map, bgp);
4092
05c7a1cc
QY
4093 FOREACH_AFI_SAFI (afi, safi) {
4094 /* For table route-map updates. */
4095 if (!bgp_fibupd_safi(safi))
4096 continue;
d62a17ae 4097
05c7a1cc
QY
4098 if (bgp->table_map[afi][safi].name
4099 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
4100 == 0)) {
b4897fa5 4101
4102 /* bgp->table_map[afi][safi].map is NULL.
4103 * i.e Route map creation event.
4104 * So update applied_counter.
4105 * If it is not NULL, i.e It may be routemap updation or
4106 * deletion. so no need to update the counter.
4107 */
4108 if (!bgp->table_map[afi][safi].map)
4109 route_map_counter_increment(map);
05c7a1cc
QY
4110 bgp->table_map[afi][safi].map = map;
4111
4112 if (BGP_DEBUG(zebra, ZEBRA))
4113 zlog_debug(
11b228cd
DS
4114 "Processing route_map %s(%s:%s) update on table map",
4115 rmap_name, afi2str(afi),
4116 safi2str(safi));
05c7a1cc
QY
4117 if (route_update)
4118 bgp_zebra_announce_table(bgp, afi, safi);
4119 }
d62a17ae 4120
05c7a1cc
QY
4121 /* For network route-map updates. */
4122 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
96f10e1e 4123 bn = bgp_route_next(bn)) {
9bcb3eef 4124 bgp_static = bgp_dest_get_bgp_static_info(bn);
c9837105
DS
4125 if (!bgp_static)
4126 continue;
4127
4128 if (!bgp_static->rmap.name
4129 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
4130 continue;
4131
b4897fa5 4132 if (!bgp_static->rmap.map)
4133 route_map_counter_increment(map);
4134
c9837105
DS
4135 bgp_static->rmap.map = map;
4136
4137 if (route_update && !bgp_static->backdoor) {
b54892e0 4138 const struct prefix *bn_p =
9bcb3eef 4139 bgp_dest_get_prefix(bn);
b54892e0
DS
4140
4141 if (bgp_debug_zebra(bn_p))
c9837105 4142 zlog_debug(
11b228cd
DS
4143 "Processing route_map %s(%s:%s) update on static route %s",
4144 rmap_name, afi2str(afi),
4145 safi2str(safi),
b54892e0
DS
4146 inet_ntop(bn_p->family,
4147 &bn_p->u.prefix, buf,
07380148 4148 sizeof(buf)));
b54892e0 4149 bgp_static_update(bgp, bn_p, bgp_static, afi,
c9837105 4150 safi);
05c7a1cc 4151 }
96f10e1e 4152 }
20894f50
DA
4153
4154 /* For aggregate-address route-map updates. */
4155 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
4156 bn = bgp_route_next(bn)) {
9bcb3eef 4157 aggregate = bgp_dest_get_bgp_aggregate_info(bn);
20894f50
DA
4158 if (!aggregate)
4159 continue;
4160
4056a5f6 4161 matched = false;
20894f50 4162
365ab2e7
RZ
4163 /* Update suppress map pointer. */
4164 if (aggregate->suppress_map_name
4165 && strmatch(aggregate->suppress_map_name,
4166 rmap_name)) {
4056a5f6 4167 if (aggregate->rmap.map == NULL)
365ab2e7 4168 route_map_counter_increment(map);
20894f50 4169
365ab2e7 4170 aggregate->suppress_map = map;
4056a5f6
RZ
4171
4172 bgp_aggregate_toggle_suppressed(
4173 aggregate, bgp, bgp_dest_get_prefix(bn),
4174 afi, safi, false);
4175
4176 matched = true;
365ab2e7
RZ
4177 }
4178
4056a5f6
RZ
4179 if (aggregate->rmap.name
4180 && strmatch(rmap_name, aggregate->rmap.name)) {
4181 if (aggregate->rmap.map == NULL)
4182 route_map_counter_increment(map);
20894f50 4183
4056a5f6 4184 aggregate->rmap.map = map;
20894f50 4185
4056a5f6
RZ
4186 matched = true;
4187 }
20894f50 4188
4056a5f6 4189 if (matched && route_update) {
b54892e0 4190 const struct prefix *bn_p =
9bcb3eef 4191 bgp_dest_get_prefix(bn);
b54892e0
DS
4192
4193 if (bgp_debug_zebra(bn_p))
20894f50 4194 zlog_debug(
11b228cd
DS
4195 "Processing route_map %s(%s:%s) update on aggregate-address route %s",
4196 rmap_name, afi2str(afi),
4197 safi2str(safi),
b54892e0
DS
4198 inet_ntop(bn_p->family,
4199 &bn_p->u.prefix, buf,
07380148 4200 sizeof(buf)));
b54892e0 4201 bgp_aggregate_route(bgp, bn_p, afi, safi,
20894f50
DA
4202 aggregate);
4203 }
4204 }
05c7a1cc 4205 }
d62a17ae 4206
4207 /* For redistribute route-map updates. */
4208 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4209 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
4210 struct list *red_list;
d62a17ae 4211 struct bgp_redist *red;
4212
4213 red_list = bgp->redist[afi][i];
4214 if (!red_list)
4215 continue;
4216
4217 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
c9837105
DS
4218 if (!red->rmap.name
4219 || (strcmp(rmap_name, red->rmap.name) != 0))
4220 continue;
4221
b4897fa5 4222 if (!red->rmap.map)
4223 route_map_counter_increment(map);
4224
c9837105
DS
4225 red->rmap.map = map;
4226
4227 if (!route_update)
4228 continue;
4229
4230 if (BGP_DEBUG(zebra, ZEBRA))
4231 zlog_debug(
11b228cd
DS
4232 "Processing route_map %s(%s:%s) update on redistributed routes",
4233 rmap_name, afi2str(afi),
4234 safi2str(safi));
c9837105
DS
4235
4236 bgp_redistribute_resend(bgp, afi, i,
d62a17ae 4237 red->instance);
d62a17ae 4238 }
4239 }
53c84f78
MK
4240
4241 /* for type5 command route-maps */
4242 FOREACH_AFI_SAFI (afi, safi) {
c9837105
DS
4243 if (!bgp->adv_cmd_rmap[afi][safi].name
4244 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4245 != 0)
4246 continue;
4247
2686df6a
NS
4248 /* Make sure the route-map is populated here if not already done */
4249 bgp->adv_cmd_rmap[afi][safi].map = map;
4250
c9837105
DS
4251 if (BGP_DEBUG(zebra, ZEBRA))
4252 zlog_debug(
11b228cd
DS
4253 "Processing route_map %s(%s:%s) update on advertise type5 route command",
4254 rmap_name, afi2str(afi), safi2str(safi));
2686df6a 4255
456a4697 4256 if (route_update && advertise_type5_routes(bgp, afi)) {
2686df6a
NS
4257 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4258 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4259 }
53c84f78 4260 }
d62a17ae 4261}
4262
46a69f10 4263static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 4264{
4265 struct listnode *node, *nnode;
4266 struct bgp *bgp;
4267
ddb5b488 4268 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
f1aa4929 4269 bgp_route_map_process_update(bgp, rmap_name, true);
5fe9f963 4270
49e5a4a0 4271#ifdef ENABLE_BGP_VNC
ddb5b488 4272 vnc_routemap_update(bgp, __func__);
65efcfce 4273#endif
ddb5b488
PZ
4274 }
4275
4276 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
4277}
4278
cc9f21da 4279void bgp_route_map_update_timer(struct thread *thread)
518f0eb1 4280{
d62a17ae 4281 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1
DS
4282}
4283
d62a17ae 4284static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 4285{
47c8fa1f
NT
4286 struct listnode *node, *nnode;
4287 struct bgp *bgp;
4288
4289 /* If new update is received before the current timer timed out,
4290 * turn it off and start a new timer.
4291 */
28ef0ee1 4292 THREAD_OFF(bm->t_rmap_update);
47c8fa1f
NT
4293
4294 /* rmap_update_timer of 0 means don't do route updates */
4295 if (bm->rmap_update_timer) {
4296 thread_add_timer(bm->master, bgp_route_map_update_timer,
4297 NULL, bm->rmap_update_timer,
4298 &bm->t_rmap_update);
4299
4300 /* Signal the groups that a route-map update event has
4301 * started */
4302 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
f1aa4929
DA
4303 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
4304 rmap_name, true, 1);
47c8fa1f 4305 } else {
f6e7507e 4306 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
f1aa4929 4307 bgp_route_map_process_update(bgp, rmap_name, false);
49e5a4a0 4308#ifdef ENABLE_BGP_VNC
f6e7507e 4309 vnc_routemap_update(bgp, __func__);
65efcfce 4310#endif
f6e7507e
IR
4311 }
4312
4313 vpn_policy_routemap_event(rmap_name);
d62a17ae 4314 }
718e3744 4315}
6b0655a2 4316
d62a17ae 4317static void bgp_route_map_add(const char *rmap_name)
73ac8160 4318{
7096e938 4319 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4320 bgp_route_map_mark_update(rmap_name);
73ac8160 4321
d62a17ae 4322 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 4323}
518f0eb1 4324
d62a17ae 4325static void bgp_route_map_delete(const char *rmap_name)
73ac8160 4326{
7096e938 4327 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4328 bgp_route_map_mark_update(rmap_name);
73ac8160 4329
d62a17ae 4330 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 4331}
518f0eb1 4332
097b5973 4333static void bgp_route_map_event(const char *rmap_name)
73ac8160 4334{
7096e938 4335 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4336 bgp_route_map_mark_update(rmap_name);
518f0eb1 4337
d62a17ae 4338 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
4339}
4340
48cb7ea9
SP
4341DEFUN_YANG (match_mac_address,
4342 match_mac_address_cmd,
c60dec36 4343 "match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4344 MATCH_STR
4345 "mac address\n"
4346 "Match address of route\n"
4347 "MAC Access-list name\n")
d37ba549 4348{
48cb7ea9
SP
4349 const char *xpath =
4350 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4351 char xpath_value[XPATH_MAXLEN];
4352
4353 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4354 snprintf(xpath_value, sizeof(xpath_value),
4355 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4356 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4357
4358 return nb_cli_apply_changes(vty, NULL);
d37ba549
MK
4359}
4360
48cb7ea9
SP
4361DEFUN_YANG (no_match_mac_address,
4362 no_match_mac_address_cmd,
c60dec36 4363 "no match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4364 NO_STR
4365 MATCH_STR
4366 "mac\n"
4367 "Match address of route\n"
4368 "MAC acess-list name\n")
d37ba549 4369{
48cb7ea9
SP
4370 const char *xpath =
4371 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4372
4373 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4374 return nb_cli_apply_changes(vty, NULL);
d37ba549 4375}
73ac8160 4376
38677473
SW
4377/*
4378 * Helper to handle the case of the user passing in a number or type string
4379 */
4380static const char *parse_evpn_rt_type(const char *num_rt_type)
4381{
4382 switch (num_rt_type[0]) {
4383 case '1':
4384 return "ead";
4385 case '2':
4386 return "macip";
4387 case '3':
4388 return "multicast";
4389 case '4':
4390 return "es";
4391 case '5':
4392 return "prefix";
4393 default:
4394 break;
4395 }
4396
4397 /* Was already full type string */
4398 return num_rt_type;
4399}
4400
48cb7ea9
SP
4401DEFUN_YANG (match_evpn_route_type,
4402 match_evpn_route_type_cmd,
2514d231 4403 "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4404 MATCH_STR
4405 EVPN_HELP_STR
4406 EVPN_TYPE_HELP_STR
bd44ab08
CS
4407 EVPN_TYPE_1_HELP_STR
4408 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4409 EVPN_TYPE_2_HELP_STR
4410 EVPN_TYPE_2_HELP_STR
4411 EVPN_TYPE_3_HELP_STR
4412 EVPN_TYPE_3_HELP_STR
2514d231
CS
4413 EVPN_TYPE_4_HELP_STR
4414 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4415 EVPN_TYPE_5_HELP_STR
4416 EVPN_TYPE_5_HELP_STR)
38677473 4417{
48cb7ea9
SP
4418 const char *xpath =
4419 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4420 char xpath_value[XPATH_MAXLEN];
33c2ff62 4421
48cb7ea9
SP
4422 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4423 snprintf(xpath_value, sizeof(xpath_value),
4424 "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4425 xpath);
4426 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4427 parse_evpn_rt_type(argv[3]->arg));
33c2ff62 4428
48cb7ea9
SP
4429 return nb_cli_apply_changes(vty, NULL);
4430}
4431
4432DEFUN_YANG (no_match_evpn_route_type,
4433 no_match_evpn_route_type_cmd,
2514d231 4434 "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4435 NO_STR
4436 MATCH_STR
4437 EVPN_HELP_STR
4438 EVPN_TYPE_HELP_STR
bd44ab08
CS
4439 EVPN_TYPE_1_HELP_STR
4440 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4441 EVPN_TYPE_2_HELP_STR
4442 EVPN_TYPE_2_HELP_STR
4443 EVPN_TYPE_3_HELP_STR
4444 EVPN_TYPE_3_HELP_STR
2514d231
CS
4445 EVPN_TYPE_4_HELP_STR
4446 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4447 EVPN_TYPE_5_HELP_STR
4448 EVPN_TYPE_5_HELP_STR)
16f7ce2b 4449{
48cb7ea9
SP
4450 const char *xpath =
4451 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4452
4453 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4454
4455 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4456}
4457
48cb7ea9
SP
4458
4459DEFUN_YANG (match_evpn_vni,
4460 match_evpn_vni_cmd,
4461 "match evpn vni " CMD_VNI_RANGE,
4462 MATCH_STR
4463 EVPN_HELP_STR
4464 "Match VNI\n"
4465 "VNI ID\n")
4466{
4467 const char *xpath =
4468 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4469 char xpath_value[XPATH_MAXLEN];
4470
4471 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4472 snprintf(xpath_value, sizeof(xpath_value),
4473 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4474 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4475
4476 return nb_cli_apply_changes(vty, NULL);
4477}
4478
4479DEFUN_YANG (no_match_evpn_vni,
4480 no_match_evpn_vni_cmd,
4481 "no match evpn vni " CMD_VNI_RANGE,
4482 NO_STR
4483 MATCH_STR
4484 EVPN_HELP_STR
4485 "Match VNI\n"
4486 "VNI ID\n")
16f7ce2b 4487{
48cb7ea9
SP
4488 const char *xpath =
4489 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4490 char xpath_value[XPATH_MAXLEN];
4491
4492 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4493 snprintf(xpath_value, sizeof(xpath_value),
4494 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4495 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4496
4497 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4498}
4499
48cb7ea9
SP
4500DEFUN_YANG (match_evpn_default_route,
4501 match_evpn_default_route_cmd,
4502 "match evpn default-route",
4503 MATCH_STR
4504 EVPN_HELP_STR
4505 "default EVPN type-5 route\n")
6fb219da 4506{
48cb7ea9
SP
4507 const char *xpath =
4508 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4509 char xpath_value[XPATH_MAXLEN];
4510
4511 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4512
4513 snprintf(xpath_value, sizeof(xpath_value),
4514 "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4515 xpath);
4516 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4517
4518 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4519}
4520
48cb7ea9
SP
4521DEFUN_YANG (no_match_evpn_default_route,
4522 no_match_evpn_default_route_cmd,
4523 "no match evpn default-route",
4524 NO_STR
4525 MATCH_STR
4526 EVPN_HELP_STR
4527 "default EVPN type-5 route\n")
6fb219da 4528{
48cb7ea9
SP
4529 const char *xpath =
4530 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4531
4532 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4533
4534 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4535}
4536
48cb7ea9
SP
4537DEFUN_YANG (match_evpn_rd,
4538 match_evpn_rd_cmd,
4539 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4540 MATCH_STR
4541 EVPN_HELP_STR
4542 "Route Distinguisher\n"
4543 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4544{
48cb7ea9
SP
4545 const char *xpath =
4546 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4547 char xpath_value[XPATH_MAXLEN];
4548
4549 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4550 snprintf(
4551 xpath_value, sizeof(xpath_value),
4552 "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4553 xpath);
4554 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4555
4556 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4557}
4558
48cb7ea9
SP
4559DEFUN_YANG (no_match_evpn_rd,
4560 no_match_evpn_rd_cmd,
4561 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4562 NO_STR
4563 MATCH_STR
4564 EVPN_HELP_STR
4565 "Route Distinguisher\n"
4566 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4567{
48cb7ea9
SP
4568 const char *xpath =
4569 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4570
4571 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4572 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4573}
4574
d0a4ee60
AD
4575DEFUN_YANG (set_evpn_gw_ip_ipv4,
4576 set_evpn_gw_ip_ipv4_cmd,
4577 "set evpn gateway-ip ipv4 A.B.C.D",
4578 SET_STR
4579 EVPN_HELP_STR
4580 "Set gateway IP for prefix advertisement route\n"
4581 "IPv4 address\n"
4582 "Gateway IP address in IPv4 format\n")
4583{
4584 int ret;
4585 union sockunion su;
4586 const char *xpath =
4587 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4588 char xpath_value[XPATH_MAXLEN];
4589
4590 ret = str2sockunion(argv[4]->arg, &su);
4591 if (ret < 0) {
4592 vty_out(vty, "%% Malformed gateway IP\n");
4593 return CMD_WARNING_CONFIG_FAILED;
4594 }
4595
e24a6977
DA
4596 if (su.sin.sin_addr.s_addr == 0 ||
4597 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4598 vty_out(vty,
4599 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4600 return CMD_WARNING_CONFIG_FAILED;
4601 }
4602
4603 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4604
4605 snprintf(xpath_value, sizeof(xpath_value),
4606 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4607 xpath);
4608
4609 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4610 return nb_cli_apply_changes(vty, NULL);
4611}
4612
4613DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4614 no_set_evpn_gw_ip_ipv4_cmd,
4615 "no set evpn gateway-ip ipv4 A.B.C.D",
4616 NO_STR
4617 SET_STR
4618 EVPN_HELP_STR
4619 "Set gateway IP for prefix advertisement route\n"
4620 "IPv4 address\n"
4621 "Gateway IP address in IPv4 format\n")
4622{
4623 int ret;
4624 union sockunion su;
4625 const char *xpath =
4626 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4627
4628 ret = str2sockunion(argv[5]->arg, &su);
4629 if (ret < 0) {
4630 vty_out(vty, "%% Malformed gateway IP\n");
4631 return CMD_WARNING_CONFIG_FAILED;
4632 }
4633
e24a6977
DA
4634 if (su.sin.sin_addr.s_addr == 0 ||
4635 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4636 vty_out(vty,
4637 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4638 return CMD_WARNING_CONFIG_FAILED;
4639 }
4640
4641 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4642
4643 return nb_cli_apply_changes(vty, NULL);
4644}
4645
4646DEFUN_YANG (set_evpn_gw_ip_ipv6,
4647 set_evpn_gw_ip_ipv6_cmd,
4648 "set evpn gateway-ip ipv6 X:X::X:X",
4649 SET_STR
4650 EVPN_HELP_STR
4651 "Set gateway IP for prefix advertisement route\n"
4652 "IPv6 address\n"
4653 "Gateway IP address in IPv6 format\n")
4654{
4655 int ret;
4656 union sockunion su;
4657 const char *xpath =
4658 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4659 char xpath_value[XPATH_MAXLEN];
4660
4661 ret = str2sockunion(argv[4]->arg, &su);
4662 if (ret < 0) {
4663 vty_out(vty, "%% Malformed gateway IP\n");
4664 return CMD_WARNING_CONFIG_FAILED;
4665 }
4666
4667 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4668 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4669 vty_out(vty,
4670 "%% Gateway IP cannot be a linklocal or multicast address\n");
4671 return CMD_WARNING_CONFIG_FAILED;
4672 }
4673
4674 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4675
4676 snprintf(xpath_value, sizeof(xpath_value),
4677 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4678 xpath);
4679
4680 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4681 return nb_cli_apply_changes(vty, NULL);
4682}
4683
4684DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4685 no_set_evpn_gw_ip_ipv6_cmd,
4686 "no set evpn gateway-ip ipv6 X:X::X:X",
4687 NO_STR
4688 SET_STR
4689 EVPN_HELP_STR
4690 "Set gateway IP for prefix advertisement route\n"
4691 "IPv4 address\n"
4692 "Gateway IP address in IPv4 format\n")
4693{
4694 int ret;
4695 union sockunion su;
4696 const char *xpath =
4697 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4698
4699 ret = str2sockunion(argv[5]->arg, &su);
4700 if (ret < 0) {
4701 vty_out(vty, "%% Malformed gateway IP\n");
4702 return CMD_WARNING_CONFIG_FAILED;
4703 }
4704
4705 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4706 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4707 vty_out(vty,
4708 "%% Gateway IP cannot be a linklocal or multicast address\n");
4709 return CMD_WARNING_CONFIG_FAILED;
4710 }
4711
4712 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4713
4714 return nb_cli_apply_changes(vty, NULL);
4715}
4716
48cb7ea9 4717DEFPY_YANG(match_vrl_source_vrf,
1dcc9e5b
CS
4718 match_vrl_source_vrf_cmd,
4719 "match source-vrf NAME$vrf_name",
4720 MATCH_STR
4721 "source vrf\n"
4722 "The VRF name\n")
4723{
48cb7ea9
SP
4724 const char *xpath =
4725 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4726 char xpath_value[XPATH_MAXLEN];
4727
4728 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4729 snprintf(xpath_value, sizeof(xpath_value),
4730 "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4731 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4732
4733 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4734}
4735
48cb7ea9 4736DEFPY_YANG(no_match_vrl_source_vrf,
1dcc9e5b
CS
4737 no_match_vrl_source_vrf_cmd,
4738 "no match source-vrf NAME$vrf_name",
48cb7ea9 4739 NO_STR MATCH_STR
1dcc9e5b
CS
4740 "source vrf\n"
4741 "The VRF name\n")
4742{
48cb7ea9
SP
4743 const char *xpath =
4744 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4745
4746 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4747 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4748}
4749
48cb7ea9 4750DEFPY_YANG (match_peer,
fee0f4c6 4751 match_peer_cmd,
48cb7ea9 4752 "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
fee0f4c6 4753 MATCH_STR
4754 "Match peer address\n"
6e13ed4a 4755 "IP address of peer\n"
8c3433e4 4756 "IPv6 address of peer\n"
1bb1c0cf 4757 "Interface name of peer or peer group name\n")
fee0f4c6 4758{
48cb7ea9
SP
4759 const char *xpath =
4760 "./match-condition[condition='frr-bgp-route-map:peer']";
4761 char xpath_value[XPATH_MAXLEN];
4762
4763 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4764
4765 if (addrv4_str) {
4766 snprintf(
4767 xpath_value, sizeof(xpath_value),
4768 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4769 xpath);
4770 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4771 addrv4_str);
4772 } else if (addrv6_str) {
4773 snprintf(
4774 xpath_value, sizeof(xpath_value),
4775 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4776 xpath);
4777 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4778 addrv6_str);
4779 } else {
4780 snprintf(
4781 xpath_value, sizeof(xpath_value),
4782 "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4783 xpath);
4784 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4785 }
4786
4787 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4788}
4789
48cb7ea9
SP
4790DEFUN_YANG (match_peer_local,
4791 match_peer_local_cmd,
4792 "match peer local",
4793 MATCH_STR
4794 "Match peer address\n"
4795 "Static or Redistributed routes\n")
fee0f4c6 4796{
48cb7ea9
SP
4797 const char *xpath =
4798 "./match-condition[condition='frr-bgp-route-map:peer']";
4799 char xpath_value[XPATH_MAXLEN];
4800
4801 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4802
4803 snprintf(xpath_value, sizeof(xpath_value),
4804 "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4805 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4806
4807 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4808}
4809
48cb7ea9
SP
4810DEFUN_YANG (no_match_peer,
4811 no_match_peer_cmd,
4812 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4813 NO_STR
4814 MATCH_STR
4815 "Match peer address\n"
4816 "Static or Redistributed routes\n"
4817 "IP address of peer\n"
4818 "IPv6 address of peer\n"
4819 "Interface name of peer\n")
fee0f4c6 4820{
48cb7ea9
SP
4821 const char *xpath =
4822 "./match-condition[condition='frr-bgp-route-map:peer']";
4823
4824 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4c9bd275 4825
48cb7ea9 4826 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4827}
4828
fa22080d 4829#ifdef HAVE_SCRIPTING
48cb7ea9
SP
4830DEFUN_YANG (match_script,
4831 match_script_cmd,
4832 "[no] match script WORD",
4833 NO_STR
4834 MATCH_STR
4835 "Execute script to determine match\n"
4836 "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
1d7c7ace 4837{
b4becb06
QY
4838 bool no = strmatch(argv[0]->text, "no");
4839 int i = 0;
4840 argv_find(argv, argc, "WORD", &i);
4841 const char *script = argv[i]->arg;
48cb7ea9
SP
4842 const char *xpath =
4843 "./match-condition[condition='frr-bgp-route-map:match-script']";
4844 char xpath_value[XPATH_MAXLEN];
b4becb06
QY
4845
4846 if (no) {
48cb7ea9
SP
4847 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4848 snprintf(xpath_value, sizeof(xpath_value),
4849 "%s/rmap-match-condition/frr-bgp-route-map:script",
4850 xpath);
4851 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4852 script);
4853
4854 return nb_cli_apply_changes(vty, NULL);
b4becb06 4855 }
48cb7ea9
SP
4856
4857 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4858 snprintf(xpath_value, sizeof(xpath_value),
4859 "%s/rmap-match-condition/frr-bgp-route-map:script",
4860 xpath);
4861 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4862 script);
4863
4864 return nb_cli_apply_changes(vty, NULL);
1d7c7ace 4865}
fa22080d 4866#endif /* HAVE_SCRIPTING */
fee0f4c6 4867
4c9bd275 4868/* match probability */
48cb7ea9
SP
4869DEFUN_YANG (match_probability,
4870 match_probability_cmd,
4871 "match probability (0-100)",
4872 MATCH_STR
4873 "Match portion of routes defined by percentage value\n"
4874 "Percentage of routes\n")
1add115a 4875{
d62a17ae 4876 int idx_number = 2;
48cb7ea9
SP
4877
4878 const char *xpath =
4879 "./match-condition[condition='frr-bgp-route-map:probability']";
4880 char xpath_value[XPATH_MAXLEN];
4881
4882 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4883 snprintf(xpath_value, sizeof(xpath_value),
4884 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4885 xpath);
4886 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4887 argv[idx_number]->arg);
4888
4889 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4890}
4891
4c9bd275 4892
48cb7ea9
SP
4893DEFUN_YANG (no_match_probability,
4894 no_match_probability_cmd,
4895 "no match probability [(1-99)]",
4896 NO_STR
4897 MATCH_STR
4898 "Match portion of routes defined by percentage value\n"
4899 "Percentage of routes\n")
1add115a 4900{
d62a17ae 4901 int idx_number = 3;
48cb7ea9
SP
4902 const char *xpath =
4903 "./match-condition[condition='frr-bgp-route-map:probability']";
4904 char xpath_value[XPATH_MAXLEN];
4905
4906 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4907
d62a17ae 4908 if (argc <= idx_number)
48cb7ea9
SP
4909 return nb_cli_apply_changes(vty, NULL);
4910
4911 snprintf(xpath_value, sizeof(xpath_value),
4912 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4913 xpath);
4914 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4915 argv[idx_number]->arg);
4916
4917 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4918}
4919
1add115a 4920
48cb7ea9 4921DEFPY_YANG (match_ip_route_source,
c1643bb7 4922 match_ip_route_source_cmd,
c60dec36 4923 "match ip route-source ACCESSLIST4_NAME",
c1643bb7 4924 MATCH_STR
4925 IP_STR
4926 "Match advertising source address of route\n"
7e869991 4927 "IP Access-list name\n")
c1643bb7 4928{
48cb7ea9
SP
4929 const char *xpath =
4930 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4931 char xpath_value[XPATH_MAXLEN + 32];
d62a17ae 4932 int idx_acl = 3;
48cb7ea9
SP
4933
4934 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4935 snprintf(xpath_value, sizeof(xpath_value),
4936 "%s/rmap-match-condition/frr-bgp-route-map:list-name",
4937 xpath);
4938 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4939 argv[idx_acl]->arg);
4940
4941 return nb_cli_apply_changes(vty, NULL);
c1643bb7 4942}
4943
4c9bd275 4944
48cb7ea9
SP
4945DEFUN_YANG (no_match_ip_route_source,
4946 no_match_ip_route_source_cmd,
c60dec36 4947 "no match ip route-source [ACCESSLIST4_NAME]",
48cb7ea9
SP
4948 NO_STR
4949 MATCH_STR
4950 IP_STR
4951 "Match advertising source address of route\n"
7e869991 4952 "IP Access-list name\n")
c1643bb7 4953{
48cb7ea9
SP
4954 const char *xpath =
4955 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
c1643bb7 4956
48cb7ea9
SP
4957 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4958 return nb_cli_apply_changes(vty, NULL);
4959}
c1643bb7 4960
48cb7ea9
SP
4961DEFUN_YANG (match_ip_route_source_prefix_list,
4962 match_ip_route_source_prefix_list_cmd,
943224a1 4963 "match ip route-source prefix-list PREFIXLIST_NAME",
48cb7ea9
SP
4964 MATCH_STR
4965 IP_STR
4966 "Match advertising source address of route\n"
4967 "Match entries of prefix-lists\n"
4968 "IP prefix-list name\n")
c1643bb7 4969{
d62a17ae 4970 int idx_word = 4;
48cb7ea9
SP
4971 const char *xpath =
4972 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4973 char xpath_value[XPATH_MAXLEN + 32];
4974
4975 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4976 snprintf(xpath_value, sizeof(xpath_value),
4977 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4978 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4979 argv[idx_word]->arg);
4980
4981 return nb_cli_apply_changes(vty, NULL);
c1643bb7 4982}
4983
4c9bd275 4984
48cb7ea9
SP
4985DEFUN_YANG (no_match_ip_route_source_prefix_list,
4986 no_match_ip_route_source_prefix_list_cmd,
943224a1 4987 "no match ip route-source prefix-list [PREFIXLIST_NAME]",
48cb7ea9
SP
4988 NO_STR
4989 MATCH_STR
4990 IP_STR
4991 "Match advertising source address of route\n"
4992 "Match entries of prefix-lists\n"
4993 "IP prefix-list name\n")
c1643bb7 4994{
48cb7ea9
SP
4995 const char *xpath =
4996 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
c1643bb7 4997
48cb7ea9
SP
4998 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4999 return nb_cli_apply_changes(vty, NULL);
5000}
c1643bb7 5001
48cb7ea9
SP
5002DEFUN_YANG (match_local_pref,
5003 match_local_pref_cmd,
5004 "match local-preference (0-4294967295)",
5005 MATCH_STR
5006 "Match local-preference of route\n"
5007 "Metric value\n")
af291c15 5008{
d62a17ae 5009 int idx_number = 2;
48cb7ea9
SP
5010
5011 const char *xpath =
5012 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5013 char xpath_value[XPATH_MAXLEN];
5014
5015 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5016 snprintf(xpath_value, sizeof(xpath_value),
5017 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5018 xpath);
5019 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5020 argv[idx_number]->arg);
5021
5022 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
5023}
5024
4c9bd275 5025
48cb7ea9
SP
5026DEFUN_YANG (no_match_local_pref,
5027 no_match_local_pref_cmd,
5028 "no match local-preference [(0-4294967295)]",
5029 NO_STR
5030 MATCH_STR
5031 "Match local preference of route\n"
5032 "Local preference value\n")
af291c15 5033{
d62a17ae 5034 int idx_localpref = 3;
48cb7ea9
SP
5035 const char *xpath =
5036 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5037 char xpath_value[XPATH_MAXLEN];
5038
5039 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5040
d62a17ae 5041 if (argc <= idx_localpref)
48cb7ea9
SP
5042 return nb_cli_apply_changes(vty, NULL);
5043
5044 snprintf(xpath_value, sizeof(xpath_value),
5045 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5046 xpath);
5047 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5048 argv[idx_localpref]->arg);
5049
5050 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
5051}
5052
2690f18c
DA
5053DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
5054 MATCH_STR
5055 "Match BGP community alias name\n"
5056 "BGP community alias name\n")
5057{
5058 const char *alias = argv[2]->arg;
5059 struct community_alias ca1;
5060 struct community_alias *lookup_alias;
5061
5062 const char *xpath =
5063 "./match-condition[condition='frr-bgp-route-map:match-alias']";
5064 char xpath_value[XPATH_MAXLEN];
5065
5066 memset(&ca1, 0, sizeof(ca1));
5067 strlcpy(ca1.alias, alias, sizeof(ca1.alias));
5068 lookup_alias = bgp_ca_alias_lookup(&ca1);
5069 if (!lookup_alias) {
5070 vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
5071 return CMD_WARNING_CONFIG_FAILED;
5072 }
5073
5074 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5075 snprintf(xpath_value, sizeof(xpath_value),
5076 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5077 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
5078
5079 return nb_cli_apply_changes(vty, NULL);
5080}
5081
5082
5083DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
5084 NO_STR MATCH_STR
5085 "Match BGP community alias name\n"
5086 "BGP community alias name\n")
5087{
5088 int idx_alias = 3;
5089 const char *xpath =
5090 "./match-condition[condition='frr-bgp-route-map:match-alias']";
5091 char xpath_value[XPATH_MAXLEN];
5092
5093 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5094
5095 if (argc <= idx_alias)
5096 return nb_cli_apply_changes(vty, NULL);
5097
5098 snprintf(xpath_value, sizeof(xpath_value),
5099 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5100 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5101 argv[idx_alias]->arg);
5102
5103 return nb_cli_apply_changes(vty, NULL);
5104}
af291c15 5105
48cb7ea9 5106DEFPY_YANG (match_community,
718e3744 5107 match_community_cmd,
a2099c1d 5108 "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
718e3744 5109 MATCH_STR
5110 "Match BGP community list\n"
5111 "Community-list number (standard)\n"
5112 "Community-list number (expanded)\n"
5113 "Community-list name\n"
5114 "Do exact matching of communities\n")
5115{
48cb7ea9
SP
5116 const char *xpath =
5117 "./match-condition[condition='frr-bgp-route-map:match-community']";
5118 char xpath_value[XPATH_MAXLEN];
5119 char xpath_match[XPATH_MAXLEN];
d62a17ae 5120 int idx_comm_list = 2;
718e3744 5121
48cb7ea9 5122 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 5123
48cb7ea9
SP
5124 snprintf(
5125 xpath_value, sizeof(xpath_value),
5126 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5127 xpath);
5128 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
718e3744 5129
48cb7ea9
SP
5130 if (argc == 4) {
5131 snprintf(
5132 xpath_match, sizeof(xpath_match),
5133 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5134 xpath);
5135 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5136 "true");
5137 } else {
5138 snprintf(
5139 xpath_match, sizeof(xpath_match),
5140 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5141 xpath);
5142 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5143 "false");
5144 }
718e3744 5145
48cb7ea9
SP
5146 return nb_cli_apply_changes(vty, NULL);
5147}
5148
5149DEFUN_YANG (no_match_community,
5150 no_match_community_cmd,
a2099c1d 5151 "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
5152 NO_STR
5153 MATCH_STR
5154 "Match BGP community list\n"
5155 "Community-list number (standard)\n"
5156 "Community-list number (expanded)\n"
5157 "Community-list name\n"
5158 "Do exact matching of communities\n")
5159{
5160 const char *xpath =
5161 "./match-condition[condition='frr-bgp-route-map:match-community']";
5162
5163 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5164 return nb_cli_apply_changes(vty, NULL);
5165}
5166
5167DEFPY_YANG (match_lcommunity,
5168 match_lcommunity_cmd,
a2099c1d 5169 "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
48cb7ea9
SP
5170 MATCH_STR
5171 "Match BGP large community list\n"
5172 "Large Community-list number (standard)\n"
5173 "Large Community-list number (expanded)\n"
5174 "Large Community-list name\n"
5175 "Do exact matching of communities\n")
5176{
5177 const char *xpath =
5178 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5179 char xpath_value[XPATH_MAXLEN];
5180 char xpath_match[XPATH_MAXLEN];
03ff9a14 5181 int idx_lcomm_list = 2;
03ff9a14 5182
48cb7ea9 5183 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
03ff9a14 5184
48cb7ea9
SP
5185 snprintf(
5186 xpath_value, sizeof(xpath_value),
5187 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5188 xpath);
5189 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
03ff9a14 5190
48cb7ea9
SP
5191 if (argc == 4) {
5192 snprintf(
5193 xpath_match, sizeof(xpath_match),
5194 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5195 xpath);
5196 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5197 "true");
5198 } else {
5199 snprintf(
5200 xpath_match, sizeof(xpath_match),
5201 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5202 xpath);
5203 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5204 "false");
5205 }
03ff9a14 5206
48cb7ea9 5207 return nb_cli_apply_changes(vty, NULL);
57d187bc 5208}
718e3744 5209
48cb7ea9
SP
5210DEFUN_YANG (no_match_lcommunity,
5211 no_match_lcommunity_cmd,
a2099c1d 5212 "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
5213 NO_STR
5214 MATCH_STR
5215 "Match BGP large community list\n"
5216 "Large Community-list number (standard)\n"
5217 "Large Community-list number (expanded)\n"
5218 "Large Community-list name\n"
5219 "Do exact matching of communities\n")
57d187bc 5220{
48cb7ea9
SP
5221 const char *xpath =
5222 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5223
5224 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5225 return nb_cli_apply_changes(vty, NULL);
57d187bc 5226}
718e3744 5227
48cb7ea9
SP
5228DEFPY_YANG (match_ecommunity,
5229 match_ecommunity_cmd,
a2099c1d 5230 "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
48cb7ea9
SP
5231 MATCH_STR
5232 "Match BGP/VPN extended community list\n"
5233 "Extended community-list number (standard)\n"
5234 "Extended community-list number (expanded)\n"
5235 "Extended community-list name\n")
73ffb25b 5236{
48cb7ea9
SP
5237 const char *xpath =
5238 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5239 char xpath_value[XPATH_MAXLEN];
d62a17ae 5240 int idx_comm_list = 2;
48cb7ea9
SP
5241
5242 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5243
5244 snprintf(
5245 xpath_value, sizeof(xpath_value),
5246 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5247 xpath);
5248 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5249
5250 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5251}
5252
4c9bd275 5253
48cb7ea9
SP
5254DEFUN_YANG (no_match_ecommunity,
5255 no_match_ecommunity_cmd,
a2099c1d 5256 "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
48cb7ea9
SP
5257 NO_STR
5258 MATCH_STR
5259 "Match BGP/VPN extended community list\n"
5260 "Extended community-list number (standard)\n"
5261 "Extended community-list number (expanded)\n"
5262 "Extended community-list name\n")
73ffb25b 5263{
48cb7ea9
SP
5264 const char *xpath =
5265 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5266
5267 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5268 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5269}
5270
73ffb25b 5271
48cb7ea9
SP
5272DEFUN_YANG (match_aspath,
5273 match_aspath_cmd,
2a342b35 5274 "match as-path AS_PATH_FILTER_NAME",
48cb7ea9
SP
5275 MATCH_STR
5276 "Match BGP AS path list\n"
5277 "AS path access-list name\n")
718e3744 5278{
d62a17ae 5279 int idx_word = 2;
48cb7ea9
SP
5280
5281 const char *xpath =
5282 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5283 char xpath_value[XPATH_MAXLEN];
5284
5285 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5286 snprintf(xpath_value, sizeof(xpath_value),
5287 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5288 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5289 argv[idx_word]->arg);
5290
5291 return nb_cli_apply_changes(vty, NULL);
718e3744 5292}
5293
4c9bd275 5294
48cb7ea9
SP
5295DEFUN_YANG (no_match_aspath,
5296 no_match_aspath_cmd,
2a342b35 5297 "no match as-path [AS_PATH_FILTER_NAME]",
48cb7ea9
SP
5298 NO_STR
5299 MATCH_STR
5300 "Match BGP AS path list\n"
5301 "AS path access-list name\n")
718e3744 5302{
48cb7ea9
SP
5303 const char *xpath =
5304 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
718e3744 5305
48cb7ea9 5306 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
718e3744 5307
48cb7ea9
SP
5308 return nb_cli_apply_changes(vty, NULL);
5309}
5310
5311DEFUN_YANG (match_origin,
5312 match_origin_cmd,
5313 "match origin <egp|igp|incomplete>",
5314 MATCH_STR
5315 "BGP origin code\n"
5316 "remote EGP\n"
5317 "local IGP\n"
5318 "unknown heritage\n")
718e3744 5319{
d62a17ae 5320 int idx_origin = 2;
48cb7ea9
SP
5321 const char *origin_type;
5322 const char *xpath =
5323 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5324 char xpath_value[XPATH_MAXLEN];
5325
d62a17ae 5326 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
48cb7ea9
SP
5327 origin_type = "igp";
5328 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5329 origin_type = "egp";
5330 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5331 origin_type = "incomplete";
5332 else {
5333 vty_out(vty, "%% Invalid match origin type\n");
5334 return CMD_WARNING_CONFIG_FAILED;
5335 }
5336
5337 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5338 snprintf(xpath_value, sizeof(xpath_value),
5339 "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5340 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
718e3744 5341
48cb7ea9 5342 return nb_cli_apply_changes(vty, NULL);
718e3744 5343}
5344
4c9bd275 5345
48cb7ea9
SP
5346DEFUN_YANG (no_match_origin,
5347 no_match_origin_cmd,
5348 "no match origin [<egp|igp|incomplete>]",
5349 NO_STR
5350 MATCH_STR
5351 "BGP origin code\n"
5352 "remote EGP\n"
5353 "local IGP\n"
5354 "unknown heritage\n")
718e3744 5355{
48cb7ea9
SP
5356 const char *xpath =
5357 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5358 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5359 return nb_cli_apply_changes(vty, NULL);
718e3744 5360}
5361
48cb7ea9
SP
5362DEFUN_YANG (set_table_id,
5363 set_table_id_cmd,
5364 "set table (1-4294967295)",
5365 SET_STR
5366 "export route to non-main kernel table\n"
5367 "Kernel routing table id\n")
951745bd 5368{
48cb7ea9
SP
5369 int idx_number = 2;
5370 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5371 char xpath_value[XPATH_MAXLEN];
5372
5373 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5374 snprintf(xpath_value, sizeof(xpath_value),
5375 "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5376 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5377 argv[idx_number]->arg);
5378 return nb_cli_apply_changes(vty, NULL);
5379}
5380
5381DEFUN_YANG (no_set_table_id,
5382 no_set_table_id_cmd,
5383 "no set table",
5384 NO_STR
5385 SET_STR
5386 "export route to non-main kernel table\n")
5387{
5388 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5389 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5390 return nb_cli_apply_changes(vty, NULL);
5391}
5392
5393DEFUN_YANG (set_ip_nexthop_peer,
5394 set_ip_nexthop_peer_cmd,
5395 "[no] set ip next-hop peer-address",
5396 NO_STR
5397 SET_STR
5398 IP_STR
5399 "Next hop address\n"
5400 "Use peer address (for BGP only)\n")
5401{
5402 char xpath_value[XPATH_MAXLEN];
5403 const char *xpath =
5404 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5405
5406 if (strmatch(argv[0]->text, "no"))
5407 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5408 else {
5409 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5410 snprintf(xpath_value, sizeof(xpath_value),
5411 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5412 xpath);
5413 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5414 "peer-address");
5415 }
5416 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5417}
5418
48cb7ea9
SP
5419DEFUN_YANG (set_ip_nexthop_unchanged,
5420 set_ip_nexthop_unchanged_cmd,
5421 "[no] set ip next-hop unchanged",
5422 NO_STR
5423 SET_STR
5424 IP_STR
5425 "Next hop address\n"
5426 "Don't modify existing Next hop address\n")
951745bd 5427{
48cb7ea9
SP
5428 char xpath_value[XPATH_MAXLEN];
5429 const char *xpath =
5430 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
951745bd 5431
48cb7ea9
SP
5432 if (strmatch(argv[0]->text, "no"))
5433 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5434 else {
5435 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5436 snprintf(xpath_value, sizeof(xpath_value),
5437 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5438 xpath);
5439 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5440 "unchanged");
5441 }
5442 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5443}
5444
48cb7ea9
SP
5445DEFUN_YANG (set_distance,
5446 set_distance_cmd,
5447 "set distance (0-255)",
5448 SET_STR
5449 "BGP Administrative Distance to use\n"
5450 "Distance value\n")
af5cd0a5 5451{
48cb7ea9
SP
5452 int idx_number = 2;
5453 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5454 char xpath_value[XPATH_MAXLEN];
89602edb 5455
48cb7ea9
SP
5456 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5457 snprintf(xpath_value, sizeof(xpath_value),
5458 "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5459 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5460 argv[idx_number]->arg);
5461 return nb_cli_apply_changes(vty, NULL);
af5cd0a5 5462}
5463
48cb7ea9
SP
5464DEFUN_YANG (no_set_distance,
5465 no_set_distance_cmd,
5466 "no set distance [(0-255)]",
5467 NO_STR SET_STR
5468 "BGP Administrative Distance to use\n"
5469 "Distance value\n")
316e074d 5470{
48cb7ea9 5471 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
cca30ba8 5472
48cb7ea9
SP
5473 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5474 return nb_cli_apply_changes(vty, NULL);
718e3744 5475}
5476
1bb550b6
PG
5477DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
5478 "[no] set l3vpn next-hop encapsulation gre",
5479 NO_STR SET_STR
5480 "L3VPN operations\n"
5481 "Next hop Information\n"
5482 "Encapsulation options (for BGP only)\n"
5483 "Accept L3VPN traffic over GRE encapsulation\n")
5484{
5485 const char *xpath =
5486 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
5487 const char *xpath_value =
5488 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
5489 enum nb_operation operation;
5490
5491 if (no)
5492 operation = NB_OP_DESTROY;
5493 else
5494 operation = NB_OP_CREATE;
5495
5496 nb_cli_enqueue_change(vty, xpath, operation, NULL);
5497 if (operation == NB_OP_DESTROY)
5498 return nb_cli_apply_changes(vty, NULL);
5499
5500 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
5501
5502 return nb_cli_apply_changes(vty, NULL);
5503}
5504
48cb7ea9
SP
5505DEFUN_YANG (set_local_pref,
5506 set_local_pref_cmd,
5507 "set local-preference WORD",
5508 SET_STR
5509 "BGP local preference path attribute\n"
5510 "Preference value (0-4294967295)\n")
7b7d48e5
DS
5511{
5512 int idx_number = 2;
48cb7ea9
SP
5513 const char *xpath =
5514 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5515 char xpath_value[XPATH_MAXLEN];
7b7d48e5 5516
48cb7ea9
SP
5517 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5518 snprintf(xpath_value, sizeof(xpath_value),
5519 "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5520 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5521 argv[idx_number]->arg);
5522 return nb_cli_apply_changes(vty, NULL);
7b7d48e5
DS
5523}
5524
48cb7ea9
SP
5525DEFUN_YANG (no_set_local_pref,
5526 no_set_local_pref_cmd,
5527 "no set local-preference [WORD]",
5528 NO_STR
5529 SET_STR
5530 "BGP local preference path attribute\n"
5531 "Preference value (0-4294967295)\n")
7b7d48e5 5532{
48cb7ea9
SP
5533 const char *xpath =
5534 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5535
5536 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5537 return nb_cli_apply_changes(vty, NULL);
7b7d48e5 5538}
718e3744 5539
48cb7ea9
SP
5540DEFUN_YANG (set_weight,
5541 set_weight_cmd,
5542 "set weight (0-4294967295)",
5543 SET_STR
5544 "BGP weight for routing table\n"
5545 "Weight value\n")
718e3744 5546{
d62a17ae 5547 int idx_number = 2;
48cb7ea9
SP
5548 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5549 char xpath_value[XPATH_MAXLEN];
4c9bd275 5550
48cb7ea9
SP
5551 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5552 snprintf(xpath_value, sizeof(xpath_value),
5553 "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5554 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5555 argv[idx_number]->arg);
5556 return nb_cli_apply_changes(vty, NULL);
718e3744 5557}
5558
48cb7ea9
SP
5559DEFUN_YANG (no_set_weight,
5560 no_set_weight_cmd,
5561 "no set weight [(0-4294967295)]",
5562 NO_STR
5563 SET_STR
5564 "BGP weight for routing table\n"
5565 "Weight value\n")
718e3744 5566{
48cb7ea9 5567 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
718e3744 5568
48cb7ea9
SP
5569 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5570 return nb_cli_apply_changes(vty, NULL);
718e3744 5571}
5572
48cb7ea9
SP
5573DEFUN_YANG (set_label_index,
5574 set_label_index_cmd,
5575 "set label-index (0-1048560)",
5576 SET_STR
5577 "Label index to associate with the prefix\n"
5578 "Label index value\n")
d990e384 5579{
d62a17ae 5580 int idx_number = 2;
48cb7ea9
SP
5581 const char *xpath =
5582 "./set-action[action='frr-bgp-route-map:label-index']";
5583 char xpath_value[XPATH_MAXLEN];
5584
5585 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5586 snprintf(xpath_value, sizeof(xpath_value),
5587 "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5588 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5589 argv[idx_number]->arg);
5590 return nb_cli_apply_changes(vty, NULL);
d990e384
DS
5591}
5592
48cb7ea9
SP
5593DEFUN_YANG (no_set_label_index,
5594 no_set_label_index_cmd,
5595 "no set label-index [(0-1048560)]",
5596 NO_STR
5597 SET_STR
5598 "Label index to associate with the prefix\n"
5599 "Label index value\n")
d990e384 5600{
48cb7ea9
SP
5601 const char *xpath =
5602 "./set-action[action='frr-bgp-route-map:label-index']";
5603
5604 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5605 return nb_cli_apply_changes(vty, NULL);
d990e384 5606}
718e3744 5607
48cb7ea9
SP
5608DEFUN_YANG (set_aspath_prepend_asn,
5609 set_aspath_prepend_asn_cmd,
5610 "set as-path prepend (1-4294967295)...",
5611 SET_STR
5612 "Transform BGP AS_PATH attribute\n"
5613 "Prepend to the as-path\n"
5614 "AS number\n")
718e3744 5615{
d62a17ae 5616 int idx_asn = 3;
5617 int ret;
5618 char *str;
718e3744 5619
d62a17ae 5620 str = argv_concat(argv, argc, idx_asn);
718e3744 5621
48cb7ea9
SP
5622 const char *xpath =
5623 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5624 char xpath_value[XPATH_MAXLEN];
5625
5626 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5627 snprintf(xpath_value, sizeof(xpath_value),
5628 "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5629 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5630 ret = nb_cli_apply_changes(vty, NULL);
5631 XFREE(MTYPE_TMP, str);
d62a17ae 5632 return ret;
718e3744 5633}
5634
48cb7ea9
SP
5635DEFUN_YANG (set_aspath_prepend_lastas,
5636 set_aspath_prepend_lastas_cmd,
5637 "set as-path prepend last-as (1-10)",
5638 SET_STR
5639 "Transform BGP AS_PATH attribute\n"
5640 "Prepend to the as-path\n"
6ba0adac 5641 "Use the last AS-number in the as-path\n"
48cb7ea9 5642 "Number of times to insert\n")
12dcf78e 5643{
48cb7ea9
SP
5644 int idx_num = 4;
5645
5646 const char *xpath =
5647 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5648 char xpath_value[XPATH_MAXLEN];
5649
5650 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5651 snprintf(xpath_value, sizeof(xpath_value),
5652 "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5653 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5654 argv[idx_num]->arg);
5655 return nb_cli_apply_changes(vty, NULL);
12dcf78e 5656}
bc3dd427 5657
77e3d821
DA
5658DEFPY_YANG (set_aspath_replace_asn,
5659 set_aspath_replace_asn_cmd,
5660 "set as-path replace <any|(1-4294967295)>$replace",
5661 SET_STR
5662 "Transform BGP AS_PATH attribute\n"
5663 "Replace AS number to local AS number\n"
5664 "Replace any AS number to local AS number\n"
5665 "Replace a specific AS number to local AS number\n")
5666{
5667 const char *xpath =
5668 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5669 char xpath_value[XPATH_MAXLEN];
5670
5671 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5672 snprintf(xpath_value, sizeof(xpath_value),
5673 "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5674 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5675 return nb_cli_apply_changes(vty, NULL);
5676}
5677
5678DEFPY_YANG (no_set_aspath_replace_asn,
5679 no_set_aspath_replace_asn_cmd,
5680 "no set as-path replace [<any|(1-4294967295)>]",
5681 NO_STR
5682 SET_STR
5683 "Transform BGP AS_PATH attribute\n"
5684 "Replace AS number to local AS number\n"
5685 "Replace any AS number to local AS number\n"
5686 "Replace a specific AS number to local AS number\n")
5687{
5688 const char *xpath =
5689 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5690
5691 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5692 return nb_cli_apply_changes(vty, NULL);
5693}
5694
48cb7ea9
SP
5695DEFUN_YANG (no_set_aspath_prepend,
5696 no_set_aspath_prepend_cmd,
5697 "no set as-path prepend [(1-4294967295)]",
5698 NO_STR
5699 SET_STR
5700 "Transform BGP AS_PATH attribute\n"
5701 "Prepend to the as-path\n"
5702 "AS number\n")
718e3744 5703{
48cb7ea9
SP
5704 const char *xpath =
5705 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
a7f93f3e 5706
48cb7ea9
SP
5707 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5708 return nb_cli_apply_changes(vty, NULL);
718e3744 5709}
5710
48cb7ea9
SP
5711DEFUN_YANG (no_set_aspath_prepend_lastas,
5712 no_set_aspath_prepend_lastas_cmd,
5713 "no set as-path prepend last-as [(1-10)]",
5714 NO_STR
5715 SET_STR
5716 "Transform BGP AS_PATH attribute\n"
5717 "Prepend to the as-path\n"
5718 "Use the peers AS-number\n"
5719 "Number of times to insert\n")
9131e6e8 5720{
48cb7ea9
SP
5721 const char *xpath =
5722 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5723
5724 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5725 return nb_cli_apply_changes(vty, NULL);
9131e6e8 5726}
718e3744 5727
48cb7ea9
SP
5728DEFUN_YANG (set_aspath_exclude,
5729 set_aspath_exclude_cmd,
5730 "set as-path exclude (1-4294967295)...",
5731 SET_STR
5732 "Transform BGP AS-path attribute\n"
5733 "Exclude from the as-path\n"
5734 "AS number\n")
841f7a57 5735{
d62a17ae 5736 int idx_asn = 3;
5737 int ret;
5738 char *str;
841f7a57 5739
d62a17ae 5740 str = argv_concat(argv, argc, idx_asn);
48cb7ea9
SP
5741
5742 const char *xpath =
5743 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5744 char xpath_value[XPATH_MAXLEN];
5745
5746 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5747 snprintf(xpath_value, sizeof(xpath_value),
5748 "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5749 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5750 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5751 XFREE(MTYPE_TMP, str);
5752 return ret;
841f7a57
DO
5753}
5754
48cb7ea9
SP
5755DEFUN_YANG (no_set_aspath_exclude,
5756 no_set_aspath_exclude_cmd,
5757 "no set as-path exclude (1-4294967295)...",
5758 NO_STR
5759 SET_STR
5760 "Transform BGP AS_PATH attribute\n"
5761 "Exclude from the as-path\n"
5762 "AS number\n")
841f7a57 5763{
48cb7ea9
SP
5764 const char *xpath =
5765 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
841f7a57 5766
48cb7ea9
SP
5767 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5768 return nb_cli_apply_changes(vty, NULL);
841f7a57
DO
5769}
5770
48cb7ea9
SP
5771ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5772 "no set as-path exclude",
5773 NO_STR SET_STR
5774 "Transform BGP AS_PATH attribute\n"
5775 "Exclude from the as-path\n")
841f7a57 5776
48cb7ea9
SP
5777DEFUN_YANG (set_community,
5778 set_community_cmd,
5779 "set community AA:NN...",
5780 SET_STR
5781 "BGP community attribute\n"
5782 COMMUNITY_VAL_STR)
718e3744 5783{
d62a17ae 5784 int idx_aa_nn = 2;
5785 int i;
5786 int first = 0;
5787 int additive = 0;
5788 struct buffer *b;
5789 struct community *com = NULL;
5790 char *str;
48cb7ea9 5791 char *argstr = NULL;
d62a17ae 5792 int ret;
5793
48cb7ea9
SP
5794 const char *xpath =
5795 "./set-action[action='frr-bgp-route-map:set-community']";
5796 char xpath_value[XPATH_MAXLEN];
5797
5798 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5799 snprintf(xpath_value, sizeof(xpath_value),
5800 "%s/rmap-set-action/frr-bgp-route-map:community-string",
5801 xpath);
5802
d62a17ae 5803 b = buffer_new(1024);
5804
5805 for (i = idx_aa_nn; i < argc; i++) {
5806 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5807 == 0) {
5808 additive = 1;
5809 continue;
5810 }
5811
5812 if (first)
5813 buffer_putc(b, ' ');
5814 else
5815 first = 1;
5816
5817 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5818 == 0) {
5819 buffer_putstr(b, "internet");
5820 continue;
5821 }
5822 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5823 == 0) {
5824 buffer_putstr(b, "local-AS");
5825 continue;
5826 }
5827 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5828 && strncmp(argv[i]->arg, "no-advertise",
5829 strlen(argv[i]->arg))
5830 == 0) {
5831 buffer_putstr(b, "no-advertise");
5832 continue;
5833 }
5834 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5835 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5836 == 0) {
5837 buffer_putstr(b, "no-export");
5838 continue;
5839 }
2721dd61
DA
5840 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
5841 == 0) {
5842 buffer_putstr(b, "blackhole");
5843 continue;
5844 }
a4d82a8a
PZ
5845 if (strncmp(argv[i]->arg, "graceful-shutdown",
5846 strlen(argv[i]->arg))
7f323236
DW
5847 == 0) {
5848 buffer_putstr(b, "graceful-shutdown");
5849 continue;
5850 }
d62a17ae 5851 buffer_putstr(b, argv[i]->arg);
5852 }
5853 buffer_putc(b, '\0');
5854
5855 /* Fetch result string then compile it to communities attribute. */
5856 str = buffer_getstr(b);
5857 buffer_free(b);
5858
c0945b78 5859 if (str)
d62a17ae 5860 com = community_str2com(str);
d62a17ae 5861
5862 /* Can't compile user input into communities attribute. */
5863 if (!com) {
c0945b78
DA
5864 vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
5865 XFREE(MTYPE_TMP, str);
d62a17ae 5866 return CMD_WARNING_CONFIG_FAILED;
5867 }
c0945b78 5868 XFREE(MTYPE_TMP, str);
d62a17ae 5869
5870 /* Set communites attribute string. */
c0945b78 5871 str = community_str(com, false, false);
d62a17ae 5872
5873 if (additive) {
552d6491
QY
5874 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
5875 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
5876 strlcpy(argstr, str, argstr_sz);
5877 strlcat(argstr, " additive", argstr_sz);
48cb7ea9 5878 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
d62a17ae 5879 } else
48cb7ea9
SP
5880 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5881
5882 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5883
48cb7ea9
SP
5884 if (argstr)
5885 XFREE(MTYPE_TMP, argstr);
3c1f53de 5886 community_free(&com);
d62a17ae 5887
5888 return ret;
718e3744 5889}
5890
48cb7ea9
SP
5891DEFUN_YANG (set_community_none,
5892 set_community_none_cmd,
5893 "set community none",
5894 SET_STR
5895 "BGP community attribute\n"
5896 "No community attribute\n")
718e3744 5897{
48cb7ea9
SP
5898 const char *xpath =
5899 "./set-action[action='frr-bgp-route-map:set-community']";
5900 char xpath_value[XPATH_MAXLEN];
5901
5902 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5903
5904 snprintf(xpath_value, sizeof(xpath_value),
5905 "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
5906 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5907 return nb_cli_apply_changes(vty, NULL);
718e3744 5908}
5909
48cb7ea9
SP
5910DEFUN_YANG (no_set_community,
5911 no_set_community_cmd,
5912 "no set community AA:NN...",
5913 NO_STR
5914 SET_STR
5915 "BGP community attribute\n"
5916 COMMUNITY_VAL_STR)
718e3744 5917{
48cb7ea9
SP
5918 const char *xpath =
5919 "./set-action[action='frr-bgp-route-map:set-community']";
718e3744 5920
48cb7ea9
SP
5921 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5922 return nb_cli_apply_changes(vty, NULL);
5923}
2929de9e 5924
48cb7ea9
SP
5925ALIAS_YANG (no_set_community,
5926 no_set_community_short_cmd,
5927 "no set community",
5928 NO_STR
5929 SET_STR
5930 "BGP community attribute\n")
718e3744 5931
48cb7ea9 5932DEFPY_YANG (set_community_delete,
718e3744 5933 set_community_delete_cmd,
a2099c1d 5934 "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
718e3744 5935 SET_STR
5936 "set BGP community list (for deletion)\n"
5937 "Community-list number (standard)\n"
5e3edbf5 5938 "Community-list number (expanded)\n"
718e3744 5939 "Community-list name\n"
5940 "Delete matching communities\n")
5941{
48cb7ea9
SP
5942 const char *xpath =
5943 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5944 char xpath_value[XPATH_MAXLEN];
d62a17ae 5945 int idx_comm_list = 2;
718e3744 5946
48cb7ea9
SP
5947 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5948
5949 snprintf(xpath_value, sizeof(xpath_value),
5950 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5951 xpath);
5952 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5953 argv[idx_comm_list]->arg);
5954
5955 return nb_cli_apply_changes(vty, NULL);
718e3744 5956
718e3744 5957}
5958
48cb7ea9
SP
5959DEFUN_YANG (no_set_community_delete,
5960 no_set_community_delete_cmd,
a2099c1d 5961 "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
48cb7ea9
SP
5962 NO_STR
5963 SET_STR
5964 "set BGP community list (for deletion)\n"
5965 "Community-list number (standard)\n"
5966 "Community-list number (expanded)\n"
5967 "Community-list name\n"
5968 "Delete matching communities\n")
718e3744 5969{
48cb7ea9
SP
5970 const char *xpath =
5971 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5972
5973 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5974 return nb_cli_apply_changes(vty, NULL);
718e3744 5975}
5976
48cb7ea9
SP
5977DEFUN_YANG (set_lcommunity,
5978 set_lcommunity_cmd,
5979 "set large-community AA:BB:CC...",
5980 SET_STR
5981 "BGP large community attribute\n"
5982 "Large Community number in aa:bb:cc format or additive\n")
57d187bc 5983{
d62a17ae 5984 char *str;
48cb7ea9
SP
5985 int ret;
5986 const char *xpath =
5987 "./set-action[action='frr-bgp-route-map:set-large-community']";
5988 char xpath_value[XPATH_MAXLEN];
5989
5990 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 5991
48cb7ea9
SP
5992 snprintf(xpath_value, sizeof(xpath_value),
5993 "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
5994 xpath);
d62a17ae 5995 str = argv_concat(argv, argc, 2);
48cb7ea9
SP
5996 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5997 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5998 XFREE(MTYPE_TMP, str);
d62a17ae 5999 return ret;
57d187bc
JS
6000}
6001
48cb7ea9
SP
6002DEFUN_YANG (set_lcommunity_none,
6003 set_lcommunity_none_cmd,
6004 "set large-community none",
6005 SET_STR
6006 "BGP large community attribute\n"
6007 "No large community attribute\n")
57d187bc 6008{
48cb7ea9
SP
6009 const char *xpath =
6010 "./set-action[action='frr-bgp-route-map:set-large-community']";
6011 char xpath_value[XPATH_MAXLEN];
6012
6013 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6014
6015 snprintf(xpath_value, sizeof(xpath_value),
6016 "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
6017 xpath);
6018 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6019 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
6020}
6021
48cb7ea9
SP
6022DEFUN_YANG (no_set_lcommunity,
6023 no_set_lcommunity_cmd,
6024 "no set large-community none",
6025 NO_STR
6026 SET_STR
6027 "BGP large community attribute\n"
6028 "No community attribute\n")
57d187bc 6029{
48cb7ea9
SP
6030 const char *xpath =
6031 "./set-action[action='frr-bgp-route-map:set-large-community']";
6032
6033 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6034 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
6035}
6036
48cb7ea9
SP
6037DEFUN_YANG (no_set_lcommunity1,
6038 no_set_lcommunity1_cmd,
6039 "no set large-community AA:BB:CC...",
6040 NO_STR
6041 SET_STR
6042 "BGP large community attribute\n"
6043 "Large community in AA:BB:CC... format or additive\n")
52951b63 6044{
48cb7ea9
SP
6045 const char *xpath =
6046 "./set-action[action='frr-bgp-route-map:set-large-community']";
6047
6048 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6049 return nb_cli_apply_changes(vty, NULL);
52951b63 6050}
57d187bc 6051
48cb7ea9
SP
6052ALIAS_YANG (no_set_lcommunity1,
6053 no_set_lcommunity1_short_cmd,
6054 "no set large-community",
6055 NO_STR
6056 SET_STR
6057 "BGP large community attribute\n")
76a20aa9 6058
48cb7ea9 6059DEFPY_YANG (set_lcommunity_delete,
57d187bc 6060 set_lcommunity_delete_cmd,
a2099c1d 6061 "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
57d187bc
JS
6062 SET_STR
6063 "set BGP large community list (for deletion)\n"
6064 "Large Community-list number (standard)\n"
6065 "Large Communitly-list number (expanded)\n"
6066 "Large Community-list name\n"
6067 "Delete matching large communities\n")
6068{
48cb7ea9
SP
6069 const char *xpath =
6070 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6071 char xpath_value[XPATH_MAXLEN];
4cae2269 6072 int idx_lcomm_list = 2;
4cae2269 6073
48cb7ea9 6074 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 6075
48cb7ea9
SP
6076 snprintf(xpath_value, sizeof(xpath_value),
6077 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6078 xpath);
6079 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6080 argv[idx_lcomm_list]->arg);
6081
6082 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
6083}
6084
48cb7ea9
SP
6085DEFUN_YANG (no_set_lcommunity_delete,
6086 no_set_lcommunity_delete_cmd,
a2099c1d 6087 "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
48cb7ea9
SP
6088 NO_STR
6089 SET_STR
6090 "set BGP large community list (for deletion)\n"
6091 "Large Community-list number (standard)\n"
6092 "Large Communitly-list number (expanded)\n"
6093 "Large Community-list name\n"
6094 "Delete matching large communities\n")
57d187bc 6095{
48cb7ea9
SP
6096 const char *xpath =
6097 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6098
6099 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6100 return nb_cli_apply_changes(vty, NULL);
57d187bc 6101}
718e3744 6102
48cb7ea9
SP
6103ALIAS_YANG (no_set_lcommunity_delete,
6104 no_set_lcommunity_delete_short_cmd,
6105 "no set large-comm-list",
6106 NO_STR
6107 SET_STR
6108 "set BGP large community list (for deletion)\n")
76a20aa9 6109
48cb7ea9
SP
6110DEFUN_YANG (set_ecommunity_rt,
6111 set_ecommunity_rt_cmd,
6112 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6113 SET_STR
6114 "BGP extended community attribute\n"
6115 "Route Target extended community\n"
6116 "VPN extended community\n")
718e3744 6117{
d62a17ae 6118 int idx_asn_nn = 3;
d62a17ae 6119 char *str;
48cb7ea9
SP
6120 int ret;
6121 const char *xpath =
6122 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6123 char xpath_value[XPATH_MAXLEN];
6124
6125 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 6126
48cb7ea9
SP
6127 snprintf(xpath_value, sizeof(xpath_value),
6128 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
d62a17ae 6129 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
6130 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6131 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 6132 XFREE(MTYPE_TMP, str);
d62a17ae 6133 return ret;
718e3744 6134}
6135
48cb7ea9
SP
6136DEFUN_YANG (no_set_ecommunity_rt,
6137 no_set_ecommunity_rt_cmd,
6138 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6139 NO_STR
6140 SET_STR
6141 "BGP extended community attribute\n"
6142 "Route Target extended community\n"
6143 "VPN extended community\n")
6144{
6145 const char *xpath =
6146 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6147 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6148 return nb_cli_apply_changes(vty, NULL);
6149}
6150
6151ALIAS_YANG (no_set_ecommunity_rt,
6152 no_set_ecommunity_rt_short_cmd,
6153 "no set extcommunity rt",
6154 NO_STR
6155 SET_STR
6156 "BGP extended community attribute\n"
6157 "Route Target extended community\n")
6158
6159DEFUN_YANG (set_ecommunity_soo,
6160 set_ecommunity_soo_cmd,
6161 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6162 SET_STR
6163 "BGP extended community attribute\n"
6164 "Site-of-Origin extended community\n"
6165 "VPN extended community\n")
718e3744 6166{
d62a17ae 6167 int idx_asn_nn = 3;
d62a17ae 6168 char *str;
48cb7ea9
SP
6169 int ret;
6170 const char *xpath =
6171 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6172 char xpath_value[XPATH_MAXLEN];
718e3744 6173
48cb7ea9
SP
6174 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6175
6176 snprintf(xpath_value, sizeof(xpath_value),
6177 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
6178 xpath);
d62a17ae 6179 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
6180 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6181 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 6182 XFREE(MTYPE_TMP, str);
6183 return ret;
718e3744 6184}
6185
48cb7ea9
SP
6186DEFUN_YANG (no_set_ecommunity_soo,
6187 no_set_ecommunity_soo_cmd,
6188 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6189 NO_STR
6190 SET_STR
6191 "BGP extended community attribute\n"
6192 "Site-of-Origin extended community\n"
6193 "VPN extended community\n")
6194{
6195 const char *xpath =
6196 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6197 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6198 return nb_cli_apply_changes(vty, NULL);
6199}
6200
6201ALIAS_YANG (no_set_ecommunity_soo,
6202 no_set_ecommunity_soo_short_cmd,
6203 "no set extcommunity soo",
6204 NO_STR
6205 SET_STR
6206 "GP extended community attribute\n"
6207 "Site-of-Origin extended community\n")
6208
bb4dcdd1
DA
6209DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
6210 "set extcommunity none",
6211 SET_STR
6212 "BGP extended community attribute\n"
6213 "No extended community attribute\n")
6214{
6215 const char *xpath =
6216 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6217 char xpath_value[XPATH_MAXLEN];
6218
6219 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6220
6221 snprintf(xpath_value, sizeof(xpath_value),
6222 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6223 xpath);
6224 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6225 return nb_cli_apply_changes(vty, NULL);
6226}
6227
6228DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6229 "no set extcommunity none",
6230 NO_STR SET_STR
6231 "BGP extended community attribute\n"
6232 "No extended community attribute\n")
6233{
6234 const char *xpath =
6235 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6236 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6237 return nb_cli_apply_changes(vty, NULL);
6238}
6239
48cb7ea9
SP
6240DEFUN_YANG (set_ecommunity_lb,
6241 set_ecommunity_lb_cmd,
6242 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6243 SET_STR
6244 "BGP extended community attribute\n"
6245 "Link bandwidth extended community\n"
6246 "Bandwidth value in Mbps\n"
6247 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6248 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6249 "Attribute is set as non-transitive\n")
718e3744 6250{
48cb7ea9 6251 int idx_lb = 3;
3b225ee7 6252 int idx_non_transitive = 0;
48cb7ea9
SP
6253 const char *xpath =
6254 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6255 char xpath_lb_type[XPATH_MAXLEN];
6256 char xpath_bandwidth[XPATH_MAXLEN];
6257 char xpath_non_transitive[XPATH_MAXLEN];
6258
6259 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6260
6261 snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6262 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6263 xpath);
6264 snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6265 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6266 xpath);
6267 snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6268 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6269 xpath);
6270
6271 if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6272 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6273 "cumulative-bandwidth");
6274 else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6275 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6276 "computed-bandwidth");
6277 else {
6278 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6279 "explicit-bandwidth");
6280 nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6281 argv[idx_lb]->arg);
6282 }
718e3744 6283
3b225ee7 6284 if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
48cb7ea9
SP
6285 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6286 "true");
6287 else
6288 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6289 "false");
6290
6291 return nb_cli_apply_changes(vty, NULL);
6292}
6293
6294DEFUN_YANG (no_set_ecommunity_lb,
6295 no_set_ecommunity_lb_cmd,
6296 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6297 NO_STR
6298 SET_STR
6299 "BGP extended community attribute\n"
6300 "Link bandwidth extended community\n"
6301 "Bandwidth value in Mbps\n"
6302 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6303 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6304 "Attribute is set as non-transitive\n")
6305{
6306 const char *xpath =
6307 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6308
6309 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6310 return nb_cli_apply_changes(vty, NULL);
6311}
6312
6313ALIAS_YANG (no_set_ecommunity_lb,
6314 no_set_ecommunity_lb_short_cmd,
6315 "no set extcommunity bandwidth",
6316 NO_STR
6317 SET_STR
6318 "BGP extended community attribute\n"
6319 "Link bandwidth extended community\n")
6320
6321DEFUN_YANG (set_origin,
6322 set_origin_cmd,
6323 "set origin <egp|igp|incomplete>",
6324 SET_STR
6325 "BGP origin code\n"
6326 "remote EGP\n"
6327 "local IGP\n"
6328 "unknown heritage\n")
ca9ac3ef 6329{
48cb7ea9
SP
6330 int idx_origin = 2;
6331 const char *origin_type;
6332 const char *xpath =
6333 "./set-action[action='frr-bgp-route-map:set-origin']";
6334 char xpath_value[XPATH_MAXLEN];
ca9ac3ef 6335
48cb7ea9
SP
6336 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6337 origin_type = "igp";
6338 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6339 origin_type = "egp";
6340 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6341 origin_type = "incomplete";
6342 else {
6343 vty_out(vty, "%% Invalid match origin type\n");
6344 return CMD_WARNING_CONFIG_FAILED;
6345 }
ca9ac3ef 6346
48cb7ea9
SP
6347 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6348 snprintf(xpath_value, sizeof(xpath_value),
6349 "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6350 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
ca9ac3ef 6351
48cb7ea9 6352 return nb_cli_apply_changes(vty, NULL);
ca9ac3ef 6353}
6354
48cb7ea9
SP
6355DEFUN_YANG (no_set_origin,
6356 no_set_origin_cmd,
6357 "no set origin [<egp|igp|incomplete>]",
6358 NO_STR
6359 SET_STR
6360 "BGP origin code\n"
6361 "remote EGP\n"
6362 "local IGP\n"
6363 "unknown heritage\n")
718e3744 6364{
48cb7ea9
SP
6365 const char *xpath =
6366 "./set-action[action='frr-bgp-route-map:set-origin']";
718e3744 6367
48cb7ea9
SP
6368 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6369 return nb_cli_apply_changes(vty, NULL);
718e3744 6370}
6371
48cb7ea9
SP
6372DEFUN_YANG (set_atomic_aggregate,
6373 set_atomic_aggregate_cmd,
6374 "set atomic-aggregate",
6375 SET_STR
6376 "BGP atomic aggregate attribute\n" )
718e3744 6377{
48cb7ea9
SP
6378 const char *xpath =
6379 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6380 char xpath_value[XPATH_MAXLEN];
718e3744 6381
48cb7ea9
SP
6382 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6383 snprintf(xpath_value, sizeof(xpath_value),
6384 "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6385 xpath);
6386 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
718e3744 6387
48cb7ea9 6388 return nb_cli_apply_changes(vty, NULL);
718e3744 6389}
6390
48cb7ea9
SP
6391DEFUN_YANG (no_set_atomic_aggregate,
6392 no_set_atomic_aggregate_cmd,
6393 "no set atomic-aggregate",
6394 NO_STR
6395 SET_STR
6396 "BGP atomic aggregate attribute\n" )
718e3744 6397{
48cb7ea9
SP
6398 const char *xpath =
6399 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6400
6401 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6402 return nb_cli_apply_changes(vty, NULL);
718e3744 6403}
6404
97a52c82
DA
6405DEFPY_YANG (set_aigp_metric,
6406 set_aigp_metric_cmd,
6407 "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
6408 SET_STR
6409 "BGP AIGP attribute (AIGP Metric TLV)\n"
6410 "AIGP Metric value from IGP protocol\n"
6411 "Manual AIGP Metric value\n")
6412{
6413 const char *xpath =
6414 "./set-action[action='frr-bgp-route-map:aigp-metric']";
6415 char xpath_value[XPATH_MAXLEN];
6416
6417 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6418 snprintf(xpath_value, sizeof(xpath_value),
6419 "%s/rmap-set-action/frr-bgp-route-map:aigp-metric", xpath);
6420 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, aigp_metric);
6421
6422 return nb_cli_apply_changes(vty, NULL);
6423}
6424
6425DEFPY_YANG (no_set_aigp_metric,
6426 no_set_aigp_metric_cmd,
6427 "no set aigp-metric [<igp-metric|(1-4294967295)>]",
6428 NO_STR
6429 SET_STR
6430 "BGP AIGP attribute (AIGP Metric TLV)\n"
6431 "AIGP Metric value from IGP protocol\n"
6432 "Manual AIGP Metric value\n")
6433{
6434 const char *xpath =
6435 "./set-action[action='frr-bgp-route-map:aigp-metric']";
6436
6437 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6438 return nb_cli_apply_changes(vty, NULL);
6439}
6440
48cb7ea9
SP
6441DEFUN_YANG (set_aggregator_as,
6442 set_aggregator_as_cmd,
6443 "set aggregator as (1-4294967295) A.B.C.D",
6444 SET_STR
6445 "BGP aggregator attribute\n"
6446 "AS number of aggregator\n"
6447 "AS number\n"
6448 "IP address of aggregator\n")
718e3744 6449{
d62a17ae 6450 int idx_number = 3;
6451 int idx_ipv4 = 4;
48cb7ea9
SP
6452 char xpath_asn[XPATH_MAXLEN];
6453 char xpath_addr[XPATH_MAXLEN];
6454 const char *xpath =
6455 "./set-action[action='frr-bgp-route-map:aggregator']";
e52702f2 6456
48cb7ea9 6457 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 6458
48cb7ea9
SP
6459 snprintf(
6460 xpath_asn, sizeof(xpath_asn),
6461 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6462 xpath);
6463 nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6464 argv[idx_number]->arg);
718e3744 6465
48cb7ea9
SP
6466 snprintf(
6467 xpath_addr, sizeof(xpath_addr),
6468 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6469 xpath);
6470 nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6471 argv[idx_ipv4]->arg);
718e3744 6472
48cb7ea9 6473 return nb_cli_apply_changes(vty, NULL);
718e3744 6474}
6475
48cb7ea9
SP
6476DEFUN_YANG (no_set_aggregator_as,
6477 no_set_aggregator_as_cmd,
6478 "no set aggregator as [(1-4294967295) A.B.C.D]",
6479 NO_STR
6480 SET_STR
6481 "BGP aggregator attribute\n"
6482 "AS number of aggregator\n"
6483 "AS number\n"
6484 "IP address of aggregator\n")
718e3744 6485{
48cb7ea9
SP
6486 const char *xpath =
6487 "./set-action[action='frr-bgp-route-map:aggregator']";
718e3744 6488
48cb7ea9
SP
6489 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6490 return nb_cli_apply_changes(vty, NULL);
6491}
718e3744 6492
48cb7ea9
SP
6493DEFUN_YANG (match_ipv6_next_hop,
6494 match_ipv6_next_hop_cmd,
bc63ba98
DA
6495 "match ipv6 next-hop ACCESSLIST6_NAME",
6496 MATCH_STR
6497 IPV6_STR
6498 "Match IPv6 next-hop address of route\n"
6499 "IPv6 access-list name\n")
6500{
6501 const char *xpath =
6502 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6503 char xpath_value[XPATH_MAXLEN];
6504
6505 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6506 snprintf(xpath_value, sizeof(xpath_value),
6507 "%s/rmap-match-condition/list-name", xpath);
6508 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6509 argv[argc - 1]->arg);
6510
6511 return nb_cli_apply_changes(vty, NULL);
6512}
6513
6514DEFUN_YANG (no_match_ipv6_next_hop,
6515 no_match_ipv6_next_hop_cmd,
6516 "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6517 NO_STR
6518 MATCH_STR
6519 IPV6_STR
6520 "Match IPv6 next-hop address of route\n"
6521 "IPv6 access-list name\n")
6522{
6523 const char *xpath =
6524 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6525
6526 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6527 return nb_cli_apply_changes(vty, NULL);
6528}
6529
6530DEFUN_YANG (match_ipv6_next_hop_address,
6531 match_ipv6_next_hop_address_cmd,
03030106 6532 "match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6533 MATCH_STR
6534 IPV6_STR
6535 "Match IPv6 next-hop address of route\n"
03030106 6536 "IPv6 address\n"
48cb7ea9
SP
6537 "IPv6 address of next hop\n")
6538{
6539 const char *xpath =
6540 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6541 char xpath_value[XPATH_MAXLEN];
718e3744 6542
48cb7ea9
SP
6543 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6544 snprintf(xpath_value, sizeof(xpath_value),
6545 "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6546 xpath);
bc63ba98
DA
6547 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6548 argv[argc - 1]->arg);
718e3744 6549
48cb7ea9 6550 return nb_cli_apply_changes(vty, NULL);
718e3744 6551}
6552
bc63ba98
DA
6553DEFUN_YANG (no_match_ipv6_next_hop_address,
6554 no_match_ipv6_next_hop_address_cmd,
03030106 6555 "no match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6556 NO_STR
6557 MATCH_STR
6558 IPV6_STR
6559 "Match IPv6 next-hop address of route\n"
03030106 6560 "IPv6 address\n"
48cb7ea9 6561 "IPv6 address of next hop\n")
718e3744 6562{
48cb7ea9
SP
6563 const char *xpath =
6564 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
718e3744 6565
48cb7ea9
SP
6566 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6567 return nb_cli_apply_changes(vty, NULL);
718e3744 6568}
6569
bc63ba98 6570ALIAS_HIDDEN (match_ipv6_next_hop_address,
03030106
IR
6571 match_ipv6_next_hop_old_cmd,
6572 "match ipv6 next-hop X:X::X:X",
6573 MATCH_STR
6574 IPV6_STR
6575 "Match IPv6 next-hop address of route\n"
6576 "IPv6 address of next hop\n")
6577
bc63ba98 6578ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
03030106
IR
6579 no_match_ipv6_next_hop_old_cmd,
6580 "no match ipv6 next-hop X:X::X:X",
6581 NO_STR
6582 MATCH_STR
6583 IPV6_STR
6584 "Match IPv6 next-hop address of route\n"
6585 "IPv6 address of next hop\n")
6586
82f191a2
DA
6587DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6588 match_ipv6_next_hop_prefix_list_cmd,
6589 "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6590 MATCH_STR
6591 IPV6_STR
6592 "Match IPv6 next-hop address of route\n"
6593 "Match entries by prefix-list\n"
6594 "IPv6 prefix-list name\n")
6595{
6596 const char *xpath =
6597 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6598 char xpath_value[XPATH_MAXLEN];
6599
6600 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6601 snprintf(xpath_value, sizeof(xpath_value),
6602 "%s/rmap-match-condition/list-name", xpath);
6603 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6604 argv[argc - 1]->arg);
6605
6606 return nb_cli_apply_changes(vty, NULL);
6607}
6608
6609DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6610 no_match_ipv6_next_hop_prefix_list_cmd,
6611 "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6612 NO_STR
6613 MATCH_STR
6614 IPV6_STR
6615 "Match IPv6 next-hop address of route\n"
6616 "Match entries by prefix-list\n"
6617 "IPv6 prefix-list name\n")
6618{
6619 const char *xpath =
6620 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6621
6622 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6623 return nb_cli_apply_changes(vty, NULL);
6624}
6625
48cb7ea9 6626DEFPY_YANG (match_ipv4_next_hop,
be7735b3 6627 match_ipv4_next_hop_cmd,
17ac51eb 6628 "match ip next-hop address A.B.C.D",
be7735b3
PG
6629 MATCH_STR
6630 IP_STR
6631 "Match IP next-hop address of route\n"
6632 "IP address\n"
6633 "IP address of next-hop\n")
6634{
48cb7ea9
SP
6635 const char *xpath =
6636 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6637 char xpath_value[XPATH_MAXLEN];
6638
6639 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6640 snprintf(xpath_value, sizeof(xpath_value),
6641 "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6642 xpath);
6643 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
be7735b3 6644
48cb7ea9 6645 return nb_cli_apply_changes(vty, NULL);
17ac51eb 6646}
be7735b3 6647
48cb7ea9 6648DEFPY_YANG (no_match_ipv4_next_hop,
17ac51eb
DS
6649 no_match_ipv4_next_hop_cmd,
6650 "no match ip next-hop address [A.B.C.D]",
6651 NO_STR
6652 MATCH_STR
6653 IP_STR
6654 "Match IP next-hop address of route\n"
6655 "IP address\n"
6656 "IP address of next-hop\n")
6657{
48cb7ea9
SP
6658 const char *xpath =
6659 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6660
6661 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6662 return nb_cli_apply_changes(vty, NULL);
be7735b3 6663}
718e3744 6664
48cb7ea9
SP
6665DEFUN_YANG (set_ipv6_nexthop_peer,
6666 set_ipv6_nexthop_peer_cmd,
6667 "set ipv6 next-hop peer-address",
6668 SET_STR
6669 IPV6_STR
6670 "Next hop address\n"
6671 "Use peer address (for BGP only)\n")
90916ac2 6672{
48cb7ea9
SP
6673 const char *xpath =
6674 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6675 char xpath_value[XPATH_MAXLEN];
6676
6677 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6678 snprintf(xpath_value, sizeof(xpath_value),
6679 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6680 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6681
6682 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6683}
6684
48cb7ea9
SP
6685DEFUN_YANG (no_set_ipv6_nexthop_peer,
6686 no_set_ipv6_nexthop_peer_cmd,
6687 "no set ipv6 next-hop peer-address",
6688 NO_STR
6689 SET_STR
6690 IPV6_STR
6691 "IPv6 next-hop address\n"
6692 "Use peer address (for BGP only)\n")
90916ac2 6693{
48cb7ea9
SP
6694 const char *xpath =
6695 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6696
6697 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6698 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6699}
6700
48cb7ea9
SP
6701DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6702 set_ipv6_nexthop_prefer_global_cmd,
6703 "set ipv6 next-hop prefer-global",
6704 SET_STR
6705 IPV6_STR
6706 "IPv6 next-hop address\n"
6707 "Prefer global over link-local if both exist\n")
161995ea 6708{
48cb7ea9
SP
6709 const char *xpath =
6710 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6711 char xpath_value[XPATH_MAXLEN];
6712
6713 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6714 snprintf(xpath_value, sizeof(xpath_value),
6715 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6716 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6717
6718 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6719}
6720
48cb7ea9
SP
6721DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6722 no_set_ipv6_nexthop_prefer_global_cmd,
6723 "no set ipv6 next-hop prefer-global",
6724 NO_STR
6725 SET_STR
6726 IPV6_STR
6727 "IPv6 next-hop address\n"
6728 "Prefer global over link-local if both exist\n")
161995ea 6729{
48cb7ea9
SP
6730 const char *xpath =
6731 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6732
6733 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6734 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6735}
6736
48cb7ea9
SP
6737DEFUN_YANG (set_ipv6_nexthop_global,
6738 set_ipv6_nexthop_global_cmd,
6739 "set ipv6 next-hop global X:X::X:X",
6740 SET_STR
6741 IPV6_STR
6742 "IPv6 next-hop address\n"
6743 "IPv6 global address\n"
6744 "IPv6 address of next hop\n")
718e3744 6745{
d62a17ae 6746 int idx_ipv6 = 4;
48cb7ea9
SP
6747 const char *xpath =
6748 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6749 char xpath_value[XPATH_MAXLEN];
bf8b3d27 6750
48cb7ea9
SP
6751 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6752 snprintf(xpath_value, sizeof(xpath_value),
6753 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6754 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6755 argv[idx_ipv6]->arg);
bf8b3d27 6756
48cb7ea9 6757 return nb_cli_apply_changes(vty, NULL);
718e3744 6758}
6759
48cb7ea9
SP
6760DEFUN_YANG (no_set_ipv6_nexthop_global,
6761 no_set_ipv6_nexthop_global_cmd,
6762 "no set ipv6 next-hop global X:X::X:X",
6763 NO_STR
6764 SET_STR
6765 IPV6_STR
6766 "IPv6 next-hop address\n"
6767 "IPv6 global address\n"
6768 "IPv6 address of next hop\n")
718e3744 6769{
48cb7ea9
SP
6770 const char *xpath =
6771 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6772
6773 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6774 return nb_cli_apply_changes(vty, NULL);
718e3744 6775}
718e3744 6776
d6902373 6777#ifdef KEEP_OLD_VPN_COMMANDS
48cb7ea9
SP
6778DEFUN_YANG (set_vpn_nexthop,
6779 set_vpn_nexthop_cmd,
6780 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6781 SET_STR
6782 "VPNv4 information\n"
6783 "VPN next-hop address\n"
6784 "IP address of next hop\n"
6785 "VPNv6 information\n"
6786 "VPN next-hop address\n"
6787 "IPv6 address of next hop\n")
718e3744 6788{
d62a17ae 6789 int idx_ip = 3;
6790 afi_t afi;
6791 int idx = 0;
4ad4ae64 6792 char xpath_value[XPATH_MAXLEN];
d62a17ae 6793
6794 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6795 if (afi == AFI_IP) {
6796 const char *xpath =
6797 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6798
6799 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6800 snprintf(
6801 xpath_value, sizeof(xpath_value),
6802 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6803 xpath);
6804 } else {
6805 const char *xpath =
6806 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6807
6808 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6809 snprintf(
6810 xpath_value, sizeof(xpath_value),
6811 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6812 xpath);
6813 }
6814
6815 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6816 argv[idx_ip]->arg);
6817
6818 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6819 }
48cb7ea9 6820
d62a17ae 6821 return CMD_SUCCESS;
d6902373 6822}
a4b2b610 6823
48cb7ea9
SP
6824DEFUN_YANG (no_set_vpn_nexthop,
6825 no_set_vpn_nexthop_cmd,
6826 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6827 NO_STR
6828 SET_STR
6829 "VPNv4 information\n"
6830 "VPN next-hop address\n"
6831 "IP address of next hop\n"
6832 "VPNv6 information\n"
6833 "VPN next-hop address\n"
6834 "IPv6 address of next hop\n")
718e3744 6835{
d62a17ae 6836 afi_t afi;
6837 int idx = 0;
6838
d62a17ae 6839 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6840 if (afi == AFI_IP) {
6841 const char *xpath =
6842 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6843 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6844 } else {
6845 const char *xpath =
6846 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6847 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6848 }
6849 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6850 }
6851 return CMD_SUCCESS;
d6902373
PG
6852}
6853#endif /* KEEP_OLD_VPN_COMMANDS */
6854
7be9666f 6855DEFPY_YANG (set_ipx_vpn_nexthop,
48cb7ea9 6856 set_ipx_vpn_nexthop_cmd,
7be9666f 6857 "set <ipv4|ipv6> vpn next-hop <A.B.C.D$addrv4|X:X::X:X$addrv6>",
48cb7ea9
SP
6858 SET_STR
6859 "IPv4 information\n"
6860 "IPv6 information\n"
6861 "VPN information\n"
6862 "VPN next-hop address\n"
6863 "IP address of next hop\n"
6864 "IPv6 address of next hop\n")
d6902373 6865{
d62a17ae 6866 int idx_ip = 4;
6867 afi_t afi;
6868 int idx = 0;
48cb7ea9 6869 char xpath_value[XPATH_MAXLEN];
d62a17ae 6870
6871 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9 6872 if (afi == AFI_IP) {
7be9666f
DA
6873 if (addrv6_str) {
6874 vty_out(vty, "%% IPv4 next-hop expected\n");
6875 return CMD_WARNING_CONFIG_FAILED;
6876 }
6877
48cb7ea9
SP
6878 const char *xpath =
6879 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6880
6881 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6882 snprintf(
6883 xpath_value, sizeof(xpath_value),
6884 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6885 xpath);
6886 } else {
7be9666f
DA
6887 if (addrv4_str) {
6888 vty_out(vty, "%% IPv6 next-hop expected\n");
6889 return CMD_WARNING_CONFIG_FAILED;
6890 }
6891
48cb7ea9
SP
6892 const char *xpath =
6893 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6894
6895 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6896 snprintf(
6897 xpath_value, sizeof(xpath_value),
6898 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6899 xpath);
6900 }
6901 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6902 argv[idx_ip]->arg);
6903 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6904 }
6905 return CMD_SUCCESS;
718e3744 6906}
6907
48cb7ea9
SP
6908DEFUN_YANG (no_set_ipx_vpn_nexthop,
6909 no_set_ipx_vpn_nexthop_cmd,
6910 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
6911 NO_STR
6912 SET_STR
6913 "IPv4 information\n"
6914 "IPv6 information\n"
6915 "VPN information\n"
6916 "VPN next-hop address\n"
6917 "IP address of next hop\n"
6918 "IPv6 address of next hop\n")
6919{
d62a17ae 6920 afi_t afi;
6921 int idx = 0;
6922
d62a17ae 6923 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6924 if (afi == AFI_IP) {
6925 const char *xpath =
6926 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6927 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6928 } else {
6929 const char *xpath =
6930 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6931 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6932 }
6933 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6934 }
6935 return CMD_SUCCESS;
d6902373 6936}
718e3744 6937
48cb7ea9
SP
6938DEFUN_YANG (set_originator_id,
6939 set_originator_id_cmd,
6940 "set originator-id A.B.C.D",
6941 SET_STR
6942 "BGP originator ID attribute\n"
6943 "IP address of originator\n")
718e3744 6944{
d62a17ae 6945 int idx_ipv4 = 2;
48cb7ea9
SP
6946 const char *xpath =
6947 "./set-action[action='frr-bgp-route-map:originator-id']";
6948 char xpath_value[XPATH_MAXLEN];
718e3744 6949
48cb7ea9
SP
6950 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6951 snprintf(xpath_value, sizeof(xpath_value),
6952 "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
6953 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6954 argv[idx_ipv4]->arg);
4c9bd275 6955
48cb7ea9
SP
6956 return nb_cli_apply_changes(vty, NULL);
6957}
6958
6959DEFUN_YANG (no_set_originator_id,
6960 no_set_originator_id_cmd,
6961 "no set originator-id [A.B.C.D]",
6962 NO_STR
6963 SET_STR
6964 "BGP originator ID attribute\n"
6965 "IP address of originator\n")
718e3744 6966{
48cb7ea9
SP
6967 const char *xpath =
6968 "./set-action[action='frr-bgp-route-map:originator-id']";
0d702986 6969
48cb7ea9
SP
6970 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6971 return nb_cli_apply_changes(vty, NULL);
718e3744 6972}
6973
324e8b1f
DA
6974DEFPY_YANG (match_rpki_extcommunity,
6975 match_rpki_extcommunity_cmd,
6976 "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
6977 NO_STR
6978 MATCH_STR
6979 "BGP RPKI (Origin Validation State) extended community attribute\n"
6980 "Valid prefix\n"
6981 "Invalid prefix\n"
6982 "Prefix not found\n")
6983{
6984 const char *xpath =
6985 "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
6986 char xpath_value[XPATH_MAXLEN];
6987
6988 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6989
6990 if (!no) {
6991 snprintf(
6992 xpath_value, sizeof(xpath_value),
6993 "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
6994 xpath);
6995 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6996 argv[2]->arg);
6997 }
6998
6999 return nb_cli_apply_changes(vty, NULL);
7000}
7001
718e3744 7002/* Initialization of route map. */
d62a17ae 7003void bgp_route_map_init(void)
7004{
7005 route_map_init();
7006
7007 route_map_add_hook(bgp_route_map_add);
7008 route_map_delete_hook(bgp_route_map_delete);
7009 route_map_event_hook(bgp_route_map_event);
7010
7011 route_map_match_interface_hook(generic_match_add);
7012 route_map_no_match_interface_hook(generic_match_delete);
7013
7014 route_map_match_ip_address_hook(generic_match_add);
7015 route_map_no_match_ip_address_hook(generic_match_delete);
7016
7017 route_map_match_ip_address_prefix_list_hook(generic_match_add);
7018 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
7019
7020 route_map_match_ip_next_hop_hook(generic_match_add);
7021 route_map_no_match_ip_next_hop_hook(generic_match_delete);
7022
bc63ba98
DA
7023 route_map_match_ipv6_next_hop_hook(generic_match_add);
7024 route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
7025
d62a17ae 7026 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
7027 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
7028
61ad901e
DA
7029 route_map_match_ip_next_hop_type_hook(generic_match_add);
7030 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
7031
d62a17ae 7032 route_map_match_ipv6_address_hook(generic_match_add);
7033 route_map_no_match_ipv6_address_hook(generic_match_delete);
7034
7035 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
7036 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
7037
61ad901e
DA
7038 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
7039 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
7040
82f191a2
DA
7041 route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
7042 route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
7043
d62a17ae 7044 route_map_match_metric_hook(generic_match_add);
7045 route_map_no_match_metric_hook(generic_match_delete);
7046
7047 route_map_match_tag_hook(generic_match_add);
7048 route_map_no_match_tag_hook(generic_match_delete);
7049
ef3e0d04
SM
7050 route_map_set_srte_color_hook(generic_set_add);
7051 route_map_no_set_srte_color_hook(generic_set_delete);
7052
d62a17ae 7053 route_map_set_ip_nexthop_hook(generic_set_add);
7054 route_map_no_set_ip_nexthop_hook(generic_set_delete);
7055
7056 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
7057 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
7058
7059 route_map_set_metric_hook(generic_set_add);
7060 route_map_no_set_metric_hook(generic_set_delete);
7061
7062 route_map_set_tag_hook(generic_set_add);
7063 route_map_no_set_tag_hook(generic_set_delete);
7064
7065 route_map_install_match(&route_match_peer_cmd);
2690f18c 7066 route_map_install_match(&route_match_alias_cmd);
d62a17ae 7067 route_map_install_match(&route_match_local_pref_cmd);
fa22080d 7068#ifdef HAVE_SCRIPTING
b4becb06 7069 route_map_install_match(&route_match_script_cmd);
1d7c7ace 7070#endif
d62a17ae 7071 route_map_install_match(&route_match_ip_address_cmd);
7072 route_map_install_match(&route_match_ip_next_hop_cmd);
7073 route_map_install_match(&route_match_ip_route_source_cmd);
7074 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
7075 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 7076 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 7077 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
7078 route_map_install_match(&route_match_aspath_cmd);
7079 route_map_install_match(&route_match_community_cmd);
7080 route_map_install_match(&route_match_lcommunity_cmd);
7081 route_map_install_match(&route_match_ecommunity_cmd);
7082 route_map_install_match(&route_match_local_pref_cmd);
7083 route_map_install_match(&route_match_metric_cmd);
7084 route_map_install_match(&route_match_origin_cmd);
7085 route_map_install_match(&route_match_probability_cmd);
7086 route_map_install_match(&route_match_interface_cmd);
7087 route_map_install_match(&route_match_tag_cmd);
d37ba549 7088 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 7089 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 7090 route_map_install_match(&route_match_evpn_route_type_cmd);
196c6b09 7091 route_map_install_match(&route_match_evpn_rd_cmd);
6fb219da 7092 route_map_install_match(&route_match_evpn_default_route_cmd);
1dcc9e5b 7093 route_map_install_match(&route_match_vrl_source_vrf_cmd);
d62a17ae 7094
d0a4ee60
AD
7095 route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
7096 route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
951745bd 7097 route_map_install_set(&route_set_table_id_cmd);
ef3e0d04 7098 route_map_install_set(&route_set_srte_color_cmd);
d62a17ae 7099 route_map_install_set(&route_set_ip_nexthop_cmd);
7100 route_map_install_set(&route_set_local_pref_cmd);
7101 route_map_install_set(&route_set_weight_cmd);
7102 route_map_install_set(&route_set_label_index_cmd);
7103 route_map_install_set(&route_set_metric_cmd);
7b7d48e5 7104 route_map_install_set(&route_set_distance_cmd);
d62a17ae 7105 route_map_install_set(&route_set_aspath_prepend_cmd);
7106 route_map_install_set(&route_set_aspath_exclude_cmd);
77e3d821 7107 route_map_install_set(&route_set_aspath_replace_cmd);
d62a17ae 7108 route_map_install_set(&route_set_origin_cmd);
7109 route_map_install_set(&route_set_atomic_aggregate_cmd);
97a52c82 7110 route_map_install_set(&route_set_aigp_metric_cmd);
d62a17ae 7111 route_map_install_set(&route_set_aggregator_as_cmd);
7112 route_map_install_set(&route_set_community_cmd);
7113 route_map_install_set(&route_set_community_delete_cmd);
7114 route_map_install_set(&route_set_lcommunity_cmd);
7115 route_map_install_set(&route_set_lcommunity_delete_cmd);
7116 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
7117 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
7118 route_map_install_set(&route_set_originator_id_cmd);
7119 route_map_install_set(&route_set_ecommunity_rt_cmd);
7120 route_map_install_set(&route_set_ecommunity_soo_cmd);
ca9ac3ef 7121 route_map_install_set(&route_set_ecommunity_lb_cmd);
bb4dcdd1 7122 route_map_install_set(&route_set_ecommunity_none_cmd);
d62a17ae 7123 route_map_install_set(&route_set_tag_cmd);
7124 route_map_install_set(&route_set_label_index_cmd);
1bb550b6 7125 route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
d62a17ae 7126
7127 install_element(RMAP_NODE, &match_peer_cmd);
7128 install_element(RMAP_NODE, &match_peer_local_cmd);
7129 install_element(RMAP_NODE, &no_match_peer_cmd);
7130 install_element(RMAP_NODE, &match_ip_route_source_cmd);
7131 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
7132 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
7133 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
7134 install_element(RMAP_NODE, &match_mac_address_cmd);
7135 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
7136 install_element(RMAP_NODE, &match_evpn_vni_cmd);
7137 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
7138 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
7139 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
196c6b09
LK
7140 install_element(RMAP_NODE, &match_evpn_rd_cmd);
7141 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
6fb219da
MK
7142 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
7143 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
d0a4ee60
AD
7144 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
7145 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
7146 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
7147 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
1dcc9e5b
CS
7148 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
7149 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
d62a17ae 7150
7151 install_element(RMAP_NODE, &match_aspath_cmd);
7152 install_element(RMAP_NODE, &no_match_aspath_cmd);
7153 install_element(RMAP_NODE, &match_local_pref_cmd);
7154 install_element(RMAP_NODE, &no_match_local_pref_cmd);
2690f18c
DA
7155 install_element(RMAP_NODE, &match_alias_cmd);
7156 install_element(RMAP_NODE, &no_match_alias_cmd);
d62a17ae 7157 install_element(RMAP_NODE, &match_community_cmd);
7158 install_element(RMAP_NODE, &no_match_community_cmd);
7159 install_element(RMAP_NODE, &match_lcommunity_cmd);
7160 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
7161 install_element(RMAP_NODE, &match_ecommunity_cmd);
7162 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
7163 install_element(RMAP_NODE, &match_origin_cmd);
7164 install_element(RMAP_NODE, &no_match_origin_cmd);
7165 install_element(RMAP_NODE, &match_probability_cmd);
7166 install_element(RMAP_NODE, &no_match_probability_cmd);
7167
951745bd
PG
7168 install_element(RMAP_NODE, &no_set_table_id_cmd);
7169 install_element(RMAP_NODE, &set_table_id_cmd);
d62a17ae 7170 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
7171 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
7172 install_element(RMAP_NODE, &set_local_pref_cmd);
7b7d48e5
DS
7173 install_element(RMAP_NODE, &set_distance_cmd);
7174 install_element(RMAP_NODE, &no_set_distance_cmd);
d62a17ae 7175 install_element(RMAP_NODE, &no_set_local_pref_cmd);
7176 install_element(RMAP_NODE, &set_weight_cmd);
7177 install_element(RMAP_NODE, &set_label_index_cmd);
7178 install_element(RMAP_NODE, &no_set_weight_cmd);
7179 install_element(RMAP_NODE, &no_set_label_index_cmd);
7180 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
7181 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
7182 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
77e3d821 7183 install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
d62a17ae 7184 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
9131e6e8 7185 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
d62a17ae 7186 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
499ceb3d 7187 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
77e3d821 7188 install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
d62a17ae 7189 install_element(RMAP_NODE, &set_origin_cmd);
7190 install_element(RMAP_NODE, &no_set_origin_cmd);
7191 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
7192 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
97a52c82
DA
7193 install_element(RMAP_NODE, &set_aigp_metric_cmd);
7194 install_element(RMAP_NODE, &no_set_aigp_metric_cmd);
d62a17ae 7195 install_element(RMAP_NODE, &set_aggregator_as_cmd);
7196 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
7197 install_element(RMAP_NODE, &set_community_cmd);
7198 install_element(RMAP_NODE, &set_community_none_cmd);
7199 install_element(RMAP_NODE, &no_set_community_cmd);
2929de9e 7200 install_element(RMAP_NODE, &no_set_community_short_cmd);
d62a17ae 7201 install_element(RMAP_NODE, &set_community_delete_cmd);
7202 install_element(RMAP_NODE, &no_set_community_delete_cmd);
7203 install_element(RMAP_NODE, &set_lcommunity_cmd);
7204 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
7205 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
7206 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
76a20aa9 7207 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
d62a17ae 7208 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
7209 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
76a20aa9 7210 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
d62a17ae 7211 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
7212 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4db5ee8e 7213 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
d62a17ae 7214 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
7215 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4db5ee8e 7216 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
ca9ac3ef 7217 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
7218 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
7219 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
bb4dcdd1
DA
7220 install_element(RMAP_NODE, &set_ecommunity_none_cmd);
7221 install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
d6902373 7222#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 7223 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
7224 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 7225#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 7226 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
7227 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
7228 install_element(RMAP_NODE, &set_originator_id_cmd);
7229 install_element(RMAP_NODE, &no_set_originator_id_cmd);
1bb550b6 7230 install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
d62a17ae 7231
7232 route_map_install_match(&route_match_ipv6_address_cmd);
7233 route_map_install_match(&route_match_ipv6_next_hop_cmd);
bc63ba98 7234 route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
82f191a2 7235 route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
be7735b3 7236 route_map_install_match(&route_match_ipv4_next_hop_cmd);
d62a17ae 7237 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 7238 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 7239 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
7240 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
7241 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
7242 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
324e8b1f 7243 route_map_install_match(&route_match_rpki_extcommunity_cmd);
d62a17ae 7244
7245 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
bc63ba98 7246 install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
82f191a2 7247 install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
d62a17ae 7248 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
bc63ba98 7249 install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
82f191a2 7250 install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
03030106
IR
7251 install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
7252 install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
be7735b3 7253 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
17ac51eb 7254 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
d62a17ae 7255 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
7256 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
7257 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
7258 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
7259 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
7260 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
324e8b1f 7261 install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
fa22080d 7262#ifdef HAVE_SCRIPTING
b4becb06 7263 install_element(RMAP_NODE, &match_script_cmd);
1d7c7ace 7264#endif
d62a17ae 7265}
7266
7267void bgp_route_map_terminate(void)
7268{
7269 /* ToDo: Cleanup all the used memory */
d62a17ae 7270 route_map_finish();
518f0eb1 7271}