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