]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
bgpd: add route-map to `no` advertise ipvX * cmd
[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
718e3744 1956/* `set local-preference LOCAL_PREF' */
1957
1958/* Set local preference. */
b68885f9 1959static enum route_map_cmd_result_t
1782514f 1960route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1961{
1962 struct rmap_value *rv;
9b6d8fcf 1963 struct bgp_path_info *path;
d7c0a89a 1964 uint32_t locpref = 0;
d62a17ae 1965
1782514f
DS
1966 /* Fetch routemap's rule information. */
1967 rv = rule;
1968 path = object;
d62a17ae 1969
1782514f 1970 /* Set local preference value. */
0f05ea43 1971 if (path->attr->local_pref)
1782514f 1972 locpref = path->attr->local_pref;
d62a17ae 1973
1782514f
DS
1974 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1975 path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
718e3744 1976
d62a17ae 1977 return RMAP_OKAY;
718e3744 1978}
1979
718e3744 1980/* Set local preference rule structure. */
364deb04
DL
1981static const struct route_map_rule_cmd route_set_local_pref_cmd = {
1982 "local-preference",
1983 route_set_local_pref,
1984 route_value_compile,
d62a17ae 1985 route_value_free,
718e3744 1986};
6b0655a2 1987
718e3744 1988/* `set weight WEIGHT' */
1989
1990/* Set weight. */
b68885f9 1991static enum route_map_cmd_result_t
1782514f 1992route_set_weight(void *rule, const struct prefix *prefix, void *object)
718e3744 1993{
d62a17ae 1994 struct rmap_value *rv;
9b6d8fcf 1995 struct bgp_path_info *path;
718e3744 1996
1782514f
DS
1997 /* Fetch routemap's rule information. */
1998 rv = rule;
1999 path = object;
e52702f2 2000
1782514f
DS
2001 /* Set weight value. */
2002 path->attr->weight = route_value_adjust(rv, 0, path->peer);
718e3744 2003
d62a17ae 2004 return RMAP_OKAY;
718e3744 2005}
2006
718e3744 2007/* Set local preference rule structure. */
364deb04
DL
2008static const struct route_map_rule_cmd route_set_weight_cmd = {
2009 "weight",
2010 route_set_weight,
2011 route_value_compile,
2012 route_value_free,
718e3744 2013};
6b0655a2 2014
7b7d48e5
DS
2015/* `set distance DISTANCE */
2016static enum route_map_cmd_result_t
1782514f 2017route_set_distance(void *rule, const struct prefix *prefix, void *object)
7b7d48e5
DS
2018{
2019 struct bgp_path_info *path = object;
2020 struct rmap_value *rv = rule;
2021
7b7d48e5
DS
2022 path->attr->distance = rv->value;
2023
2024 return RMAP_OKAY;
2025}
2026
2027/* set distance rule structure */
364deb04 2028static const struct route_map_rule_cmd route_set_distance_cmd = {
7b7d48e5
DS
2029 "distance",
2030 route_set_distance,
2031 route_value_compile,
2032 route_value_free,
2033};
2034
718e3744 2035/* `set metric METRIC' */
2036
2037/* Set metric to attribute. */
b68885f9 2038static enum route_map_cmd_result_t
1782514f 2039route_set_metric(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2040{
2041 struct rmap_value *rv;
9b6d8fcf 2042 struct bgp_path_info *path;
d7c0a89a 2043 uint32_t med = 0;
d62a17ae 2044
1782514f
DS
2045 /* Fetch routemap's rule information. */
2046 rv = rule;
2047 path = object;
d62a17ae 2048
1782514f
DS
2049 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
2050 med = path->attr->med;
2051
2052 path->attr->med = route_value_adjust(rv, med, path->peer);
2053 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
d62a17ae 2054
d62a17ae 2055 return RMAP_OKAY;
718e3744 2056}
2057
718e3744 2058/* Set metric rule structure. */
364deb04
DL
2059static const struct route_map_rule_cmd route_set_metric_cmd = {
2060 "metric",
2061 route_set_metric,
2062 route_value_compile,
2063 route_value_free,
718e3744 2064};
6b0655a2 2065
951745bd
PG
2066/* `set table (1-4294967295)' */
2067
1782514f
DS
2068static enum route_map_cmd_result_t
2069route_set_table_id(void *rule, const struct prefix *prefix,
2070
2071 void *object)
951745bd
PG
2072{
2073 struct rmap_value *rv;
2074 struct bgp_path_info *path;
2075
1782514f
DS
2076 /* Fetch routemap's rule information. */
2077 rv = rule;
2078 path = object;
2079
2080 path->attr->rmap_table_id = rv->value;
951745bd 2081
951745bd
PG
2082 return RMAP_OKAY;
2083}
2084
2085/* Set table_id rule structure. */
364deb04
DL
2086static const struct route_map_rule_cmd route_set_table_id_cmd = {
2087 "table",
2088 route_set_table_id,
2089 route_value_compile,
2090 route_value_free
951745bd
PG
2091};
2092
718e3744 2093/* `set as-path prepend ASPATH' */
2094
2095/* For AS path prepend mechanism. */
b68885f9 2096static enum route_map_cmd_result_t
1782514f 2097route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2098{
2099 struct aspath *aspath;
2100 struct aspath *new;
9b6d8fcf 2101 struct bgp_path_info *path;
d62a17ae 2102
1782514f 2103 path = object;
d62a17ae 2104
1782514f
DS
2105 if (path->attr->aspath->refcnt)
2106 new = aspath_dup(path->attr->aspath);
2107 else
2108 new = path->attr->aspath;
bc3dd427 2109
1782514f
DS
2110 if ((uintptr_t)rule > 10) {
2111 aspath = rule;
2112 aspath_prepend(aspath, new);
2113 } else {
2114 as_t as = aspath_leftmost(new);
6ba0adac
DS
2115 if (as)
2116 new = aspath_add_seq_n(new, as, (uintptr_t)rule);
d62a17ae 2117 }
718e3744 2118
1782514f
DS
2119 path->attr->aspath = new;
2120
d62a17ae 2121 return RMAP_OKAY;
718e3744 2122}
2123
d62a17ae 2124static void *route_set_aspath_prepend_compile(const char *arg)
bc3dd427 2125{
d62a17ae 2126 unsigned int num;
bc3dd427 2127
d62a17ae 2128 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
2129 return (void *)(uintptr_t)num;
bc3dd427 2130
d62a17ae 2131 return route_aspath_compile(arg);
bc3dd427
DW
2132}
2133
d62a17ae 2134static void route_set_aspath_prepend_free(void *rule)
bc3dd427 2135{
d62a17ae 2136 if ((uintptr_t)rule > 10)
2137 route_aspath_free(rule);
bc3dd427
DW
2138}
2139
2140
515e500c 2141/* Set as-path prepend rule structure. */
364deb04
DL
2142static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
2143 "as-path prepend",
2144 route_set_aspath_prepend,
2145 route_set_aspath_prepend_compile,
2146 route_set_aspath_prepend_free,
718e3744 2147};
6b0655a2 2148
841f7a57
DO
2149/* `set as-path exclude ASn' */
2150
2151/* For ASN exclude mechanism.
d62a17ae 2152 * Iterate over ASns requested and filter them from the given AS_PATH one by
2153 * one.
841f7a57
DO
2154 * Make a deep copy of existing AS_PATH, but for the first ASn only.
2155 */
b68885f9 2156static enum route_map_cmd_result_t
1782514f 2157route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
d62a17ae 2158{
2159 struct aspath *new_path, *exclude_path;
9b6d8fcf 2160 struct bgp_path_info *path;
d62a17ae 2161
1782514f
DS
2162 exclude_path = rule;
2163 path = object;
2164 if (path->attr->aspath->refcnt)
2165 new_path = aspath_dup(path->attr->aspath);
2166 else
2167 new_path = path->attr->aspath;
2168 path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
2169
d62a17ae 2170 return RMAP_OKAY;
841f7a57
DO
2171}
2172
841f7a57 2173/* Set ASn exlude rule structure. */
364deb04
DL
2174static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2175 "as-path exclude",
2176 route_set_aspath_exclude,
2177 route_aspath_compile,
d62a17ae 2178 route_aspath_free,
841f7a57 2179};
6b0655a2 2180
77e3d821
DA
2181/* `set as-path replace AS-PATH` */
2182static void *route_aspath_replace_compile(const char *arg)
2183{
2184 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
2185}
2186
2187static void route_aspath_replace_free(void *rule)
2188{
2189 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2190}
2191
2192static enum route_map_cmd_result_t
2193route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
2194{
2195 struct aspath *aspath_new;
2196 const char *replace = rule;
2197 struct bgp_path_info *path = object;
2198 as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
2199 : path->peer->local_as;
2200
2201 if (path->peer->sort != BGP_PEER_EBGP) {
2202 zlog_warn(
2203 "`set as-path replace` is supported only for EBGP peers");
2204 return RMAP_NOOP;
2205 }
2206
2207 if (path->attr->aspath->refcnt)
2208 aspath_new = aspath_dup(path->attr->aspath);
2209 else
2210 aspath_new = path->attr->aspath;
2211
2212 if (strmatch(replace, "any")) {
2213 path->attr->aspath =
2214 aspath_replace_all_asn(aspath_new, own_asn);
2215 } else {
2216 as_t replace_asn = strtoul(replace, NULL, 10);
2217
2218 path->attr->aspath = aspath_replace_specific_asn(
2219 aspath_new, replace_asn, own_asn);
2220 }
2221
2222 return RMAP_OKAY;
2223}
2224
2225static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
2226 "as-path replace",
2227 route_set_aspath_replace,
2228 route_aspath_replace_compile,
2229 route_aspath_replace_free,
2230};
2231
718e3744 2232/* `set community COMMUNITY' */
d62a17ae 2233struct rmap_com_set {
2234 struct community *com;
2235 int additive;
2236 int none;
718e3744 2237};
2238
2239/* For community set mechanism. */
b68885f9 2240static enum route_map_cmd_result_t
1782514f 2241route_set_community(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2242{
2243 struct rmap_com_set *rcs;
9b6d8fcf 2244 struct bgp_path_info *path;
d62a17ae 2245 struct attr *attr;
2246 struct community *new = NULL;
2247 struct community *old;
2248 struct community *merge;
2249
1782514f
DS
2250 rcs = rule;
2251 path = object;
2252 attr = path->attr;
9a706b42 2253 old = bgp_attr_get_community(attr);
1782514f
DS
2254
2255 /* "none" case. */
2256 if (rcs->none) {
9a706b42 2257 bgp_attr_set_community(attr, NULL);
1782514f
DS
2258 /* See the longer comment down below. */
2259 if (old && old->refcnt == 0)
2260 community_free(&old);
2261 return RMAP_OKAY;
2262 }
718e3744 2263
1782514f
DS
2264 /* "additive" case. */
2265 if (rcs->additive && old) {
2266 merge = community_merge(community_dup(old), rcs->com);
d62a17ae 2267
1782514f
DS
2268 new = community_uniq_sort(merge);
2269 community_free(&merge);
2270 } else
2271 new = community_dup(rcs->com);
d62a17ae 2272
1782514f
DS
2273 /* HACK: if the old community is not intern'd,
2274 * we should free it here, or all reference to it may be
2275 * lost.
2276 * Really need to cleanup attribute caching sometime.
2277 */
2278 if (old && old->refcnt == 0)
2279 community_free(&old);
f24804f4 2280
1782514f 2281 /* will be interned by caller if required */
9a706b42 2282 bgp_attr_set_community(attr, new);
d62a17ae 2283
d62a17ae 2284 return RMAP_OKAY;
718e3744 2285}
2286
2287/* Compile function for set community. */
d62a17ae 2288static void *route_set_community_compile(const char *arg)
2289{
2290 struct rmap_com_set *rcs;
2291 struct community *com = NULL;
2292 char *sp;
2293 int additive = 0;
2294 int none = 0;
2295
2296 if (strcmp(arg, "none") == 0)
2297 none = 1;
2298 else {
2299 sp = strstr(arg, "additive");
2300
2301 if (sp && sp > arg) {
770817b4 2302 /* "additive" keyword is included. */
d62a17ae 2303 additive = 1;
2304 *(sp - 1) = '\0';
2305 }
718e3744 2306
d62a17ae 2307 com = community_str2com(arg);
718e3744 2308
d62a17ae 2309 if (additive)
2310 *(sp - 1) = ' ';
718e3744 2311
d62a17ae 2312 if (!com)
2313 return NULL;
2314 }
e52702f2 2315
d62a17ae 2316 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2317 rcs->com = com;
2318 rcs->additive = additive;
2319 rcs->none = none;
e52702f2 2320
d62a17ae 2321 return rcs;
718e3744 2322}
2323
2324/* Free function for set community. */
d62a17ae 2325static void route_set_community_free(void *rule)
718e3744 2326{
d62a17ae 2327 struct rmap_com_set *rcs = rule;
718e3744 2328
d62a17ae 2329 if (rcs->com)
3c1f53de 2330 community_free(&rcs->com);
d62a17ae 2331 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2332}
2333
2334/* Set community rule structure. */
364deb04
DL
2335static const struct route_map_rule_cmd route_set_community_cmd = {
2336 "community",
2337 route_set_community,
2338 route_set_community_compile,
d62a17ae 2339 route_set_community_free,
718e3744 2340};
6b0655a2 2341
57d187bc 2342/* `set community COMMUNITY' */
d62a17ae 2343struct rmap_lcom_set {
2344 struct lcommunity *lcom;
2345 int additive;
2346 int none;
57d187bc
JS
2347};
2348
2349
2350/* For lcommunity set mechanism. */
b68885f9 2351static enum route_map_cmd_result_t
1782514f 2352route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2353{
2354 struct rmap_lcom_set *rcs;
9b6d8fcf 2355 struct bgp_path_info *path;
d62a17ae 2356 struct attr *attr;
2357 struct lcommunity *new = NULL;
2358 struct lcommunity *old;
2359 struct lcommunity *merge;
2360
1782514f
DS
2361 rcs = rule;
2362 path = object;
2363 attr = path->attr;
1bcf3a96 2364 old = bgp_attr_get_lcommunity(attr);
d62a17ae 2365
1782514f
DS
2366 /* "none" case. */
2367 if (rcs->none) {
1bcf3a96 2368 bgp_attr_set_lcommunity(attr, NULL);
d62a17ae 2369
1782514f 2370 /* See the longer comment down below. */
4265a53e
NK
2371 if (old && old->refcnt == 0)
2372 lcommunity_free(&old);
1782514f
DS
2373 return RMAP_OKAY;
2374 }
4265a53e 2375
1782514f
DS
2376 if (rcs->additive && old) {
2377 merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
d62a17ae 2378
1782514f
DS
2379 new = lcommunity_uniq_sort(merge);
2380 lcommunity_free(&merge);
2381 } else
2382 new = lcommunity_dup(rcs->lcom);
2383
2384 /* HACK: if the old large-community is not intern'd,
2385 * we should free it here, or all reference to it may be
2386 * lost.
2387 * Really need to cleanup attribute caching sometime.
2388 */
2389 if (old && old->refcnt == 0)
2390 lcommunity_free(&old);
2391
2392 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1bcf3a96 2393 bgp_attr_set_lcommunity(attr, new);
1782514f 2394
d62a17ae 2395 return RMAP_OKAY;
2396}
57d187bc 2397
d62a17ae 2398/* Compile function for set community. */
2399static void *route_set_lcommunity_compile(const char *arg)
2400{
2401 struct rmap_lcom_set *rcs;
2402 struct lcommunity *lcom = NULL;
2403 char *sp;
2404 int additive = 0;
2405 int none = 0;
2406
2407 if (strcmp(arg, "none") == 0)
2408 none = 1;
2409 else {
2410 sp = strstr(arg, "additive");
2411
2412 if (sp && sp > arg) {
2413 /* "additive" keyworkd is included. */
2414 additive = 1;
2415 *(sp - 1) = '\0';
2416 }
57d187bc 2417
d62a17ae 2418 lcom = lcommunity_str2com(arg);
57d187bc 2419
d62a17ae 2420 if (additive)
2421 *(sp - 1) = ' ';
57d187bc 2422
d62a17ae 2423 if (!lcom)
2424 return NULL;
2425 }
57d187bc 2426
d62a17ae 2427 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2428 rcs->lcom = lcom;
2429 rcs->additive = additive;
2430 rcs->none = none;
57d187bc 2431
d62a17ae 2432 return rcs;
57d187bc
JS
2433}
2434
2435/* Free function for set lcommunity. */
d62a17ae 2436static void route_set_lcommunity_free(void *rule)
57d187bc 2437{
d62a17ae 2438 struct rmap_lcom_set *rcs = rule;
57d187bc 2439
d62a17ae 2440 if (rcs->lcom) {
2441 lcommunity_free(&rcs->lcom);
2442 }
2443 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
57d187bc
JS
2444}
2445
2446/* Set community rule structure. */
364deb04
DL
2447static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2448 "large-community",
2449 route_set_lcommunity,
2450 route_set_lcommunity_compile,
d62a17ae 2451 route_set_lcommunity_free,
57d187bc
JS
2452};
2453
2454/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2455
2456/* For large community set mechanism. */
b68885f9 2457static enum route_map_cmd_result_t
1782514f 2458route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
d62a17ae 2459{
2460 struct community_list *list;
2461 struct lcommunity *merge;
2462 struct lcommunity *new;
2463 struct lcommunity *old;
9b6d8fcf 2464 struct bgp_path_info *path;
e9a223ac 2465 struct rmap_community *rcom = rule;
d62a17ae 2466
1782514f
DS
2467 if (!rcom)
2468 return RMAP_OKAY;
d62a17ae 2469
1782514f
DS
2470 path = object;
2471 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2472 LARGE_COMMUNITY_LIST_MASTER);
1bcf3a96 2473 old = bgp_attr_get_lcommunity(path->attr);
1782514f
DS
2474
2475 if (list && old) {
2476 merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
2477 new = lcommunity_uniq_sort(merge);
2478 lcommunity_free(&merge);
2479
2480 /* HACK: if the old community is not intern'd,
2481 * we should free it here, or all reference to it may be
2482 * lost.
2483 * Really need to cleanup attribute caching sometime.
2484 */
2485 if (old->refcnt == 0)
2486 lcommunity_free(&old);
2487
2488 if (new->size == 0) {
1bcf3a96 2489 bgp_attr_set_lcommunity(path->attr, NULL);
1782514f
DS
2490 lcommunity_free(&new);
2491 } else {
1bcf3a96 2492 bgp_attr_set_lcommunity(path->attr, new);
d62a17ae 2493 }
2494 }
2495
2496 return RMAP_OKAY;
57d187bc
JS
2497}
2498
2499/* Compile function for set lcommunity. */
d62a17ae 2500static void *route_set_lcommunity_delete_compile(const char *arg)
57d187bc 2501{
e9a223ac 2502 struct rmap_community *rcom;
caa5af30
DA
2503 char **splits;
2504 int num;
57d187bc 2505
caa5af30 2506 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2507
caa5af30
DA
2508 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2509 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2510 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2511
caa5af30
DA
2512 for (int i = 0; i < num; i++)
2513 XFREE(MTYPE_TMP, splits[i]);
2514 XFREE(MTYPE_TMP, splits);
2515
e9a223ac 2516 return rcom;
57d187bc
JS
2517}
2518
2519/* Free function for set lcommunity. */
d62a17ae 2520static void route_set_lcommunity_delete_free(void *rule)
57d187bc 2521{
e9a223ac
DS
2522 struct rmap_community *rcom = rule;
2523
2524 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2525 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
2526}
2527
2528/* Set lcommunity rule structure. */
364deb04
DL
2529static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2530 "large-comm-list",
2531 route_set_lcommunity_delete,
2532 route_set_lcommunity_delete_compile,
2533 route_set_lcommunity_delete_free,
57d187bc
JS
2534};
2535
2536
fee6e4e4 2537/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 2538
2539/* For community set mechanism. */
b68885f9
LK
2540static enum route_map_cmd_result_t
2541route_set_community_delete(void *rule, const struct prefix *prefix,
1782514f 2542 void *object)
d62a17ae 2543{
2544 struct community_list *list;
2545 struct community *merge;
2546 struct community *new;
2547 struct community *old;
9b6d8fcf 2548 struct bgp_path_info *path;
e9a223ac 2549 struct rmap_community *rcom = rule;
d62a17ae 2550
1782514f
DS
2551 if (!rcom)
2552 return RMAP_OKAY;
d62a17ae 2553
1782514f
DS
2554 path = object;
2555 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2556 COMMUNITY_LIST_MASTER);
9a706b42 2557 old = bgp_attr_get_community(path->attr);
1782514f
DS
2558
2559 if (list && old) {
2560 merge = community_list_match_delete(community_dup(old), list);
2561 new = community_uniq_sort(merge);
2562 community_free(&merge);
2563
2564 /* HACK: if the old community is not intern'd,
2565 * we should free it here, or all reference to it may be
2566 * lost.
2567 * Really need to cleanup attribute caching sometime.
2568 */
2569 if (old->refcnt == 0)
2570 community_free(&old);
2571
2572 if (new->size == 0) {
9a706b42 2573 bgp_attr_set_community(path->attr, NULL);
1782514f
DS
2574 community_free(&new);
2575 } else {
9a706b42 2576 bgp_attr_set_community(path->attr, new);
d62a17ae 2577 }
718e3744 2578 }
718e3744 2579
d62a17ae 2580 return RMAP_OKAY;
718e3744 2581}
2582
2583/* Compile function for set community. */
d62a17ae 2584static void *route_set_community_delete_compile(const char *arg)
718e3744 2585{
e9a223ac 2586 struct rmap_community *rcom;
60762f8f
DA
2587 char **splits;
2588 int num;
718e3744 2589
60762f8f 2590 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2591
60762f8f
DA
2592 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2593 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2594 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2595
60762f8f
DA
2596 for (int i = 0; i < num; i++)
2597 XFREE(MTYPE_TMP, splits[i]);
2598 XFREE(MTYPE_TMP, splits);
2599
e9a223ac 2600 return rcom;
718e3744 2601}
2602
2603/* Free function for set community. */
d62a17ae 2604static void route_set_community_delete_free(void *rule)
718e3744 2605{
e9a223ac
DS
2606 struct rmap_community *rcom = rule;
2607
2608 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2609 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 2610}
2611
2612/* Set community rule structure. */
364deb04
DL
2613static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2614 "comm-list",
2615 route_set_community_delete,
2616 route_set_community_delete_compile,
2617 route_set_community_delete_free,
718e3744 2618};
6b0655a2 2619
718e3744 2620/* `set extcommunity rt COMMUNITY' */
2621
bb4dcdd1
DA
2622struct rmap_ecom_set {
2623 struct ecommunity *ecom;
2624 bool none;
2625};
2626
73d78ea0 2627/* For community set mechanism. Used by _rt and _soo. */
b68885f9 2628static enum route_map_cmd_result_t
1782514f 2629route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2630{
bb4dcdd1 2631 struct rmap_ecom_set *rcs;
d62a17ae 2632 struct ecommunity *new_ecom;
2633 struct ecommunity *old_ecom;
9b6d8fcf 2634 struct bgp_path_info *path;
bb4dcdd1 2635 struct attr *attr;
d62a17ae 2636
bb4dcdd1 2637 rcs = rule;
1782514f 2638 path = object;
bb4dcdd1 2639 attr = path->attr;
d62a17ae 2640
bb4dcdd1 2641 if (rcs->none) {
b53e67a3 2642 bgp_attr_set_ecommunity(attr, NULL);
bb4dcdd1
DA
2643 return RMAP_OKAY;
2644 }
2645
2646 if (!rcs->ecom)
1782514f 2647 return RMAP_OKAY;
d62a17ae 2648
1782514f 2649 /* We assume additive for Extended Community. */
b53e67a3 2650 old_ecom = bgp_attr_get_ecommunity(path->attr);
1782514f
DS
2651
2652 if (old_ecom) {
bb4dcdd1
DA
2653 new_ecom =
2654 ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
d62a17ae 2655
1782514f
DS
2656 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2657 * bgp_update_receive()
2658 * ->refcnt = 0 => set by a previous route-map
2659 * statement */
2660 if (!old_ecom->refcnt)
2661 ecommunity_free(&old_ecom);
2662 } else
bb4dcdd1 2663 new_ecom = ecommunity_dup(rcs->ecom);
d62a17ae 2664
1782514f 2665 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
b53e67a3 2666 bgp_attr_set_ecommunity(path->attr, new_ecom);
d62a17ae 2667
d62a17ae 2668 return RMAP_OKAY;
718e3744 2669}
2670
bb4dcdd1
DA
2671static void *route_set_ecommunity_none_compile(const char *arg)
2672{
2673 struct rmap_ecom_set *rcs;
2674 bool none = false;
2675
2676 if (strncmp(arg, "none", 4) == 0)
2677 none = true;
2678
2679 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2680 rcs->ecom = NULL;
2681 rcs->none = none;
2682
2683 return rcs;
2684}
2685
d62a17ae 2686static void *route_set_ecommunity_rt_compile(const char *arg)
718e3744 2687{
bb4dcdd1 2688 struct rmap_ecom_set *rcs;
d62a17ae 2689 struct ecommunity *ecom;
718e3744 2690
d62a17ae 2691 ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2692 if (!ecom)
2693 return NULL;
bb4dcdd1
DA
2694
2695 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2696 rcs->ecom = ecommunity_intern(ecom);
2697 rcs->none = false;
2698
2699 return rcs;
718e3744 2700}
2701
73d78ea0 2702/* Free function for set community. Used by _rt and _soo */
d62a17ae 2703static void route_set_ecommunity_free(void *rule)
718e3744 2704{
bb4dcdd1
DA
2705 struct rmap_ecom_set *rcs = rule;
2706
2707 if (rcs->ecom)
2708 ecommunity_unintern(&rcs->ecom);
2709
2710 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2711}
2712
bb4dcdd1
DA
2713static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
2714 "extcommunity",
2715 route_set_ecommunity,
2716 route_set_ecommunity_none_compile,
2717 route_set_ecommunity_free,
2718};
2719
718e3744 2720/* Set community rule structure. */
364deb04
DL
2721static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2722 "extcommunity rt",
2723 route_set_ecommunity,
2724 route_set_ecommunity_rt_compile,
2725 route_set_ecommunity_free,
718e3744 2726};
2727
2728/* `set extcommunity soo COMMUNITY' */
2729
718e3744 2730/* Compile function for set community. */
d62a17ae 2731static void *route_set_ecommunity_soo_compile(const char *arg)
718e3744 2732{
bb4dcdd1 2733 struct rmap_ecom_set *rcs;
d62a17ae 2734 struct ecommunity *ecom;
718e3744 2735
d62a17ae 2736 ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2737 if (!ecom)
2738 return NULL;
e52702f2 2739
bb4dcdd1
DA
2740 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2741 rcs->ecom = ecommunity_intern(ecom);
2742 rcs->none = false;
2743
2744 return rcs;
718e3744 2745}
2746
718e3744 2747/* Set community rule structure. */
364deb04
DL
2748static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2749 "extcommunity soo",
2750 route_set_ecommunity,
2751 route_set_ecommunity_soo_compile,
2752 route_set_ecommunity_free,
718e3744 2753};
6b0655a2 2754
ca9ac3ef 2755/* `set extcommunity bandwidth' */
2756
2757struct rmap_ecomm_lb_set {
2758 uint8_t lb_type;
2759#define RMAP_ECOMM_LB_SET_VALUE 1
2760#define RMAP_ECOMM_LB_SET_CUMUL 2
2761#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2762 bool non_trans;
2763 uint32_t bw;
2764};
2765
2766static enum route_map_cmd_result_t
1782514f 2767route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
ca9ac3ef 2768{
2769 struct rmap_ecomm_lb_set *rels = rule;
2770 struct bgp_path_info *path;
2771 struct peer *peer;
2772 struct ecommunity ecom_lb = {0};
2773 struct ecommunity_val lb_eval;
2774 uint32_t bw_bytes = 0;
b1875e65 2775 uint16_t mpath_count = 0;
ca9ac3ef 2776 struct ecommunity *new_ecom;
2777 struct ecommunity *old_ecom;
2778 as_t as;
2779
ca9ac3ef 2780 path = object;
2781 peer = path->peer;
2782 if (!peer || !peer->bgp)
2783 return RMAP_ERROR;
2784
2785 /* Build link bandwidth extended community */
2786 as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
b1875e65 2787 if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
87b42e3b 2788 bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
b1875e65 2789 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2790 /* process this only for the best path. */
2791 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2792 return RMAP_OKAY;
2793
2794 bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2795 if (!bw_bytes)
2796 return RMAP_OKAY;
2797
2798 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2799
2800 /* process this only for the best path. */
2801 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2802 return RMAP_OKAY;
2803
87b42e3b 2804 bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
b1875e65 2805 mpath_count = bgp_path_info_mpath_count(path) + 1;
2806 bw_bytes *= mpath_count;
2807 }
ca9ac3ef 2808
27aa23a4
DA
2809 encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
2810 CHECK_FLAG(peer->flags,
2811 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
ca9ac3ef 2812
2813 /* add to route or merge with existing */
b53e67a3 2814 old_ecom = bgp_attr_get_ecommunity(path->attr);
ca9ac3ef 2815 if (old_ecom) {
f6ca545a 2816 new_ecom = ecommunity_dup(old_ecom);
2817 ecommunity_add_val(new_ecom, &lb_eval, true, true);
ca9ac3ef 2818 if (!old_ecom->refcnt)
2819 ecommunity_free(&old_ecom);
f6ca545a 2820 } else {
2821 ecom_lb.size = 1;
7659ad68 2822 ecom_lb.unit_size = ECOMMUNITY_SIZE;
f6ca545a 2823 ecom_lb.val = (uint8_t *)lb_eval.val;
ca9ac3ef 2824 new_ecom = ecommunity_dup(&ecom_lb);
f6ca545a 2825 }
ca9ac3ef 2826
2827 /* new_ecom will be intern()'d or attr_flush()'d in call stack */
b53e67a3 2828 bgp_attr_set_ecommunity(path->attr, new_ecom);
ca9ac3ef 2829
7b651a32 2830 /* Mark that route-map has set link bandwidth; used in attribute
2831 * setting decisions.
2832 */
2833 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
ca9ac3ef 2834
2835 return RMAP_OKAY;
2836}
2837
2838static void *route_set_ecommunity_lb_compile(const char *arg)
2839{
2840 struct rmap_ecomm_lb_set *rels;
2841 uint8_t lb_type;
2842 uint32_t bw = 0;
4c13ffe4 2843 char bw_str[40] = {0};
2844 char *p, *str;
2845 bool non_trans = false;
ca9ac3ef 2846
4c13ffe4 2847 str = (char *)arg;
2848 p = strchr(arg, ' ');
2849 if (p) {
2850 int len;
2851
2852 len = p - arg;
2853 memcpy(bw_str, arg, len);
2854 non_trans = true;
2855 str = bw_str;
2856 }
2857
2858 if (strcmp(str, "cumulative") == 0)
ca9ac3ef 2859 lb_type = RMAP_ECOMM_LB_SET_CUMUL;
4c13ffe4 2860 else if (strcmp(str, "num-multipaths") == 0)
ca9ac3ef 2861 lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
2862 else {
2863 char *end = NULL;
2864
4c13ffe4 2865 bw = strtoul(str, &end, 10);
ca9ac3ef 2866 if (*end != '\0')
2867 return NULL;
2868 lb_type = RMAP_ECOMM_LB_SET_VALUE;
2869 }
2870
2871 rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2872 sizeof(struct rmap_ecomm_lb_set));
2873 rels->lb_type = lb_type;
2874 rels->bw = bw;
4c13ffe4 2875 rels->non_trans = non_trans;
ca9ac3ef 2876
2877 return rels;
2878}
2879
2880static void route_set_ecommunity_lb_free(void *rule)
2881{
2882 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2883}
2884
2885/* Set community rule structure. */
2886struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
2887 "extcommunity bandwidth",
2888 route_set_ecommunity_lb,
2889 route_set_ecommunity_lb_compile,
2890 route_set_ecommunity_lb_free,
2891};
2892
718e3744 2893/* `set origin ORIGIN' */
2894
2895/* For origin set. */
b68885f9 2896static enum route_map_cmd_result_t
1782514f 2897route_set_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 2898{
d7c0a89a 2899 uint8_t *origin;
9b6d8fcf 2900 struct bgp_path_info *path;
718e3744 2901
1782514f
DS
2902 origin = rule;
2903 path = object;
e52702f2 2904
1782514f 2905 path->attr->origin = *origin;
718e3744 2906
d62a17ae 2907 return RMAP_OKAY;
718e3744 2908}
2909
2910/* Compile function for origin set. */
d62a17ae 2911static void *route_set_origin_compile(const char *arg)
718e3744 2912{
d7c0a89a 2913 uint8_t *origin;
718e3744 2914
d7c0a89a 2915 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 2916
d62a17ae 2917 if (strcmp(arg, "igp") == 0)
2918 *origin = 0;
2919 else if (strcmp(arg, "egp") == 0)
2920 *origin = 1;
2921 else
2922 *origin = 2;
718e3744 2923
d62a17ae 2924 return origin;
718e3744 2925}
2926
2927/* Compile function for origin set. */
d62a17ae 2928static void route_set_origin_free(void *rule)
718e3744 2929{
d62a17ae 2930 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2931}
2932
515e500c 2933/* Set origin rule structure. */
364deb04
DL
2934static const struct route_map_rule_cmd route_set_origin_cmd = {
2935 "origin",
2936 route_set_origin,
2937 route_set_origin_compile,
d62a17ae 2938 route_set_origin_free,
718e3744 2939};
6b0655a2 2940
718e3744 2941/* `set atomic-aggregate' */
2942
2943/* For atomic aggregate set. */
b68885f9 2944static enum route_map_cmd_result_t
1782514f 2945route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
718e3744 2946{
9b6d8fcf 2947 struct bgp_path_info *path;
718e3744 2948
1782514f
DS
2949 path = object;
2950 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
718e3744 2951
d62a17ae 2952 return RMAP_OKAY;
718e3744 2953}
2954
2955/* Compile function for atomic aggregate. */
d62a17ae 2956static void *route_set_atomic_aggregate_compile(const char *arg)
718e3744 2957{
d62a17ae 2958 return (void *)1;
718e3744 2959}
2960
2961/* Compile function for atomic aggregate. */
d62a17ae 2962static void route_set_atomic_aggregate_free(void *rule)
718e3744 2963{
d62a17ae 2964 return;
718e3744 2965}
2966
2967/* Set atomic aggregate rule structure. */
364deb04
DL
2968static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
2969 "atomic-aggregate",
2970 route_set_atomic_aggregate,
2971 route_set_atomic_aggregate_compile,
2972 route_set_atomic_aggregate_free,
718e3744 2973};
6b0655a2 2974
718e3744 2975/* `set aggregator as AS A.B.C.D' */
d62a17ae 2976struct aggregator {
2977 as_t as;
2978 struct in_addr address;
718e3744 2979};
2980
b68885f9 2981static enum route_map_cmd_result_t
1782514f 2982route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
718e3744 2983{
9b6d8fcf 2984 struct bgp_path_info *path;
d62a17ae 2985 struct aggregator *aggregator;
718e3744 2986
1782514f
DS
2987 path = object;
2988 aggregator = rule;
e52702f2 2989
1782514f
DS
2990 path->attr->aggregator_as = aggregator->as;
2991 path->attr->aggregator_addr = aggregator->address;
2992 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
718e3744 2993
d62a17ae 2994 return RMAP_OKAY;
718e3744 2995}
2996
d62a17ae 2997static void *route_set_aggregator_as_compile(const char *arg)
718e3744 2998{
d62a17ae 2999 struct aggregator *aggregator;
3000 char as[10];
3001 char address[20];
3002 int ret;
718e3744 3003
d62a17ae 3004 aggregator =
3005 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
116e176d
DS
3006 if (sscanf(arg, "%s %s", as, address) != 2) {
3007 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3008 return NULL;
3009 }
718e3744 3010
d62a17ae 3011 aggregator->as = strtoul(as, NULL, 10);
3012 ret = inet_aton(address, &aggregator->address);
3013 if (ret == 0) {
3014 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3015 return NULL;
3016 }
3017 return aggregator;
718e3744 3018}
3019
d62a17ae 3020static void route_set_aggregator_as_free(void *rule)
718e3744 3021{
d62a17ae 3022 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3023}
3024
364deb04
DL
3025static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
3026 "aggregator as",
3027 route_set_aggregator_as,
3028 route_set_aggregator_as_compile,
3029 route_set_aggregator_as_free,
718e3744 3030};
6b0655a2 3031
4b7e6066 3032/* Set tag to object. object must be pointer to struct bgp_path_info */
b68885f9 3033static enum route_map_cmd_result_t
1782514f 3034route_set_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 3035{
d62a17ae 3036 route_tag_t *tag;
9b6d8fcf 3037 struct bgp_path_info *path;
0d9551dc 3038
1782514f
DS
3039 tag = rule;
3040 path = object;
0d9551dc 3041
1782514f
DS
3042 /* Set tag value */
3043 path->attr->tag = *tag;
0d9551dc 3044
d62a17ae 3045 return RMAP_OKAY;
0d9551dc
DS
3046}
3047
0d9551dc 3048/* Route map commands for tag set. */
364deb04
DL
3049static const struct route_map_rule_cmd route_set_tag_cmd = {
3050 "tag",
3051 route_set_tag,
3052 route_map_rule_tag_compile,
d62a17ae 3053 route_map_rule_tag_free,
0d9551dc
DS
3054};
3055
4b7e6066 3056/* Set label-index to object. object must be pointer to struct bgp_path_info */
b68885f9 3057static enum route_map_cmd_result_t
1782514f 3058route_set_label_index(void *rule, const struct prefix *prefix, void *object)
d62a17ae 3059{
3060 struct rmap_value *rv;
9b6d8fcf 3061 struct bgp_path_info *path;
d7c0a89a 3062 uint32_t label_index;
d62a17ae 3063
1782514f
DS
3064 /* Fetch routemap's rule information. */
3065 rv = rule;
3066 path = object;
d62a17ae 3067
1782514f
DS
3068 /* Set label-index value. */
3069 label_index = rv->value;
3070 if (label_index) {
3071 path->attr->label_index = label_index;
3072 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
d62a17ae 3073 }
d990e384 3074
d62a17ae 3075 return RMAP_OKAY;
d990e384
DS
3076}
3077
3078/* Route map commands for label-index set. */
364deb04
DL
3079static const struct route_map_rule_cmd route_set_label_index_cmd = {
3080 "label-index",
3081 route_set_label_index,
3082 route_value_compile,
d62a17ae 3083 route_value_free,
d990e384 3084};
0d9551dc 3085
718e3744 3086/* `match ipv6 address IP_ACCESS_LIST' */
3087
b68885f9 3088static enum route_map_cmd_result_t
1782514f 3089route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
718e3744 3090{
d62a17ae 3091 struct access_list *alist;
718e3744 3092
1782514f 3093 if (prefix->family == AF_INET6) {
d62a17ae 3094 alist = access_list_lookup(AFI_IP6, (char *)rule);
3095 if (alist == NULL)
3096 return RMAP_NOMATCH;
e52702f2 3097
d62a17ae 3098 return (access_list_apply(alist, prefix) == FILTER_DENY
3099 ? RMAP_NOMATCH
3100 : RMAP_MATCH);
3101 }
3102 return RMAP_NOMATCH;
718e3744 3103}
3104
d62a17ae 3105static void *route_match_ipv6_address_compile(const char *arg)
718e3744 3106{
d62a17ae 3107 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3108}
3109
d62a17ae 3110static void route_match_ipv6_address_free(void *rule)
718e3744 3111{
d62a17ae 3112 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3113}
3114
3115/* Route map commands for ip address matching. */
364deb04
DL
3116static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
3117 "ipv6 address",
3118 route_match_ipv6_address,
3119 route_match_ipv6_address_compile,
3120 route_match_ipv6_address_free
3121};
6b0655a2 3122
bc63ba98
DA
3123/* `match ipv6 next-hop ACCESSLIST6_NAME' */
3124static enum route_map_cmd_result_t
3125route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
3126{
3127 struct bgp_path_info *path;
3128 struct access_list *alist;
3129 struct prefix_ipv6 p;
3130
3131 if (prefix->family == AF_INET6) {
3132 path = object;
3133 p.family = AF_INET6;
3134 p.prefix = path->attr->mp_nexthop_global;
3135 p.prefixlen = IPV6_MAX_BITLEN;
3136
3137 alist = access_list_lookup(AFI_IP6, (char *)rule);
3138 if (!alist)
3139 return RMAP_NOMATCH;
3140
3141 if (access_list_apply(alist, &p) == FILTER_PERMIT)
3142 return RMAP_MATCH;
3143
3144 if (path->attr->mp_nexthop_len
3145 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3146 p.prefix = path->attr->mp_nexthop_local;
3147 if (access_list_apply(alist, &p) == FILTER_PERMIT)
3148 return RMAP_MATCH;
3149 }
3150 }
3151
3152 return RMAP_NOMATCH;
3153}
3154
3155static void *route_match_ipv6_next_hop_compile(const char *arg)
3156{
3157 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3158}
3159
3160static void route_match_ipv6_next_hop_free(void *rule)
3161{
3162 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3163}
3164
3165static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
3166 "ipv6 next-hop",
3167 route_match_ipv6_next_hop,
3168 route_match_ipv6_next_hop_compile,
3169 route_match_ipv6_next_hop_free
3170};
3171
718e3744 3172/* `match ipv6 next-hop IP_ADDRESS' */
3173
b68885f9 3174static enum route_map_cmd_result_t
bc63ba98
DA
3175route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
3176 void *object)
718e3744 3177{
d62a17ae 3178 struct in6_addr *addr = rule;
9b6d8fcf 3179 struct bgp_path_info *path;
718e3744 3180
1782514f 3181 path = object;
718e3744 3182
1782514f
DS
3183 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
3184 return RMAP_MATCH;
718e3744 3185
1782514f
DS
3186 if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
3187 && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
3188 return RMAP_MATCH;
718e3744 3189
d62a17ae 3190 return RMAP_NOMATCH;
718e3744 3191}
3192
bc63ba98 3193static void *route_match_ipv6_next_hop_address_compile(const char *arg)
718e3744 3194{
d62a17ae 3195 struct in6_addr *address;
3196 int ret;
718e3744 3197
d62a17ae 3198 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3199
d62a17ae 3200 ret = inet_pton(AF_INET6, arg, address);
3201 if (!ret) {
3202 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3203 return NULL;
3204 }
718e3744 3205
d62a17ae 3206 return address;
718e3744 3207}
3208
bc63ba98 3209static void route_match_ipv6_next_hop_address_free(void *rule)
718e3744 3210{
d62a17ae 3211 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3212}
3213
bc63ba98 3214static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
03030106 3215 "ipv6 next-hop address",
bc63ba98
DA
3216 route_match_ipv6_next_hop_address,
3217 route_match_ipv6_next_hop_address_compile,
3218 route_match_ipv6_next_hop_address_free
364deb04 3219};
6b0655a2 3220
be7735b3
PG
3221/* `match ip next-hop IP_ADDRESS' */
3222
3223static enum route_map_cmd_result_t
1782514f 3224route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
be7735b3
PG
3225{
3226 struct in_addr *addr = rule;
3227 struct bgp_path_info *path;
3228
1782514f 3229 path = object;
be7735b3 3230
1782514f
DS
3231 if (path->attr->nexthop.s_addr == addr->s_addr
3232 || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
3233 && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
3234 return RMAP_MATCH;
be7735b3
PG
3235
3236 return RMAP_NOMATCH;
3237}
3238
3239static void *route_match_ipv4_next_hop_compile(const char *arg)
3240{
3241 struct in_addr *address;
3242 int ret;
3243
3244 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3245
3246 ret = inet_pton(AF_INET, arg, address);
3247 if (!ret) {
3248 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3249 return NULL;
3250 }
3251
3252 return address;
3253}
3254
3255static void route_match_ipv4_next_hop_free(void *rule)
3256{
3257 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3258}
3259
3260static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
3261 "ip next-hop address",
3262 route_match_ipv4_next_hop,
3263 route_match_ipv4_next_hop_compile,
3264 route_match_ipv4_next_hop_free
3265};
3266
718e3744 3267/* `match ipv6 address prefix-list PREFIX_LIST' */
3268
b68885f9 3269static enum route_map_cmd_result_t
123214ef 3270route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1782514f 3271 void *object)
718e3744 3272{
1782514f 3273 return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
718e3744 3274}
3275
d62a17ae 3276static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 3277{
d62a17ae 3278 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3279}
3280
d62a17ae 3281static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 3282{
d62a17ae 3283 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3284}
3285
364deb04
DL
3286static const struct route_map_rule_cmd
3287 route_match_ipv6_address_prefix_list_cmd = {
3288 "ipv6 address prefix-list",
3289 route_match_ipv6_address_prefix_list,
d62a17ae 3290 route_match_ipv6_address_prefix_list_compile,
364deb04
DL
3291 route_match_ipv6_address_prefix_list_free
3292};
6b0655a2 3293
61ad901e
DA
3294/* `match ipv6 next-hop type <TYPE>' */
3295
b68885f9 3296static enum route_map_cmd_result_t
61ad901e 3297route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1782514f 3298 void *object)
61ad901e 3299{
9b6d8fcf 3300 struct bgp_path_info *path;
61ad901e
DA
3301 struct in6_addr *addr = rule;
3302
1782514f 3303 if (prefix->family == AF_INET6) {
9b6d8fcf 3304 path = (struct bgp_path_info *)object;
05864da7 3305 if (!path)
b68885f9 3306 return RMAP_NOMATCH;
61ad901e 3307
9b6d8fcf
DS
3308 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
3309 && !path->attr->nh_ifindex)
61ad901e
DA
3310 return RMAP_MATCH;
3311 }
1782514f 3312
61ad901e
DA
3313 return RMAP_NOMATCH;
3314}
3315
3316static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3317{
3318 struct in6_addr *address;
3319 int ret;
3320
3321 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3322
3323 ret = inet_pton(AF_INET6, "::0", address);
3324 if (!ret) {
3325 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3326 return NULL;
3327 }
3328
3329 return address;
3330}
3331
3332static void route_match_ipv6_next_hop_type_free(void *rule)
3333{
3334 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3335}
3336
364deb04
DL
3337static const struct route_map_rule_cmd
3338 route_match_ipv6_next_hop_type_cmd = {
3339 "ipv6 next-hop type",
3340 route_match_ipv6_next_hop_type,
61ad901e 3341 route_match_ipv6_next_hop_type_compile,
364deb04
DL
3342 route_match_ipv6_next_hop_type_free
3343};
61ad901e 3344
718e3744 3345/* `set ipv6 nexthop global IP_ADDRESS' */
3346
581776fa 3347/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3348static enum route_map_cmd_result_t
1782514f 3349route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
718e3744 3350{
d62a17ae 3351 struct in6_addr *address;
9b6d8fcf 3352 struct bgp_path_info *path;
718e3744 3353
1782514f
DS
3354 /* Fetch routemap's rule information. */
3355 address = rule;
3356 path = object;
e52702f2 3357
1782514f
DS
3358 /* Set next hop value. */
3359 path->attr->mp_nexthop_global = *address;
3f9c7369 3360
1782514f
DS
3361 /* Set nexthop length. */
3362 if (path->attr->mp_nexthop_len == 0)
3363 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 3364
1782514f
DS
3365 SET_FLAG(path->attr->rmap_change_flags,
3366 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
718e3744 3367
d62a17ae 3368 return RMAP_OKAY;
718e3744 3369}
3370
3371/* Route map `ip next-hop' compile function. Given string is converted
3372 to struct in_addr structure. */
d62a17ae 3373static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 3374{
d62a17ae 3375 int ret;
3376 struct in6_addr *address;
718e3744 3377
d62a17ae 3378 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3379
d62a17ae 3380 ret = inet_pton(AF_INET6, arg, address);
718e3744 3381
d62a17ae 3382 if (ret == 0) {
3383 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3384 return NULL;
3385 }
718e3744 3386
d62a17ae 3387 return address;
718e3744 3388}
3389
3390/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3391static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 3392{
d62a17ae 3393 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3394}
3395
3396/* Route map commands for ip nexthop set. */
364deb04
DL
3397static const struct route_map_rule_cmd
3398 route_set_ipv6_nexthop_global_cmd = {
3399 "ipv6 next-hop global",
3400 route_set_ipv6_nexthop_global,
d62a17ae 3401 route_set_ipv6_nexthop_global_compile,
364deb04
DL
3402 route_set_ipv6_nexthop_global_free
3403};
6b0655a2 3404
161995ea 3405/* Set next-hop preference value. */
b68885f9 3406static enum route_map_cmd_result_t
123214ef 3407route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
1782514f 3408 void *object)
d62a17ae 3409{
9b6d8fcf 3410 struct bgp_path_info *path;
d62a17ae 3411 struct peer *peer;
3412
1782514f
DS
3413 /* Fetch routemap's rule information. */
3414 path = object;
3415 peer = path->peer;
d62a17ae 3416
1782514f
DS
3417 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3418 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
3419 /* Set next hop preference to global */
3420 path->attr->mp_nexthop_prefer_global = true;
3421 SET_FLAG(path->attr->rmap_change_flags,
3422 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3423 } else {
3424 path->attr->mp_nexthop_prefer_global = false;
3425 SET_FLAG(path->attr->rmap_change_flags,
3426 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
161995ea 3427 }
1782514f 3428
d62a17ae 3429 return RMAP_OKAY;
161995ea
DS
3430}
3431
d62a17ae 3432static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 3433{
d62a17ae 3434 int *rins = NULL;
161995ea 3435
d62a17ae 3436 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3437 *rins = 1;
161995ea 3438
d62a17ae 3439 return rins;
161995ea
DS
3440}
3441
3442/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3443static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 3444{
d62a17ae 3445 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
3446}
3447
3448/* Route map commands for ip nexthop set preferred. */
364deb04
DL
3449static const struct route_map_rule_cmd
3450 route_set_ipv6_nexthop_prefer_global_cmd = {
3451 "ipv6 next-hop prefer-global",
3452 route_set_ipv6_nexthop_prefer_global,
d62a17ae 3453 route_set_ipv6_nexthop_prefer_global_compile,
364deb04
DL
3454 route_set_ipv6_nexthop_prefer_global_free
3455};
161995ea 3456
718e3744 3457/* `set ipv6 nexthop local IP_ADDRESS' */
3458
581776fa 3459/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3460static enum route_map_cmd_result_t
1782514f 3461route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
d62a17ae 3462{
3463 struct in6_addr *address;
9b6d8fcf 3464 struct bgp_path_info *path;
d62a17ae 3465
1782514f
DS
3466 /* Fetch routemap's rule information. */
3467 address = rule;
3468 path = object;
d62a17ae 3469
1782514f
DS
3470 /* Set next hop value. */
3471 path->attr->mp_nexthop_local = *address;
d62a17ae 3472
1782514f
DS
3473 /* Set nexthop length. */
3474 if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3475 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 3476
1782514f
DS
3477 SET_FLAG(path->attr->rmap_change_flags,
3478 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 3479
d62a17ae 3480 return RMAP_OKAY;
718e3744 3481}
3482
3483/* Route map `ip nexthop' compile function. Given string is converted
3484 to struct in_addr structure. */
d62a17ae 3485static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 3486{
d62a17ae 3487 int ret;
3488 struct in6_addr *address;
718e3744 3489
d62a17ae 3490 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3491
d62a17ae 3492 ret = inet_pton(AF_INET6, arg, address);
718e3744 3493
d62a17ae 3494 if (ret == 0) {
3495 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3496 return NULL;
3497 }
718e3744 3498
d62a17ae 3499 return address;
718e3744 3500}
3501
3502/* Free route map's compiled `ip nexthop' value. */
d62a17ae 3503static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 3504{
d62a17ae 3505 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3506}
3507
3508/* Route map commands for ip nexthop set. */
364deb04
DL
3509static const struct route_map_rule_cmd
3510 route_set_ipv6_nexthop_local_cmd = {
3511 "ipv6 next-hop local",
3512 route_set_ipv6_nexthop_local,
d62a17ae 3513 route_set_ipv6_nexthop_local_compile,
364deb04
DL
3514 route_set_ipv6_nexthop_local_free
3515};
90916ac2
DS
3516
3517/* `set ipv6 nexthop peer-address' */
3518
581776fa 3519/* Set nexthop to object. object must be pointer to struct attr. */
b68885f9 3520static enum route_map_cmd_result_t
1782514f 3521route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
d62a17ae 3522{
3523 struct in6_addr peer_address;
9b6d8fcf 3524 struct bgp_path_info *path;
d62a17ae 3525 struct peer *peer;
3526
1782514f
DS
3527 /* Fetch routemap's rule information. */
3528 path = object;
3529 peer = path->peer;
d62a17ae 3530
1782514f
DS
3531 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3532 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3533 && peer->su_remote
3534 && sockunion_family(peer->su_remote) == AF_INET6) {
3535 peer_address = peer->su_remote->sin6.sin6_addr;
3536 /* Set next hop value and length in attribute. */
3537 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3538 path->attr->mp_nexthop_local = peer_address;
3539 if (path->attr->mp_nexthop_len
3540 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3541 path->attr->mp_nexthop_len =
3542 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3543 } else {
3544 path->attr->mp_nexthop_global = peer_address;
3545 if (path->attr->mp_nexthop_len == 0)
3546 path->attr->mp_nexthop_len =
3547 BGP_ATTR_NHLEN_IPV6_GLOBAL;
d62a17ae 3548 }
1782514f
DS
3549
3550 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3551 /* The next hop value will be set as part of packet
3552 * rewrite.
3553 * Set the flags here to indicate that rewrite needs to
3554 * be done.
3555 * Also, clear the value - we clear both global and
3556 * link-local
3557 * nexthops, whether we send one or both is determined
3558 * elsewhere.
3559 */
3560 SET_FLAG(path->attr->rmap_change_flags,
3561 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3562 /* clear next hop value. */
3563 memset(&(path->attr->mp_nexthop_global), 0,
3564 sizeof(struct in6_addr));
3565 memset(&(path->attr->mp_nexthop_local), 0,
3566 sizeof(struct in6_addr));
90916ac2 3567 }
90916ac2 3568
d62a17ae 3569 return RMAP_OKAY;
90916ac2
DS
3570}
3571
3572/* Route map `ip next-hop' compile function. Given string is converted
3573 to struct in_addr structure. */
d62a17ae 3574static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 3575{
d62a17ae 3576 int *rins = NULL;
90916ac2 3577
d62a17ae 3578 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3579 *rins = 1;
90916ac2 3580
d62a17ae 3581 return rins;
90916ac2
DS
3582}
3583
3584/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3585static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 3586{
d62a17ae 3587 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
3588}
3589
3590/* Route map commands for ip nexthop set. */
364deb04
DL
3591static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3592 "ipv6 next-hop peer-address",
3593 route_set_ipv6_nexthop_peer,
3594 route_set_ipv6_nexthop_peer_compile,
3595 route_set_ipv6_nexthop_peer_free
3596};
90916ac2 3597
69ba6dd7 3598/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 3599
b68885f9 3600static enum route_map_cmd_result_t
1782514f 3601route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
718e3744 3602{
d62a17ae 3603 struct in_addr *address;
9b6d8fcf 3604 struct bgp_path_info *path;
718e3744 3605
1782514f
DS
3606 /* Fetch routemap's rule information. */
3607 address = rule;
3608 path = object;
e52702f2 3609
1782514f
DS
3610 /* Set next hop value. */
3611 path->attr->mp_nexthop_global_in = *address;
3612 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
718e3744 3613
d62a17ae 3614 return RMAP_OKAY;
718e3744 3615}
3616
d62a17ae 3617static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 3618{
d62a17ae 3619 int ret;
3620 struct in_addr *address;
718e3744 3621
d62a17ae 3622 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3623
d62a17ae 3624 ret = inet_aton(arg, address);
718e3744 3625
d62a17ae 3626 if (ret == 0) {
3627 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3628 return NULL;
3629 }
718e3744 3630
d62a17ae 3631 return address;
718e3744 3632}
3633
69ba6dd7 3634/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 3635
b68885f9 3636static enum route_map_cmd_result_t
1782514f 3637route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
d6902373 3638{
d62a17ae 3639 struct in6_addr *address;
9b6d8fcf 3640 struct bgp_path_info *path;
d6902373 3641
1782514f
DS
3642 /* Fetch routemap's rule information. */
3643 address = rule;
3644 path = object;
d6902373 3645
1782514f
DS
3646 /* Set next hop value. */
3647 memcpy(&path->attr->mp_nexthop_global, address,
3648 sizeof(struct in6_addr));
3649 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
d6902373 3650
d62a17ae 3651 return RMAP_OKAY;
d6902373
PG
3652}
3653
d62a17ae 3654static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 3655{
d62a17ae 3656 int ret;
3657 struct in6_addr *address;
d6902373 3658
d62a17ae 3659 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3660 ret = inet_pton(AF_INET6, arg, address);
d6902373 3661
d62a17ae 3662 if (ret == 0) {
3663 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3664 return NULL;
3665 }
d6902373 3666
d62a17ae 3667 return address;
d6902373
PG
3668}
3669
d62a17ae 3670static void route_set_vpn_nexthop_free(void *rule)
718e3744 3671{
d62a17ae 3672 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3673}
3674
69ba6dd7 3675/* Route map commands for ipv4 next-hop set. */
364deb04
DL
3676static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3677 "ipv4 vpn next-hop",
3678 route_set_vpnv4_nexthop,
3679 route_set_vpnv4_nexthop_compile,
3680 route_set_vpn_nexthop_free
3681};
d6902373 3682
69ba6dd7 3683/* Route map commands for ipv6 next-hop set. */
364deb04
DL
3684static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3685 "ipv6 vpn next-hop",
3686 route_set_vpnv6_nexthop,
3687 route_set_vpnv6_nexthop_compile,
3688 route_set_vpn_nexthop_free
3689};
6b0655a2 3690
718e3744 3691/* `set originator-id' */
3692
3693/* For origin set. */
b68885f9 3694static enum route_map_cmd_result_t
1782514f 3695route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
718e3744 3696{
d62a17ae 3697 struct in_addr *address;
9b6d8fcf 3698 struct bgp_path_info *path;
718e3744 3699
1782514f
DS
3700 address = rule;
3701 path = object;
e52702f2 3702
1782514f
DS
3703 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3704 path->attr->originator_id = *address;
718e3744 3705
d62a17ae 3706 return RMAP_OKAY;
718e3744 3707}
3708
3709/* Compile function for originator-id set. */
d62a17ae 3710static void *route_set_originator_id_compile(const char *arg)
718e3744 3711{
d62a17ae 3712 int ret;
3713 struct in_addr *address;
718e3744 3714
d62a17ae 3715 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3716
d62a17ae 3717 ret = inet_aton(arg, address);
718e3744 3718
d62a17ae 3719 if (ret == 0) {
3720 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3721 return NULL;
3722 }
718e3744 3723
d62a17ae 3724 return address;
718e3744 3725}
3726
3727/* Compile function for originator_id set. */
d62a17ae 3728static void route_set_originator_id_free(void *rule)
718e3744 3729{
d62a17ae 3730 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3731}
3732
515e500c 3733/* Set originator-id rule structure. */
364deb04
DL
3734static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3735 "originator-id",
3736 route_set_originator_id,
3737 route_set_originator_id_compile,
3738 route_set_originator_id_free,
718e3744 3739};
6b0655a2 3740
518f0eb1 3741/*
2a3d5731 3742 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
3743 * modifications.
3744 */
d62a17ae 3745static void bgp_route_map_process_peer(const char *rmap_name,
3746 struct route_map *map, struct peer *peer,
3747 int afi, int safi, int route_update)
3748{
d62a17ae 3749 struct bgp_filter *filter;
3750
3751 if (!peer || !rmap_name)
3752 return;
3753
3754 filter = &peer->filter[afi][safi];
3755 /*
3756 * in is for non-route-server clients,
3757 * out is for all peers
3758 */
db77a501
DS
3759 if (filter->map[RMAP_IN].name
3760 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3761 filter->map[RMAP_IN].map = map;
d62a17ae 3762
feb17238 3763 if (route_update && peer_established(peer)) {
d62a17ae 3764 if (CHECK_FLAG(peer->af_flags[afi][safi],
3765 PEER_FLAG_SOFT_RECONFIG)) {
3766 if (bgp_debug_update(peer, NULL, NULL, 1))
3767 zlog_debug(
11b228cd
DS
3768 "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
3769 rmap_name, afi2str(afi),
3770 safi2str(safi), peer->host);
d62a17ae 3771
3772 bgp_soft_reconfig_in(peer, afi, safi);
3773 } else if (CHECK_FLAG(peer->cap,
3774 PEER_CAP_REFRESH_OLD_RCV)
3775 || CHECK_FLAG(peer->cap,
3776 PEER_CAP_REFRESH_NEW_RCV)) {
3777 if (bgp_debug_update(peer, NULL, NULL, 1))
3778 zlog_debug(
11b228cd
DS
3779 "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
3780 rmap_name, afi2str(afi),
3781 safi2str(safi), peer->host);
9af52ccf
DA
3782 bgp_route_refresh_send(
3783 peer, afi, safi, 0, 0, 0,
3784 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 3785 }
d62a17ae 3786 }
518f0eb1 3787 }
d62a17ae 3788
3789 /*
3790 * For outbound, unsuppress and default-originate map change (content or
3791 * map created), merely update the "config" here, the actual route
3792 * announcement happens at the group level.
3793 */
3794 if (filter->map[RMAP_OUT].name
3795 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3796 filter->map[RMAP_OUT].map = map;
3797
3798 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3799 filter->usmap.map = map;
3800
7f7940e6
MK
3801 if (filter->advmap.aname
3802 && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
3803 filter->advmap.amap = map;
7f7940e6
MK
3804 }
3805
3806 if (filter->advmap.cname
3807 && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
3808 filter->advmap.cmap = map;
7f7940e6
MK
3809 }
3810
d62a17ae 3811 if (peer->default_rmap[afi][safi].name
3812 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
3813 peer->default_rmap[afi][safi].map = map;
c5aec50b
MK
3814
3815 /* Notify BGP conditional advertisement scanner percess */
c385f82a 3816 peer->advmap_config_change[afi][safi] = true;
d62a17ae 3817}
3818
3819static void bgp_route_map_update_peer_group(const char *rmap_name,
3820 struct route_map *map,
3821 struct bgp *bgp)
3822{
3823 struct peer_group *group;
3824 struct listnode *node, *nnode;
3825 struct bgp_filter *filter;
3826 int afi, safi;
3827 int direct;
3828
3829 if (!bgp)
3830 return;
3831
3832 /* All the peers have been updated correctly already. This is
3833 * just updating the placeholder data. No real update required.
3834 */
05c7a1cc
QY
3835 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
3836 FOREACH_AFI_SAFI (afi, safi) {
3837 filter = &group->conf->filter[afi][safi];
3838
3839 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
3840 if ((filter->map[direct].name)
3841 && (strcmp(rmap_name,
3842 filter->map[direct].name)
d62a17ae 3843 == 0))
05c7a1cc 3844 filter->map[direct].map = map;
d62a17ae 3845 }
05c7a1cc
QY
3846
3847 if (filter->usmap.name
3848 && (strcmp(rmap_name, filter->usmap.name) == 0))
3849 filter->usmap.map = map;
9118301e
DA
3850
3851 if (filter->advmap.aname &&
3852 (strcmp(rmap_name, filter->advmap.aname) == 0))
3853 filter->advmap.amap = map;
3854
3855 if (filter->advmap.cname &&
3856 (strcmp(rmap_name, filter->advmap.cname) == 0))
3857 filter->advmap.cmap = map;
05c7a1cc
QY
3858 }
3859 }
518f0eb1
DS
3860}
3861
a6e0d253
DW
3862/*
3863 * Note that if an extreme number (tens of thousands) of route-maps are in use
3864 * and if bgp has an extreme number of peers, network statements, etc then this
3865 * function can consume a lot of cycles. This is due to this function being
3866 * called for each route-map and within this function we walk the list of peers,
3867 * network statements, etc looking to see if they use this route-map.
3868 */
d62a17ae 3869static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
f1aa4929 3870 bool route_update)
d62a17ae 3871{
3872 int i;
4056a5f6 3873 bool matched;
d62a17ae 3874 afi_t afi;
3875 safi_t safi;
3876 struct peer *peer;
9bcb3eef 3877 struct bgp_dest *bn;
d62a17ae 3878 struct bgp_static *bgp_static;
20894f50 3879 struct bgp_aggregate *aggregate;
d62a17ae 3880 struct listnode *node, *nnode;
3881 struct route_map *map;
3882 char buf[INET6_ADDRSTRLEN];
3883
3884 map = route_map_lookup_by_name(rmap_name);
3885
3886 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
3887
3888 /* Ignore dummy peer-group structure */
3889 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3890 continue;
3891
05c7a1cc
QY
3892 FOREACH_AFI_SAFI (afi, safi) {
3893 /* process in/out/import/export/default-orig
3894 * route-maps */
3895 bgp_route_map_process_peer(rmap_name, map, peer, afi,
3896 safi, route_update);
3897 }
d62a17ae 3898 }
3899
3900 /* for outbound/default-orig route-maps, process for groups */
3901 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
3902 route_update, 0);
3903
3904 /* update peer-group config (template) */
3905 bgp_route_map_update_peer_group(rmap_name, map, bgp);
3906
05c7a1cc
QY
3907 FOREACH_AFI_SAFI (afi, safi) {
3908 /* For table route-map updates. */
3909 if (!bgp_fibupd_safi(safi))
3910 continue;
d62a17ae 3911
05c7a1cc
QY
3912 if (bgp->table_map[afi][safi].name
3913 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
3914 == 0)) {
b4897fa5 3915
3916 /* bgp->table_map[afi][safi].map is NULL.
3917 * i.e Route map creation event.
3918 * So update applied_counter.
3919 * If it is not NULL, i.e It may be routemap updation or
3920 * deletion. so no need to update the counter.
3921 */
3922 if (!bgp->table_map[afi][safi].map)
3923 route_map_counter_increment(map);
05c7a1cc
QY
3924 bgp->table_map[afi][safi].map = map;
3925
3926 if (BGP_DEBUG(zebra, ZEBRA))
3927 zlog_debug(
11b228cd
DS
3928 "Processing route_map %s(%s:%s) update on table map",
3929 rmap_name, afi2str(afi),
3930 safi2str(safi));
05c7a1cc
QY
3931 if (route_update)
3932 bgp_zebra_announce_table(bgp, afi, safi);
3933 }
d62a17ae 3934
05c7a1cc
QY
3935 /* For network route-map updates. */
3936 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
96f10e1e 3937 bn = bgp_route_next(bn)) {
9bcb3eef 3938 bgp_static = bgp_dest_get_bgp_static_info(bn);
c9837105
DS
3939 if (!bgp_static)
3940 continue;
3941
3942 if (!bgp_static->rmap.name
3943 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
3944 continue;
3945
b4897fa5 3946 if (!bgp_static->rmap.map)
3947 route_map_counter_increment(map);
3948
c9837105
DS
3949 bgp_static->rmap.map = map;
3950
3951 if (route_update && !bgp_static->backdoor) {
b54892e0 3952 const struct prefix *bn_p =
9bcb3eef 3953 bgp_dest_get_prefix(bn);
b54892e0
DS
3954
3955 if (bgp_debug_zebra(bn_p))
c9837105 3956 zlog_debug(
11b228cd
DS
3957 "Processing route_map %s(%s:%s) update on static route %s",
3958 rmap_name, afi2str(afi),
3959 safi2str(safi),
b54892e0
DS
3960 inet_ntop(bn_p->family,
3961 &bn_p->u.prefix, buf,
c9837105 3962 INET6_ADDRSTRLEN));
b54892e0 3963 bgp_static_update(bgp, bn_p, bgp_static, afi,
c9837105 3964 safi);
05c7a1cc 3965 }
96f10e1e 3966 }
20894f50
DA
3967
3968 /* For aggregate-address route-map updates. */
3969 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
3970 bn = bgp_route_next(bn)) {
9bcb3eef 3971 aggregate = bgp_dest_get_bgp_aggregate_info(bn);
20894f50
DA
3972 if (!aggregate)
3973 continue;
3974
4056a5f6 3975 matched = false;
20894f50 3976
365ab2e7
RZ
3977 /* Update suppress map pointer. */
3978 if (aggregate->suppress_map_name
3979 && strmatch(aggregate->suppress_map_name,
3980 rmap_name)) {
4056a5f6 3981 if (aggregate->rmap.map == NULL)
365ab2e7 3982 route_map_counter_increment(map);
20894f50 3983
365ab2e7 3984 aggregate->suppress_map = map;
4056a5f6
RZ
3985
3986 bgp_aggregate_toggle_suppressed(
3987 aggregate, bgp, bgp_dest_get_prefix(bn),
3988 afi, safi, false);
3989
3990 matched = true;
365ab2e7
RZ
3991 }
3992
4056a5f6
RZ
3993 if (aggregate->rmap.name
3994 && strmatch(rmap_name, aggregate->rmap.name)) {
3995 if (aggregate->rmap.map == NULL)
3996 route_map_counter_increment(map);
20894f50 3997
4056a5f6 3998 aggregate->rmap.map = map;
20894f50 3999
4056a5f6
RZ
4000 matched = true;
4001 }
20894f50 4002
4056a5f6 4003 if (matched && route_update) {
b54892e0 4004 const struct prefix *bn_p =
9bcb3eef 4005 bgp_dest_get_prefix(bn);
b54892e0
DS
4006
4007 if (bgp_debug_zebra(bn_p))
20894f50 4008 zlog_debug(
11b228cd
DS
4009 "Processing route_map %s(%s:%s) update on aggregate-address route %s",
4010 rmap_name, afi2str(afi),
4011 safi2str(safi),
b54892e0
DS
4012 inet_ntop(bn_p->family,
4013 &bn_p->u.prefix, buf,
20894f50 4014 INET6_ADDRSTRLEN));
b54892e0 4015 bgp_aggregate_route(bgp, bn_p, afi, safi,
20894f50
DA
4016 aggregate);
4017 }
4018 }
05c7a1cc 4019 }
d62a17ae 4020
4021 /* For redistribute route-map updates. */
4022 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4023 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
4024 struct list *red_list;
d62a17ae 4025 struct bgp_redist *red;
4026
4027 red_list = bgp->redist[afi][i];
4028 if (!red_list)
4029 continue;
4030
4031 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
c9837105
DS
4032 if (!red->rmap.name
4033 || (strcmp(rmap_name, red->rmap.name) != 0))
4034 continue;
4035
b4897fa5 4036 if (!red->rmap.map)
4037 route_map_counter_increment(map);
4038
c9837105
DS
4039 red->rmap.map = map;
4040
4041 if (!route_update)
4042 continue;
4043
4044 if (BGP_DEBUG(zebra, ZEBRA))
4045 zlog_debug(
11b228cd
DS
4046 "Processing route_map %s(%s:%s) update on redistributed routes",
4047 rmap_name, afi2str(afi),
4048 safi2str(safi));
c9837105
DS
4049
4050 bgp_redistribute_resend(bgp, afi, i,
d62a17ae 4051 red->instance);
d62a17ae 4052 }
4053 }
53c84f78
MK
4054
4055 /* for type5 command route-maps */
4056 FOREACH_AFI_SAFI (afi, safi) {
c9837105
DS
4057 if (!bgp->adv_cmd_rmap[afi][safi].name
4058 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4059 != 0)
4060 continue;
4061
2686df6a
NS
4062 /* Make sure the route-map is populated here if not already done */
4063 bgp->adv_cmd_rmap[afi][safi].map = map;
4064
c9837105
DS
4065 if (BGP_DEBUG(zebra, ZEBRA))
4066 zlog_debug(
11b228cd
DS
4067 "Processing route_map %s(%s:%s) update on advertise type5 route command",
4068 rmap_name, afi2str(afi), safi2str(safi));
2686df6a 4069
456a4697 4070 if (route_update && advertise_type5_routes(bgp, afi)) {
2686df6a
NS
4071 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4072 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4073 }
53c84f78 4074 }
d62a17ae 4075}
4076
46a69f10 4077static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 4078{
4079 struct listnode *node, *nnode;
4080 struct bgp *bgp;
4081
ddb5b488 4082 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
f1aa4929 4083 bgp_route_map_process_update(bgp, rmap_name, true);
5fe9f963 4084
49e5a4a0 4085#ifdef ENABLE_BGP_VNC
ddb5b488 4086 vnc_routemap_update(bgp, __func__);
65efcfce 4087#endif
ddb5b488
PZ
4088 }
4089
4090 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
4091}
4092
cc9f21da 4093void bgp_route_map_update_timer(struct thread *thread)
518f0eb1 4094{
d62a17ae 4095 bm->t_rmap_update = NULL;
518f0eb1 4096
d62a17ae 4097 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1
DS
4098}
4099
d62a17ae 4100static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 4101{
47c8fa1f
NT
4102 struct listnode *node, *nnode;
4103 struct bgp *bgp;
4104
4105 /* If new update is received before the current timer timed out,
4106 * turn it off and start a new timer.
4107 */
28ef0ee1 4108 THREAD_OFF(bm->t_rmap_update);
47c8fa1f
NT
4109
4110 /* rmap_update_timer of 0 means don't do route updates */
4111 if (bm->rmap_update_timer) {
4112 thread_add_timer(bm->master, bgp_route_map_update_timer,
4113 NULL, bm->rmap_update_timer,
4114 &bm->t_rmap_update);
4115
4116 /* Signal the groups that a route-map update event has
4117 * started */
4118 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
f1aa4929
DA
4119 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
4120 rmap_name, true, 1);
47c8fa1f 4121 } else {
f6e7507e 4122 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
f1aa4929 4123 bgp_route_map_process_update(bgp, rmap_name, false);
49e5a4a0 4124#ifdef ENABLE_BGP_VNC
f6e7507e 4125 vnc_routemap_update(bgp, __func__);
65efcfce 4126#endif
f6e7507e
IR
4127 }
4128
4129 vpn_policy_routemap_event(rmap_name);
d62a17ae 4130 }
718e3744 4131}
6b0655a2 4132
d62a17ae 4133static void bgp_route_map_add(const char *rmap_name)
73ac8160 4134{
7096e938 4135 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4136 bgp_route_map_mark_update(rmap_name);
73ac8160 4137
d62a17ae 4138 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 4139}
518f0eb1 4140
d62a17ae 4141static void bgp_route_map_delete(const char *rmap_name)
73ac8160 4142{
7096e938 4143 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4144 bgp_route_map_mark_update(rmap_name);
73ac8160 4145
d62a17ae 4146 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 4147}
518f0eb1 4148
097b5973 4149static void bgp_route_map_event(const char *rmap_name)
73ac8160 4150{
7096e938 4151 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4152 bgp_route_map_mark_update(rmap_name);
518f0eb1 4153
d62a17ae 4154 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
4155}
4156
48cb7ea9
SP
4157DEFUN_YANG (match_mac_address,
4158 match_mac_address_cmd,
c60dec36 4159 "match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4160 MATCH_STR
4161 "mac address\n"
4162 "Match address of route\n"
4163 "MAC Access-list name\n")
d37ba549 4164{
48cb7ea9
SP
4165 const char *xpath =
4166 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4167 char xpath_value[XPATH_MAXLEN];
4168
4169 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4170 snprintf(xpath_value, sizeof(xpath_value),
4171 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4172 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4173
4174 return nb_cli_apply_changes(vty, NULL);
d37ba549
MK
4175}
4176
48cb7ea9
SP
4177DEFUN_YANG (no_match_mac_address,
4178 no_match_mac_address_cmd,
c60dec36 4179 "no match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4180 NO_STR
4181 MATCH_STR
4182 "mac\n"
4183 "Match address of route\n"
4184 "MAC acess-list name\n")
d37ba549 4185{
48cb7ea9
SP
4186 const char *xpath =
4187 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4188
4189 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4190 return nb_cli_apply_changes(vty, NULL);
d37ba549 4191}
73ac8160 4192
38677473
SW
4193/*
4194 * Helper to handle the case of the user passing in a number or type string
4195 */
4196static const char *parse_evpn_rt_type(const char *num_rt_type)
4197{
4198 switch (num_rt_type[0]) {
4199 case '1':
4200 return "ead";
4201 case '2':
4202 return "macip";
4203 case '3':
4204 return "multicast";
4205 case '4':
4206 return "es";
4207 case '5':
4208 return "prefix";
4209 default:
4210 break;
4211 }
4212
4213 /* Was already full type string */
4214 return num_rt_type;
4215}
4216
48cb7ea9
SP
4217DEFUN_YANG (match_evpn_route_type,
4218 match_evpn_route_type_cmd,
2514d231 4219 "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4220 MATCH_STR
4221 EVPN_HELP_STR
4222 EVPN_TYPE_HELP_STR
bd44ab08
CS
4223 EVPN_TYPE_1_HELP_STR
4224 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4225 EVPN_TYPE_2_HELP_STR
4226 EVPN_TYPE_2_HELP_STR
4227 EVPN_TYPE_3_HELP_STR
4228 EVPN_TYPE_3_HELP_STR
2514d231
CS
4229 EVPN_TYPE_4_HELP_STR
4230 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4231 EVPN_TYPE_5_HELP_STR
4232 EVPN_TYPE_5_HELP_STR)
38677473 4233{
48cb7ea9
SP
4234 const char *xpath =
4235 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4236 char xpath_value[XPATH_MAXLEN];
33c2ff62 4237
48cb7ea9
SP
4238 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4239 snprintf(xpath_value, sizeof(xpath_value),
4240 "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4241 xpath);
4242 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4243 parse_evpn_rt_type(argv[3]->arg));
33c2ff62 4244
48cb7ea9
SP
4245 return nb_cli_apply_changes(vty, NULL);
4246}
4247
4248DEFUN_YANG (no_match_evpn_route_type,
4249 no_match_evpn_route_type_cmd,
2514d231 4250 "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4251 NO_STR
4252 MATCH_STR
4253 EVPN_HELP_STR
4254 EVPN_TYPE_HELP_STR
bd44ab08
CS
4255 EVPN_TYPE_1_HELP_STR
4256 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4257 EVPN_TYPE_2_HELP_STR
4258 EVPN_TYPE_2_HELP_STR
4259 EVPN_TYPE_3_HELP_STR
4260 EVPN_TYPE_3_HELP_STR
2514d231
CS
4261 EVPN_TYPE_4_HELP_STR
4262 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4263 EVPN_TYPE_5_HELP_STR
4264 EVPN_TYPE_5_HELP_STR)
16f7ce2b 4265{
48cb7ea9
SP
4266 const char *xpath =
4267 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4268
4269 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4270
4271 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4272}
4273
48cb7ea9
SP
4274
4275DEFUN_YANG (match_evpn_vni,
4276 match_evpn_vni_cmd,
4277 "match evpn vni " CMD_VNI_RANGE,
4278 MATCH_STR
4279 EVPN_HELP_STR
4280 "Match VNI\n"
4281 "VNI ID\n")
4282{
4283 const char *xpath =
4284 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
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:evpn-vni", xpath);
4290 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4291
4292 return nb_cli_apply_changes(vty, NULL);
4293}
4294
4295DEFUN_YANG (no_match_evpn_vni,
4296 no_match_evpn_vni_cmd,
4297 "no match evpn vni " CMD_VNI_RANGE,
4298 NO_STR
4299 MATCH_STR
4300 EVPN_HELP_STR
4301 "Match VNI\n"
4302 "VNI ID\n")
16f7ce2b 4303{
48cb7ea9
SP
4304 const char *xpath =
4305 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4306 char xpath_value[XPATH_MAXLEN];
4307
4308 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4309 snprintf(xpath_value, sizeof(xpath_value),
4310 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4311 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4312
4313 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4314}
4315
48cb7ea9
SP
4316DEFUN_YANG (match_evpn_default_route,
4317 match_evpn_default_route_cmd,
4318 "match evpn default-route",
4319 MATCH_STR
4320 EVPN_HELP_STR
4321 "default EVPN type-5 route\n")
6fb219da 4322{
48cb7ea9
SP
4323 const char *xpath =
4324 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4325 char xpath_value[XPATH_MAXLEN];
4326
4327 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4328
4329 snprintf(xpath_value, sizeof(xpath_value),
4330 "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4331 xpath);
4332 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4333
4334 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4335}
4336
48cb7ea9
SP
4337DEFUN_YANG (no_match_evpn_default_route,
4338 no_match_evpn_default_route_cmd,
4339 "no match evpn default-route",
4340 NO_STR
4341 MATCH_STR
4342 EVPN_HELP_STR
4343 "default EVPN type-5 route\n")
6fb219da 4344{
48cb7ea9
SP
4345 const char *xpath =
4346 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4347
4348 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4349
4350 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4351}
4352
48cb7ea9
SP
4353DEFUN_YANG (match_evpn_rd,
4354 match_evpn_rd_cmd,
4355 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4356 MATCH_STR
4357 EVPN_HELP_STR
4358 "Route Distinguisher\n"
4359 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4360{
48cb7ea9
SP
4361 const char *xpath =
4362 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4363 char xpath_value[XPATH_MAXLEN];
4364
4365 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4366 snprintf(
4367 xpath_value, sizeof(xpath_value),
4368 "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4369 xpath);
4370 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4371
4372 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4373}
4374
48cb7ea9
SP
4375DEFUN_YANG (no_match_evpn_rd,
4376 no_match_evpn_rd_cmd,
4377 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4378 NO_STR
4379 MATCH_STR
4380 EVPN_HELP_STR
4381 "Route Distinguisher\n"
4382 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4383{
48cb7ea9
SP
4384 const char *xpath =
4385 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4386
4387 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4388 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4389}
4390
d0a4ee60
AD
4391DEFUN_YANG (set_evpn_gw_ip_ipv4,
4392 set_evpn_gw_ip_ipv4_cmd,
4393 "set evpn gateway-ip ipv4 A.B.C.D",
4394 SET_STR
4395 EVPN_HELP_STR
4396 "Set gateway IP for prefix advertisement route\n"
4397 "IPv4 address\n"
4398 "Gateway IP address in IPv4 format\n")
4399{
4400 int ret;
4401 union sockunion su;
4402 const char *xpath =
4403 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4404 char xpath_value[XPATH_MAXLEN];
4405
4406 ret = str2sockunion(argv[4]->arg, &su);
4407 if (ret < 0) {
4408 vty_out(vty, "%% Malformed gateway IP\n");
4409 return CMD_WARNING_CONFIG_FAILED;
4410 }
4411
e24a6977
DA
4412 if (su.sin.sin_addr.s_addr == 0 ||
4413 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4414 vty_out(vty,
4415 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4416 return CMD_WARNING_CONFIG_FAILED;
4417 }
4418
4419 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4420
4421 snprintf(xpath_value, sizeof(xpath_value),
4422 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4423 xpath);
4424
4425 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4426 return nb_cli_apply_changes(vty, NULL);
4427}
4428
4429DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4430 no_set_evpn_gw_ip_ipv4_cmd,
4431 "no set evpn gateway-ip ipv4 A.B.C.D",
4432 NO_STR
4433 SET_STR
4434 EVPN_HELP_STR
4435 "Set gateway IP for prefix advertisement route\n"
4436 "IPv4 address\n"
4437 "Gateway IP address in IPv4 format\n")
4438{
4439 int ret;
4440 union sockunion su;
4441 const char *xpath =
4442 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4443
4444 ret = str2sockunion(argv[5]->arg, &su);
4445 if (ret < 0) {
4446 vty_out(vty, "%% Malformed gateway IP\n");
4447 return CMD_WARNING_CONFIG_FAILED;
4448 }
4449
e24a6977
DA
4450 if (su.sin.sin_addr.s_addr == 0 ||
4451 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4452 vty_out(vty,
4453 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4454 return CMD_WARNING_CONFIG_FAILED;
4455 }
4456
4457 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4458
4459 return nb_cli_apply_changes(vty, NULL);
4460}
4461
4462DEFUN_YANG (set_evpn_gw_ip_ipv6,
4463 set_evpn_gw_ip_ipv6_cmd,
4464 "set evpn gateway-ip ipv6 X:X::X:X",
4465 SET_STR
4466 EVPN_HELP_STR
4467 "Set gateway IP for prefix advertisement route\n"
4468 "IPv6 address\n"
4469 "Gateway IP address in IPv6 format\n")
4470{
4471 int ret;
4472 union sockunion su;
4473 const char *xpath =
4474 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4475 char xpath_value[XPATH_MAXLEN];
4476
4477 ret = str2sockunion(argv[4]->arg, &su);
4478 if (ret < 0) {
4479 vty_out(vty, "%% Malformed gateway IP\n");
4480 return CMD_WARNING_CONFIG_FAILED;
4481 }
4482
4483 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4484 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4485 vty_out(vty,
4486 "%% Gateway IP cannot be a linklocal or multicast address\n");
4487 return CMD_WARNING_CONFIG_FAILED;
4488 }
4489
4490 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4491
4492 snprintf(xpath_value, sizeof(xpath_value),
4493 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4494 xpath);
4495
4496 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4497 return nb_cli_apply_changes(vty, NULL);
4498}
4499
4500DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4501 no_set_evpn_gw_ip_ipv6_cmd,
4502 "no set evpn gateway-ip ipv6 X:X::X:X",
4503 NO_STR
4504 SET_STR
4505 EVPN_HELP_STR
4506 "Set gateway IP for prefix advertisement route\n"
4507 "IPv4 address\n"
4508 "Gateway IP address in IPv4 format\n")
4509{
4510 int ret;
4511 union sockunion su;
4512 const char *xpath =
4513 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4514
4515 ret = str2sockunion(argv[5]->arg, &su);
4516 if (ret < 0) {
4517 vty_out(vty, "%% Malformed gateway IP\n");
4518 return CMD_WARNING_CONFIG_FAILED;
4519 }
4520
4521 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4522 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4523 vty_out(vty,
4524 "%% Gateway IP cannot be a linklocal or multicast address\n");
4525 return CMD_WARNING_CONFIG_FAILED;
4526 }
4527
4528 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4529
4530 return nb_cli_apply_changes(vty, NULL);
4531}
4532
48cb7ea9 4533DEFPY_YANG(match_vrl_source_vrf,
1dcc9e5b
CS
4534 match_vrl_source_vrf_cmd,
4535 "match source-vrf NAME$vrf_name",
4536 MATCH_STR
4537 "source vrf\n"
4538 "The VRF name\n")
4539{
48cb7ea9
SP
4540 const char *xpath =
4541 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4542 char xpath_value[XPATH_MAXLEN];
4543
4544 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4545 snprintf(xpath_value, sizeof(xpath_value),
4546 "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4547 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4548
4549 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4550}
4551
48cb7ea9 4552DEFPY_YANG(no_match_vrl_source_vrf,
1dcc9e5b
CS
4553 no_match_vrl_source_vrf_cmd,
4554 "no match source-vrf NAME$vrf_name",
48cb7ea9 4555 NO_STR MATCH_STR
1dcc9e5b
CS
4556 "source vrf\n"
4557 "The VRF name\n")
4558{
48cb7ea9
SP
4559 const char *xpath =
4560 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4561
4562 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4563 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4564}
4565
48cb7ea9 4566DEFPY_YANG (match_peer,
fee0f4c6 4567 match_peer_cmd,
48cb7ea9 4568 "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
fee0f4c6 4569 MATCH_STR
4570 "Match peer address\n"
6e13ed4a 4571 "IP address of peer\n"
8c3433e4 4572 "IPv6 address of peer\n"
1bb1c0cf 4573 "Interface name of peer or peer group name\n")
fee0f4c6 4574{
48cb7ea9
SP
4575 const char *xpath =
4576 "./match-condition[condition='frr-bgp-route-map:peer']";
4577 char xpath_value[XPATH_MAXLEN];
4578
4579 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4580
4581 if (addrv4_str) {
4582 snprintf(
4583 xpath_value, sizeof(xpath_value),
4584 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4585 xpath);
4586 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4587 addrv4_str);
4588 } else if (addrv6_str) {
4589 snprintf(
4590 xpath_value, sizeof(xpath_value),
4591 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4592 xpath);
4593 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4594 addrv6_str);
4595 } else {
4596 snprintf(
4597 xpath_value, sizeof(xpath_value),
4598 "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4599 xpath);
4600 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4601 }
4602
4603 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4604}
4605
48cb7ea9
SP
4606DEFUN_YANG (match_peer_local,
4607 match_peer_local_cmd,
4608 "match peer local",
4609 MATCH_STR
4610 "Match peer address\n"
4611 "Static or Redistributed routes\n")
fee0f4c6 4612{
48cb7ea9
SP
4613 const char *xpath =
4614 "./match-condition[condition='frr-bgp-route-map:peer']";
4615 char xpath_value[XPATH_MAXLEN];
4616
4617 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4618
4619 snprintf(xpath_value, sizeof(xpath_value),
4620 "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4621 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4622
4623 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4624}
4625
48cb7ea9
SP
4626DEFUN_YANG (no_match_peer,
4627 no_match_peer_cmd,
4628 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4629 NO_STR
4630 MATCH_STR
4631 "Match peer address\n"
4632 "Static or Redistributed routes\n"
4633 "IP address of peer\n"
4634 "IPv6 address of peer\n"
4635 "Interface name of peer\n")
fee0f4c6 4636{
48cb7ea9
SP
4637 const char *xpath =
4638 "./match-condition[condition='frr-bgp-route-map:peer']";
4639
4640 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4c9bd275 4641
48cb7ea9 4642 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4643}
4644
fa22080d 4645#ifdef HAVE_SCRIPTING
48cb7ea9
SP
4646DEFUN_YANG (match_script,
4647 match_script_cmd,
4648 "[no] match script WORD",
4649 NO_STR
4650 MATCH_STR
4651 "Execute script to determine match\n"
4652 "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
1d7c7ace 4653{
b4becb06
QY
4654 bool no = strmatch(argv[0]->text, "no");
4655 int i = 0;
4656 argv_find(argv, argc, "WORD", &i);
4657 const char *script = argv[i]->arg;
48cb7ea9
SP
4658 const char *xpath =
4659 "./match-condition[condition='frr-bgp-route-map:match-script']";
4660 char xpath_value[XPATH_MAXLEN];
b4becb06
QY
4661
4662 if (no) {
48cb7ea9
SP
4663 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4664 snprintf(xpath_value, sizeof(xpath_value),
4665 "%s/rmap-match-condition/frr-bgp-route-map:script",
4666 xpath);
4667 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4668 script);
4669
4670 return nb_cli_apply_changes(vty, NULL);
b4becb06 4671 }
48cb7ea9
SP
4672
4673 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4674 snprintf(xpath_value, sizeof(xpath_value),
4675 "%s/rmap-match-condition/frr-bgp-route-map:script",
4676 xpath);
4677 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4678 script);
4679
4680 return nb_cli_apply_changes(vty, NULL);
1d7c7ace 4681}
fa22080d 4682#endif /* HAVE_SCRIPTING */
fee0f4c6 4683
4c9bd275 4684/* match probability */
48cb7ea9
SP
4685DEFUN_YANG (match_probability,
4686 match_probability_cmd,
4687 "match probability (0-100)",
4688 MATCH_STR
4689 "Match portion of routes defined by percentage value\n"
4690 "Percentage of routes\n")
1add115a 4691{
d62a17ae 4692 int idx_number = 2;
48cb7ea9
SP
4693
4694 const char *xpath =
4695 "./match-condition[condition='frr-bgp-route-map:probability']";
4696 char xpath_value[XPATH_MAXLEN];
4697
4698 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4699 snprintf(xpath_value, sizeof(xpath_value),
4700 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4701 xpath);
4702 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4703 argv[idx_number]->arg);
4704
4705 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4706}
4707
4c9bd275 4708
48cb7ea9
SP
4709DEFUN_YANG (no_match_probability,
4710 no_match_probability_cmd,
4711 "no match probability [(1-99)]",
4712 NO_STR
4713 MATCH_STR
4714 "Match portion of routes defined by percentage value\n"
4715 "Percentage of routes\n")
1add115a 4716{
d62a17ae 4717 int idx_number = 3;
48cb7ea9
SP
4718 const char *xpath =
4719 "./match-condition[condition='frr-bgp-route-map:probability']";
4720 char xpath_value[XPATH_MAXLEN];
4721
4722 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4723
d62a17ae 4724 if (argc <= idx_number)
48cb7ea9
SP
4725 return nb_cli_apply_changes(vty, NULL);
4726
4727 snprintf(xpath_value, sizeof(xpath_value),
4728 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4729 xpath);
4730 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4731 argv[idx_number]->arg);
4732
4733 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4734}
4735
1add115a 4736
48cb7ea9 4737DEFPY_YANG (match_ip_route_source,
c1643bb7 4738 match_ip_route_source_cmd,
c60dec36 4739 "match ip route-source ACCESSLIST4_NAME",
c1643bb7 4740 MATCH_STR
4741 IP_STR
4742 "Match advertising source address of route\n"
7e869991 4743 "IP Access-list name\n")
c1643bb7 4744{
48cb7ea9
SP
4745 const char *xpath =
4746 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4747 char xpath_value[XPATH_MAXLEN + 32];
d62a17ae 4748 int idx_acl = 3;
48cb7ea9
SP
4749
4750 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4751 snprintf(xpath_value, sizeof(xpath_value),
4752 "%s/rmap-match-condition/frr-bgp-route-map:list-name",
4753 xpath);
4754 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4755 argv[idx_acl]->arg);
4756
4757 return nb_cli_apply_changes(vty, NULL);
c1643bb7 4758}
4759
4c9bd275 4760
48cb7ea9
SP
4761DEFUN_YANG (no_match_ip_route_source,
4762 no_match_ip_route_source_cmd,
c60dec36 4763 "no match ip route-source [ACCESSLIST4_NAME]",
48cb7ea9
SP
4764 NO_STR
4765 MATCH_STR
4766 IP_STR
4767 "Match advertising source address of route\n"
7e869991 4768 "IP Access-list name\n")
c1643bb7 4769{
48cb7ea9
SP
4770 const char *xpath =
4771 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
c1643bb7 4772
48cb7ea9
SP
4773 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4774 return nb_cli_apply_changes(vty, NULL);
4775}
c1643bb7 4776
48cb7ea9
SP
4777DEFUN_YANG (match_ip_route_source_prefix_list,
4778 match_ip_route_source_prefix_list_cmd,
943224a1 4779 "match ip route-source prefix-list PREFIXLIST_NAME",
48cb7ea9
SP
4780 MATCH_STR
4781 IP_STR
4782 "Match advertising source address of route\n"
4783 "Match entries of prefix-lists\n"
4784 "IP prefix-list name\n")
c1643bb7 4785{
d62a17ae 4786 int idx_word = 4;
48cb7ea9
SP
4787 const char *xpath =
4788 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4789 char xpath_value[XPATH_MAXLEN + 32];
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:list-name", xpath);
4794 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4795 argv[idx_word]->arg);
4796
4797 return nb_cli_apply_changes(vty, NULL);
c1643bb7 4798}
4799
4c9bd275 4800
48cb7ea9
SP
4801DEFUN_YANG (no_match_ip_route_source_prefix_list,
4802 no_match_ip_route_source_prefix_list_cmd,
943224a1 4803 "no match ip route-source prefix-list [PREFIXLIST_NAME]",
48cb7ea9
SP
4804 NO_STR
4805 MATCH_STR
4806 IP_STR
4807 "Match advertising source address of route\n"
4808 "Match entries of prefix-lists\n"
4809 "IP prefix-list name\n")
c1643bb7 4810{
48cb7ea9
SP
4811 const char *xpath =
4812 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
c1643bb7 4813
48cb7ea9
SP
4814 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4815 return nb_cli_apply_changes(vty, NULL);
4816}
c1643bb7 4817
48cb7ea9
SP
4818DEFUN_YANG (match_local_pref,
4819 match_local_pref_cmd,
4820 "match local-preference (0-4294967295)",
4821 MATCH_STR
4822 "Match local-preference of route\n"
4823 "Metric value\n")
af291c15 4824{
d62a17ae 4825 int idx_number = 2;
48cb7ea9
SP
4826
4827 const char *xpath =
4828 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
4829 char xpath_value[XPATH_MAXLEN];
4830
4831 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4832 snprintf(xpath_value, sizeof(xpath_value),
4833 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
4834 xpath);
4835 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4836 argv[idx_number]->arg);
4837
4838 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
4839}
4840
4c9bd275 4841
48cb7ea9
SP
4842DEFUN_YANG (no_match_local_pref,
4843 no_match_local_pref_cmd,
4844 "no match local-preference [(0-4294967295)]",
4845 NO_STR
4846 MATCH_STR
4847 "Match local preference of route\n"
4848 "Local preference value\n")
af291c15 4849{
d62a17ae 4850 int idx_localpref = 3;
48cb7ea9
SP
4851 const char *xpath =
4852 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
4853 char xpath_value[XPATH_MAXLEN];
4854
4855 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4856
d62a17ae 4857 if (argc <= idx_localpref)
48cb7ea9
SP
4858 return nb_cli_apply_changes(vty, NULL);
4859
4860 snprintf(xpath_value, sizeof(xpath_value),
4861 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
4862 xpath);
4863 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4864 argv[idx_localpref]->arg);
4865
4866 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
4867}
4868
2690f18c
DA
4869DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
4870 MATCH_STR
4871 "Match BGP community alias name\n"
4872 "BGP community alias name\n")
4873{
4874 const char *alias = argv[2]->arg;
4875 struct community_alias ca1;
4876 struct community_alias *lookup_alias;
4877
4878 const char *xpath =
4879 "./match-condition[condition='frr-bgp-route-map:match-alias']";
4880 char xpath_value[XPATH_MAXLEN];
4881
4882 memset(&ca1, 0, sizeof(ca1));
4883 strlcpy(ca1.alias, alias, sizeof(ca1.alias));
4884 lookup_alias = bgp_ca_alias_lookup(&ca1);
4885 if (!lookup_alias) {
4886 vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
4887 return CMD_WARNING_CONFIG_FAILED;
4888 }
4889
4890 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4891 snprintf(xpath_value, sizeof(xpath_value),
4892 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
4893 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
4894
4895 return nb_cli_apply_changes(vty, NULL);
4896}
4897
4898
4899DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
4900 NO_STR MATCH_STR
4901 "Match BGP community alias name\n"
4902 "BGP community alias name\n")
4903{
4904 int idx_alias = 3;
4905 const char *xpath =
4906 "./match-condition[condition='frr-bgp-route-map:match-alias']";
4907 char xpath_value[XPATH_MAXLEN];
4908
4909 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4910
4911 if (argc <= idx_alias)
4912 return nb_cli_apply_changes(vty, NULL);
4913
4914 snprintf(xpath_value, sizeof(xpath_value),
4915 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
4916 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4917 argv[idx_alias]->arg);
4918
4919 return nb_cli_apply_changes(vty, NULL);
4920}
af291c15 4921
48cb7ea9 4922DEFPY_YANG (match_community,
718e3744 4923 match_community_cmd,
a2099c1d 4924 "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
718e3744 4925 MATCH_STR
4926 "Match BGP community list\n"
4927 "Community-list number (standard)\n"
4928 "Community-list number (expanded)\n"
4929 "Community-list name\n"
4930 "Do exact matching of communities\n")
4931{
48cb7ea9
SP
4932 const char *xpath =
4933 "./match-condition[condition='frr-bgp-route-map:match-community']";
4934 char xpath_value[XPATH_MAXLEN];
4935 char xpath_match[XPATH_MAXLEN];
d62a17ae 4936 int idx_comm_list = 2;
718e3744 4937
48cb7ea9 4938 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 4939
48cb7ea9
SP
4940 snprintf(
4941 xpath_value, sizeof(xpath_value),
4942 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
4943 xpath);
4944 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
718e3744 4945
48cb7ea9
SP
4946 if (argc == 4) {
4947 snprintf(
4948 xpath_match, sizeof(xpath_match),
4949 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
4950 xpath);
4951 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
4952 "true");
4953 } else {
4954 snprintf(
4955 xpath_match, sizeof(xpath_match),
4956 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
4957 xpath);
4958 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
4959 "false");
4960 }
718e3744 4961
48cb7ea9
SP
4962 return nb_cli_apply_changes(vty, NULL);
4963}
4964
4965DEFUN_YANG (no_match_community,
4966 no_match_community_cmd,
a2099c1d 4967 "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
4968 NO_STR
4969 MATCH_STR
4970 "Match BGP community list\n"
4971 "Community-list number (standard)\n"
4972 "Community-list number (expanded)\n"
4973 "Community-list name\n"
4974 "Do exact matching of communities\n")
4975{
4976 const char *xpath =
4977 "./match-condition[condition='frr-bgp-route-map:match-community']";
4978
4979 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4980 return nb_cli_apply_changes(vty, NULL);
4981}
4982
4983DEFPY_YANG (match_lcommunity,
4984 match_lcommunity_cmd,
a2099c1d 4985 "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
48cb7ea9
SP
4986 MATCH_STR
4987 "Match BGP large community list\n"
4988 "Large Community-list number (standard)\n"
4989 "Large Community-list number (expanded)\n"
4990 "Large Community-list name\n"
4991 "Do exact matching of communities\n")
4992{
4993 const char *xpath =
4994 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
4995 char xpath_value[XPATH_MAXLEN];
4996 char xpath_match[XPATH_MAXLEN];
03ff9a14 4997 int idx_lcomm_list = 2;
03ff9a14 4998
48cb7ea9 4999 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
03ff9a14 5000
48cb7ea9
SP
5001 snprintf(
5002 xpath_value, sizeof(xpath_value),
5003 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5004 xpath);
5005 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
03ff9a14 5006
48cb7ea9
SP
5007 if (argc == 4) {
5008 snprintf(
5009 xpath_match, sizeof(xpath_match),
5010 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5011 xpath);
5012 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5013 "true");
5014 } else {
5015 snprintf(
5016 xpath_match, sizeof(xpath_match),
5017 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5018 xpath);
5019 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5020 "false");
5021 }
03ff9a14 5022
48cb7ea9 5023 return nb_cli_apply_changes(vty, NULL);
57d187bc 5024}
718e3744 5025
48cb7ea9
SP
5026DEFUN_YANG (no_match_lcommunity,
5027 no_match_lcommunity_cmd,
a2099c1d 5028 "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
5029 NO_STR
5030 MATCH_STR
5031 "Match BGP large community list\n"
5032 "Large Community-list number (standard)\n"
5033 "Large Community-list number (expanded)\n"
5034 "Large Community-list name\n"
5035 "Do exact matching of communities\n")
57d187bc 5036{
48cb7ea9
SP
5037 const char *xpath =
5038 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5039
5040 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5041 return nb_cli_apply_changes(vty, NULL);
57d187bc 5042}
718e3744 5043
48cb7ea9
SP
5044DEFPY_YANG (match_ecommunity,
5045 match_ecommunity_cmd,
a2099c1d 5046 "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
48cb7ea9
SP
5047 MATCH_STR
5048 "Match BGP/VPN extended community list\n"
5049 "Extended community-list number (standard)\n"
5050 "Extended community-list number (expanded)\n"
5051 "Extended community-list name\n")
73ffb25b 5052{
48cb7ea9
SP
5053 const char *xpath =
5054 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5055 char xpath_value[XPATH_MAXLEN];
d62a17ae 5056 int idx_comm_list = 2;
48cb7ea9
SP
5057
5058 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5059
5060 snprintf(
5061 xpath_value, sizeof(xpath_value),
5062 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5063 xpath);
5064 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5065
5066 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5067}
5068
4c9bd275 5069
48cb7ea9
SP
5070DEFUN_YANG (no_match_ecommunity,
5071 no_match_ecommunity_cmd,
a2099c1d 5072 "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
48cb7ea9
SP
5073 NO_STR
5074 MATCH_STR
5075 "Match BGP/VPN extended community list\n"
5076 "Extended community-list number (standard)\n"
5077 "Extended community-list number (expanded)\n"
5078 "Extended community-list name\n")
73ffb25b 5079{
48cb7ea9
SP
5080 const char *xpath =
5081 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5082
5083 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5084 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5085}
5086
73ffb25b 5087
48cb7ea9
SP
5088DEFUN_YANG (match_aspath,
5089 match_aspath_cmd,
2a342b35 5090 "match as-path AS_PATH_FILTER_NAME",
48cb7ea9
SP
5091 MATCH_STR
5092 "Match BGP AS path list\n"
5093 "AS path access-list name\n")
718e3744 5094{
d62a17ae 5095 int idx_word = 2;
48cb7ea9
SP
5096
5097 const char *xpath =
5098 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5099 char xpath_value[XPATH_MAXLEN];
5100
5101 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5102 snprintf(xpath_value, sizeof(xpath_value),
5103 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5104 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5105 argv[idx_word]->arg);
5106
5107 return nb_cli_apply_changes(vty, NULL);
718e3744 5108}
5109
4c9bd275 5110
48cb7ea9
SP
5111DEFUN_YANG (no_match_aspath,
5112 no_match_aspath_cmd,
2a342b35 5113 "no match as-path [AS_PATH_FILTER_NAME]",
48cb7ea9
SP
5114 NO_STR
5115 MATCH_STR
5116 "Match BGP AS path list\n"
5117 "AS path access-list name\n")
718e3744 5118{
48cb7ea9
SP
5119 const char *xpath =
5120 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
718e3744 5121
48cb7ea9 5122 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
718e3744 5123
48cb7ea9
SP
5124 return nb_cli_apply_changes(vty, NULL);
5125}
5126
5127DEFUN_YANG (match_origin,
5128 match_origin_cmd,
5129 "match origin <egp|igp|incomplete>",
5130 MATCH_STR
5131 "BGP origin code\n"
5132 "remote EGP\n"
5133 "local IGP\n"
5134 "unknown heritage\n")
718e3744 5135{
d62a17ae 5136 int idx_origin = 2;
48cb7ea9
SP
5137 const char *origin_type;
5138 const char *xpath =
5139 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5140 char xpath_value[XPATH_MAXLEN];
5141
d62a17ae 5142 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
48cb7ea9
SP
5143 origin_type = "igp";
5144 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5145 origin_type = "egp";
5146 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5147 origin_type = "incomplete";
5148 else {
5149 vty_out(vty, "%% Invalid match origin type\n");
5150 return CMD_WARNING_CONFIG_FAILED;
5151 }
5152
5153 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5154 snprintf(xpath_value, sizeof(xpath_value),
5155 "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5156 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
718e3744 5157
48cb7ea9 5158 return nb_cli_apply_changes(vty, NULL);
718e3744 5159}
5160
4c9bd275 5161
48cb7ea9
SP
5162DEFUN_YANG (no_match_origin,
5163 no_match_origin_cmd,
5164 "no match origin [<egp|igp|incomplete>]",
5165 NO_STR
5166 MATCH_STR
5167 "BGP origin code\n"
5168 "remote EGP\n"
5169 "local IGP\n"
5170 "unknown heritage\n")
718e3744 5171{
48cb7ea9
SP
5172 const char *xpath =
5173 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5174 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5175 return nb_cli_apply_changes(vty, NULL);
718e3744 5176}
5177
48cb7ea9
SP
5178DEFUN_YANG (set_table_id,
5179 set_table_id_cmd,
5180 "set table (1-4294967295)",
5181 SET_STR
5182 "export route to non-main kernel table\n"
5183 "Kernel routing table id\n")
951745bd 5184{
48cb7ea9
SP
5185 int idx_number = 2;
5186 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5187 char xpath_value[XPATH_MAXLEN];
5188
5189 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5190 snprintf(xpath_value, sizeof(xpath_value),
5191 "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5192 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5193 argv[idx_number]->arg);
5194 return nb_cli_apply_changes(vty, NULL);
5195}
5196
5197DEFUN_YANG (no_set_table_id,
5198 no_set_table_id_cmd,
5199 "no set table",
5200 NO_STR
5201 SET_STR
5202 "export route to non-main kernel table\n")
5203{
5204 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5205 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5206 return nb_cli_apply_changes(vty, NULL);
5207}
5208
5209DEFUN_YANG (set_ip_nexthop_peer,
5210 set_ip_nexthop_peer_cmd,
5211 "[no] set ip next-hop peer-address",
5212 NO_STR
5213 SET_STR
5214 IP_STR
5215 "Next hop address\n"
5216 "Use peer address (for BGP only)\n")
5217{
5218 char xpath_value[XPATH_MAXLEN];
5219 const char *xpath =
5220 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5221
5222 if (strmatch(argv[0]->text, "no"))
5223 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5224 else {
5225 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5226 snprintf(xpath_value, sizeof(xpath_value),
5227 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5228 xpath);
5229 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5230 "peer-address");
5231 }
5232 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5233}
5234
48cb7ea9
SP
5235DEFUN_YANG (set_ip_nexthop_unchanged,
5236 set_ip_nexthop_unchanged_cmd,
5237 "[no] set ip next-hop unchanged",
5238 NO_STR
5239 SET_STR
5240 IP_STR
5241 "Next hop address\n"
5242 "Don't modify existing Next hop address\n")
951745bd 5243{
48cb7ea9
SP
5244 char xpath_value[XPATH_MAXLEN];
5245 const char *xpath =
5246 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
951745bd 5247
48cb7ea9
SP
5248 if (strmatch(argv[0]->text, "no"))
5249 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5250 else {
5251 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5252 snprintf(xpath_value, sizeof(xpath_value),
5253 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5254 xpath);
5255 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5256 "unchanged");
5257 }
5258 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5259}
5260
48cb7ea9
SP
5261DEFUN_YANG (set_distance,
5262 set_distance_cmd,
5263 "set distance (0-255)",
5264 SET_STR
5265 "BGP Administrative Distance to use\n"
5266 "Distance value\n")
af5cd0a5 5267{
48cb7ea9
SP
5268 int idx_number = 2;
5269 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5270 char xpath_value[XPATH_MAXLEN];
89602edb 5271
48cb7ea9
SP
5272 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5273 snprintf(xpath_value, sizeof(xpath_value),
5274 "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5275 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5276 argv[idx_number]->arg);
5277 return nb_cli_apply_changes(vty, NULL);
af5cd0a5 5278}
5279
48cb7ea9
SP
5280DEFUN_YANG (no_set_distance,
5281 no_set_distance_cmd,
5282 "no set distance [(0-255)]",
5283 NO_STR SET_STR
5284 "BGP Administrative Distance to use\n"
5285 "Distance value\n")
316e074d 5286{
48cb7ea9 5287 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
cca30ba8 5288
48cb7ea9
SP
5289 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5290 return nb_cli_apply_changes(vty, NULL);
718e3744 5291}
5292
48cb7ea9
SP
5293DEFUN_YANG (set_local_pref,
5294 set_local_pref_cmd,
5295 "set local-preference WORD",
5296 SET_STR
5297 "BGP local preference path attribute\n"
5298 "Preference value (0-4294967295)\n")
7b7d48e5
DS
5299{
5300 int idx_number = 2;
48cb7ea9
SP
5301 const char *xpath =
5302 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5303 char xpath_value[XPATH_MAXLEN];
7b7d48e5 5304
48cb7ea9
SP
5305 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5306 snprintf(xpath_value, sizeof(xpath_value),
5307 "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5308 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5309 argv[idx_number]->arg);
5310 return nb_cli_apply_changes(vty, NULL);
7b7d48e5
DS
5311}
5312
48cb7ea9
SP
5313DEFUN_YANG (no_set_local_pref,
5314 no_set_local_pref_cmd,
5315 "no set local-preference [WORD]",
5316 NO_STR
5317 SET_STR
5318 "BGP local preference path attribute\n"
5319 "Preference value (0-4294967295)\n")
7b7d48e5 5320{
48cb7ea9
SP
5321 const char *xpath =
5322 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5323
5324 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5325 return nb_cli_apply_changes(vty, NULL);
7b7d48e5 5326}
718e3744 5327
48cb7ea9
SP
5328DEFUN_YANG (set_weight,
5329 set_weight_cmd,
5330 "set weight (0-4294967295)",
5331 SET_STR
5332 "BGP weight for routing table\n"
5333 "Weight value\n")
718e3744 5334{
d62a17ae 5335 int idx_number = 2;
48cb7ea9
SP
5336 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5337 char xpath_value[XPATH_MAXLEN];
4c9bd275 5338
48cb7ea9
SP
5339 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5340 snprintf(xpath_value, sizeof(xpath_value),
5341 "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5342 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5343 argv[idx_number]->arg);
5344 return nb_cli_apply_changes(vty, NULL);
718e3744 5345}
5346
48cb7ea9
SP
5347DEFUN_YANG (no_set_weight,
5348 no_set_weight_cmd,
5349 "no set weight [(0-4294967295)]",
5350 NO_STR
5351 SET_STR
5352 "BGP weight for routing table\n"
5353 "Weight value\n")
718e3744 5354{
48cb7ea9 5355 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
718e3744 5356
48cb7ea9
SP
5357 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5358 return nb_cli_apply_changes(vty, NULL);
718e3744 5359}
5360
48cb7ea9
SP
5361DEFUN_YANG (set_label_index,
5362 set_label_index_cmd,
5363 "set label-index (0-1048560)",
5364 SET_STR
5365 "Label index to associate with the prefix\n"
5366 "Label index value\n")
d990e384 5367{
d62a17ae 5368 int idx_number = 2;
48cb7ea9
SP
5369 const char *xpath =
5370 "./set-action[action='frr-bgp-route-map:label-index']";
5371 char xpath_value[XPATH_MAXLEN];
5372
5373 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5374 snprintf(xpath_value, sizeof(xpath_value),
5375 "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5376 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5377 argv[idx_number]->arg);
5378 return nb_cli_apply_changes(vty, NULL);
d990e384
DS
5379}
5380
48cb7ea9
SP
5381DEFUN_YANG (no_set_label_index,
5382 no_set_label_index_cmd,
5383 "no set label-index [(0-1048560)]",
5384 NO_STR
5385 SET_STR
5386 "Label index to associate with the prefix\n"
5387 "Label index value\n")
d990e384 5388{
48cb7ea9
SP
5389 const char *xpath =
5390 "./set-action[action='frr-bgp-route-map:label-index']";
5391
5392 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5393 return nb_cli_apply_changes(vty, NULL);
d990e384 5394}
718e3744 5395
48cb7ea9
SP
5396DEFUN_YANG (set_aspath_prepend_asn,
5397 set_aspath_prepend_asn_cmd,
5398 "set as-path prepend (1-4294967295)...",
5399 SET_STR
5400 "Transform BGP AS_PATH attribute\n"
5401 "Prepend to the as-path\n"
5402 "AS number\n")
718e3744 5403{
d62a17ae 5404 int idx_asn = 3;
5405 int ret;
5406 char *str;
718e3744 5407
d62a17ae 5408 str = argv_concat(argv, argc, idx_asn);
718e3744 5409
48cb7ea9
SP
5410 const char *xpath =
5411 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5412 char xpath_value[XPATH_MAXLEN];
5413
5414 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5415 snprintf(xpath_value, sizeof(xpath_value),
5416 "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5417 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5418 ret = nb_cli_apply_changes(vty, NULL);
5419 XFREE(MTYPE_TMP, str);
d62a17ae 5420 return ret;
718e3744 5421}
5422
48cb7ea9
SP
5423DEFUN_YANG (set_aspath_prepend_lastas,
5424 set_aspath_prepend_lastas_cmd,
5425 "set as-path prepend last-as (1-10)",
5426 SET_STR
5427 "Transform BGP AS_PATH attribute\n"
5428 "Prepend to the as-path\n"
6ba0adac 5429 "Use the last AS-number in the as-path\n"
48cb7ea9 5430 "Number of times to insert\n")
12dcf78e 5431{
48cb7ea9
SP
5432 int idx_num = 4;
5433
5434 const char *xpath =
5435 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5436 char xpath_value[XPATH_MAXLEN];
5437
5438 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5439 snprintf(xpath_value, sizeof(xpath_value),
5440 "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5441 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5442 argv[idx_num]->arg);
5443 return nb_cli_apply_changes(vty, NULL);
12dcf78e 5444}
bc3dd427 5445
77e3d821
DA
5446DEFPY_YANG (set_aspath_replace_asn,
5447 set_aspath_replace_asn_cmd,
5448 "set as-path replace <any|(1-4294967295)>$replace",
5449 SET_STR
5450 "Transform BGP AS_PATH attribute\n"
5451 "Replace AS number to local AS number\n"
5452 "Replace any AS number to local AS number\n"
5453 "Replace a specific AS number to local AS number\n")
5454{
5455 const char *xpath =
5456 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5457 char xpath_value[XPATH_MAXLEN];
5458
5459 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5460 snprintf(xpath_value, sizeof(xpath_value),
5461 "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5462 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5463 return nb_cli_apply_changes(vty, NULL);
5464}
5465
5466DEFPY_YANG (no_set_aspath_replace_asn,
5467 no_set_aspath_replace_asn_cmd,
5468 "no set as-path replace [<any|(1-4294967295)>]",
5469 NO_STR
5470 SET_STR
5471 "Transform BGP AS_PATH attribute\n"
5472 "Replace AS number to local AS number\n"
5473 "Replace any AS number to local AS number\n"
5474 "Replace a specific AS number to local AS number\n")
5475{
5476 const char *xpath =
5477 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5478
5479 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5480 return nb_cli_apply_changes(vty, NULL);
5481}
5482
48cb7ea9
SP
5483DEFUN_YANG (no_set_aspath_prepend,
5484 no_set_aspath_prepend_cmd,
5485 "no set as-path prepend [(1-4294967295)]",
5486 NO_STR
5487 SET_STR
5488 "Transform BGP AS_PATH attribute\n"
5489 "Prepend to the as-path\n"
5490 "AS number\n")
718e3744 5491{
48cb7ea9
SP
5492 const char *xpath =
5493 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
a7f93f3e 5494
48cb7ea9
SP
5495 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5496 return nb_cli_apply_changes(vty, NULL);
718e3744 5497}
5498
48cb7ea9
SP
5499DEFUN_YANG (no_set_aspath_prepend_lastas,
5500 no_set_aspath_prepend_lastas_cmd,
5501 "no set as-path prepend last-as [(1-10)]",
5502 NO_STR
5503 SET_STR
5504 "Transform BGP AS_PATH attribute\n"
5505 "Prepend to the as-path\n"
5506 "Use the peers AS-number\n"
5507 "Number of times to insert\n")
9131e6e8 5508{
48cb7ea9
SP
5509 const char *xpath =
5510 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5511
5512 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5513 return nb_cli_apply_changes(vty, NULL);
9131e6e8 5514}
718e3744 5515
48cb7ea9
SP
5516DEFUN_YANG (set_aspath_exclude,
5517 set_aspath_exclude_cmd,
5518 "set as-path exclude (1-4294967295)...",
5519 SET_STR
5520 "Transform BGP AS-path attribute\n"
5521 "Exclude from the as-path\n"
5522 "AS number\n")
841f7a57 5523{
d62a17ae 5524 int idx_asn = 3;
5525 int ret;
5526 char *str;
841f7a57 5527
d62a17ae 5528 str = argv_concat(argv, argc, idx_asn);
48cb7ea9
SP
5529
5530 const char *xpath =
5531 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5532 char xpath_value[XPATH_MAXLEN];
5533
5534 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5535 snprintf(xpath_value, sizeof(xpath_value),
5536 "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5537 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5538 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5539 XFREE(MTYPE_TMP, str);
5540 return ret;
841f7a57
DO
5541}
5542
48cb7ea9
SP
5543DEFUN_YANG (no_set_aspath_exclude,
5544 no_set_aspath_exclude_cmd,
5545 "no set as-path exclude (1-4294967295)...",
5546 NO_STR
5547 SET_STR
5548 "Transform BGP AS_PATH attribute\n"
5549 "Exclude from the as-path\n"
5550 "AS number\n")
841f7a57 5551{
48cb7ea9
SP
5552 const char *xpath =
5553 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
841f7a57 5554
48cb7ea9
SP
5555 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5556 return nb_cli_apply_changes(vty, NULL);
841f7a57
DO
5557}
5558
48cb7ea9
SP
5559ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5560 "no set as-path exclude",
5561 NO_STR SET_STR
5562 "Transform BGP AS_PATH attribute\n"
5563 "Exclude from the as-path\n")
841f7a57 5564
48cb7ea9
SP
5565DEFUN_YANG (set_community,
5566 set_community_cmd,
5567 "set community AA:NN...",
5568 SET_STR
5569 "BGP community attribute\n"
5570 COMMUNITY_VAL_STR)
718e3744 5571{
d62a17ae 5572 int idx_aa_nn = 2;
5573 int i;
5574 int first = 0;
5575 int additive = 0;
5576 struct buffer *b;
5577 struct community *com = NULL;
5578 char *str;
48cb7ea9 5579 char *argstr = NULL;
d62a17ae 5580 int ret;
5581
48cb7ea9
SP
5582 const char *xpath =
5583 "./set-action[action='frr-bgp-route-map:set-community']";
5584 char xpath_value[XPATH_MAXLEN];
5585
5586 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5587 snprintf(xpath_value, sizeof(xpath_value),
5588 "%s/rmap-set-action/frr-bgp-route-map:community-string",
5589 xpath);
5590
d62a17ae 5591 b = buffer_new(1024);
5592
5593 for (i = idx_aa_nn; i < argc; i++) {
5594 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5595 == 0) {
5596 additive = 1;
5597 continue;
5598 }
5599
5600 if (first)
5601 buffer_putc(b, ' ');
5602 else
5603 first = 1;
5604
5605 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5606 == 0) {
5607 buffer_putstr(b, "internet");
5608 continue;
5609 }
5610 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5611 == 0) {
5612 buffer_putstr(b, "local-AS");
5613 continue;
5614 }
5615 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5616 && strncmp(argv[i]->arg, "no-advertise",
5617 strlen(argv[i]->arg))
5618 == 0) {
5619 buffer_putstr(b, "no-advertise");
5620 continue;
5621 }
5622 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5623 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5624 == 0) {
5625 buffer_putstr(b, "no-export");
5626 continue;
5627 }
2721dd61
DA
5628 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
5629 == 0) {
5630 buffer_putstr(b, "blackhole");
5631 continue;
5632 }
a4d82a8a
PZ
5633 if (strncmp(argv[i]->arg, "graceful-shutdown",
5634 strlen(argv[i]->arg))
7f323236
DW
5635 == 0) {
5636 buffer_putstr(b, "graceful-shutdown");
5637 continue;
5638 }
d62a17ae 5639 buffer_putstr(b, argv[i]->arg);
5640 }
5641 buffer_putc(b, '\0');
5642
5643 /* Fetch result string then compile it to communities attribute. */
5644 str = buffer_getstr(b);
5645 buffer_free(b);
5646
c0945b78 5647 if (str)
d62a17ae 5648 com = community_str2com(str);
d62a17ae 5649
5650 /* Can't compile user input into communities attribute. */
5651 if (!com) {
c0945b78
DA
5652 vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
5653 XFREE(MTYPE_TMP, str);
d62a17ae 5654 return CMD_WARNING_CONFIG_FAILED;
5655 }
c0945b78 5656 XFREE(MTYPE_TMP, str);
d62a17ae 5657
5658 /* Set communites attribute string. */
c0945b78 5659 str = community_str(com, false, false);
d62a17ae 5660
5661 if (additive) {
552d6491
QY
5662 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
5663 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
5664 strlcpy(argstr, str, argstr_sz);
5665 strlcat(argstr, " additive", argstr_sz);
48cb7ea9 5666 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
d62a17ae 5667 } else
48cb7ea9
SP
5668 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5669
5670 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5671
48cb7ea9
SP
5672 if (argstr)
5673 XFREE(MTYPE_TMP, argstr);
3c1f53de 5674 community_free(&com);
d62a17ae 5675
5676 return ret;
718e3744 5677}
5678
48cb7ea9
SP
5679DEFUN_YANG (set_community_none,
5680 set_community_none_cmd,
5681 "set community none",
5682 SET_STR
5683 "BGP community attribute\n"
5684 "No community attribute\n")
718e3744 5685{
48cb7ea9
SP
5686 const char *xpath =
5687 "./set-action[action='frr-bgp-route-map:set-community']";
5688 char xpath_value[XPATH_MAXLEN];
5689
5690 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5691
5692 snprintf(xpath_value, sizeof(xpath_value),
5693 "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
5694 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5695 return nb_cli_apply_changes(vty, NULL);
718e3744 5696}
5697
48cb7ea9
SP
5698DEFUN_YANG (no_set_community,
5699 no_set_community_cmd,
5700 "no set community AA:NN...",
5701 NO_STR
5702 SET_STR
5703 "BGP community attribute\n"
5704 COMMUNITY_VAL_STR)
718e3744 5705{
48cb7ea9
SP
5706 const char *xpath =
5707 "./set-action[action='frr-bgp-route-map:set-community']";
718e3744 5708
48cb7ea9
SP
5709 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5710 return nb_cli_apply_changes(vty, NULL);
5711}
2929de9e 5712
48cb7ea9
SP
5713ALIAS_YANG (no_set_community,
5714 no_set_community_short_cmd,
5715 "no set community",
5716 NO_STR
5717 SET_STR
5718 "BGP community attribute\n")
718e3744 5719
48cb7ea9 5720DEFPY_YANG (set_community_delete,
718e3744 5721 set_community_delete_cmd,
a2099c1d 5722 "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
718e3744 5723 SET_STR
5724 "set BGP community list (for deletion)\n"
5725 "Community-list number (standard)\n"
5e3edbf5 5726 "Community-list number (expanded)\n"
718e3744 5727 "Community-list name\n"
5728 "Delete matching communities\n")
5729{
48cb7ea9
SP
5730 const char *xpath =
5731 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5732 char xpath_value[XPATH_MAXLEN];
d62a17ae 5733 int idx_comm_list = 2;
718e3744 5734
48cb7ea9
SP
5735 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5736
5737 snprintf(xpath_value, sizeof(xpath_value),
5738 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5739 xpath);
5740 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5741 argv[idx_comm_list]->arg);
5742
5743 return nb_cli_apply_changes(vty, NULL);
718e3744 5744
718e3744 5745}
5746
48cb7ea9
SP
5747DEFUN_YANG (no_set_community_delete,
5748 no_set_community_delete_cmd,
a2099c1d 5749 "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
48cb7ea9
SP
5750 NO_STR
5751 SET_STR
5752 "set BGP community list (for deletion)\n"
5753 "Community-list number (standard)\n"
5754 "Community-list number (expanded)\n"
5755 "Community-list name\n"
5756 "Delete matching communities\n")
718e3744 5757{
48cb7ea9
SP
5758 const char *xpath =
5759 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5760
5761 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5762 return nb_cli_apply_changes(vty, NULL);
718e3744 5763}
5764
48cb7ea9
SP
5765DEFUN_YANG (set_lcommunity,
5766 set_lcommunity_cmd,
5767 "set large-community AA:BB:CC...",
5768 SET_STR
5769 "BGP large community attribute\n"
5770 "Large Community number in aa:bb:cc format or additive\n")
57d187bc 5771{
d62a17ae 5772 char *str;
48cb7ea9
SP
5773 int ret;
5774 const char *xpath =
5775 "./set-action[action='frr-bgp-route-map:set-large-community']";
5776 char xpath_value[XPATH_MAXLEN];
5777
5778 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 5779
48cb7ea9
SP
5780 snprintf(xpath_value, sizeof(xpath_value),
5781 "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
5782 xpath);
d62a17ae 5783 str = argv_concat(argv, argc, 2);
48cb7ea9
SP
5784 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5785 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5786 XFREE(MTYPE_TMP, str);
d62a17ae 5787 return ret;
57d187bc
JS
5788}
5789
48cb7ea9
SP
5790DEFUN_YANG (set_lcommunity_none,
5791 set_lcommunity_none_cmd,
5792 "set large-community none",
5793 SET_STR
5794 "BGP large community attribute\n"
5795 "No large community attribute\n")
57d187bc 5796{
48cb7ea9
SP
5797 const char *xpath =
5798 "./set-action[action='frr-bgp-route-map:set-large-community']";
5799 char xpath_value[XPATH_MAXLEN];
5800
5801 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5802
5803 snprintf(xpath_value, sizeof(xpath_value),
5804 "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
5805 xpath);
5806 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5807 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
5808}
5809
48cb7ea9
SP
5810DEFUN_YANG (no_set_lcommunity,
5811 no_set_lcommunity_cmd,
5812 "no set large-community none",
5813 NO_STR
5814 SET_STR
5815 "BGP large community attribute\n"
5816 "No community attribute\n")
57d187bc 5817{
48cb7ea9
SP
5818 const char *xpath =
5819 "./set-action[action='frr-bgp-route-map:set-large-community']";
5820
5821 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5822 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
5823}
5824
48cb7ea9
SP
5825DEFUN_YANG (no_set_lcommunity1,
5826 no_set_lcommunity1_cmd,
5827 "no set large-community AA:BB:CC...",
5828 NO_STR
5829 SET_STR
5830 "BGP large community attribute\n"
5831 "Large community in AA:BB:CC... format or additive\n")
52951b63 5832{
48cb7ea9
SP
5833 const char *xpath =
5834 "./set-action[action='frr-bgp-route-map:set-large-community']";
5835
5836 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5837 return nb_cli_apply_changes(vty, NULL);
52951b63 5838}
57d187bc 5839
48cb7ea9
SP
5840ALIAS_YANG (no_set_lcommunity1,
5841 no_set_lcommunity1_short_cmd,
5842 "no set large-community",
5843 NO_STR
5844 SET_STR
5845 "BGP large community attribute\n")
76a20aa9 5846
48cb7ea9 5847DEFPY_YANG (set_lcommunity_delete,
57d187bc 5848 set_lcommunity_delete_cmd,
a2099c1d 5849 "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
57d187bc
JS
5850 SET_STR
5851 "set BGP large community list (for deletion)\n"
5852 "Large Community-list number (standard)\n"
5853 "Large Communitly-list number (expanded)\n"
5854 "Large Community-list name\n"
5855 "Delete matching large communities\n")
5856{
48cb7ea9
SP
5857 const char *xpath =
5858 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
5859 char xpath_value[XPATH_MAXLEN];
4cae2269 5860 int idx_lcomm_list = 2;
4cae2269 5861
48cb7ea9 5862 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 5863
48cb7ea9
SP
5864 snprintf(xpath_value, sizeof(xpath_value),
5865 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5866 xpath);
5867 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5868 argv[idx_lcomm_list]->arg);
5869
5870 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
5871}
5872
48cb7ea9
SP
5873DEFUN_YANG (no_set_lcommunity_delete,
5874 no_set_lcommunity_delete_cmd,
a2099c1d 5875 "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
48cb7ea9
SP
5876 NO_STR
5877 SET_STR
5878 "set BGP large community list (for deletion)\n"
5879 "Large Community-list number (standard)\n"
5880 "Large Communitly-list number (expanded)\n"
5881 "Large Community-list name\n"
5882 "Delete matching large communities\n")
57d187bc 5883{
48cb7ea9
SP
5884 const char *xpath =
5885 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
5886
5887 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5888 return nb_cli_apply_changes(vty, NULL);
57d187bc 5889}
718e3744 5890
48cb7ea9
SP
5891ALIAS_YANG (no_set_lcommunity_delete,
5892 no_set_lcommunity_delete_short_cmd,
5893 "no set large-comm-list",
5894 NO_STR
5895 SET_STR
5896 "set BGP large community list (for deletion)\n")
76a20aa9 5897
48cb7ea9
SP
5898DEFUN_YANG (set_ecommunity_rt,
5899 set_ecommunity_rt_cmd,
5900 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
5901 SET_STR
5902 "BGP extended community attribute\n"
5903 "Route Target extended community\n"
5904 "VPN extended community\n")
718e3744 5905{
d62a17ae 5906 int idx_asn_nn = 3;
d62a17ae 5907 char *str;
48cb7ea9
SP
5908 int ret;
5909 const char *xpath =
5910 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
5911 char xpath_value[XPATH_MAXLEN];
5912
5913 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 5914
48cb7ea9
SP
5915 snprintf(xpath_value, sizeof(xpath_value),
5916 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
d62a17ae 5917 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
5918 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5919 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5920 XFREE(MTYPE_TMP, str);
d62a17ae 5921 return ret;
718e3744 5922}
5923
48cb7ea9
SP
5924DEFUN_YANG (no_set_ecommunity_rt,
5925 no_set_ecommunity_rt_cmd,
5926 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
5927 NO_STR
5928 SET_STR
5929 "BGP extended community attribute\n"
5930 "Route Target extended community\n"
5931 "VPN extended community\n")
5932{
5933 const char *xpath =
5934 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
5935 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5936 return nb_cli_apply_changes(vty, NULL);
5937}
5938
5939ALIAS_YANG (no_set_ecommunity_rt,
5940 no_set_ecommunity_rt_short_cmd,
5941 "no set extcommunity rt",
5942 NO_STR
5943 SET_STR
5944 "BGP extended community attribute\n"
5945 "Route Target extended community\n")
5946
5947DEFUN_YANG (set_ecommunity_soo,
5948 set_ecommunity_soo_cmd,
5949 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
5950 SET_STR
5951 "BGP extended community attribute\n"
5952 "Site-of-Origin extended community\n"
5953 "VPN extended community\n")
718e3744 5954{
d62a17ae 5955 int idx_asn_nn = 3;
d62a17ae 5956 char *str;
48cb7ea9
SP
5957 int ret;
5958 const char *xpath =
5959 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
5960 char xpath_value[XPATH_MAXLEN];
718e3744 5961
48cb7ea9
SP
5962 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5963
5964 snprintf(xpath_value, sizeof(xpath_value),
5965 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
5966 xpath);
d62a17ae 5967 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
5968 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5969 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5970 XFREE(MTYPE_TMP, str);
5971 return ret;
718e3744 5972}
5973
48cb7ea9
SP
5974DEFUN_YANG (no_set_ecommunity_soo,
5975 no_set_ecommunity_soo_cmd,
5976 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
5977 NO_STR
5978 SET_STR
5979 "BGP extended community attribute\n"
5980 "Site-of-Origin extended community\n"
5981 "VPN extended community\n")
5982{
5983 const char *xpath =
5984 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
5985 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5986 return nb_cli_apply_changes(vty, NULL);
5987}
5988
5989ALIAS_YANG (no_set_ecommunity_soo,
5990 no_set_ecommunity_soo_short_cmd,
5991 "no set extcommunity soo",
5992 NO_STR
5993 SET_STR
5994 "GP extended community attribute\n"
5995 "Site-of-Origin extended community\n")
5996
bb4dcdd1
DA
5997DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
5998 "set extcommunity none",
5999 SET_STR
6000 "BGP extended community attribute\n"
6001 "No extended community attribute\n")
6002{
6003 const char *xpath =
6004 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6005 char xpath_value[XPATH_MAXLEN];
6006
6007 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6008
6009 snprintf(xpath_value, sizeof(xpath_value),
6010 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6011 xpath);
6012 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6013 return nb_cli_apply_changes(vty, NULL);
6014}
6015
6016DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6017 "no set extcommunity none",
6018 NO_STR SET_STR
6019 "BGP extended community attribute\n"
6020 "No extended community attribute\n")
6021{
6022 const char *xpath =
6023 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6024 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6025 return nb_cli_apply_changes(vty, NULL);
6026}
6027
48cb7ea9
SP
6028DEFUN_YANG (set_ecommunity_lb,
6029 set_ecommunity_lb_cmd,
6030 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6031 SET_STR
6032 "BGP extended community attribute\n"
6033 "Link bandwidth extended community\n"
6034 "Bandwidth value in Mbps\n"
6035 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6036 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6037 "Attribute is set as non-transitive\n")
718e3744 6038{
48cb7ea9 6039 int idx_lb = 3;
3b225ee7 6040 int idx_non_transitive = 0;
48cb7ea9
SP
6041 const char *xpath =
6042 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6043 char xpath_lb_type[XPATH_MAXLEN];
6044 char xpath_bandwidth[XPATH_MAXLEN];
6045 char xpath_non_transitive[XPATH_MAXLEN];
6046
6047 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6048
6049 snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6050 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6051 xpath);
6052 snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6053 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6054 xpath);
6055 snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6056 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6057 xpath);
6058
6059 if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6060 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6061 "cumulative-bandwidth");
6062 else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6063 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6064 "computed-bandwidth");
6065 else {
6066 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6067 "explicit-bandwidth");
6068 nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6069 argv[idx_lb]->arg);
6070 }
718e3744 6071
3b225ee7 6072 if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
48cb7ea9
SP
6073 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6074 "true");
6075 else
6076 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6077 "false");
6078
6079 return nb_cli_apply_changes(vty, NULL);
6080}
6081
6082DEFUN_YANG (no_set_ecommunity_lb,
6083 no_set_ecommunity_lb_cmd,
6084 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6085 NO_STR
6086 SET_STR
6087 "BGP extended community attribute\n"
6088 "Link bandwidth extended community\n"
6089 "Bandwidth value in Mbps\n"
6090 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6091 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6092 "Attribute is set as non-transitive\n")
6093{
6094 const char *xpath =
6095 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6096
6097 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6098 return nb_cli_apply_changes(vty, NULL);
6099}
6100
6101ALIAS_YANG (no_set_ecommunity_lb,
6102 no_set_ecommunity_lb_short_cmd,
6103 "no set extcommunity bandwidth",
6104 NO_STR
6105 SET_STR
6106 "BGP extended community attribute\n"
6107 "Link bandwidth extended community\n")
6108
6109DEFUN_YANG (set_origin,
6110 set_origin_cmd,
6111 "set origin <egp|igp|incomplete>",
6112 SET_STR
6113 "BGP origin code\n"
6114 "remote EGP\n"
6115 "local IGP\n"
6116 "unknown heritage\n")
ca9ac3ef 6117{
48cb7ea9
SP
6118 int idx_origin = 2;
6119 const char *origin_type;
6120 const char *xpath =
6121 "./set-action[action='frr-bgp-route-map:set-origin']";
6122 char xpath_value[XPATH_MAXLEN];
ca9ac3ef 6123
48cb7ea9
SP
6124 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6125 origin_type = "igp";
6126 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6127 origin_type = "egp";
6128 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6129 origin_type = "incomplete";
6130 else {
6131 vty_out(vty, "%% Invalid match origin type\n");
6132 return CMD_WARNING_CONFIG_FAILED;
6133 }
ca9ac3ef 6134
48cb7ea9
SP
6135 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6136 snprintf(xpath_value, sizeof(xpath_value),
6137 "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6138 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
ca9ac3ef 6139
48cb7ea9 6140 return nb_cli_apply_changes(vty, NULL);
ca9ac3ef 6141}
6142
48cb7ea9
SP
6143DEFUN_YANG (no_set_origin,
6144 no_set_origin_cmd,
6145 "no set origin [<egp|igp|incomplete>]",
6146 NO_STR
6147 SET_STR
6148 "BGP origin code\n"
6149 "remote EGP\n"
6150 "local IGP\n"
6151 "unknown heritage\n")
718e3744 6152{
48cb7ea9
SP
6153 const char *xpath =
6154 "./set-action[action='frr-bgp-route-map:set-origin']";
718e3744 6155
48cb7ea9
SP
6156 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6157 return nb_cli_apply_changes(vty, NULL);
718e3744 6158}
6159
48cb7ea9
SP
6160DEFUN_YANG (set_atomic_aggregate,
6161 set_atomic_aggregate_cmd,
6162 "set atomic-aggregate",
6163 SET_STR
6164 "BGP atomic aggregate attribute\n" )
718e3744 6165{
48cb7ea9
SP
6166 const char *xpath =
6167 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6168 char xpath_value[XPATH_MAXLEN];
718e3744 6169
48cb7ea9
SP
6170 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6171 snprintf(xpath_value, sizeof(xpath_value),
6172 "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6173 xpath);
6174 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
718e3744 6175
48cb7ea9 6176 return nb_cli_apply_changes(vty, NULL);
718e3744 6177}
6178
48cb7ea9
SP
6179DEFUN_YANG (no_set_atomic_aggregate,
6180 no_set_atomic_aggregate_cmd,
6181 "no set atomic-aggregate",
6182 NO_STR
6183 SET_STR
6184 "BGP atomic aggregate attribute\n" )
718e3744 6185{
48cb7ea9
SP
6186 const char *xpath =
6187 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6188
6189 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6190 return nb_cli_apply_changes(vty, NULL);
718e3744 6191}
6192
48cb7ea9
SP
6193DEFUN_YANG (set_aggregator_as,
6194 set_aggregator_as_cmd,
6195 "set aggregator as (1-4294967295) A.B.C.D",
6196 SET_STR
6197 "BGP aggregator attribute\n"
6198 "AS number of aggregator\n"
6199 "AS number\n"
6200 "IP address of aggregator\n")
718e3744 6201{
d62a17ae 6202 int idx_number = 3;
6203 int idx_ipv4 = 4;
48cb7ea9
SP
6204 char xpath_asn[XPATH_MAXLEN];
6205 char xpath_addr[XPATH_MAXLEN];
6206 const char *xpath =
6207 "./set-action[action='frr-bgp-route-map:aggregator']";
e52702f2 6208
48cb7ea9 6209 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 6210
48cb7ea9
SP
6211 snprintf(
6212 xpath_asn, sizeof(xpath_asn),
6213 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6214 xpath);
6215 nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6216 argv[idx_number]->arg);
718e3744 6217
48cb7ea9
SP
6218 snprintf(
6219 xpath_addr, sizeof(xpath_addr),
6220 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6221 xpath);
6222 nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6223 argv[idx_ipv4]->arg);
718e3744 6224
48cb7ea9 6225 return nb_cli_apply_changes(vty, NULL);
718e3744 6226}
6227
48cb7ea9
SP
6228DEFUN_YANG (no_set_aggregator_as,
6229 no_set_aggregator_as_cmd,
6230 "no set aggregator as [(1-4294967295) A.B.C.D]",
6231 NO_STR
6232 SET_STR
6233 "BGP aggregator attribute\n"
6234 "AS number of aggregator\n"
6235 "AS number\n"
6236 "IP address of aggregator\n")
718e3744 6237{
48cb7ea9
SP
6238 const char *xpath =
6239 "./set-action[action='frr-bgp-route-map:aggregator']";
718e3744 6240
48cb7ea9
SP
6241 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6242 return nb_cli_apply_changes(vty, NULL);
6243}
718e3744 6244
48cb7ea9
SP
6245DEFUN_YANG (match_ipv6_next_hop,
6246 match_ipv6_next_hop_cmd,
bc63ba98
DA
6247 "match ipv6 next-hop ACCESSLIST6_NAME",
6248 MATCH_STR
6249 IPV6_STR
6250 "Match IPv6 next-hop address of route\n"
6251 "IPv6 access-list name\n")
6252{
6253 const char *xpath =
6254 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6255 char xpath_value[XPATH_MAXLEN];
6256
6257 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6258 snprintf(xpath_value, sizeof(xpath_value),
6259 "%s/rmap-match-condition/list-name", xpath);
6260 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6261 argv[argc - 1]->arg);
6262
6263 return nb_cli_apply_changes(vty, NULL);
6264}
6265
6266DEFUN_YANG (no_match_ipv6_next_hop,
6267 no_match_ipv6_next_hop_cmd,
6268 "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6269 NO_STR
6270 MATCH_STR
6271 IPV6_STR
6272 "Match IPv6 next-hop address of route\n"
6273 "IPv6 access-list name\n")
6274{
6275 const char *xpath =
6276 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6277
6278 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6279 return nb_cli_apply_changes(vty, NULL);
6280}
6281
6282DEFUN_YANG (match_ipv6_next_hop_address,
6283 match_ipv6_next_hop_address_cmd,
03030106 6284 "match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6285 MATCH_STR
6286 IPV6_STR
6287 "Match IPv6 next-hop address of route\n"
03030106 6288 "IPv6 address\n"
48cb7ea9
SP
6289 "IPv6 address of next hop\n")
6290{
6291 const char *xpath =
6292 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6293 char xpath_value[XPATH_MAXLEN];
718e3744 6294
48cb7ea9
SP
6295 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6296 snprintf(xpath_value, sizeof(xpath_value),
6297 "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6298 xpath);
bc63ba98
DA
6299 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6300 argv[argc - 1]->arg);
718e3744 6301
48cb7ea9 6302 return nb_cli_apply_changes(vty, NULL);
718e3744 6303}
6304
bc63ba98
DA
6305DEFUN_YANG (no_match_ipv6_next_hop_address,
6306 no_match_ipv6_next_hop_address_cmd,
03030106 6307 "no match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6308 NO_STR
6309 MATCH_STR
6310 IPV6_STR
6311 "Match IPv6 next-hop address of route\n"
03030106 6312 "IPv6 address\n"
48cb7ea9 6313 "IPv6 address of next hop\n")
718e3744 6314{
48cb7ea9
SP
6315 const char *xpath =
6316 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
718e3744 6317
48cb7ea9
SP
6318 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6319 return nb_cli_apply_changes(vty, NULL);
718e3744 6320}
6321
bc63ba98 6322ALIAS_HIDDEN (match_ipv6_next_hop_address,
03030106
IR
6323 match_ipv6_next_hop_old_cmd,
6324 "match ipv6 next-hop X:X::X:X",
6325 MATCH_STR
6326 IPV6_STR
6327 "Match IPv6 next-hop address of route\n"
6328 "IPv6 address of next hop\n")
6329
bc63ba98 6330ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
03030106
IR
6331 no_match_ipv6_next_hop_old_cmd,
6332 "no match ipv6 next-hop X:X::X:X",
6333 NO_STR
6334 MATCH_STR
6335 IPV6_STR
6336 "Match IPv6 next-hop address of route\n"
6337 "IPv6 address of next hop\n")
6338
82f191a2
DA
6339DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6340 match_ipv6_next_hop_prefix_list_cmd,
6341 "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6342 MATCH_STR
6343 IPV6_STR
6344 "Match IPv6 next-hop address of route\n"
6345 "Match entries by prefix-list\n"
6346 "IPv6 prefix-list name\n")
6347{
6348 const char *xpath =
6349 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6350 char xpath_value[XPATH_MAXLEN];
6351
6352 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6353 snprintf(xpath_value, sizeof(xpath_value),
6354 "%s/rmap-match-condition/list-name", xpath);
6355 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6356 argv[argc - 1]->arg);
6357
6358 return nb_cli_apply_changes(vty, NULL);
6359}
6360
6361DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6362 no_match_ipv6_next_hop_prefix_list_cmd,
6363 "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6364 NO_STR
6365 MATCH_STR
6366 IPV6_STR
6367 "Match IPv6 next-hop address of route\n"
6368 "Match entries by prefix-list\n"
6369 "IPv6 prefix-list name\n")
6370{
6371 const char *xpath =
6372 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6373
6374 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6375 return nb_cli_apply_changes(vty, NULL);
6376}
6377
48cb7ea9 6378DEFPY_YANG (match_ipv4_next_hop,
be7735b3 6379 match_ipv4_next_hop_cmd,
17ac51eb 6380 "match ip next-hop address A.B.C.D",
be7735b3
PG
6381 MATCH_STR
6382 IP_STR
6383 "Match IP next-hop address of route\n"
6384 "IP address\n"
6385 "IP address of next-hop\n")
6386{
48cb7ea9
SP
6387 const char *xpath =
6388 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6389 char xpath_value[XPATH_MAXLEN];
6390
6391 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6392 snprintf(xpath_value, sizeof(xpath_value),
6393 "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6394 xpath);
6395 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
be7735b3 6396
48cb7ea9 6397 return nb_cli_apply_changes(vty, NULL);
17ac51eb 6398}
be7735b3 6399
48cb7ea9 6400DEFPY_YANG (no_match_ipv4_next_hop,
17ac51eb
DS
6401 no_match_ipv4_next_hop_cmd,
6402 "no match ip next-hop address [A.B.C.D]",
6403 NO_STR
6404 MATCH_STR
6405 IP_STR
6406 "Match IP next-hop address of route\n"
6407 "IP address\n"
6408 "IP address of next-hop\n")
6409{
48cb7ea9
SP
6410 const char *xpath =
6411 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6412
6413 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6414 return nb_cli_apply_changes(vty, NULL);
be7735b3 6415}
718e3744 6416
48cb7ea9
SP
6417DEFUN_YANG (set_ipv6_nexthop_peer,
6418 set_ipv6_nexthop_peer_cmd,
6419 "set ipv6 next-hop peer-address",
6420 SET_STR
6421 IPV6_STR
6422 "Next hop address\n"
6423 "Use peer address (for BGP only)\n")
90916ac2 6424{
48cb7ea9
SP
6425 const char *xpath =
6426 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6427 char xpath_value[XPATH_MAXLEN];
6428
6429 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6430 snprintf(xpath_value, sizeof(xpath_value),
6431 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6432 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6433
6434 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6435}
6436
48cb7ea9
SP
6437DEFUN_YANG (no_set_ipv6_nexthop_peer,
6438 no_set_ipv6_nexthop_peer_cmd,
6439 "no set ipv6 next-hop peer-address",
6440 NO_STR
6441 SET_STR
6442 IPV6_STR
6443 "IPv6 next-hop address\n"
6444 "Use peer address (for BGP only)\n")
90916ac2 6445{
48cb7ea9
SP
6446 const char *xpath =
6447 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6448
6449 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6450 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6451}
6452
48cb7ea9
SP
6453DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6454 set_ipv6_nexthop_prefer_global_cmd,
6455 "set ipv6 next-hop prefer-global",
6456 SET_STR
6457 IPV6_STR
6458 "IPv6 next-hop address\n"
6459 "Prefer global over link-local if both exist\n")
161995ea 6460{
48cb7ea9
SP
6461 const char *xpath =
6462 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6463 char xpath_value[XPATH_MAXLEN];
6464
6465 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6466 snprintf(xpath_value, sizeof(xpath_value),
6467 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6468 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6469
6470 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6471}
6472
48cb7ea9
SP
6473DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6474 no_set_ipv6_nexthop_prefer_global_cmd,
6475 "no set ipv6 next-hop prefer-global",
6476 NO_STR
6477 SET_STR
6478 IPV6_STR
6479 "IPv6 next-hop address\n"
6480 "Prefer global over link-local if both exist\n")
161995ea 6481{
48cb7ea9
SP
6482 const char *xpath =
6483 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6484
6485 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6486 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6487}
6488
48cb7ea9
SP
6489DEFUN_YANG (set_ipv6_nexthop_global,
6490 set_ipv6_nexthop_global_cmd,
6491 "set ipv6 next-hop global X:X::X:X",
6492 SET_STR
6493 IPV6_STR
6494 "IPv6 next-hop address\n"
6495 "IPv6 global address\n"
6496 "IPv6 address of next hop\n")
718e3744 6497{
d62a17ae 6498 int idx_ipv6 = 4;
48cb7ea9
SP
6499 const char *xpath =
6500 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6501 char xpath_value[XPATH_MAXLEN];
bf8b3d27 6502
48cb7ea9
SP
6503 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6504 snprintf(xpath_value, sizeof(xpath_value),
6505 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6506 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6507 argv[idx_ipv6]->arg);
bf8b3d27 6508
48cb7ea9 6509 return nb_cli_apply_changes(vty, NULL);
718e3744 6510}
6511
48cb7ea9
SP
6512DEFUN_YANG (no_set_ipv6_nexthop_global,
6513 no_set_ipv6_nexthop_global_cmd,
6514 "no set ipv6 next-hop global X:X::X:X",
6515 NO_STR
6516 SET_STR
6517 IPV6_STR
6518 "IPv6 next-hop address\n"
6519 "IPv6 global address\n"
6520 "IPv6 address of next hop\n")
718e3744 6521{
48cb7ea9
SP
6522 const char *xpath =
6523 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6524
6525 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6526 return nb_cli_apply_changes(vty, NULL);
718e3744 6527}
718e3744 6528
d6902373 6529#ifdef KEEP_OLD_VPN_COMMANDS
48cb7ea9
SP
6530DEFUN_YANG (set_vpn_nexthop,
6531 set_vpn_nexthop_cmd,
6532 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6533 SET_STR
6534 "VPNv4 information\n"
6535 "VPN next-hop address\n"
6536 "IP address of next hop\n"
6537 "VPNv6 information\n"
6538 "VPN next-hop address\n"
6539 "IPv6 address of next hop\n")
718e3744 6540{
d62a17ae 6541 int idx_ip = 3;
6542 afi_t afi;
6543 int idx = 0;
4ad4ae64 6544 char xpath_value[XPATH_MAXLEN];
d62a17ae 6545
6546 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6547 if (afi == AFI_IP) {
6548 const char *xpath =
6549 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6550
6551 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6552 snprintf(
6553 xpath_value, sizeof(xpath_value),
6554 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6555 xpath);
6556 } else {
6557 const char *xpath =
6558 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6559
6560 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6561 snprintf(
6562 xpath_value, sizeof(xpath_value),
6563 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6564 xpath);
6565 }
6566
6567 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6568 argv[idx_ip]->arg);
6569
6570 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6571 }
48cb7ea9 6572
d62a17ae 6573 return CMD_SUCCESS;
d6902373 6574}
a4b2b610 6575
48cb7ea9
SP
6576DEFUN_YANG (no_set_vpn_nexthop,
6577 no_set_vpn_nexthop_cmd,
6578 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6579 NO_STR
6580 SET_STR
6581 "VPNv4 information\n"
6582 "VPN next-hop address\n"
6583 "IP address of next hop\n"
6584 "VPNv6 information\n"
6585 "VPN next-hop address\n"
6586 "IPv6 address of next hop\n")
718e3744 6587{
d62a17ae 6588 afi_t afi;
6589 int idx = 0;
6590
d62a17ae 6591 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6592 if (afi == AFI_IP) {
6593 const char *xpath =
6594 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6595 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6596 } else {
6597 const char *xpath =
6598 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6599 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6600 }
6601 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6602 }
6603 return CMD_SUCCESS;
d6902373
PG
6604}
6605#endif /* KEEP_OLD_VPN_COMMANDS */
6606
48cb7ea9
SP
6607DEFUN_YANG (set_ipx_vpn_nexthop,
6608 set_ipx_vpn_nexthop_cmd,
6609 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
6610 SET_STR
6611 "IPv4 information\n"
6612 "IPv6 information\n"
6613 "VPN information\n"
6614 "VPN next-hop address\n"
6615 "IP address of next hop\n"
6616 "IPv6 address of next hop\n")
d6902373 6617{
d62a17ae 6618 int idx_ip = 4;
6619 afi_t afi;
6620 int idx = 0;
48cb7ea9 6621 char xpath_value[XPATH_MAXLEN];
d62a17ae 6622
6623 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6624 if (afi == AFI_IP) {
6625 const char *xpath =
6626 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6627
6628 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6629 snprintf(
6630 xpath_value, sizeof(xpath_value),
6631 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6632 xpath);
6633 } else {
6634 const char *xpath =
6635 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6636
6637 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6638 snprintf(
6639 xpath_value, sizeof(xpath_value),
6640 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6641 xpath);
6642 }
6643 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6644 argv[idx_ip]->arg);
6645 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6646 }
6647 return CMD_SUCCESS;
718e3744 6648}
6649
48cb7ea9
SP
6650DEFUN_YANG (no_set_ipx_vpn_nexthop,
6651 no_set_ipx_vpn_nexthop_cmd,
6652 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
6653 NO_STR
6654 SET_STR
6655 "IPv4 information\n"
6656 "IPv6 information\n"
6657 "VPN information\n"
6658 "VPN next-hop address\n"
6659 "IP address of next hop\n"
6660 "IPv6 address of next hop\n")
6661{
d62a17ae 6662 afi_t afi;
6663 int idx = 0;
6664
d62a17ae 6665 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6666 if (afi == AFI_IP) {
6667 const char *xpath =
6668 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6669 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6670 } else {
6671 const char *xpath =
6672 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6673 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6674 }
6675 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6676 }
6677 return CMD_SUCCESS;
d6902373 6678}
718e3744 6679
48cb7ea9
SP
6680DEFUN_YANG (set_originator_id,
6681 set_originator_id_cmd,
6682 "set originator-id A.B.C.D",
6683 SET_STR
6684 "BGP originator ID attribute\n"
6685 "IP address of originator\n")
718e3744 6686{
d62a17ae 6687 int idx_ipv4 = 2;
48cb7ea9
SP
6688 const char *xpath =
6689 "./set-action[action='frr-bgp-route-map:originator-id']";
6690 char xpath_value[XPATH_MAXLEN];
718e3744 6691
48cb7ea9
SP
6692 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6693 snprintf(xpath_value, sizeof(xpath_value),
6694 "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
6695 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6696 argv[idx_ipv4]->arg);
4c9bd275 6697
48cb7ea9
SP
6698 return nb_cli_apply_changes(vty, NULL);
6699}
6700
6701DEFUN_YANG (no_set_originator_id,
6702 no_set_originator_id_cmd,
6703 "no set originator-id [A.B.C.D]",
6704 NO_STR
6705 SET_STR
6706 "BGP originator ID attribute\n"
6707 "IP address of originator\n")
718e3744 6708{
48cb7ea9
SP
6709 const char *xpath =
6710 "./set-action[action='frr-bgp-route-map:originator-id']";
0d702986 6711
48cb7ea9
SP
6712 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6713 return nb_cli_apply_changes(vty, NULL);
718e3744 6714}
6715
718e3744 6716/* Initialization of route map. */
d62a17ae 6717void bgp_route_map_init(void)
6718{
6719 route_map_init();
6720
6721 route_map_add_hook(bgp_route_map_add);
6722 route_map_delete_hook(bgp_route_map_delete);
6723 route_map_event_hook(bgp_route_map_event);
6724
6725 route_map_match_interface_hook(generic_match_add);
6726 route_map_no_match_interface_hook(generic_match_delete);
6727
6728 route_map_match_ip_address_hook(generic_match_add);
6729 route_map_no_match_ip_address_hook(generic_match_delete);
6730
6731 route_map_match_ip_address_prefix_list_hook(generic_match_add);
6732 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
6733
6734 route_map_match_ip_next_hop_hook(generic_match_add);
6735 route_map_no_match_ip_next_hop_hook(generic_match_delete);
6736
bc63ba98
DA
6737 route_map_match_ipv6_next_hop_hook(generic_match_add);
6738 route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
6739
d62a17ae 6740 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
6741 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
6742
61ad901e
DA
6743 route_map_match_ip_next_hop_type_hook(generic_match_add);
6744 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
6745
d62a17ae 6746 route_map_match_ipv6_address_hook(generic_match_add);
6747 route_map_no_match_ipv6_address_hook(generic_match_delete);
6748
6749 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
6750 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
6751
61ad901e
DA
6752 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
6753 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
6754
82f191a2
DA
6755 route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
6756 route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
6757
d62a17ae 6758 route_map_match_metric_hook(generic_match_add);
6759 route_map_no_match_metric_hook(generic_match_delete);
6760
6761 route_map_match_tag_hook(generic_match_add);
6762 route_map_no_match_tag_hook(generic_match_delete);
6763
ef3e0d04
SM
6764 route_map_set_srte_color_hook(generic_set_add);
6765 route_map_no_set_srte_color_hook(generic_set_delete);
6766
d62a17ae 6767 route_map_set_ip_nexthop_hook(generic_set_add);
6768 route_map_no_set_ip_nexthop_hook(generic_set_delete);
6769
6770 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
6771 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
6772
6773 route_map_set_metric_hook(generic_set_add);
6774 route_map_no_set_metric_hook(generic_set_delete);
6775
6776 route_map_set_tag_hook(generic_set_add);
6777 route_map_no_set_tag_hook(generic_set_delete);
6778
6779 route_map_install_match(&route_match_peer_cmd);
2690f18c 6780 route_map_install_match(&route_match_alias_cmd);
d62a17ae 6781 route_map_install_match(&route_match_local_pref_cmd);
fa22080d 6782#ifdef HAVE_SCRIPTING
b4becb06 6783 route_map_install_match(&route_match_script_cmd);
1d7c7ace 6784#endif
d62a17ae 6785 route_map_install_match(&route_match_ip_address_cmd);
6786 route_map_install_match(&route_match_ip_next_hop_cmd);
6787 route_map_install_match(&route_match_ip_route_source_cmd);
6788 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
6789 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 6790 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 6791 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
6792 route_map_install_match(&route_match_aspath_cmd);
6793 route_map_install_match(&route_match_community_cmd);
6794 route_map_install_match(&route_match_lcommunity_cmd);
6795 route_map_install_match(&route_match_ecommunity_cmd);
6796 route_map_install_match(&route_match_local_pref_cmd);
6797 route_map_install_match(&route_match_metric_cmd);
6798 route_map_install_match(&route_match_origin_cmd);
6799 route_map_install_match(&route_match_probability_cmd);
6800 route_map_install_match(&route_match_interface_cmd);
6801 route_map_install_match(&route_match_tag_cmd);
d37ba549 6802 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 6803 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 6804 route_map_install_match(&route_match_evpn_route_type_cmd);
196c6b09 6805 route_map_install_match(&route_match_evpn_rd_cmd);
6fb219da 6806 route_map_install_match(&route_match_evpn_default_route_cmd);
1dcc9e5b 6807 route_map_install_match(&route_match_vrl_source_vrf_cmd);
d62a17ae 6808
d0a4ee60
AD
6809 route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
6810 route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
951745bd 6811 route_map_install_set(&route_set_table_id_cmd);
ef3e0d04 6812 route_map_install_set(&route_set_srte_color_cmd);
d62a17ae 6813 route_map_install_set(&route_set_ip_nexthop_cmd);
6814 route_map_install_set(&route_set_local_pref_cmd);
6815 route_map_install_set(&route_set_weight_cmd);
6816 route_map_install_set(&route_set_label_index_cmd);
6817 route_map_install_set(&route_set_metric_cmd);
7b7d48e5 6818 route_map_install_set(&route_set_distance_cmd);
d62a17ae 6819 route_map_install_set(&route_set_aspath_prepend_cmd);
6820 route_map_install_set(&route_set_aspath_exclude_cmd);
77e3d821 6821 route_map_install_set(&route_set_aspath_replace_cmd);
d62a17ae 6822 route_map_install_set(&route_set_origin_cmd);
6823 route_map_install_set(&route_set_atomic_aggregate_cmd);
6824 route_map_install_set(&route_set_aggregator_as_cmd);
6825 route_map_install_set(&route_set_community_cmd);
6826 route_map_install_set(&route_set_community_delete_cmd);
6827 route_map_install_set(&route_set_lcommunity_cmd);
6828 route_map_install_set(&route_set_lcommunity_delete_cmd);
6829 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
6830 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
6831 route_map_install_set(&route_set_originator_id_cmd);
6832 route_map_install_set(&route_set_ecommunity_rt_cmd);
6833 route_map_install_set(&route_set_ecommunity_soo_cmd);
ca9ac3ef 6834 route_map_install_set(&route_set_ecommunity_lb_cmd);
bb4dcdd1 6835 route_map_install_set(&route_set_ecommunity_none_cmd);
d62a17ae 6836 route_map_install_set(&route_set_tag_cmd);
6837 route_map_install_set(&route_set_label_index_cmd);
6838
6839 install_element(RMAP_NODE, &match_peer_cmd);
6840 install_element(RMAP_NODE, &match_peer_local_cmd);
6841 install_element(RMAP_NODE, &no_match_peer_cmd);
6842 install_element(RMAP_NODE, &match_ip_route_source_cmd);
6843 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
6844 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
6845 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
6846 install_element(RMAP_NODE, &match_mac_address_cmd);
6847 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
6848 install_element(RMAP_NODE, &match_evpn_vni_cmd);
6849 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
6850 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
6851 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
196c6b09
LK
6852 install_element(RMAP_NODE, &match_evpn_rd_cmd);
6853 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
6fb219da
MK
6854 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
6855 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
d0a4ee60
AD
6856 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
6857 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
6858 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
6859 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
1dcc9e5b
CS
6860 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
6861 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
d62a17ae 6862
6863 install_element(RMAP_NODE, &match_aspath_cmd);
6864 install_element(RMAP_NODE, &no_match_aspath_cmd);
6865 install_element(RMAP_NODE, &match_local_pref_cmd);
6866 install_element(RMAP_NODE, &no_match_local_pref_cmd);
2690f18c
DA
6867 install_element(RMAP_NODE, &match_alias_cmd);
6868 install_element(RMAP_NODE, &no_match_alias_cmd);
d62a17ae 6869 install_element(RMAP_NODE, &match_community_cmd);
6870 install_element(RMAP_NODE, &no_match_community_cmd);
6871 install_element(RMAP_NODE, &match_lcommunity_cmd);
6872 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
6873 install_element(RMAP_NODE, &match_ecommunity_cmd);
6874 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
6875 install_element(RMAP_NODE, &match_origin_cmd);
6876 install_element(RMAP_NODE, &no_match_origin_cmd);
6877 install_element(RMAP_NODE, &match_probability_cmd);
6878 install_element(RMAP_NODE, &no_match_probability_cmd);
6879
951745bd
PG
6880 install_element(RMAP_NODE, &no_set_table_id_cmd);
6881 install_element(RMAP_NODE, &set_table_id_cmd);
d62a17ae 6882 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
6883 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
6884 install_element(RMAP_NODE, &set_local_pref_cmd);
7b7d48e5
DS
6885 install_element(RMAP_NODE, &set_distance_cmd);
6886 install_element(RMAP_NODE, &no_set_distance_cmd);
d62a17ae 6887 install_element(RMAP_NODE, &no_set_local_pref_cmd);
6888 install_element(RMAP_NODE, &set_weight_cmd);
6889 install_element(RMAP_NODE, &set_label_index_cmd);
6890 install_element(RMAP_NODE, &no_set_weight_cmd);
6891 install_element(RMAP_NODE, &no_set_label_index_cmd);
6892 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
6893 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
6894 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
77e3d821 6895 install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
d62a17ae 6896 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
9131e6e8 6897 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
d62a17ae 6898 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
499ceb3d 6899 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
77e3d821 6900 install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
d62a17ae 6901 install_element(RMAP_NODE, &set_origin_cmd);
6902 install_element(RMAP_NODE, &no_set_origin_cmd);
6903 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
6904 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
6905 install_element(RMAP_NODE, &set_aggregator_as_cmd);
6906 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
6907 install_element(RMAP_NODE, &set_community_cmd);
6908 install_element(RMAP_NODE, &set_community_none_cmd);
6909 install_element(RMAP_NODE, &no_set_community_cmd);
2929de9e 6910 install_element(RMAP_NODE, &no_set_community_short_cmd);
d62a17ae 6911 install_element(RMAP_NODE, &set_community_delete_cmd);
6912 install_element(RMAP_NODE, &no_set_community_delete_cmd);
6913 install_element(RMAP_NODE, &set_lcommunity_cmd);
6914 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
6915 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
6916 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
76a20aa9 6917 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
d62a17ae 6918 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
6919 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
76a20aa9 6920 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
d62a17ae 6921 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
6922 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4db5ee8e 6923 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
d62a17ae 6924 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
6925 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4db5ee8e 6926 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
ca9ac3ef 6927 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
6928 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
6929 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
bb4dcdd1
DA
6930 install_element(RMAP_NODE, &set_ecommunity_none_cmd);
6931 install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
d6902373 6932#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 6933 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
6934 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 6935#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 6936 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
6937 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
6938 install_element(RMAP_NODE, &set_originator_id_cmd);
6939 install_element(RMAP_NODE, &no_set_originator_id_cmd);
6940
6941 route_map_install_match(&route_match_ipv6_address_cmd);
6942 route_map_install_match(&route_match_ipv6_next_hop_cmd);
bc63ba98 6943 route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
82f191a2 6944 route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
be7735b3 6945 route_map_install_match(&route_match_ipv4_next_hop_cmd);
d62a17ae 6946 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 6947 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 6948 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
6949 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
6950 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
6951 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
6952
6953 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
bc63ba98 6954 install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
82f191a2 6955 install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
d62a17ae 6956 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
bc63ba98 6957 install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
82f191a2 6958 install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
03030106
IR
6959 install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
6960 install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
be7735b3 6961 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
17ac51eb 6962 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
d62a17ae 6963 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
6964 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
6965 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
6966 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
6967 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
6968 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
fa22080d 6969#ifdef HAVE_SCRIPTING
b4becb06 6970 install_element(RMAP_NODE, &match_script_cmd);
1d7c7ace 6971#endif
d62a17ae 6972}
6973
6974void bgp_route_map_terminate(void)
6975{
6976 /* ToDo: Cleanup all the used memory */
d62a17ae 6977 route_map_finish();
518f0eb1 6978}