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