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