]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
bgpd: Wrap IPV4_CLASS_DE into ipv4_unicast_valid() helper
[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
DS
1970 /* Set local preference value. */
1971 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
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,
3870 int route_update)
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)) {
d62a17ae 4083 bgp_route_map_process_update(bgp, rmap_name, 1);
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))
4119 update_group_policy_update(bgp,
4120 BGP_POLICY_ROUTE_MAP,
4121 rmap_name, 1, 1);
4122 } else {
f6e7507e 4123 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
47c8fa1f 4124 bgp_route_map_process_update(bgp, rmap_name, 0);
49e5a4a0 4125#ifdef ENABLE_BGP_VNC
f6e7507e 4126 vnc_routemap_update(bgp, __func__);
65efcfce 4127#endif
f6e7507e
IR
4128 }
4129
4130 vpn_policy_routemap_event(rmap_name);
d62a17ae 4131 }
718e3744 4132}
6b0655a2 4133
d62a17ae 4134static void bgp_route_map_add(const char *rmap_name)
73ac8160 4135{
7096e938 4136 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4137 bgp_route_map_mark_update(rmap_name);
73ac8160 4138
d62a17ae 4139 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 4140}
518f0eb1 4141
d62a17ae 4142static void bgp_route_map_delete(const char *rmap_name)
73ac8160 4143{
7096e938 4144 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4145 bgp_route_map_mark_update(rmap_name);
73ac8160 4146
d62a17ae 4147 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 4148}
518f0eb1 4149
097b5973 4150static void bgp_route_map_event(const char *rmap_name)
73ac8160 4151{
7096e938 4152 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 4153 bgp_route_map_mark_update(rmap_name);
518f0eb1 4154
d62a17ae 4155 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
4156}
4157
48cb7ea9
SP
4158DEFUN_YANG (match_mac_address,
4159 match_mac_address_cmd,
c60dec36 4160 "match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4161 MATCH_STR
4162 "mac address\n"
4163 "Match address of route\n"
4164 "MAC Access-list name\n")
d37ba549 4165{
48cb7ea9
SP
4166 const char *xpath =
4167 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4168 char xpath_value[XPATH_MAXLEN];
4169
4170 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4171 snprintf(xpath_value, sizeof(xpath_value),
4172 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4173 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4174
4175 return nb_cli_apply_changes(vty, NULL);
d37ba549
MK
4176}
4177
48cb7ea9
SP
4178DEFUN_YANG (no_match_mac_address,
4179 no_match_mac_address_cmd,
c60dec36 4180 "no match mac address ACCESSLIST_MAC_NAME",
48cb7ea9
SP
4181 NO_STR
4182 MATCH_STR
4183 "mac\n"
4184 "Match address of route\n"
4185 "MAC acess-list name\n")
d37ba549 4186{
48cb7ea9
SP
4187 const char *xpath =
4188 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4189
4190 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4191 return nb_cli_apply_changes(vty, NULL);
d37ba549 4192}
73ac8160 4193
38677473
SW
4194/*
4195 * Helper to handle the case of the user passing in a number or type string
4196 */
4197static const char *parse_evpn_rt_type(const char *num_rt_type)
4198{
4199 switch (num_rt_type[0]) {
4200 case '1':
4201 return "ead";
4202 case '2':
4203 return "macip";
4204 case '3':
4205 return "multicast";
4206 case '4':
4207 return "es";
4208 case '5':
4209 return "prefix";
4210 default:
4211 break;
4212 }
4213
4214 /* Was already full type string */
4215 return num_rt_type;
4216}
4217
48cb7ea9
SP
4218DEFUN_YANG (match_evpn_route_type,
4219 match_evpn_route_type_cmd,
2514d231 4220 "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4221 MATCH_STR
4222 EVPN_HELP_STR
4223 EVPN_TYPE_HELP_STR
bd44ab08
CS
4224 EVPN_TYPE_1_HELP_STR
4225 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4226 EVPN_TYPE_2_HELP_STR
4227 EVPN_TYPE_2_HELP_STR
4228 EVPN_TYPE_3_HELP_STR
4229 EVPN_TYPE_3_HELP_STR
2514d231
CS
4230 EVPN_TYPE_4_HELP_STR
4231 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4232 EVPN_TYPE_5_HELP_STR
4233 EVPN_TYPE_5_HELP_STR)
38677473 4234{
48cb7ea9
SP
4235 const char *xpath =
4236 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4237 char xpath_value[XPATH_MAXLEN];
33c2ff62 4238
48cb7ea9
SP
4239 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4240 snprintf(xpath_value, sizeof(xpath_value),
4241 "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4242 xpath);
4243 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4244 parse_evpn_rt_type(argv[3]->arg));
33c2ff62 4245
48cb7ea9
SP
4246 return nb_cli_apply_changes(vty, NULL);
4247}
4248
4249DEFUN_YANG (no_match_evpn_route_type,
4250 no_match_evpn_route_type_cmd,
2514d231 4251 "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
48cb7ea9
SP
4252 NO_STR
4253 MATCH_STR
4254 EVPN_HELP_STR
4255 EVPN_TYPE_HELP_STR
bd44ab08
CS
4256 EVPN_TYPE_1_HELP_STR
4257 EVPN_TYPE_1_HELP_STR
48cb7ea9
SP
4258 EVPN_TYPE_2_HELP_STR
4259 EVPN_TYPE_2_HELP_STR
4260 EVPN_TYPE_3_HELP_STR
4261 EVPN_TYPE_3_HELP_STR
2514d231
CS
4262 EVPN_TYPE_4_HELP_STR
4263 EVPN_TYPE_4_HELP_STR
48cb7ea9
SP
4264 EVPN_TYPE_5_HELP_STR
4265 EVPN_TYPE_5_HELP_STR)
16f7ce2b 4266{
48cb7ea9
SP
4267 const char *xpath =
4268 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4269
4270 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4271
4272 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4273}
4274
48cb7ea9
SP
4275
4276DEFUN_YANG (match_evpn_vni,
4277 match_evpn_vni_cmd,
4278 "match evpn vni " CMD_VNI_RANGE,
4279 MATCH_STR
4280 EVPN_HELP_STR
4281 "Match VNI\n"
4282 "VNI ID\n")
4283{
4284 const char *xpath =
4285 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4286 char xpath_value[XPATH_MAXLEN];
4287
4288 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4289 snprintf(xpath_value, sizeof(xpath_value),
4290 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4291 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4292
4293 return nb_cli_apply_changes(vty, NULL);
4294}
4295
4296DEFUN_YANG (no_match_evpn_vni,
4297 no_match_evpn_vni_cmd,
4298 "no match evpn vni " CMD_VNI_RANGE,
4299 NO_STR
4300 MATCH_STR
4301 EVPN_HELP_STR
4302 "Match VNI\n"
4303 "VNI ID\n")
16f7ce2b 4304{
48cb7ea9
SP
4305 const char *xpath =
4306 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4307 char xpath_value[XPATH_MAXLEN];
4308
4309 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4310 snprintf(xpath_value, sizeof(xpath_value),
4311 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4312 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4313
4314 return nb_cli_apply_changes(vty, NULL);
16f7ce2b
MK
4315}
4316
48cb7ea9
SP
4317DEFUN_YANG (match_evpn_default_route,
4318 match_evpn_default_route_cmd,
4319 "match evpn default-route",
4320 MATCH_STR
4321 EVPN_HELP_STR
4322 "default EVPN type-5 route\n")
6fb219da 4323{
48cb7ea9
SP
4324 const char *xpath =
4325 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4326 char xpath_value[XPATH_MAXLEN];
4327
4328 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4329
4330 snprintf(xpath_value, sizeof(xpath_value),
4331 "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4332 xpath);
4333 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4334
4335 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4336}
4337
48cb7ea9
SP
4338DEFUN_YANG (no_match_evpn_default_route,
4339 no_match_evpn_default_route_cmd,
4340 "no match evpn default-route",
4341 NO_STR
4342 MATCH_STR
4343 EVPN_HELP_STR
4344 "default EVPN type-5 route\n")
6fb219da 4345{
48cb7ea9
SP
4346 const char *xpath =
4347 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4348
4349 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4350
4351 return nb_cli_apply_changes(vty, NULL);
6fb219da
MK
4352}
4353
48cb7ea9
SP
4354DEFUN_YANG (match_evpn_rd,
4355 match_evpn_rd_cmd,
4356 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4357 MATCH_STR
4358 EVPN_HELP_STR
4359 "Route Distinguisher\n"
4360 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4361{
48cb7ea9
SP
4362 const char *xpath =
4363 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4364 char xpath_value[XPATH_MAXLEN];
4365
4366 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4367 snprintf(
4368 xpath_value, sizeof(xpath_value),
4369 "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4370 xpath);
4371 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4372
4373 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4374}
4375
48cb7ea9
SP
4376DEFUN_YANG (no_match_evpn_rd,
4377 no_match_evpn_rd_cmd,
4378 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4379 NO_STR
4380 MATCH_STR
4381 EVPN_HELP_STR
4382 "Route Distinguisher\n"
4383 "ASN:XX or A.B.C.D:XX\n")
196c6b09 4384{
48cb7ea9
SP
4385 const char *xpath =
4386 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4387
4388 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4389 return nb_cli_apply_changes(vty, NULL);
196c6b09
LK
4390}
4391
d0a4ee60
AD
4392DEFUN_YANG (set_evpn_gw_ip_ipv4,
4393 set_evpn_gw_ip_ipv4_cmd,
4394 "set evpn gateway-ip ipv4 A.B.C.D",
4395 SET_STR
4396 EVPN_HELP_STR
4397 "Set gateway IP for prefix advertisement route\n"
4398 "IPv4 address\n"
4399 "Gateway IP address in IPv4 format\n")
4400{
4401 int ret;
4402 union sockunion su;
4403 const char *xpath =
4404 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4405 char xpath_value[XPATH_MAXLEN];
4406
4407 ret = str2sockunion(argv[4]->arg, &su);
4408 if (ret < 0) {
4409 vty_out(vty, "%% Malformed gateway IP\n");
4410 return CMD_WARNING_CONFIG_FAILED;
4411 }
4412
e24a6977
DA
4413 if (su.sin.sin_addr.s_addr == 0 ||
4414 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4415 vty_out(vty,
4416 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4417 return CMD_WARNING_CONFIG_FAILED;
4418 }
4419
4420 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4421
4422 snprintf(xpath_value, sizeof(xpath_value),
4423 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4424 xpath);
4425
4426 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4427 return nb_cli_apply_changes(vty, NULL);
4428}
4429
4430DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4431 no_set_evpn_gw_ip_ipv4_cmd,
4432 "no set evpn gateway-ip ipv4 A.B.C.D",
4433 NO_STR
4434 SET_STR
4435 EVPN_HELP_STR
4436 "Set gateway IP for prefix advertisement route\n"
4437 "IPv4 address\n"
4438 "Gateway IP address in IPv4 format\n")
4439{
4440 int ret;
4441 union sockunion su;
4442 const char *xpath =
4443 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4444
4445 ret = str2sockunion(argv[5]->arg, &su);
4446 if (ret < 0) {
4447 vty_out(vty, "%% Malformed gateway IP\n");
4448 return CMD_WARNING_CONFIG_FAILED;
4449 }
4450
e24a6977
DA
4451 if (su.sin.sin_addr.s_addr == 0 ||
4452 !ipv4_unicast_valid(&su.sin.sin_addr)) {
d0a4ee60
AD
4453 vty_out(vty,
4454 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4455 return CMD_WARNING_CONFIG_FAILED;
4456 }
4457
4458 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4459
4460 return nb_cli_apply_changes(vty, NULL);
4461}
4462
4463DEFUN_YANG (set_evpn_gw_ip_ipv6,
4464 set_evpn_gw_ip_ipv6_cmd,
4465 "set evpn gateway-ip ipv6 X:X::X:X",
4466 SET_STR
4467 EVPN_HELP_STR
4468 "Set gateway IP for prefix advertisement route\n"
4469 "IPv6 address\n"
4470 "Gateway IP address in IPv6 format\n")
4471{
4472 int ret;
4473 union sockunion su;
4474 const char *xpath =
4475 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4476 char xpath_value[XPATH_MAXLEN];
4477
4478 ret = str2sockunion(argv[4]->arg, &su);
4479 if (ret < 0) {
4480 vty_out(vty, "%% Malformed gateway IP\n");
4481 return CMD_WARNING_CONFIG_FAILED;
4482 }
4483
4484 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4485 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4486 vty_out(vty,
4487 "%% Gateway IP cannot be a linklocal or multicast address\n");
4488 return CMD_WARNING_CONFIG_FAILED;
4489 }
4490
4491 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4492
4493 snprintf(xpath_value, sizeof(xpath_value),
4494 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4495 xpath);
4496
4497 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4498 return nb_cli_apply_changes(vty, NULL);
4499}
4500
4501DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4502 no_set_evpn_gw_ip_ipv6_cmd,
4503 "no set evpn gateway-ip ipv6 X:X::X:X",
4504 NO_STR
4505 SET_STR
4506 EVPN_HELP_STR
4507 "Set gateway IP for prefix advertisement route\n"
4508 "IPv4 address\n"
4509 "Gateway IP address in IPv4 format\n")
4510{
4511 int ret;
4512 union sockunion su;
4513 const char *xpath =
4514 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4515
4516 ret = str2sockunion(argv[5]->arg, &su);
4517 if (ret < 0) {
4518 vty_out(vty, "%% Malformed gateway IP\n");
4519 return CMD_WARNING_CONFIG_FAILED;
4520 }
4521
4522 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4523 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4524 vty_out(vty,
4525 "%% Gateway IP cannot be a linklocal or multicast address\n");
4526 return CMD_WARNING_CONFIG_FAILED;
4527 }
4528
4529 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4530
4531 return nb_cli_apply_changes(vty, NULL);
4532}
4533
48cb7ea9 4534DEFPY_YANG(match_vrl_source_vrf,
1dcc9e5b
CS
4535 match_vrl_source_vrf_cmd,
4536 "match source-vrf NAME$vrf_name",
4537 MATCH_STR
4538 "source vrf\n"
4539 "The VRF name\n")
4540{
48cb7ea9
SP
4541 const char *xpath =
4542 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4543 char xpath_value[XPATH_MAXLEN];
4544
4545 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4546 snprintf(xpath_value, sizeof(xpath_value),
4547 "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4548 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4549
4550 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4551}
4552
48cb7ea9 4553DEFPY_YANG(no_match_vrl_source_vrf,
1dcc9e5b
CS
4554 no_match_vrl_source_vrf_cmd,
4555 "no match source-vrf NAME$vrf_name",
48cb7ea9 4556 NO_STR MATCH_STR
1dcc9e5b
CS
4557 "source vrf\n"
4558 "The VRF name\n")
4559{
48cb7ea9
SP
4560 const char *xpath =
4561 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4562
4563 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4564 return nb_cli_apply_changes(vty, NULL);
1dcc9e5b
CS
4565}
4566
48cb7ea9 4567DEFPY_YANG (match_peer,
fee0f4c6 4568 match_peer_cmd,
48cb7ea9 4569 "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
fee0f4c6 4570 MATCH_STR
4571 "Match peer address\n"
6e13ed4a 4572 "IP address of peer\n"
8c3433e4 4573 "IPv6 address of peer\n"
1bb1c0cf 4574 "Interface name of peer or peer group name\n")
fee0f4c6 4575{
48cb7ea9
SP
4576 const char *xpath =
4577 "./match-condition[condition='frr-bgp-route-map:peer']";
4578 char xpath_value[XPATH_MAXLEN];
4579
4580 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4581
4582 if (addrv4_str) {
4583 snprintf(
4584 xpath_value, sizeof(xpath_value),
4585 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4586 xpath);
4587 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4588 addrv4_str);
4589 } else if (addrv6_str) {
4590 snprintf(
4591 xpath_value, sizeof(xpath_value),
4592 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4593 xpath);
4594 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4595 addrv6_str);
4596 } else {
4597 snprintf(
4598 xpath_value, sizeof(xpath_value),
4599 "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4600 xpath);
4601 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4602 }
4603
4604 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4605}
4606
48cb7ea9
SP
4607DEFUN_YANG (match_peer_local,
4608 match_peer_local_cmd,
4609 "match peer local",
4610 MATCH_STR
4611 "Match peer address\n"
4612 "Static or Redistributed routes\n")
fee0f4c6 4613{
48cb7ea9
SP
4614 const char *xpath =
4615 "./match-condition[condition='frr-bgp-route-map:peer']";
4616 char xpath_value[XPATH_MAXLEN];
4617
4618 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4619
4620 snprintf(xpath_value, sizeof(xpath_value),
4621 "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4622 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4623
4624 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4625}
4626
48cb7ea9
SP
4627DEFUN_YANG (no_match_peer,
4628 no_match_peer_cmd,
4629 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4630 NO_STR
4631 MATCH_STR
4632 "Match peer address\n"
4633 "Static or Redistributed routes\n"
4634 "IP address of peer\n"
4635 "IPv6 address of peer\n"
4636 "Interface name of peer\n")
fee0f4c6 4637{
48cb7ea9
SP
4638 const char *xpath =
4639 "./match-condition[condition='frr-bgp-route-map:peer']";
4640
4641 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4c9bd275 4642
48cb7ea9 4643 return nb_cli_apply_changes(vty, NULL);
fee0f4c6 4644}
4645
fa22080d 4646#ifdef HAVE_SCRIPTING
48cb7ea9
SP
4647DEFUN_YANG (match_script,
4648 match_script_cmd,
4649 "[no] match script WORD",
4650 NO_STR
4651 MATCH_STR
4652 "Execute script to determine match\n"
4653 "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
1d7c7ace 4654{
b4becb06
QY
4655 bool no = strmatch(argv[0]->text, "no");
4656 int i = 0;
4657 argv_find(argv, argc, "WORD", &i);
4658 const char *script = argv[i]->arg;
48cb7ea9
SP
4659 const char *xpath =
4660 "./match-condition[condition='frr-bgp-route-map:match-script']";
4661 char xpath_value[XPATH_MAXLEN];
b4becb06
QY
4662
4663 if (no) {
48cb7ea9
SP
4664 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4665 snprintf(xpath_value, sizeof(xpath_value),
4666 "%s/rmap-match-condition/frr-bgp-route-map:script",
4667 xpath);
4668 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4669 script);
4670
4671 return nb_cli_apply_changes(vty, NULL);
b4becb06 4672 }
48cb7ea9
SP
4673
4674 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4675 snprintf(xpath_value, sizeof(xpath_value),
4676 "%s/rmap-match-condition/frr-bgp-route-map:script",
4677 xpath);
4678 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4679 script);
4680
4681 return nb_cli_apply_changes(vty, NULL);
1d7c7ace 4682}
fa22080d 4683#endif /* HAVE_SCRIPTING */
fee0f4c6 4684
4c9bd275 4685/* match probability */
48cb7ea9
SP
4686DEFUN_YANG (match_probability,
4687 match_probability_cmd,
4688 "match probability (0-100)",
4689 MATCH_STR
4690 "Match portion of routes defined by percentage value\n"
4691 "Percentage of routes\n")
1add115a 4692{
d62a17ae 4693 int idx_number = 2;
48cb7ea9
SP
4694
4695 const char *xpath =
4696 "./match-condition[condition='frr-bgp-route-map:probability']";
4697 char xpath_value[XPATH_MAXLEN];
4698
4699 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4700 snprintf(xpath_value, sizeof(xpath_value),
4701 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4702 xpath);
4703 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4704 argv[idx_number]->arg);
4705
4706 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4707}
4708
4c9bd275 4709
48cb7ea9
SP
4710DEFUN_YANG (no_match_probability,
4711 no_match_probability_cmd,
4712 "no match probability [(1-99)]",
4713 NO_STR
4714 MATCH_STR
4715 "Match portion of routes defined by percentage value\n"
4716 "Percentage of routes\n")
1add115a 4717{
d62a17ae 4718 int idx_number = 3;
48cb7ea9
SP
4719 const char *xpath =
4720 "./match-condition[condition='frr-bgp-route-map:probability']";
4721 char xpath_value[XPATH_MAXLEN];
4722
4723 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4724
d62a17ae 4725 if (argc <= idx_number)
48cb7ea9
SP
4726 return nb_cli_apply_changes(vty, NULL);
4727
4728 snprintf(xpath_value, sizeof(xpath_value),
4729 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4730 xpath);
4731 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4732 argv[idx_number]->arg);
4733
4734 return nb_cli_apply_changes(vty, NULL);
1add115a
VT
4735}
4736
1add115a 4737
48cb7ea9 4738DEFPY_YANG (match_ip_route_source,
c1643bb7 4739 match_ip_route_source_cmd,
c60dec36 4740 "match ip route-source ACCESSLIST4_NAME",
c1643bb7 4741 MATCH_STR
4742 IP_STR
4743 "Match advertising source address of route\n"
7e869991 4744 "IP Access-list name\n")
c1643bb7 4745{
48cb7ea9
SP
4746 const char *xpath =
4747 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4748 char xpath_value[XPATH_MAXLEN + 32];
d62a17ae 4749 int idx_acl = 3;
48cb7ea9
SP
4750
4751 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4752 snprintf(xpath_value, sizeof(xpath_value),
4753 "%s/rmap-match-condition/frr-bgp-route-map:list-name",
4754 xpath);
4755 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4756 argv[idx_acl]->arg);
4757
4758 return nb_cli_apply_changes(vty, NULL);
c1643bb7 4759}
4760
4c9bd275 4761
48cb7ea9
SP
4762DEFUN_YANG (no_match_ip_route_source,
4763 no_match_ip_route_source_cmd,
c60dec36 4764 "no match ip route-source [ACCESSLIST4_NAME]",
48cb7ea9
SP
4765 NO_STR
4766 MATCH_STR
4767 IP_STR
4768 "Match advertising source address of route\n"
7e869991 4769 "IP Access-list name\n")
c1643bb7 4770{
48cb7ea9
SP
4771 const char *xpath =
4772 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
c1643bb7 4773
48cb7ea9
SP
4774 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4775 return nb_cli_apply_changes(vty, NULL);
4776}
c1643bb7 4777
48cb7ea9
SP
4778DEFUN_YANG (match_ip_route_source_prefix_list,
4779 match_ip_route_source_prefix_list_cmd,
943224a1 4780 "match ip route-source prefix-list PREFIXLIST_NAME",
48cb7ea9
SP
4781 MATCH_STR
4782 IP_STR
4783 "Match advertising source address of route\n"
4784 "Match entries of prefix-lists\n"
4785 "IP prefix-list name\n")
c1643bb7 4786{
d62a17ae 4787 int idx_word = 4;
48cb7ea9
SP
4788 const char *xpath =
4789 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4790 char xpath_value[XPATH_MAXLEN + 32];
4791
4792 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4793 snprintf(xpath_value, sizeof(xpath_value),
4794 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4795 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4796 argv[idx_word]->arg);
4797
4798 return nb_cli_apply_changes(vty, NULL);
c1643bb7 4799}
4800
4c9bd275 4801
48cb7ea9
SP
4802DEFUN_YANG (no_match_ip_route_source_prefix_list,
4803 no_match_ip_route_source_prefix_list_cmd,
943224a1 4804 "no match ip route-source prefix-list [PREFIXLIST_NAME]",
48cb7ea9
SP
4805 NO_STR
4806 MATCH_STR
4807 IP_STR
4808 "Match advertising source address of route\n"
4809 "Match entries of prefix-lists\n"
4810 "IP prefix-list name\n")
c1643bb7 4811{
48cb7ea9
SP
4812 const char *xpath =
4813 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
c1643bb7 4814
48cb7ea9
SP
4815 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4816 return nb_cli_apply_changes(vty, NULL);
4817}
c1643bb7 4818
48cb7ea9
SP
4819DEFUN_YANG (match_local_pref,
4820 match_local_pref_cmd,
4821 "match local-preference (0-4294967295)",
4822 MATCH_STR
4823 "Match local-preference of route\n"
4824 "Metric value\n")
af291c15 4825{
d62a17ae 4826 int idx_number = 2;
48cb7ea9
SP
4827
4828 const char *xpath =
4829 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
4830 char xpath_value[XPATH_MAXLEN];
4831
4832 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4833 snprintf(xpath_value, sizeof(xpath_value),
4834 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
4835 xpath);
4836 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4837 argv[idx_number]->arg);
4838
4839 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
4840}
4841
4c9bd275 4842
48cb7ea9
SP
4843DEFUN_YANG (no_match_local_pref,
4844 no_match_local_pref_cmd,
4845 "no match local-preference [(0-4294967295)]",
4846 NO_STR
4847 MATCH_STR
4848 "Match local preference of route\n"
4849 "Local preference value\n")
af291c15 4850{
d62a17ae 4851 int idx_localpref = 3;
48cb7ea9
SP
4852 const char *xpath =
4853 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
4854 char xpath_value[XPATH_MAXLEN];
4855
4856 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4857
d62a17ae 4858 if (argc <= idx_localpref)
48cb7ea9
SP
4859 return nb_cli_apply_changes(vty, NULL);
4860
4861 snprintf(xpath_value, sizeof(xpath_value),
4862 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
4863 xpath);
4864 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4865 argv[idx_localpref]->arg);
4866
4867 return nb_cli_apply_changes(vty, NULL);
af291c15
DS
4868}
4869
2690f18c
DA
4870DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
4871 MATCH_STR
4872 "Match BGP community alias name\n"
4873 "BGP community alias name\n")
4874{
4875 const char *alias = argv[2]->arg;
4876 struct community_alias ca1;
4877 struct community_alias *lookup_alias;
4878
4879 const char *xpath =
4880 "./match-condition[condition='frr-bgp-route-map:match-alias']";
4881 char xpath_value[XPATH_MAXLEN];
4882
4883 memset(&ca1, 0, sizeof(ca1));
4884 strlcpy(ca1.alias, alias, sizeof(ca1.alias));
4885 lookup_alias = bgp_ca_alias_lookup(&ca1);
4886 if (!lookup_alias) {
4887 vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
4888 return CMD_WARNING_CONFIG_FAILED;
4889 }
4890
4891 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4892 snprintf(xpath_value, sizeof(xpath_value),
4893 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
4894 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
4895
4896 return nb_cli_apply_changes(vty, NULL);
4897}
4898
4899
4900DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
4901 NO_STR MATCH_STR
4902 "Match BGP community alias name\n"
4903 "BGP community alias name\n")
4904{
4905 int idx_alias = 3;
4906 const char *xpath =
4907 "./match-condition[condition='frr-bgp-route-map:match-alias']";
4908 char xpath_value[XPATH_MAXLEN];
4909
4910 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4911
4912 if (argc <= idx_alias)
4913 return nb_cli_apply_changes(vty, NULL);
4914
4915 snprintf(xpath_value, sizeof(xpath_value),
4916 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
4917 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4918 argv[idx_alias]->arg);
4919
4920 return nb_cli_apply_changes(vty, NULL);
4921}
af291c15 4922
48cb7ea9 4923DEFPY_YANG (match_community,
718e3744 4924 match_community_cmd,
a2099c1d 4925 "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
718e3744 4926 MATCH_STR
4927 "Match BGP community list\n"
4928 "Community-list number (standard)\n"
4929 "Community-list number (expanded)\n"
4930 "Community-list name\n"
4931 "Do exact matching of communities\n")
4932{
48cb7ea9
SP
4933 const char *xpath =
4934 "./match-condition[condition='frr-bgp-route-map:match-community']";
4935 char xpath_value[XPATH_MAXLEN];
4936 char xpath_match[XPATH_MAXLEN];
d62a17ae 4937 int idx_comm_list = 2;
718e3744 4938
48cb7ea9 4939 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 4940
48cb7ea9
SP
4941 snprintf(
4942 xpath_value, sizeof(xpath_value),
4943 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
4944 xpath);
4945 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
718e3744 4946
48cb7ea9
SP
4947 if (argc == 4) {
4948 snprintf(
4949 xpath_match, sizeof(xpath_match),
4950 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
4951 xpath);
4952 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
4953 "true");
4954 } else {
4955 snprintf(
4956 xpath_match, sizeof(xpath_match),
4957 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
4958 xpath);
4959 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
4960 "false");
4961 }
718e3744 4962
48cb7ea9
SP
4963 return nb_cli_apply_changes(vty, NULL);
4964}
4965
4966DEFUN_YANG (no_match_community,
4967 no_match_community_cmd,
a2099c1d 4968 "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
4969 NO_STR
4970 MATCH_STR
4971 "Match BGP community list\n"
4972 "Community-list number (standard)\n"
4973 "Community-list number (expanded)\n"
4974 "Community-list name\n"
4975 "Do exact matching of communities\n")
4976{
4977 const char *xpath =
4978 "./match-condition[condition='frr-bgp-route-map:match-community']";
4979
4980 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4981 return nb_cli_apply_changes(vty, NULL);
4982}
4983
4984DEFPY_YANG (match_lcommunity,
4985 match_lcommunity_cmd,
a2099c1d 4986 "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
48cb7ea9
SP
4987 MATCH_STR
4988 "Match BGP large community list\n"
4989 "Large Community-list number (standard)\n"
4990 "Large Community-list number (expanded)\n"
4991 "Large Community-list name\n"
4992 "Do exact matching of communities\n")
4993{
4994 const char *xpath =
4995 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
4996 char xpath_value[XPATH_MAXLEN];
4997 char xpath_match[XPATH_MAXLEN];
03ff9a14 4998 int idx_lcomm_list = 2;
03ff9a14 4999
48cb7ea9 5000 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
03ff9a14 5001
48cb7ea9
SP
5002 snprintf(
5003 xpath_value, sizeof(xpath_value),
5004 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5005 xpath);
5006 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
03ff9a14 5007
48cb7ea9
SP
5008 if (argc == 4) {
5009 snprintf(
5010 xpath_match, sizeof(xpath_match),
5011 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5012 xpath);
5013 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5014 "true");
5015 } else {
5016 snprintf(
5017 xpath_match, sizeof(xpath_match),
5018 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5019 xpath);
5020 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5021 "false");
5022 }
03ff9a14 5023
48cb7ea9 5024 return nb_cli_apply_changes(vty, NULL);
57d187bc 5025}
718e3744 5026
48cb7ea9
SP
5027DEFUN_YANG (no_match_lcommunity,
5028 no_match_lcommunity_cmd,
a2099c1d 5029 "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
48cb7ea9
SP
5030 NO_STR
5031 MATCH_STR
5032 "Match BGP large community list\n"
5033 "Large Community-list number (standard)\n"
5034 "Large Community-list number (expanded)\n"
5035 "Large Community-list name\n"
5036 "Do exact matching of communities\n")
57d187bc 5037{
48cb7ea9
SP
5038 const char *xpath =
5039 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5040
5041 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5042 return nb_cli_apply_changes(vty, NULL);
57d187bc 5043}
718e3744 5044
48cb7ea9
SP
5045DEFPY_YANG (match_ecommunity,
5046 match_ecommunity_cmd,
a2099c1d 5047 "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
48cb7ea9
SP
5048 MATCH_STR
5049 "Match BGP/VPN extended community list\n"
5050 "Extended community-list number (standard)\n"
5051 "Extended community-list number (expanded)\n"
5052 "Extended community-list name\n")
73ffb25b 5053{
48cb7ea9
SP
5054 const char *xpath =
5055 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5056 char xpath_value[XPATH_MAXLEN];
d62a17ae 5057 int idx_comm_list = 2;
48cb7ea9
SP
5058
5059 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5060
5061 snprintf(
5062 xpath_value, sizeof(xpath_value),
5063 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5064 xpath);
5065 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5066
5067 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5068}
5069
4c9bd275 5070
48cb7ea9
SP
5071DEFUN_YANG (no_match_ecommunity,
5072 no_match_ecommunity_cmd,
a2099c1d 5073 "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
48cb7ea9
SP
5074 NO_STR
5075 MATCH_STR
5076 "Match BGP/VPN extended community list\n"
5077 "Extended community-list number (standard)\n"
5078 "Extended community-list number (expanded)\n"
5079 "Extended community-list name\n")
73ffb25b 5080{
48cb7ea9
SP
5081 const char *xpath =
5082 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5083
5084 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5085 return nb_cli_apply_changes(vty, NULL);
73ffb25b 5086}
5087
73ffb25b 5088
48cb7ea9
SP
5089DEFUN_YANG (match_aspath,
5090 match_aspath_cmd,
2a342b35 5091 "match as-path AS_PATH_FILTER_NAME",
48cb7ea9
SP
5092 MATCH_STR
5093 "Match BGP AS path list\n"
5094 "AS path access-list name\n")
718e3744 5095{
d62a17ae 5096 int idx_word = 2;
48cb7ea9
SP
5097
5098 const char *xpath =
5099 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5100 char xpath_value[XPATH_MAXLEN];
5101
5102 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5103 snprintf(xpath_value, sizeof(xpath_value),
5104 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5105 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5106 argv[idx_word]->arg);
5107
5108 return nb_cli_apply_changes(vty, NULL);
718e3744 5109}
5110
4c9bd275 5111
48cb7ea9
SP
5112DEFUN_YANG (no_match_aspath,
5113 no_match_aspath_cmd,
2a342b35 5114 "no match as-path [AS_PATH_FILTER_NAME]",
48cb7ea9
SP
5115 NO_STR
5116 MATCH_STR
5117 "Match BGP AS path list\n"
5118 "AS path access-list name\n")
718e3744 5119{
48cb7ea9
SP
5120 const char *xpath =
5121 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
718e3744 5122
48cb7ea9 5123 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
718e3744 5124
48cb7ea9
SP
5125 return nb_cli_apply_changes(vty, NULL);
5126}
5127
5128DEFUN_YANG (match_origin,
5129 match_origin_cmd,
5130 "match origin <egp|igp|incomplete>",
5131 MATCH_STR
5132 "BGP origin code\n"
5133 "remote EGP\n"
5134 "local IGP\n"
5135 "unknown heritage\n")
718e3744 5136{
d62a17ae 5137 int idx_origin = 2;
48cb7ea9
SP
5138 const char *origin_type;
5139 const char *xpath =
5140 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5141 char xpath_value[XPATH_MAXLEN];
5142
d62a17ae 5143 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
48cb7ea9
SP
5144 origin_type = "igp";
5145 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5146 origin_type = "egp";
5147 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5148 origin_type = "incomplete";
5149 else {
5150 vty_out(vty, "%% Invalid match origin type\n");
5151 return CMD_WARNING_CONFIG_FAILED;
5152 }
5153
5154 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5155 snprintf(xpath_value, sizeof(xpath_value),
5156 "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5157 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
718e3744 5158
48cb7ea9 5159 return nb_cli_apply_changes(vty, NULL);
718e3744 5160}
5161
4c9bd275 5162
48cb7ea9
SP
5163DEFUN_YANG (no_match_origin,
5164 no_match_origin_cmd,
5165 "no match origin [<egp|igp|incomplete>]",
5166 NO_STR
5167 MATCH_STR
5168 "BGP origin code\n"
5169 "remote EGP\n"
5170 "local IGP\n"
5171 "unknown heritage\n")
718e3744 5172{
48cb7ea9
SP
5173 const char *xpath =
5174 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5175 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5176 return nb_cli_apply_changes(vty, NULL);
718e3744 5177}
5178
48cb7ea9
SP
5179DEFUN_YANG (set_table_id,
5180 set_table_id_cmd,
5181 "set table (1-4294967295)",
5182 SET_STR
5183 "export route to non-main kernel table\n"
5184 "Kernel routing table id\n")
951745bd 5185{
48cb7ea9
SP
5186 int idx_number = 2;
5187 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5188 char xpath_value[XPATH_MAXLEN];
5189
5190 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5191 snprintf(xpath_value, sizeof(xpath_value),
5192 "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5193 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5194 argv[idx_number]->arg);
5195 return nb_cli_apply_changes(vty, NULL);
5196}
5197
5198DEFUN_YANG (no_set_table_id,
5199 no_set_table_id_cmd,
5200 "no set table",
5201 NO_STR
5202 SET_STR
5203 "export route to non-main kernel table\n")
5204{
5205 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5206 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5207 return nb_cli_apply_changes(vty, NULL);
5208}
5209
5210DEFUN_YANG (set_ip_nexthop_peer,
5211 set_ip_nexthop_peer_cmd,
5212 "[no] set ip next-hop peer-address",
5213 NO_STR
5214 SET_STR
5215 IP_STR
5216 "Next hop address\n"
5217 "Use peer address (for BGP only)\n")
5218{
5219 char xpath_value[XPATH_MAXLEN];
5220 const char *xpath =
5221 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5222
5223 if (strmatch(argv[0]->text, "no"))
5224 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5225 else {
5226 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5227 snprintf(xpath_value, sizeof(xpath_value),
5228 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5229 xpath);
5230 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5231 "peer-address");
5232 }
5233 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5234}
5235
48cb7ea9
SP
5236DEFUN_YANG (set_ip_nexthop_unchanged,
5237 set_ip_nexthop_unchanged_cmd,
5238 "[no] set ip next-hop unchanged",
5239 NO_STR
5240 SET_STR
5241 IP_STR
5242 "Next hop address\n"
5243 "Don't modify existing Next hop address\n")
951745bd 5244{
48cb7ea9
SP
5245 char xpath_value[XPATH_MAXLEN];
5246 const char *xpath =
5247 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
951745bd 5248
48cb7ea9
SP
5249 if (strmatch(argv[0]->text, "no"))
5250 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5251 else {
5252 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5253 snprintf(xpath_value, sizeof(xpath_value),
5254 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5255 xpath);
5256 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5257 "unchanged");
5258 }
5259 return nb_cli_apply_changes(vty, NULL);
951745bd
PG
5260}
5261
48cb7ea9
SP
5262DEFUN_YANG (set_distance,
5263 set_distance_cmd,
5264 "set distance (0-255)",
5265 SET_STR
5266 "BGP Administrative Distance to use\n"
5267 "Distance value\n")
af5cd0a5 5268{
48cb7ea9
SP
5269 int idx_number = 2;
5270 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5271 char xpath_value[XPATH_MAXLEN];
89602edb 5272
48cb7ea9
SP
5273 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5274 snprintf(xpath_value, sizeof(xpath_value),
5275 "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5276 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5277 argv[idx_number]->arg);
5278 return nb_cli_apply_changes(vty, NULL);
af5cd0a5 5279}
5280
48cb7ea9
SP
5281DEFUN_YANG (no_set_distance,
5282 no_set_distance_cmd,
5283 "no set distance [(0-255)]",
5284 NO_STR SET_STR
5285 "BGP Administrative Distance to use\n"
5286 "Distance value\n")
316e074d 5287{
48cb7ea9 5288 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
cca30ba8 5289
48cb7ea9
SP
5290 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5291 return nb_cli_apply_changes(vty, NULL);
718e3744 5292}
5293
48cb7ea9
SP
5294DEFUN_YANG (set_local_pref,
5295 set_local_pref_cmd,
5296 "set local-preference WORD",
5297 SET_STR
5298 "BGP local preference path attribute\n"
5299 "Preference value (0-4294967295)\n")
7b7d48e5
DS
5300{
5301 int idx_number = 2;
48cb7ea9
SP
5302 const char *xpath =
5303 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5304 char xpath_value[XPATH_MAXLEN];
7b7d48e5 5305
48cb7ea9
SP
5306 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5307 snprintf(xpath_value, sizeof(xpath_value),
5308 "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5309 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5310 argv[idx_number]->arg);
5311 return nb_cli_apply_changes(vty, NULL);
7b7d48e5
DS
5312}
5313
48cb7ea9
SP
5314DEFUN_YANG (no_set_local_pref,
5315 no_set_local_pref_cmd,
5316 "no set local-preference [WORD]",
5317 NO_STR
5318 SET_STR
5319 "BGP local preference path attribute\n"
5320 "Preference value (0-4294967295)\n")
7b7d48e5 5321{
48cb7ea9
SP
5322 const char *xpath =
5323 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5324
5325 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5326 return nb_cli_apply_changes(vty, NULL);
7b7d48e5 5327}
718e3744 5328
48cb7ea9
SP
5329DEFUN_YANG (set_weight,
5330 set_weight_cmd,
5331 "set weight (0-4294967295)",
5332 SET_STR
5333 "BGP weight for routing table\n"
5334 "Weight value\n")
718e3744 5335{
d62a17ae 5336 int idx_number = 2;
48cb7ea9
SP
5337 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5338 char xpath_value[XPATH_MAXLEN];
4c9bd275 5339
48cb7ea9
SP
5340 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5341 snprintf(xpath_value, sizeof(xpath_value),
5342 "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5343 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5344 argv[idx_number]->arg);
5345 return nb_cli_apply_changes(vty, NULL);
718e3744 5346}
5347
48cb7ea9
SP
5348DEFUN_YANG (no_set_weight,
5349 no_set_weight_cmd,
5350 "no set weight [(0-4294967295)]",
5351 NO_STR
5352 SET_STR
5353 "BGP weight for routing table\n"
5354 "Weight value\n")
718e3744 5355{
48cb7ea9 5356 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
718e3744 5357
48cb7ea9
SP
5358 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5359 return nb_cli_apply_changes(vty, NULL);
718e3744 5360}
5361
48cb7ea9
SP
5362DEFUN_YANG (set_label_index,
5363 set_label_index_cmd,
5364 "set label-index (0-1048560)",
5365 SET_STR
5366 "Label index to associate with the prefix\n"
5367 "Label index value\n")
d990e384 5368{
d62a17ae 5369 int idx_number = 2;
48cb7ea9
SP
5370 const char *xpath =
5371 "./set-action[action='frr-bgp-route-map:label-index']";
5372 char xpath_value[XPATH_MAXLEN];
5373
5374 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5375 snprintf(xpath_value, sizeof(xpath_value),
5376 "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5377 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5378 argv[idx_number]->arg);
5379 return nb_cli_apply_changes(vty, NULL);
d990e384
DS
5380}
5381
48cb7ea9
SP
5382DEFUN_YANG (no_set_label_index,
5383 no_set_label_index_cmd,
5384 "no set label-index [(0-1048560)]",
5385 NO_STR
5386 SET_STR
5387 "Label index to associate with the prefix\n"
5388 "Label index value\n")
d990e384 5389{
48cb7ea9
SP
5390 const char *xpath =
5391 "./set-action[action='frr-bgp-route-map:label-index']";
5392
5393 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5394 return nb_cli_apply_changes(vty, NULL);
d990e384 5395}
718e3744 5396
48cb7ea9
SP
5397DEFUN_YANG (set_aspath_prepend_asn,
5398 set_aspath_prepend_asn_cmd,
5399 "set as-path prepend (1-4294967295)...",
5400 SET_STR
5401 "Transform BGP AS_PATH attribute\n"
5402 "Prepend to the as-path\n"
5403 "AS number\n")
718e3744 5404{
d62a17ae 5405 int idx_asn = 3;
5406 int ret;
5407 char *str;
718e3744 5408
d62a17ae 5409 str = argv_concat(argv, argc, idx_asn);
718e3744 5410
48cb7ea9
SP
5411 const char *xpath =
5412 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5413 char xpath_value[XPATH_MAXLEN];
5414
5415 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5416 snprintf(xpath_value, sizeof(xpath_value),
5417 "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5418 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5419 ret = nb_cli_apply_changes(vty, NULL);
5420 XFREE(MTYPE_TMP, str);
d62a17ae 5421 return ret;
718e3744 5422}
5423
48cb7ea9
SP
5424DEFUN_YANG (set_aspath_prepend_lastas,
5425 set_aspath_prepend_lastas_cmd,
5426 "set as-path prepend last-as (1-10)",
5427 SET_STR
5428 "Transform BGP AS_PATH attribute\n"
5429 "Prepend to the as-path\n"
6ba0adac 5430 "Use the last AS-number in the as-path\n"
48cb7ea9 5431 "Number of times to insert\n")
12dcf78e 5432{
48cb7ea9
SP
5433 int idx_num = 4;
5434
5435 const char *xpath =
5436 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5437 char xpath_value[XPATH_MAXLEN];
5438
5439 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5440 snprintf(xpath_value, sizeof(xpath_value),
5441 "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5442 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5443 argv[idx_num]->arg);
5444 return nb_cli_apply_changes(vty, NULL);
12dcf78e 5445}
bc3dd427 5446
77e3d821
DA
5447DEFPY_YANG (set_aspath_replace_asn,
5448 set_aspath_replace_asn_cmd,
5449 "set as-path replace <any|(1-4294967295)>$replace",
5450 SET_STR
5451 "Transform BGP AS_PATH attribute\n"
5452 "Replace AS number to local AS number\n"
5453 "Replace any AS number to local AS number\n"
5454 "Replace a specific AS number to local AS number\n")
5455{
5456 const char *xpath =
5457 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5458 char xpath_value[XPATH_MAXLEN];
5459
5460 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5461 snprintf(xpath_value, sizeof(xpath_value),
5462 "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5463 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5464 return nb_cli_apply_changes(vty, NULL);
5465}
5466
5467DEFPY_YANG (no_set_aspath_replace_asn,
5468 no_set_aspath_replace_asn_cmd,
5469 "no set as-path replace [<any|(1-4294967295)>]",
5470 NO_STR
5471 SET_STR
5472 "Transform BGP AS_PATH attribute\n"
5473 "Replace AS number to local AS number\n"
5474 "Replace any AS number to local AS number\n"
5475 "Replace a specific AS number to local AS number\n")
5476{
5477 const char *xpath =
5478 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5479
5480 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5481 return nb_cli_apply_changes(vty, NULL);
5482}
5483
48cb7ea9
SP
5484DEFUN_YANG (no_set_aspath_prepend,
5485 no_set_aspath_prepend_cmd,
5486 "no set as-path prepend [(1-4294967295)]",
5487 NO_STR
5488 SET_STR
5489 "Transform BGP AS_PATH attribute\n"
5490 "Prepend to the as-path\n"
5491 "AS number\n")
718e3744 5492{
48cb7ea9
SP
5493 const char *xpath =
5494 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
a7f93f3e 5495
48cb7ea9
SP
5496 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5497 return nb_cli_apply_changes(vty, NULL);
718e3744 5498}
5499
48cb7ea9
SP
5500DEFUN_YANG (no_set_aspath_prepend_lastas,
5501 no_set_aspath_prepend_lastas_cmd,
5502 "no set as-path prepend last-as [(1-10)]",
5503 NO_STR
5504 SET_STR
5505 "Transform BGP AS_PATH attribute\n"
5506 "Prepend to the as-path\n"
5507 "Use the peers AS-number\n"
5508 "Number of times to insert\n")
9131e6e8 5509{
48cb7ea9
SP
5510 const char *xpath =
5511 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5512
5513 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5514 return nb_cli_apply_changes(vty, NULL);
9131e6e8 5515}
718e3744 5516
48cb7ea9
SP
5517DEFUN_YANG (set_aspath_exclude,
5518 set_aspath_exclude_cmd,
5519 "set as-path exclude (1-4294967295)...",
5520 SET_STR
5521 "Transform BGP AS-path attribute\n"
5522 "Exclude from the as-path\n"
5523 "AS number\n")
841f7a57 5524{
d62a17ae 5525 int idx_asn = 3;
5526 int ret;
5527 char *str;
841f7a57 5528
d62a17ae 5529 str = argv_concat(argv, argc, idx_asn);
48cb7ea9
SP
5530
5531 const char *xpath =
5532 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5533 char xpath_value[XPATH_MAXLEN];
5534
5535 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5536 snprintf(xpath_value, sizeof(xpath_value),
5537 "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5538 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5539 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5540 XFREE(MTYPE_TMP, str);
5541 return ret;
841f7a57
DO
5542}
5543
48cb7ea9
SP
5544DEFUN_YANG (no_set_aspath_exclude,
5545 no_set_aspath_exclude_cmd,
5546 "no set as-path exclude (1-4294967295)...",
5547 NO_STR
5548 SET_STR
5549 "Transform BGP AS_PATH attribute\n"
5550 "Exclude from the as-path\n"
5551 "AS number\n")
841f7a57 5552{
48cb7ea9
SP
5553 const char *xpath =
5554 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
841f7a57 5555
48cb7ea9
SP
5556 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5557 return nb_cli_apply_changes(vty, NULL);
841f7a57
DO
5558}
5559
48cb7ea9
SP
5560ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5561 "no set as-path exclude",
5562 NO_STR SET_STR
5563 "Transform BGP AS_PATH attribute\n"
5564 "Exclude from the as-path\n")
841f7a57 5565
48cb7ea9
SP
5566DEFUN_YANG (set_community,
5567 set_community_cmd,
5568 "set community AA:NN...",
5569 SET_STR
5570 "BGP community attribute\n"
5571 COMMUNITY_VAL_STR)
718e3744 5572{
d62a17ae 5573 int idx_aa_nn = 2;
5574 int i;
5575 int first = 0;
5576 int additive = 0;
5577 struct buffer *b;
5578 struct community *com = NULL;
5579 char *str;
48cb7ea9 5580 char *argstr = NULL;
d62a17ae 5581 int ret;
5582
48cb7ea9
SP
5583 const char *xpath =
5584 "./set-action[action='frr-bgp-route-map:set-community']";
5585 char xpath_value[XPATH_MAXLEN];
5586
5587 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5588 snprintf(xpath_value, sizeof(xpath_value),
5589 "%s/rmap-set-action/frr-bgp-route-map:community-string",
5590 xpath);
5591
d62a17ae 5592 b = buffer_new(1024);
5593
5594 for (i = idx_aa_nn; i < argc; i++) {
5595 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5596 == 0) {
5597 additive = 1;
5598 continue;
5599 }
5600
5601 if (first)
5602 buffer_putc(b, ' ');
5603 else
5604 first = 1;
5605
5606 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5607 == 0) {
5608 buffer_putstr(b, "internet");
5609 continue;
5610 }
5611 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5612 == 0) {
5613 buffer_putstr(b, "local-AS");
5614 continue;
5615 }
5616 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5617 && strncmp(argv[i]->arg, "no-advertise",
5618 strlen(argv[i]->arg))
5619 == 0) {
5620 buffer_putstr(b, "no-advertise");
5621 continue;
5622 }
5623 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5624 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5625 == 0) {
5626 buffer_putstr(b, "no-export");
5627 continue;
5628 }
2721dd61
DA
5629 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
5630 == 0) {
5631 buffer_putstr(b, "blackhole");
5632 continue;
5633 }
a4d82a8a
PZ
5634 if (strncmp(argv[i]->arg, "graceful-shutdown",
5635 strlen(argv[i]->arg))
7f323236
DW
5636 == 0) {
5637 buffer_putstr(b, "graceful-shutdown");
5638 continue;
5639 }
d62a17ae 5640 buffer_putstr(b, argv[i]->arg);
5641 }
5642 buffer_putc(b, '\0');
5643
5644 /* Fetch result string then compile it to communities attribute. */
5645 str = buffer_getstr(b);
5646 buffer_free(b);
5647
c0945b78 5648 if (str)
d62a17ae 5649 com = community_str2com(str);
d62a17ae 5650
5651 /* Can't compile user input into communities attribute. */
5652 if (!com) {
c0945b78
DA
5653 vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
5654 XFREE(MTYPE_TMP, str);
d62a17ae 5655 return CMD_WARNING_CONFIG_FAILED;
5656 }
c0945b78 5657 XFREE(MTYPE_TMP, str);
d62a17ae 5658
5659 /* Set communites attribute string. */
c0945b78 5660 str = community_str(com, false, false);
d62a17ae 5661
5662 if (additive) {
552d6491
QY
5663 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
5664 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
5665 strlcpy(argstr, str, argstr_sz);
5666 strlcat(argstr, " additive", argstr_sz);
48cb7ea9 5667 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
d62a17ae 5668 } else
48cb7ea9
SP
5669 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5670
5671 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5672
48cb7ea9
SP
5673 if (argstr)
5674 XFREE(MTYPE_TMP, argstr);
3c1f53de 5675 community_free(&com);
d62a17ae 5676
5677 return ret;
718e3744 5678}
5679
48cb7ea9
SP
5680DEFUN_YANG (set_community_none,
5681 set_community_none_cmd,
5682 "set community none",
5683 SET_STR
5684 "BGP community attribute\n"
5685 "No community attribute\n")
718e3744 5686{
48cb7ea9
SP
5687 const char *xpath =
5688 "./set-action[action='frr-bgp-route-map:set-community']";
5689 char xpath_value[XPATH_MAXLEN];
5690
5691 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5692
5693 snprintf(xpath_value, sizeof(xpath_value),
5694 "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
5695 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5696 return nb_cli_apply_changes(vty, NULL);
718e3744 5697}
5698
48cb7ea9
SP
5699DEFUN_YANG (no_set_community,
5700 no_set_community_cmd,
5701 "no set community AA:NN...",
5702 NO_STR
5703 SET_STR
5704 "BGP community attribute\n"
5705 COMMUNITY_VAL_STR)
718e3744 5706{
48cb7ea9
SP
5707 const char *xpath =
5708 "./set-action[action='frr-bgp-route-map:set-community']";
718e3744 5709
48cb7ea9
SP
5710 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5711 return nb_cli_apply_changes(vty, NULL);
5712}
2929de9e 5713
48cb7ea9
SP
5714ALIAS_YANG (no_set_community,
5715 no_set_community_short_cmd,
5716 "no set community",
5717 NO_STR
5718 SET_STR
5719 "BGP community attribute\n")
718e3744 5720
48cb7ea9 5721DEFPY_YANG (set_community_delete,
718e3744 5722 set_community_delete_cmd,
a2099c1d 5723 "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
718e3744 5724 SET_STR
5725 "set BGP community list (for deletion)\n"
5726 "Community-list number (standard)\n"
5e3edbf5 5727 "Community-list number (expanded)\n"
718e3744 5728 "Community-list name\n"
5729 "Delete matching communities\n")
5730{
48cb7ea9
SP
5731 const char *xpath =
5732 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5733 char xpath_value[XPATH_MAXLEN];
d62a17ae 5734 int idx_comm_list = 2;
718e3744 5735
48cb7ea9
SP
5736 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5737
5738 snprintf(xpath_value, sizeof(xpath_value),
5739 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5740 xpath);
5741 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5742 argv[idx_comm_list]->arg);
5743
5744 return nb_cli_apply_changes(vty, NULL);
718e3744 5745
718e3744 5746}
5747
48cb7ea9
SP
5748DEFUN_YANG (no_set_community_delete,
5749 no_set_community_delete_cmd,
a2099c1d 5750 "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
48cb7ea9
SP
5751 NO_STR
5752 SET_STR
5753 "set BGP community list (for deletion)\n"
5754 "Community-list number (standard)\n"
5755 "Community-list number (expanded)\n"
5756 "Community-list name\n"
5757 "Delete matching communities\n")
718e3744 5758{
48cb7ea9
SP
5759 const char *xpath =
5760 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5761
5762 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5763 return nb_cli_apply_changes(vty, NULL);
718e3744 5764}
5765
48cb7ea9
SP
5766DEFUN_YANG (set_lcommunity,
5767 set_lcommunity_cmd,
5768 "set large-community AA:BB:CC...",
5769 SET_STR
5770 "BGP large community attribute\n"
5771 "Large Community number in aa:bb:cc format or additive\n")
57d187bc 5772{
d62a17ae 5773 char *str;
48cb7ea9
SP
5774 int ret;
5775 const char *xpath =
5776 "./set-action[action='frr-bgp-route-map:set-large-community']";
5777 char xpath_value[XPATH_MAXLEN];
5778
5779 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 5780
48cb7ea9
SP
5781 snprintf(xpath_value, sizeof(xpath_value),
5782 "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
5783 xpath);
d62a17ae 5784 str = argv_concat(argv, argc, 2);
48cb7ea9
SP
5785 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5786 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5787 XFREE(MTYPE_TMP, str);
d62a17ae 5788 return ret;
57d187bc
JS
5789}
5790
48cb7ea9
SP
5791DEFUN_YANG (set_lcommunity_none,
5792 set_lcommunity_none_cmd,
5793 "set large-community none",
5794 SET_STR
5795 "BGP large community attribute\n"
5796 "No large community attribute\n")
57d187bc 5797{
48cb7ea9
SP
5798 const char *xpath =
5799 "./set-action[action='frr-bgp-route-map:set-large-community']";
5800 char xpath_value[XPATH_MAXLEN];
5801
5802 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5803
5804 snprintf(xpath_value, sizeof(xpath_value),
5805 "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
5806 xpath);
5807 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5808 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
5809}
5810
48cb7ea9
SP
5811DEFUN_YANG (no_set_lcommunity,
5812 no_set_lcommunity_cmd,
5813 "no set large-community none",
5814 NO_STR
5815 SET_STR
5816 "BGP large community attribute\n"
5817 "No community attribute\n")
57d187bc 5818{
48cb7ea9
SP
5819 const char *xpath =
5820 "./set-action[action='frr-bgp-route-map:set-large-community']";
5821
5822 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5823 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
5824}
5825
48cb7ea9
SP
5826DEFUN_YANG (no_set_lcommunity1,
5827 no_set_lcommunity1_cmd,
5828 "no set large-community AA:BB:CC...",
5829 NO_STR
5830 SET_STR
5831 "BGP large community attribute\n"
5832 "Large community in AA:BB:CC... format or additive\n")
52951b63 5833{
48cb7ea9
SP
5834 const char *xpath =
5835 "./set-action[action='frr-bgp-route-map:set-large-community']";
5836
5837 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5838 return nb_cli_apply_changes(vty, NULL);
52951b63 5839}
57d187bc 5840
48cb7ea9
SP
5841ALIAS_YANG (no_set_lcommunity1,
5842 no_set_lcommunity1_short_cmd,
5843 "no set large-community",
5844 NO_STR
5845 SET_STR
5846 "BGP large community attribute\n")
76a20aa9 5847
48cb7ea9 5848DEFPY_YANG (set_lcommunity_delete,
57d187bc 5849 set_lcommunity_delete_cmd,
a2099c1d 5850 "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
57d187bc
JS
5851 SET_STR
5852 "set BGP large community list (for deletion)\n"
5853 "Large Community-list number (standard)\n"
5854 "Large Communitly-list number (expanded)\n"
5855 "Large Community-list name\n"
5856 "Delete matching large communities\n")
5857{
48cb7ea9
SP
5858 const char *xpath =
5859 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
5860 char xpath_value[XPATH_MAXLEN];
4cae2269 5861 int idx_lcomm_list = 2;
4cae2269 5862
48cb7ea9 5863 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
57d187bc 5864
48cb7ea9
SP
5865 snprintf(xpath_value, sizeof(xpath_value),
5866 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5867 xpath);
5868 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5869 argv[idx_lcomm_list]->arg);
5870
5871 return nb_cli_apply_changes(vty, NULL);
57d187bc
JS
5872}
5873
48cb7ea9
SP
5874DEFUN_YANG (no_set_lcommunity_delete,
5875 no_set_lcommunity_delete_cmd,
a2099c1d 5876 "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
48cb7ea9
SP
5877 NO_STR
5878 SET_STR
5879 "set BGP large community list (for deletion)\n"
5880 "Large Community-list number (standard)\n"
5881 "Large Communitly-list number (expanded)\n"
5882 "Large Community-list name\n"
5883 "Delete matching large communities\n")
57d187bc 5884{
48cb7ea9
SP
5885 const char *xpath =
5886 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
5887
5888 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5889 return nb_cli_apply_changes(vty, NULL);
57d187bc 5890}
718e3744 5891
48cb7ea9
SP
5892ALIAS_YANG (no_set_lcommunity_delete,
5893 no_set_lcommunity_delete_short_cmd,
5894 "no set large-comm-list",
5895 NO_STR
5896 SET_STR
5897 "set BGP large community list (for deletion)\n")
76a20aa9 5898
48cb7ea9
SP
5899DEFUN_YANG (set_ecommunity_rt,
5900 set_ecommunity_rt_cmd,
5901 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
5902 SET_STR
5903 "BGP extended community attribute\n"
5904 "Route Target extended community\n"
5905 "VPN extended community\n")
718e3744 5906{
d62a17ae 5907 int idx_asn_nn = 3;
d62a17ae 5908 char *str;
48cb7ea9
SP
5909 int ret;
5910 const char *xpath =
5911 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
5912 char xpath_value[XPATH_MAXLEN];
5913
5914 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 5915
48cb7ea9
SP
5916 snprintf(xpath_value, sizeof(xpath_value),
5917 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
d62a17ae 5918 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
5919 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5920 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5921 XFREE(MTYPE_TMP, str);
d62a17ae 5922 return ret;
718e3744 5923}
5924
48cb7ea9
SP
5925DEFUN_YANG (no_set_ecommunity_rt,
5926 no_set_ecommunity_rt_cmd,
5927 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
5928 NO_STR
5929 SET_STR
5930 "BGP extended community attribute\n"
5931 "Route Target extended community\n"
5932 "VPN extended community\n")
5933{
5934 const char *xpath =
5935 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
5936 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5937 return nb_cli_apply_changes(vty, NULL);
5938}
5939
5940ALIAS_YANG (no_set_ecommunity_rt,
5941 no_set_ecommunity_rt_short_cmd,
5942 "no set extcommunity rt",
5943 NO_STR
5944 SET_STR
5945 "BGP extended community attribute\n"
5946 "Route Target extended community\n")
5947
5948DEFUN_YANG (set_ecommunity_soo,
5949 set_ecommunity_soo_cmd,
5950 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
5951 SET_STR
5952 "BGP extended community attribute\n"
5953 "Site-of-Origin extended community\n"
5954 "VPN extended community\n")
718e3744 5955{
d62a17ae 5956 int idx_asn_nn = 3;
d62a17ae 5957 char *str;
48cb7ea9
SP
5958 int ret;
5959 const char *xpath =
5960 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
5961 char xpath_value[XPATH_MAXLEN];
718e3744 5962
48cb7ea9
SP
5963 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5964
5965 snprintf(xpath_value, sizeof(xpath_value),
5966 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
5967 xpath);
d62a17ae 5968 str = argv_concat(argv, argc, idx_asn_nn);
48cb7ea9
SP
5969 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5970 ret = nb_cli_apply_changes(vty, NULL);
d62a17ae 5971 XFREE(MTYPE_TMP, str);
5972 return ret;
718e3744 5973}
5974
48cb7ea9
SP
5975DEFUN_YANG (no_set_ecommunity_soo,
5976 no_set_ecommunity_soo_cmd,
5977 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
5978 NO_STR
5979 SET_STR
5980 "BGP extended community attribute\n"
5981 "Site-of-Origin extended community\n"
5982 "VPN extended community\n")
5983{
5984 const char *xpath =
5985 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
5986 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5987 return nb_cli_apply_changes(vty, NULL);
5988}
5989
5990ALIAS_YANG (no_set_ecommunity_soo,
5991 no_set_ecommunity_soo_short_cmd,
5992 "no set extcommunity soo",
5993 NO_STR
5994 SET_STR
5995 "GP extended community attribute\n"
5996 "Site-of-Origin extended community\n")
5997
bb4dcdd1
DA
5998DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
5999 "set extcommunity none",
6000 SET_STR
6001 "BGP extended community attribute\n"
6002 "No extended community attribute\n")
6003{
6004 const char *xpath =
6005 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6006 char xpath_value[XPATH_MAXLEN];
6007
6008 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6009
6010 snprintf(xpath_value, sizeof(xpath_value),
6011 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6012 xpath);
6013 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6014 return nb_cli_apply_changes(vty, NULL);
6015}
6016
6017DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6018 "no set extcommunity none",
6019 NO_STR SET_STR
6020 "BGP extended community attribute\n"
6021 "No extended community attribute\n")
6022{
6023 const char *xpath =
6024 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6025 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6026 return nb_cli_apply_changes(vty, NULL);
6027}
6028
48cb7ea9
SP
6029DEFUN_YANG (set_ecommunity_lb,
6030 set_ecommunity_lb_cmd,
6031 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6032 SET_STR
6033 "BGP extended community attribute\n"
6034 "Link bandwidth extended community\n"
6035 "Bandwidth value in Mbps\n"
6036 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6037 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6038 "Attribute is set as non-transitive\n")
718e3744 6039{
48cb7ea9 6040 int idx_lb = 3;
3b225ee7 6041 int idx_non_transitive = 0;
48cb7ea9
SP
6042 const char *xpath =
6043 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6044 char xpath_lb_type[XPATH_MAXLEN];
6045 char xpath_bandwidth[XPATH_MAXLEN];
6046 char xpath_non_transitive[XPATH_MAXLEN];
6047
6048 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6049
6050 snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6051 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6052 xpath);
6053 snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6054 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6055 xpath);
6056 snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6057 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6058 xpath);
6059
6060 if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6061 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6062 "cumulative-bandwidth");
6063 else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6064 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6065 "computed-bandwidth");
6066 else {
6067 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6068 "explicit-bandwidth");
6069 nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6070 argv[idx_lb]->arg);
6071 }
718e3744 6072
3b225ee7 6073 if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
48cb7ea9
SP
6074 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6075 "true");
6076 else
6077 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6078 "false");
6079
6080 return nb_cli_apply_changes(vty, NULL);
6081}
6082
6083DEFUN_YANG (no_set_ecommunity_lb,
6084 no_set_ecommunity_lb_cmd,
6085 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6086 NO_STR
6087 SET_STR
6088 "BGP extended community attribute\n"
6089 "Link bandwidth extended community\n"
6090 "Bandwidth value in Mbps\n"
6091 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6092 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6093 "Attribute is set as non-transitive\n")
6094{
6095 const char *xpath =
6096 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6097
6098 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6099 return nb_cli_apply_changes(vty, NULL);
6100}
6101
6102ALIAS_YANG (no_set_ecommunity_lb,
6103 no_set_ecommunity_lb_short_cmd,
6104 "no set extcommunity bandwidth",
6105 NO_STR
6106 SET_STR
6107 "BGP extended community attribute\n"
6108 "Link bandwidth extended community\n")
6109
6110DEFUN_YANG (set_origin,
6111 set_origin_cmd,
6112 "set origin <egp|igp|incomplete>",
6113 SET_STR
6114 "BGP origin code\n"
6115 "remote EGP\n"
6116 "local IGP\n"
6117 "unknown heritage\n")
ca9ac3ef 6118{
48cb7ea9
SP
6119 int idx_origin = 2;
6120 const char *origin_type;
6121 const char *xpath =
6122 "./set-action[action='frr-bgp-route-map:set-origin']";
6123 char xpath_value[XPATH_MAXLEN];
ca9ac3ef 6124
48cb7ea9
SP
6125 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6126 origin_type = "igp";
6127 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6128 origin_type = "egp";
6129 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6130 origin_type = "incomplete";
6131 else {
6132 vty_out(vty, "%% Invalid match origin type\n");
6133 return CMD_WARNING_CONFIG_FAILED;
6134 }
ca9ac3ef 6135
48cb7ea9
SP
6136 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6137 snprintf(xpath_value, sizeof(xpath_value),
6138 "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6139 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
ca9ac3ef 6140
48cb7ea9 6141 return nb_cli_apply_changes(vty, NULL);
ca9ac3ef 6142}
6143
48cb7ea9
SP
6144DEFUN_YANG (no_set_origin,
6145 no_set_origin_cmd,
6146 "no set origin [<egp|igp|incomplete>]",
6147 NO_STR
6148 SET_STR
6149 "BGP origin code\n"
6150 "remote EGP\n"
6151 "local IGP\n"
6152 "unknown heritage\n")
718e3744 6153{
48cb7ea9
SP
6154 const char *xpath =
6155 "./set-action[action='frr-bgp-route-map:set-origin']";
718e3744 6156
48cb7ea9
SP
6157 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6158 return nb_cli_apply_changes(vty, NULL);
718e3744 6159}
6160
48cb7ea9
SP
6161DEFUN_YANG (set_atomic_aggregate,
6162 set_atomic_aggregate_cmd,
6163 "set atomic-aggregate",
6164 SET_STR
6165 "BGP atomic aggregate attribute\n" )
718e3744 6166{
48cb7ea9
SP
6167 const char *xpath =
6168 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6169 char xpath_value[XPATH_MAXLEN];
718e3744 6170
48cb7ea9
SP
6171 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6172 snprintf(xpath_value, sizeof(xpath_value),
6173 "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6174 xpath);
6175 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
718e3744 6176
48cb7ea9 6177 return nb_cli_apply_changes(vty, NULL);
718e3744 6178}
6179
48cb7ea9
SP
6180DEFUN_YANG (no_set_atomic_aggregate,
6181 no_set_atomic_aggregate_cmd,
6182 "no set atomic-aggregate",
6183 NO_STR
6184 SET_STR
6185 "BGP atomic aggregate attribute\n" )
718e3744 6186{
48cb7ea9
SP
6187 const char *xpath =
6188 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6189
6190 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6191 return nb_cli_apply_changes(vty, NULL);
718e3744 6192}
6193
48cb7ea9
SP
6194DEFUN_YANG (set_aggregator_as,
6195 set_aggregator_as_cmd,
6196 "set aggregator as (1-4294967295) A.B.C.D",
6197 SET_STR
6198 "BGP aggregator attribute\n"
6199 "AS number of aggregator\n"
6200 "AS number\n"
6201 "IP address of aggregator\n")
718e3744 6202{
d62a17ae 6203 int idx_number = 3;
6204 int idx_ipv4 = 4;
48cb7ea9
SP
6205 char xpath_asn[XPATH_MAXLEN];
6206 char xpath_addr[XPATH_MAXLEN];
6207 const char *xpath =
6208 "./set-action[action='frr-bgp-route-map:aggregator']";
e52702f2 6209
48cb7ea9 6210 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
718e3744 6211
48cb7ea9
SP
6212 snprintf(
6213 xpath_asn, sizeof(xpath_asn),
6214 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6215 xpath);
6216 nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6217 argv[idx_number]->arg);
718e3744 6218
48cb7ea9
SP
6219 snprintf(
6220 xpath_addr, sizeof(xpath_addr),
6221 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6222 xpath);
6223 nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6224 argv[idx_ipv4]->arg);
718e3744 6225
48cb7ea9 6226 return nb_cli_apply_changes(vty, NULL);
718e3744 6227}
6228
48cb7ea9
SP
6229DEFUN_YANG (no_set_aggregator_as,
6230 no_set_aggregator_as_cmd,
6231 "no set aggregator as [(1-4294967295) A.B.C.D]",
6232 NO_STR
6233 SET_STR
6234 "BGP aggregator attribute\n"
6235 "AS number of aggregator\n"
6236 "AS number\n"
6237 "IP address of aggregator\n")
718e3744 6238{
48cb7ea9
SP
6239 const char *xpath =
6240 "./set-action[action='frr-bgp-route-map:aggregator']";
718e3744 6241
48cb7ea9
SP
6242 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6243 return nb_cli_apply_changes(vty, NULL);
6244}
718e3744 6245
48cb7ea9
SP
6246DEFUN_YANG (match_ipv6_next_hop,
6247 match_ipv6_next_hop_cmd,
bc63ba98
DA
6248 "match ipv6 next-hop ACCESSLIST6_NAME",
6249 MATCH_STR
6250 IPV6_STR
6251 "Match IPv6 next-hop address of route\n"
6252 "IPv6 access-list name\n")
6253{
6254 const char *xpath =
6255 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6256 char xpath_value[XPATH_MAXLEN];
6257
6258 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6259 snprintf(xpath_value, sizeof(xpath_value),
6260 "%s/rmap-match-condition/list-name", xpath);
6261 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6262 argv[argc - 1]->arg);
6263
6264 return nb_cli_apply_changes(vty, NULL);
6265}
6266
6267DEFUN_YANG (no_match_ipv6_next_hop,
6268 no_match_ipv6_next_hop_cmd,
6269 "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6270 NO_STR
6271 MATCH_STR
6272 IPV6_STR
6273 "Match IPv6 next-hop address of route\n"
6274 "IPv6 access-list name\n")
6275{
6276 const char *xpath =
6277 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6278
6279 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6280 return nb_cli_apply_changes(vty, NULL);
6281}
6282
6283DEFUN_YANG (match_ipv6_next_hop_address,
6284 match_ipv6_next_hop_address_cmd,
03030106 6285 "match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6286 MATCH_STR
6287 IPV6_STR
6288 "Match IPv6 next-hop address of route\n"
03030106 6289 "IPv6 address\n"
48cb7ea9
SP
6290 "IPv6 address of next hop\n")
6291{
6292 const char *xpath =
6293 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6294 char xpath_value[XPATH_MAXLEN];
718e3744 6295
48cb7ea9
SP
6296 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6297 snprintf(xpath_value, sizeof(xpath_value),
6298 "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6299 xpath);
bc63ba98
DA
6300 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6301 argv[argc - 1]->arg);
718e3744 6302
48cb7ea9 6303 return nb_cli_apply_changes(vty, NULL);
718e3744 6304}
6305
bc63ba98
DA
6306DEFUN_YANG (no_match_ipv6_next_hop_address,
6307 no_match_ipv6_next_hop_address_cmd,
03030106 6308 "no match ipv6 next-hop address X:X::X:X",
48cb7ea9
SP
6309 NO_STR
6310 MATCH_STR
6311 IPV6_STR
6312 "Match IPv6 next-hop address of route\n"
03030106 6313 "IPv6 address\n"
48cb7ea9 6314 "IPv6 address of next hop\n")
718e3744 6315{
48cb7ea9
SP
6316 const char *xpath =
6317 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
718e3744 6318
48cb7ea9
SP
6319 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6320 return nb_cli_apply_changes(vty, NULL);
718e3744 6321}
6322
bc63ba98 6323ALIAS_HIDDEN (match_ipv6_next_hop_address,
03030106
IR
6324 match_ipv6_next_hop_old_cmd,
6325 "match ipv6 next-hop X:X::X:X",
6326 MATCH_STR
6327 IPV6_STR
6328 "Match IPv6 next-hop address of route\n"
6329 "IPv6 address of next hop\n")
6330
bc63ba98 6331ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
03030106
IR
6332 no_match_ipv6_next_hop_old_cmd,
6333 "no match ipv6 next-hop X:X::X:X",
6334 NO_STR
6335 MATCH_STR
6336 IPV6_STR
6337 "Match IPv6 next-hop address of route\n"
6338 "IPv6 address of next hop\n")
6339
82f191a2
DA
6340DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6341 match_ipv6_next_hop_prefix_list_cmd,
6342 "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6343 MATCH_STR
6344 IPV6_STR
6345 "Match IPv6 next-hop address of route\n"
6346 "Match entries by prefix-list\n"
6347 "IPv6 prefix-list name\n")
6348{
6349 const char *xpath =
6350 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6351 char xpath_value[XPATH_MAXLEN];
6352
6353 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6354 snprintf(xpath_value, sizeof(xpath_value),
6355 "%s/rmap-match-condition/list-name", xpath);
6356 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6357 argv[argc - 1]->arg);
6358
6359 return nb_cli_apply_changes(vty, NULL);
6360}
6361
6362DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6363 no_match_ipv6_next_hop_prefix_list_cmd,
6364 "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6365 NO_STR
6366 MATCH_STR
6367 IPV6_STR
6368 "Match IPv6 next-hop address of route\n"
6369 "Match entries by prefix-list\n"
6370 "IPv6 prefix-list name\n")
6371{
6372 const char *xpath =
6373 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6374
6375 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6376 return nb_cli_apply_changes(vty, NULL);
6377}
6378
48cb7ea9 6379DEFPY_YANG (match_ipv4_next_hop,
be7735b3 6380 match_ipv4_next_hop_cmd,
17ac51eb 6381 "match ip next-hop address A.B.C.D",
be7735b3
PG
6382 MATCH_STR
6383 IP_STR
6384 "Match IP next-hop address of route\n"
6385 "IP address\n"
6386 "IP address of next-hop\n")
6387{
48cb7ea9
SP
6388 const char *xpath =
6389 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6390 char xpath_value[XPATH_MAXLEN];
6391
6392 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6393 snprintf(xpath_value, sizeof(xpath_value),
6394 "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6395 xpath);
6396 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
be7735b3 6397
48cb7ea9 6398 return nb_cli_apply_changes(vty, NULL);
17ac51eb 6399}
be7735b3 6400
48cb7ea9 6401DEFPY_YANG (no_match_ipv4_next_hop,
17ac51eb
DS
6402 no_match_ipv4_next_hop_cmd,
6403 "no match ip next-hop address [A.B.C.D]",
6404 NO_STR
6405 MATCH_STR
6406 IP_STR
6407 "Match IP next-hop address of route\n"
6408 "IP address\n"
6409 "IP address of next-hop\n")
6410{
48cb7ea9
SP
6411 const char *xpath =
6412 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6413
6414 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6415 return nb_cli_apply_changes(vty, NULL);
be7735b3 6416}
718e3744 6417
48cb7ea9
SP
6418DEFUN_YANG (set_ipv6_nexthop_peer,
6419 set_ipv6_nexthop_peer_cmd,
6420 "set ipv6 next-hop peer-address",
6421 SET_STR
6422 IPV6_STR
6423 "Next hop address\n"
6424 "Use peer address (for BGP only)\n")
90916ac2 6425{
48cb7ea9
SP
6426 const char *xpath =
6427 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6428 char xpath_value[XPATH_MAXLEN];
6429
6430 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6431 snprintf(xpath_value, sizeof(xpath_value),
6432 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6433 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6434
6435 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6436}
6437
48cb7ea9
SP
6438DEFUN_YANG (no_set_ipv6_nexthop_peer,
6439 no_set_ipv6_nexthop_peer_cmd,
6440 "no set ipv6 next-hop peer-address",
6441 NO_STR
6442 SET_STR
6443 IPV6_STR
6444 "IPv6 next-hop address\n"
6445 "Use peer address (for BGP only)\n")
90916ac2 6446{
48cb7ea9
SP
6447 const char *xpath =
6448 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6449
6450 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6451 return nb_cli_apply_changes(vty, NULL);
90916ac2
DS
6452}
6453
48cb7ea9
SP
6454DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6455 set_ipv6_nexthop_prefer_global_cmd,
6456 "set ipv6 next-hop prefer-global",
6457 SET_STR
6458 IPV6_STR
6459 "IPv6 next-hop address\n"
6460 "Prefer global over link-local if both exist\n")
161995ea 6461{
48cb7ea9
SP
6462 const char *xpath =
6463 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6464 char xpath_value[XPATH_MAXLEN];
6465
6466 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6467 snprintf(xpath_value, sizeof(xpath_value),
6468 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6469 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6470
6471 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6472}
6473
48cb7ea9
SP
6474DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6475 no_set_ipv6_nexthop_prefer_global_cmd,
6476 "no set ipv6 next-hop prefer-global",
6477 NO_STR
6478 SET_STR
6479 IPV6_STR
6480 "IPv6 next-hop address\n"
6481 "Prefer global over link-local if both exist\n")
161995ea 6482{
48cb7ea9
SP
6483 const char *xpath =
6484 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6485
6486 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6487 return nb_cli_apply_changes(vty, NULL);
161995ea
DS
6488}
6489
48cb7ea9
SP
6490DEFUN_YANG (set_ipv6_nexthop_global,
6491 set_ipv6_nexthop_global_cmd,
6492 "set ipv6 next-hop global X:X::X:X",
6493 SET_STR
6494 IPV6_STR
6495 "IPv6 next-hop address\n"
6496 "IPv6 global address\n"
6497 "IPv6 address of next hop\n")
718e3744 6498{
d62a17ae 6499 int idx_ipv6 = 4;
48cb7ea9
SP
6500 const char *xpath =
6501 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6502 char xpath_value[XPATH_MAXLEN];
bf8b3d27 6503
48cb7ea9
SP
6504 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6505 snprintf(xpath_value, sizeof(xpath_value),
6506 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6507 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6508 argv[idx_ipv6]->arg);
bf8b3d27 6509
48cb7ea9 6510 return nb_cli_apply_changes(vty, NULL);
718e3744 6511}
6512
48cb7ea9
SP
6513DEFUN_YANG (no_set_ipv6_nexthop_global,
6514 no_set_ipv6_nexthop_global_cmd,
6515 "no set ipv6 next-hop global X:X::X:X",
6516 NO_STR
6517 SET_STR
6518 IPV6_STR
6519 "IPv6 next-hop address\n"
6520 "IPv6 global address\n"
6521 "IPv6 address of next hop\n")
718e3744 6522{
48cb7ea9
SP
6523 const char *xpath =
6524 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6525
6526 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6527 return nb_cli_apply_changes(vty, NULL);
718e3744 6528}
718e3744 6529
d6902373 6530#ifdef KEEP_OLD_VPN_COMMANDS
48cb7ea9
SP
6531DEFUN_YANG (set_vpn_nexthop,
6532 set_vpn_nexthop_cmd,
6533 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6534 SET_STR
6535 "VPNv4 information\n"
6536 "VPN next-hop address\n"
6537 "IP address of next hop\n"
6538 "VPNv6 information\n"
6539 "VPN next-hop address\n"
6540 "IPv6 address of next hop\n")
718e3744 6541{
d62a17ae 6542 int idx_ip = 3;
6543 afi_t afi;
6544 int idx = 0;
4ad4ae64 6545 char xpath_value[XPATH_MAXLEN];
d62a17ae 6546
6547 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6548 if (afi == AFI_IP) {
6549 const char *xpath =
6550 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6551
6552 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6553 snprintf(
6554 xpath_value, sizeof(xpath_value),
6555 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6556 xpath);
6557 } else {
6558 const char *xpath =
6559 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6560
6561 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6562 snprintf(
6563 xpath_value, sizeof(xpath_value),
6564 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6565 xpath);
6566 }
6567
6568 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6569 argv[idx_ip]->arg);
6570
6571 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6572 }
48cb7ea9 6573
d62a17ae 6574 return CMD_SUCCESS;
d6902373 6575}
a4b2b610 6576
48cb7ea9
SP
6577DEFUN_YANG (no_set_vpn_nexthop,
6578 no_set_vpn_nexthop_cmd,
6579 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6580 NO_STR
6581 SET_STR
6582 "VPNv4 information\n"
6583 "VPN next-hop address\n"
6584 "IP address of next hop\n"
6585 "VPNv6 information\n"
6586 "VPN next-hop address\n"
6587 "IPv6 address of next hop\n")
718e3744 6588{
d62a17ae 6589 afi_t afi;
6590 int idx = 0;
6591
d62a17ae 6592 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6593 if (afi == AFI_IP) {
6594 const char *xpath =
6595 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6596 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6597 } else {
6598 const char *xpath =
6599 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6600 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6601 }
6602 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6603 }
6604 return CMD_SUCCESS;
d6902373
PG
6605}
6606#endif /* KEEP_OLD_VPN_COMMANDS */
6607
48cb7ea9
SP
6608DEFUN_YANG (set_ipx_vpn_nexthop,
6609 set_ipx_vpn_nexthop_cmd,
6610 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
6611 SET_STR
6612 "IPv4 information\n"
6613 "IPv6 information\n"
6614 "VPN information\n"
6615 "VPN next-hop address\n"
6616 "IP address of next hop\n"
6617 "IPv6 address of next hop\n")
d6902373 6618{
d62a17ae 6619 int idx_ip = 4;
6620 afi_t afi;
6621 int idx = 0;
48cb7ea9 6622 char xpath_value[XPATH_MAXLEN];
d62a17ae 6623
6624 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6625 if (afi == AFI_IP) {
6626 const char *xpath =
6627 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6628
6629 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6630 snprintf(
6631 xpath_value, sizeof(xpath_value),
6632 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6633 xpath);
6634 } else {
6635 const char *xpath =
6636 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6637
6638 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6639 snprintf(
6640 xpath_value, sizeof(xpath_value),
6641 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6642 xpath);
6643 }
6644 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6645 argv[idx_ip]->arg);
6646 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6647 }
6648 return CMD_SUCCESS;
718e3744 6649}
6650
48cb7ea9
SP
6651DEFUN_YANG (no_set_ipx_vpn_nexthop,
6652 no_set_ipx_vpn_nexthop_cmd,
6653 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
6654 NO_STR
6655 SET_STR
6656 "IPv4 information\n"
6657 "IPv6 information\n"
6658 "VPN information\n"
6659 "VPN next-hop address\n"
6660 "IP address of next hop\n"
6661 "IPv6 address of next hop\n")
6662{
d62a17ae 6663 afi_t afi;
6664 int idx = 0;
6665
d62a17ae 6666 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
48cb7ea9
SP
6667 if (afi == AFI_IP) {
6668 const char *xpath =
6669 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6670 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6671 } else {
6672 const char *xpath =
6673 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6674 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6675 }
6676 return nb_cli_apply_changes(vty, NULL);
d62a17ae 6677 }
6678 return CMD_SUCCESS;
d6902373 6679}
718e3744 6680
48cb7ea9
SP
6681DEFUN_YANG (set_originator_id,
6682 set_originator_id_cmd,
6683 "set originator-id A.B.C.D",
6684 SET_STR
6685 "BGP originator ID attribute\n"
6686 "IP address of originator\n")
718e3744 6687{
d62a17ae 6688 int idx_ipv4 = 2;
48cb7ea9
SP
6689 const char *xpath =
6690 "./set-action[action='frr-bgp-route-map:originator-id']";
6691 char xpath_value[XPATH_MAXLEN];
718e3744 6692
48cb7ea9
SP
6693 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6694 snprintf(xpath_value, sizeof(xpath_value),
6695 "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
6696 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6697 argv[idx_ipv4]->arg);
4c9bd275 6698
48cb7ea9
SP
6699 return nb_cli_apply_changes(vty, NULL);
6700}
6701
6702DEFUN_YANG (no_set_originator_id,
6703 no_set_originator_id_cmd,
6704 "no set originator-id [A.B.C.D]",
6705 NO_STR
6706 SET_STR
6707 "BGP originator ID attribute\n"
6708 "IP address of originator\n")
718e3744 6709{
48cb7ea9
SP
6710 const char *xpath =
6711 "./set-action[action='frr-bgp-route-map:originator-id']";
0d702986 6712
48cb7ea9
SP
6713 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6714 return nb_cli_apply_changes(vty, NULL);
718e3744 6715}
6716
718e3744 6717/* Initialization of route map. */
d62a17ae 6718void bgp_route_map_init(void)
6719{
6720 route_map_init();
6721
6722 route_map_add_hook(bgp_route_map_add);
6723 route_map_delete_hook(bgp_route_map_delete);
6724 route_map_event_hook(bgp_route_map_event);
6725
6726 route_map_match_interface_hook(generic_match_add);
6727 route_map_no_match_interface_hook(generic_match_delete);
6728
6729 route_map_match_ip_address_hook(generic_match_add);
6730 route_map_no_match_ip_address_hook(generic_match_delete);
6731
6732 route_map_match_ip_address_prefix_list_hook(generic_match_add);
6733 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
6734
6735 route_map_match_ip_next_hop_hook(generic_match_add);
6736 route_map_no_match_ip_next_hop_hook(generic_match_delete);
6737
bc63ba98
DA
6738 route_map_match_ipv6_next_hop_hook(generic_match_add);
6739 route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
6740
d62a17ae 6741 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
6742 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
6743
61ad901e
DA
6744 route_map_match_ip_next_hop_type_hook(generic_match_add);
6745 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
6746
d62a17ae 6747 route_map_match_ipv6_address_hook(generic_match_add);
6748 route_map_no_match_ipv6_address_hook(generic_match_delete);
6749
6750 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
6751 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
6752
61ad901e
DA
6753 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
6754 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
6755
82f191a2
DA
6756 route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
6757 route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
6758
d62a17ae 6759 route_map_match_metric_hook(generic_match_add);
6760 route_map_no_match_metric_hook(generic_match_delete);
6761
6762 route_map_match_tag_hook(generic_match_add);
6763 route_map_no_match_tag_hook(generic_match_delete);
6764
ef3e0d04
SM
6765 route_map_set_srte_color_hook(generic_set_add);
6766 route_map_no_set_srte_color_hook(generic_set_delete);
6767
d62a17ae 6768 route_map_set_ip_nexthop_hook(generic_set_add);
6769 route_map_no_set_ip_nexthop_hook(generic_set_delete);
6770
6771 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
6772 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
6773
6774 route_map_set_metric_hook(generic_set_add);
6775 route_map_no_set_metric_hook(generic_set_delete);
6776
6777 route_map_set_tag_hook(generic_set_add);
6778 route_map_no_set_tag_hook(generic_set_delete);
6779
6780 route_map_install_match(&route_match_peer_cmd);
2690f18c 6781 route_map_install_match(&route_match_alias_cmd);
d62a17ae 6782 route_map_install_match(&route_match_local_pref_cmd);
fa22080d 6783#ifdef HAVE_SCRIPTING
b4becb06 6784 route_map_install_match(&route_match_script_cmd);
1d7c7ace 6785#endif
d62a17ae 6786 route_map_install_match(&route_match_ip_address_cmd);
6787 route_map_install_match(&route_match_ip_next_hop_cmd);
6788 route_map_install_match(&route_match_ip_route_source_cmd);
6789 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
6790 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 6791 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 6792 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
6793 route_map_install_match(&route_match_aspath_cmd);
6794 route_map_install_match(&route_match_community_cmd);
6795 route_map_install_match(&route_match_lcommunity_cmd);
6796 route_map_install_match(&route_match_ecommunity_cmd);
6797 route_map_install_match(&route_match_local_pref_cmd);
6798 route_map_install_match(&route_match_metric_cmd);
6799 route_map_install_match(&route_match_origin_cmd);
6800 route_map_install_match(&route_match_probability_cmd);
6801 route_map_install_match(&route_match_interface_cmd);
6802 route_map_install_match(&route_match_tag_cmd);
d37ba549 6803 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 6804 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 6805 route_map_install_match(&route_match_evpn_route_type_cmd);
196c6b09 6806 route_map_install_match(&route_match_evpn_rd_cmd);
6fb219da 6807 route_map_install_match(&route_match_evpn_default_route_cmd);
1dcc9e5b 6808 route_map_install_match(&route_match_vrl_source_vrf_cmd);
d62a17ae 6809
d0a4ee60
AD
6810 route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
6811 route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
951745bd 6812 route_map_install_set(&route_set_table_id_cmd);
ef3e0d04 6813 route_map_install_set(&route_set_srte_color_cmd);
d62a17ae 6814 route_map_install_set(&route_set_ip_nexthop_cmd);
6815 route_map_install_set(&route_set_local_pref_cmd);
6816 route_map_install_set(&route_set_weight_cmd);
6817 route_map_install_set(&route_set_label_index_cmd);
6818 route_map_install_set(&route_set_metric_cmd);
7b7d48e5 6819 route_map_install_set(&route_set_distance_cmd);
d62a17ae 6820 route_map_install_set(&route_set_aspath_prepend_cmd);
6821 route_map_install_set(&route_set_aspath_exclude_cmd);
77e3d821 6822 route_map_install_set(&route_set_aspath_replace_cmd);
d62a17ae 6823 route_map_install_set(&route_set_origin_cmd);
6824 route_map_install_set(&route_set_atomic_aggregate_cmd);
6825 route_map_install_set(&route_set_aggregator_as_cmd);
6826 route_map_install_set(&route_set_community_cmd);
6827 route_map_install_set(&route_set_community_delete_cmd);
6828 route_map_install_set(&route_set_lcommunity_cmd);
6829 route_map_install_set(&route_set_lcommunity_delete_cmd);
6830 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
6831 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
6832 route_map_install_set(&route_set_originator_id_cmd);
6833 route_map_install_set(&route_set_ecommunity_rt_cmd);
6834 route_map_install_set(&route_set_ecommunity_soo_cmd);
ca9ac3ef 6835 route_map_install_set(&route_set_ecommunity_lb_cmd);
bb4dcdd1 6836 route_map_install_set(&route_set_ecommunity_none_cmd);
d62a17ae 6837 route_map_install_set(&route_set_tag_cmd);
6838 route_map_install_set(&route_set_label_index_cmd);
6839
6840 install_element(RMAP_NODE, &match_peer_cmd);
6841 install_element(RMAP_NODE, &match_peer_local_cmd);
6842 install_element(RMAP_NODE, &no_match_peer_cmd);
6843 install_element(RMAP_NODE, &match_ip_route_source_cmd);
6844 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
6845 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
6846 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
6847 install_element(RMAP_NODE, &match_mac_address_cmd);
6848 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
6849 install_element(RMAP_NODE, &match_evpn_vni_cmd);
6850 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
6851 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
6852 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
196c6b09
LK
6853 install_element(RMAP_NODE, &match_evpn_rd_cmd);
6854 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
6fb219da
MK
6855 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
6856 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
d0a4ee60
AD
6857 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
6858 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
6859 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
6860 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
1dcc9e5b
CS
6861 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
6862 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
d62a17ae 6863
6864 install_element(RMAP_NODE, &match_aspath_cmd);
6865 install_element(RMAP_NODE, &no_match_aspath_cmd);
6866 install_element(RMAP_NODE, &match_local_pref_cmd);
6867 install_element(RMAP_NODE, &no_match_local_pref_cmd);
2690f18c
DA
6868 install_element(RMAP_NODE, &match_alias_cmd);
6869 install_element(RMAP_NODE, &no_match_alias_cmd);
d62a17ae 6870 install_element(RMAP_NODE, &match_community_cmd);
6871 install_element(RMAP_NODE, &no_match_community_cmd);
6872 install_element(RMAP_NODE, &match_lcommunity_cmd);
6873 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
6874 install_element(RMAP_NODE, &match_ecommunity_cmd);
6875 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
6876 install_element(RMAP_NODE, &match_origin_cmd);
6877 install_element(RMAP_NODE, &no_match_origin_cmd);
6878 install_element(RMAP_NODE, &match_probability_cmd);
6879 install_element(RMAP_NODE, &no_match_probability_cmd);
6880
951745bd
PG
6881 install_element(RMAP_NODE, &no_set_table_id_cmd);
6882 install_element(RMAP_NODE, &set_table_id_cmd);
d62a17ae 6883 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
6884 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
6885 install_element(RMAP_NODE, &set_local_pref_cmd);
7b7d48e5
DS
6886 install_element(RMAP_NODE, &set_distance_cmd);
6887 install_element(RMAP_NODE, &no_set_distance_cmd);
d62a17ae 6888 install_element(RMAP_NODE, &no_set_local_pref_cmd);
6889 install_element(RMAP_NODE, &set_weight_cmd);
6890 install_element(RMAP_NODE, &set_label_index_cmd);
6891 install_element(RMAP_NODE, &no_set_weight_cmd);
6892 install_element(RMAP_NODE, &no_set_label_index_cmd);
6893 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
6894 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
6895 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
77e3d821 6896 install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
d62a17ae 6897 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
9131e6e8 6898 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
d62a17ae 6899 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
499ceb3d 6900 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
77e3d821 6901 install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
d62a17ae 6902 install_element(RMAP_NODE, &set_origin_cmd);
6903 install_element(RMAP_NODE, &no_set_origin_cmd);
6904 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
6905 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
6906 install_element(RMAP_NODE, &set_aggregator_as_cmd);
6907 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
6908 install_element(RMAP_NODE, &set_community_cmd);
6909 install_element(RMAP_NODE, &set_community_none_cmd);
6910 install_element(RMAP_NODE, &no_set_community_cmd);
2929de9e 6911 install_element(RMAP_NODE, &no_set_community_short_cmd);
d62a17ae 6912 install_element(RMAP_NODE, &set_community_delete_cmd);
6913 install_element(RMAP_NODE, &no_set_community_delete_cmd);
6914 install_element(RMAP_NODE, &set_lcommunity_cmd);
6915 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
6916 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
6917 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
76a20aa9 6918 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
d62a17ae 6919 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
6920 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
76a20aa9 6921 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
d62a17ae 6922 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
6923 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4db5ee8e 6924 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
d62a17ae 6925 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
6926 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4db5ee8e 6927 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
ca9ac3ef 6928 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
6929 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
6930 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
bb4dcdd1
DA
6931 install_element(RMAP_NODE, &set_ecommunity_none_cmd);
6932 install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
d6902373 6933#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 6934 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
6935 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 6936#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 6937 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
6938 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
6939 install_element(RMAP_NODE, &set_originator_id_cmd);
6940 install_element(RMAP_NODE, &no_set_originator_id_cmd);
6941
6942 route_map_install_match(&route_match_ipv6_address_cmd);
6943 route_map_install_match(&route_match_ipv6_next_hop_cmd);
bc63ba98 6944 route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
82f191a2 6945 route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
be7735b3 6946 route_map_install_match(&route_match_ipv4_next_hop_cmd);
d62a17ae 6947 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 6948 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 6949 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
6950 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
6951 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
6952 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
6953
6954 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
bc63ba98 6955 install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
82f191a2 6956 install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
d62a17ae 6957 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
bc63ba98 6958 install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
82f191a2 6959 install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
03030106
IR
6960 install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
6961 install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
be7735b3 6962 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
17ac51eb 6963 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
d62a17ae 6964 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
6965 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
6966 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
6967 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
6968 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
6969 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
fa22080d 6970#ifdef HAVE_SCRIPTING
b4becb06 6971 install_element(RMAP_NODE, &match_script_cmd);
1d7c7ace 6972#endif
d62a17ae 6973}
6974
6975void bgp_route_map_terminate(void)
6976{
6977 /* ToDo: Cleanup all the used memory */
d62a17ae 6978 route_map_finish();
518f0eb1 6979}