]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Merge pull request #10734 from ton31337/fix/rpki_read
[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 1248
9a706b42 1249 if (bgp_attr_get_community(path->attr)) {
1ca0a0bc 1250 found = false;
9a706b42
DA
1251 frrstr_split(bgp_attr_get_community(path->attr)->str, " ",
1252 &communities, &num);
2690f18c
DA
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 1443 if (rcom->exact) {
9a706b42
DA
1444 if (community_list_exact_match(
1445 bgp_attr_get_community(path->attr), list))
1782514f
DS
1446 return RMAP_MATCH;
1447 } else {
9a706b42
DA
1448 if (community_list_match(bgp_attr_get_community(path->attr),
1449 list))
1782514f 1450 return RMAP_MATCH;
718e3744 1451 }
1782514f 1452
d62a17ae 1453 return RMAP_NOMATCH;
718e3744 1454}
1455
1456/* Compile function for community match. */
d62a17ae 1457static void *route_match_community_compile(const char *arg)
1458{
1459 struct rmap_community *rcom;
1460 int len;
1461 char *p;
1462
1463 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1464
1465 p = strchr(arg, ' ');
1466 if (p) {
1467 len = p - arg;
1468 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1469 memcpy(rcom->name, arg, len);
1470 rcom->exact = 1;
1471 } else {
1472 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1473 rcom->exact = 0;
1474 }
e237b0d2
DS
1475
1476 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1477 return rcom;
718e3744 1478}
1479
1480/* Compile function for community match. */
d62a17ae 1481static void route_match_community_free(void *rule)
718e3744 1482{
d62a17ae 1483 struct rmap_community *rcom = rule;
718e3744 1484
d62a17ae 1485 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1486 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 1487}
1488
909f3d56 1489/*
1490 * In routemap processing there is a need to add the
1491 * name as a rule_key in the dependency table. Routemap
1492 * lib is unaware of rule_key when exact-match clause
1493 * is in use. routemap lib uses the compiled output to
1494 * get the rule_key value.
1495 */
1496static void *route_match_get_community_key(void *rule)
1497{
1498 struct rmap_community *rcom;
1499
1500 rcom = rule;
1501 return rcom->name;
1502}
1503
1504
718e3744 1505/* Route map commands for community matching. */
364deb04
DL
1506static const struct route_map_rule_cmd route_match_community_cmd = {
1507 "community",
1508 route_match_community,
1509 route_match_community_compile,
1510 route_match_community_free,
1511 route_match_get_community_key
1512};
6b0655a2 1513
57d187bc 1514/* Match function for lcommunity match. */
b68885f9 1515static enum route_map_cmd_result_t
1782514f 1516route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1517{
1518 struct community_list *list;
9b6d8fcf 1519 struct bgp_path_info *path;
e9a223ac 1520 struct rmap_community *rcom = rule;
d62a17ae 1521
1782514f 1522 path = object;
d62a17ae 1523
1782514f
DS
1524 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1525 LARGE_COMMUNITY_LIST_MASTER);
1526 if (!list)
1527 return RMAP_NOMATCH;
d62a17ae 1528
1782514f 1529 if (rcom->exact) {
1bcf3a96
DA
1530 if (lcommunity_list_exact_match(
1531 bgp_attr_get_lcommunity(path->attr), list))
1782514f
DS
1532 return RMAP_MATCH;
1533 } else {
1bcf3a96
DA
1534 if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
1535 list))
1782514f 1536 return RMAP_MATCH;
d62a17ae 1537 }
1782514f 1538
d62a17ae 1539 return RMAP_NOMATCH;
57d187bc
JS
1540}
1541
1542/* Compile function for community match. */
d62a17ae 1543static void *route_match_lcommunity_compile(const char *arg)
1544{
1545 struct rmap_community *rcom;
1546 int len;
1547 char *p;
1548
1549 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1550
1551 p = strchr(arg, ' ');
1552 if (p) {
1553 len = p - arg;
1554 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1555 memcpy(rcom->name, arg, len);
03ff9a14 1556 rcom->exact = 1;
d62a17ae 1557 } else {
1558 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1559 rcom->exact = 0;
1560 }
e237b0d2
DS
1561
1562 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1563 return rcom;
57d187bc
JS
1564}
1565
1566/* Compile function for community match. */
d62a17ae 1567static void route_match_lcommunity_free(void *rule)
57d187bc 1568{
d62a17ae 1569 struct rmap_community *rcom = rule;
57d187bc 1570
d62a17ae 1571 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1572 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
1573}
1574
1575/* Route map commands for community matching. */
364deb04
DL
1576static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
1577 "large-community",
1578 route_match_lcommunity,
1579 route_match_lcommunity_compile,
1580 route_match_lcommunity_free,
1581 route_match_get_community_key
1582};
57d187bc
JS
1583
1584
73ffb25b 1585/* Match function for extcommunity match. */
b68885f9 1586static enum route_map_cmd_result_t
1782514f 1587route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
73ffb25b 1588{
d62a17ae 1589 struct community_list *list;
9b6d8fcf 1590 struct bgp_path_info *path;
e9a223ac 1591 struct rmap_community *rcom = rule;
73ffb25b 1592
1782514f 1593 path = object;
e52702f2 1594
1782514f
DS
1595 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1596 EXTCOMMUNITY_LIST_MASTER);
1597 if (!list)
1598 return RMAP_NOMATCH;
1599
b53e67a3 1600 if (ecommunity_list_match(bgp_attr_get_ecommunity(path->attr), list))
1782514f 1601 return RMAP_MATCH;
73ffb25b 1602
d62a17ae 1603 return RMAP_NOMATCH;
73ffb25b 1604}
1605
1606/* Compile function for extcommunity match. */
d62a17ae 1607static void *route_match_ecommunity_compile(const char *arg)
73ffb25b 1608{
e9a223ac
DS
1609 struct rmap_community *rcom;
1610
1611 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1612 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
e237b0d2 1613 rcom->name_hash = bgp_clist_hash_key(rcom->name);
e9a223ac
DS
1614
1615 return rcom;
73ffb25b 1616}
1617
1618/* Compile function for extcommunity match. */
d62a17ae 1619static void route_match_ecommunity_free(void *rule)
73ffb25b 1620{
e9a223ac
DS
1621 struct rmap_community *rcom = rule;
1622
1623 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1624 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
73ffb25b 1625}
1626
1627/* Route map commands for community matching. */
364deb04
DL
1628static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
1629 "extcommunity",
1630 route_match_ecommunity,
1631 route_match_ecommunity_compile,
1632 route_match_ecommunity_free
1633};
6b0655a2 1634
718e3744 1635/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1636 and `address-family vpnv4'. */
6b0655a2 1637
718e3744 1638/* `match origin' */
b68885f9 1639static enum route_map_cmd_result_t
1782514f 1640route_match_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 1641{
d7c0a89a 1642 uint8_t *origin;
9b6d8fcf 1643 struct bgp_path_info *path;
718e3744 1644
1782514f
DS
1645 origin = rule;
1646 path = object;
e52702f2 1647
1782514f
DS
1648 if (path->attr->origin == *origin)
1649 return RMAP_MATCH;
718e3744 1650
d62a17ae 1651 return RMAP_NOMATCH;
718e3744 1652}
1653
d62a17ae 1654static void *route_match_origin_compile(const char *arg)
718e3744 1655{
d7c0a89a 1656 uint8_t *origin;
718e3744 1657
d7c0a89a 1658 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 1659
d62a17ae 1660 if (strcmp(arg, "igp") == 0)
1661 *origin = 0;
1662 else if (strcmp(arg, "egp") == 0)
1663 *origin = 1;
1664 else
1665 *origin = 2;
718e3744 1666
d62a17ae 1667 return origin;
718e3744 1668}
1669
1670/* Free route map's compiled `ip address' value. */
d62a17ae 1671static void route_match_origin_free(void *rule)
718e3744 1672{
d62a17ae 1673 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1674}
1675
1676/* Route map commands for origin matching. */
364deb04
DL
1677static const struct route_map_rule_cmd route_match_origin_cmd = {
1678 "origin",
1679 route_match_origin,
1680 route_match_origin_compile,
1681 route_match_origin_free
1682};
1add115a
VT
1683
1684/* match probability { */
1685
b68885f9 1686static enum route_map_cmd_result_t
1782514f 1687route_match_probability(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1688{
5920b3eb 1689 long r = frr_weak_random();
d62a17ae 1690
1691 switch (*(long *)rule) {
1692 case 0:
1693 break;
1694 case RAND_MAX:
1695 return RMAP_MATCH;
1696 default:
1697 if (r < *(long *)rule) {
1698 return RMAP_MATCH;
1699 }
1700 }
1add115a 1701
d62a17ae 1702 return RMAP_NOMATCH;
1add115a
VT
1703}
1704
d62a17ae 1705static void *route_match_probability_compile(const char *arg)
1add115a 1706{
d62a17ae 1707 long *lobule;
1708 unsigned perc;
1add115a 1709
d62a17ae 1710 perc = atoi(arg);
1711 lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1add115a 1712
d62a17ae 1713 switch (perc) {
1714 case 0:
1715 *lobule = 0;
1716 break;
1717 case 100:
1718 *lobule = RAND_MAX;
1719 break;
1720 default:
1721 *lobule = RAND_MAX / 100 * perc;
1722 }
1add115a 1723
d62a17ae 1724 return lobule;
1add115a
VT
1725}
1726
d62a17ae 1727static void route_match_probability_free(void *rule)
1add115a 1728{
d62a17ae 1729 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1add115a
VT
1730}
1731
364deb04
DL
1732static const struct route_map_rule_cmd route_match_probability_cmd = {
1733 "probability",
1734 route_match_probability,
1735 route_match_probability_compile,
1736 route_match_probability_free
1737};
1add115a 1738
bc413143
DS
1739/* `match interface IFNAME' */
1740/* Match function should return 1 if match is success else return
1741 zero. */
b68885f9 1742static enum route_map_cmd_result_t
1782514f 1743route_match_interface(void *rule, const struct prefix *prefix, void *object)
bc413143 1744{
d62a17ae 1745 struct interface *ifp;
40381db7 1746 struct bgp_path_info *path;
bc413143 1747
1782514f 1748 path = object;
bc413143 1749
de4f1a66 1750 if (!path || !path->peer || !path->peer->bgp)
1782514f 1751 return RMAP_NOMATCH;
bc413143 1752
de4f1a66 1753 ifp = if_lookup_by_name((char *)rule, path->peer->bgp->vrf_id);
bc413143 1754
1782514f
DS
1755 if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
1756 return RMAP_NOMATCH;
bc413143 1757
1782514f 1758 return RMAP_MATCH;
bc413143
DS
1759}
1760
1761/* Route map `interface' match statement. `arg' should be
1762 interface name. */
d62a17ae 1763static void *route_match_interface_compile(const char *arg)
bc413143 1764{
d62a17ae 1765 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
bc413143
DS
1766}
1767
1768/* Free route map's compiled `interface' value. */
d62a17ae 1769static void route_match_interface_free(void *rule)
bc413143 1770{
d62a17ae 1771 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
bc413143
DS
1772}
1773
1774/* Route map commands for ip address matching. */
364deb04
DL
1775static const struct route_map_rule_cmd route_match_interface_cmd = {
1776 "interface",
1777 route_match_interface,
1778 route_match_interface_compile,
1779 route_match_interface_free
1780};
bc413143 1781
1add115a
VT
1782/* } */
1783
718e3744 1784/* `set ip next-hop IP_ADDRESS' */
1785
0d9551dc 1786/* Match function return 1 if match is success else return zero. */
b68885f9 1787static enum route_map_cmd_result_t
1782514f 1788route_match_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 1789{
d62a17ae 1790 route_tag_t *tag;
9b6d8fcf 1791 struct bgp_path_info *path;
0d9551dc 1792
1782514f
DS
1793 tag = rule;
1794 path = object;
0d9551dc 1795
1782514f 1796 return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
0d9551dc
DS
1797}
1798
1799
0d9551dc 1800/* Route map commands for tag matching. */
364deb04
DL
1801static const struct route_map_rule_cmd route_match_tag_cmd = {
1802 "tag",
1803 route_match_tag,
1804 route_map_rule_tag_compile,
d62a17ae 1805 route_map_rule_tag_free,
0d9551dc
DS
1806};
1807
ef3e0d04 1808static enum route_map_cmd_result_t
1782514f 1809route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
ef3e0d04
SM
1810{
1811 uint32_t *srte_color = rule;
1812 struct bgp_path_info *path;
1813
ef3e0d04
SM
1814 path = object;
1815
1816 path->attr->srte_color = *srte_color;
1817 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
1818
1819 return RMAP_OKAY;
1820}
1821
1822/* Route map `sr-te color' compile function */
1823static void *route_set_srte_color_compile(const char *arg)
1824{
1825 uint32_t *color;
1826
1827 color = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1828 *color = atoi(arg);
1829
1830 return color;
1831}
1832
1833/* Free route map's compiled `sr-te color' value. */
1834static void route_set_srte_color_free(void *rule)
1835{
1836 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1837}
1838
1839/* Route map commands for sr-te color set. */
1840struct route_map_rule_cmd route_set_srte_color_cmd = {
1841 "sr-te color", route_set_srte_color, route_set_srte_color_compile,
1842 route_set_srte_color_free};
0d9551dc 1843
718e3744 1844/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 1845struct rmap_ip_nexthop_set {
1846 struct in_addr *address;
1847 int peer_address;
1848 int unchanged;
ac41b2a2 1849};
1850
b68885f9 1851static enum route_map_cmd_result_t
1782514f 1852route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1853{
1854 struct rmap_ip_nexthop_set *rins = rule;
9b6d8fcf 1855 struct bgp_path_info *path;
d62a17ae 1856 struct peer *peer;
1857
77f4dfb9
DS
1858 if (prefix->family == AF_INET6)
1859 return RMAP_OKAY;
1860
2b67b6f1
DS
1861 path = object;
1862 peer = path->peer;
1863
1864 if (rins->unchanged) {
1865 SET_FLAG(path->attr->rmap_change_flags,
1866 BATTR_RMAP_NEXTHOP_UNCHANGED);
1867 } else if (rins->peer_address) {
1868 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1869 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1870 && peer->su_remote
1871 && sockunion_family(peer->su_remote) == AF_INET) {
1872 path->attr->nexthop.s_addr =
1873 sockunion2ip(peer->su_remote);
9b6d8fcf 1874 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
2b67b6f1
DS
1875 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
1876 /* The next hop value will be set as part of
1877 * packet rewrite. Set the flags here to indicate
1878 * that rewrite needs to be done.
1879 * Also, clear the value.
1880 */
9b6d8fcf 1881 SET_FLAG(path->attr->rmap_change_flags,
2b67b6f1 1882 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
975a328e 1883 path->attr->nexthop.s_addr = INADDR_ANY;
d62a17ae 1884 }
2b67b6f1
DS
1885 } else {
1886 /* Set next hop value. */
1887 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1888 path->attr->nexthop = *rins->address;
1889 SET_FLAG(path->attr->rmap_change_flags,
1890 BATTR_RMAP_IPV4_NHOP_CHANGED);
1891 /* case for MP-BGP : MPLS VPN */
1892 path->attr->mp_nexthop_global_in = *rins->address;
1893 path->attr->mp_nexthop_len = sizeof(*rins->address);
ac41b2a2 1894 }
718e3744 1895
d62a17ae 1896 return RMAP_OKAY;
718e3744 1897}
1898
1899/* Route map `ip nexthop' compile function. Given string is converted
1900 to struct in_addr structure. */
d62a17ae 1901static void *route_set_ip_nexthop_compile(const char *arg)
1902{
1903 struct rmap_ip_nexthop_set *rins;
1904 struct in_addr *address = NULL;
1905 int peer_address = 0;
1906 int unchanged = 0;
1907 int ret;
1908
1909 if (strcmp(arg, "peer-address") == 0)
1910 peer_address = 1;
1911 else if (strcmp(arg, "unchanged") == 0)
1912 unchanged = 1;
1913 else {
1914 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
1915 sizeof(struct in_addr));
1916 ret = inet_aton(arg, address);
1917
1918 if (ret == 0) {
1919 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
1920 return NULL;
1921 }
ac41b2a2 1922 }
718e3744 1923
d62a17ae 1924 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
1925 sizeof(struct rmap_ip_nexthop_set));
ac41b2a2 1926
d62a17ae 1927 rins->address = address;
1928 rins->peer_address = peer_address;
1929 rins->unchanged = unchanged;
ac41b2a2 1930
d62a17ae 1931 return rins;
718e3744 1932}
1933
1934/* Free route map's compiled `ip nexthop' value. */
d62a17ae 1935static void route_set_ip_nexthop_free(void *rule)
718e3744 1936{
d62a17ae 1937 struct rmap_ip_nexthop_set *rins = rule;
ac41b2a2 1938
0a22ddfb 1939 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
e52702f2 1940
d62a17ae 1941 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
718e3744 1942}
1943
1944/* Route map commands for ip nexthop set. */
364deb04
DL
1945static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
1946 "ip next-hop",
1947 route_set_ip_nexthop,
1948 route_set_ip_nexthop_compile,
1949 route_set_ip_nexthop_free
1950};
6b0655a2 1951
718e3744 1952/* `set local-preference LOCAL_PREF' */
1953
1954/* Set local preference. */
b68885f9 1955static enum route_map_cmd_result_t
1782514f 1956route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
d62a17ae 1957{
1958 struct rmap_value *rv;
9b6d8fcf 1959 struct bgp_path_info *path;
d7c0a89a 1960 uint32_t locpref = 0;
d62a17ae 1961
1782514f
DS
1962 /* Fetch routemap's rule information. */
1963 rv = rule;
1964 path = object;
d62a17ae 1965
1782514f
DS
1966 /* Set local preference value. */
1967 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1968 locpref = path->attr->local_pref;
d62a17ae 1969
1782514f
DS
1970 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1971 path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
718e3744 1972
d62a17ae 1973 return RMAP_OKAY;
718e3744 1974}
1975
718e3744 1976/* Set local preference rule structure. */
364deb04
DL
1977static const struct route_map_rule_cmd route_set_local_pref_cmd = {
1978 "local-preference",
1979 route_set_local_pref,
1980 route_value_compile,
d62a17ae 1981 route_value_free,
718e3744 1982};
6b0655a2 1983
718e3744 1984/* `set weight WEIGHT' */
1985
1986/* Set weight. */
b68885f9 1987static enum route_map_cmd_result_t
1782514f 1988route_set_weight(void *rule, const struct prefix *prefix, void *object)
718e3744 1989{
d62a17ae 1990 struct rmap_value *rv;
9b6d8fcf 1991 struct bgp_path_info *path;
718e3744 1992
1782514f
DS
1993 /* Fetch routemap's rule information. */
1994 rv = rule;
1995 path = object;
e52702f2 1996
1782514f
DS
1997 /* Set weight value. */
1998 path->attr->weight = route_value_adjust(rv, 0, path->peer);
718e3744 1999
d62a17ae 2000 return RMAP_OKAY;
718e3744 2001}
2002
718e3744 2003/* Set local preference rule structure. */
364deb04
DL
2004static const struct route_map_rule_cmd route_set_weight_cmd = {
2005 "weight",
2006 route_set_weight,
2007 route_value_compile,
2008 route_value_free,
718e3744 2009};
6b0655a2 2010
7b7d48e5
DS
2011/* `set distance DISTANCE */
2012static enum route_map_cmd_result_t
1782514f 2013route_set_distance(void *rule, const struct prefix *prefix, void *object)
7b7d48e5
DS
2014{
2015 struct bgp_path_info *path = object;
2016 struct rmap_value *rv = rule;
2017
7b7d48e5
DS
2018 path->attr->distance = rv->value;
2019
2020 return RMAP_OKAY;
2021}
2022
2023/* set distance rule structure */
364deb04 2024static const struct route_map_rule_cmd route_set_distance_cmd = {
7b7d48e5
DS
2025 "distance",
2026 route_set_distance,
2027 route_value_compile,
2028 route_value_free,
2029};
2030
718e3744 2031/* `set metric METRIC' */
2032
2033/* Set metric to attribute. */
b68885f9 2034static enum route_map_cmd_result_t
1782514f 2035route_set_metric(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2036{
2037 struct rmap_value *rv;
9b6d8fcf 2038 struct bgp_path_info *path;
d7c0a89a 2039 uint32_t med = 0;
d62a17ae 2040
1782514f
DS
2041 /* Fetch routemap's rule information. */
2042 rv = rule;
2043 path = object;
d62a17ae 2044
1782514f
DS
2045 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
2046 med = path->attr->med;
2047
2048 path->attr->med = route_value_adjust(rv, med, path->peer);
2049 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
d62a17ae 2050
d62a17ae 2051 return RMAP_OKAY;
718e3744 2052}
2053
718e3744 2054/* Set metric rule structure. */
364deb04
DL
2055static const struct route_map_rule_cmd route_set_metric_cmd = {
2056 "metric",
2057 route_set_metric,
2058 route_value_compile,
2059 route_value_free,
718e3744 2060};
6b0655a2 2061
951745bd
PG
2062/* `set table (1-4294967295)' */
2063
1782514f
DS
2064static enum route_map_cmd_result_t
2065route_set_table_id(void *rule, const struct prefix *prefix,
2066
2067 void *object)
951745bd
PG
2068{
2069 struct rmap_value *rv;
2070 struct bgp_path_info *path;
2071
1782514f
DS
2072 /* Fetch routemap's rule information. */
2073 rv = rule;
2074 path = object;
2075
2076 path->attr->rmap_table_id = rv->value;
951745bd 2077
951745bd
PG
2078 return RMAP_OKAY;
2079}
2080
2081/* Set table_id rule structure. */
364deb04
DL
2082static const struct route_map_rule_cmd route_set_table_id_cmd = {
2083 "table",
2084 route_set_table_id,
2085 route_value_compile,
2086 route_value_free
951745bd
PG
2087};
2088
718e3744 2089/* `set as-path prepend ASPATH' */
2090
2091/* For AS path prepend mechanism. */
b68885f9 2092static enum route_map_cmd_result_t
1782514f 2093route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2094{
2095 struct aspath *aspath;
2096 struct aspath *new;
9b6d8fcf 2097 struct bgp_path_info *path;
d62a17ae 2098
1782514f 2099 path = object;
d62a17ae 2100
1782514f
DS
2101 if (path->attr->aspath->refcnt)
2102 new = aspath_dup(path->attr->aspath);
2103 else
2104 new = path->attr->aspath;
bc3dd427 2105
1782514f
DS
2106 if ((uintptr_t)rule > 10) {
2107 aspath = rule;
2108 aspath_prepend(aspath, new);
2109 } else {
2110 as_t as = aspath_leftmost(new);
6ba0adac
DS
2111 if (as)
2112 new = aspath_add_seq_n(new, as, (uintptr_t)rule);
d62a17ae 2113 }
718e3744 2114
1782514f
DS
2115 path->attr->aspath = new;
2116
d62a17ae 2117 return RMAP_OKAY;
718e3744 2118}
2119
d62a17ae 2120static void *route_set_aspath_prepend_compile(const char *arg)
bc3dd427 2121{
d62a17ae 2122 unsigned int num;
bc3dd427 2123
d62a17ae 2124 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
2125 return (void *)(uintptr_t)num;
bc3dd427 2126
d62a17ae 2127 return route_aspath_compile(arg);
bc3dd427
DW
2128}
2129
d62a17ae 2130static void route_set_aspath_prepend_free(void *rule)
bc3dd427 2131{
d62a17ae 2132 if ((uintptr_t)rule > 10)
2133 route_aspath_free(rule);
bc3dd427
DW
2134}
2135
2136
515e500c 2137/* Set as-path prepend rule structure. */
364deb04
DL
2138static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
2139 "as-path prepend",
2140 route_set_aspath_prepend,
2141 route_set_aspath_prepend_compile,
2142 route_set_aspath_prepend_free,
718e3744 2143};
6b0655a2 2144
841f7a57
DO
2145/* `set as-path exclude ASn' */
2146
2147/* For ASN exclude mechanism.
d62a17ae 2148 * Iterate over ASns requested and filter them from the given AS_PATH one by
2149 * one.
841f7a57
DO
2150 * Make a deep copy of existing AS_PATH, but for the first ASn only.
2151 */
b68885f9 2152static enum route_map_cmd_result_t
1782514f 2153route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
d62a17ae 2154{
2155 struct aspath *new_path, *exclude_path;
9b6d8fcf 2156 struct bgp_path_info *path;
d62a17ae 2157
1782514f
DS
2158 exclude_path = rule;
2159 path = object;
2160 if (path->attr->aspath->refcnt)
2161 new_path = aspath_dup(path->attr->aspath);
2162 else
2163 new_path = path->attr->aspath;
2164 path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
2165
d62a17ae 2166 return RMAP_OKAY;
841f7a57
DO
2167}
2168
841f7a57 2169/* Set ASn exlude rule structure. */
364deb04
DL
2170static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2171 "as-path exclude",
2172 route_set_aspath_exclude,
2173 route_aspath_compile,
d62a17ae 2174 route_aspath_free,
841f7a57 2175};
6b0655a2 2176
718e3744 2177/* `set community COMMUNITY' */
d62a17ae 2178struct rmap_com_set {
2179 struct community *com;
2180 int additive;
2181 int none;
718e3744 2182};
2183
2184/* For community set mechanism. */
b68885f9 2185static enum route_map_cmd_result_t
1782514f 2186route_set_community(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2187{
2188 struct rmap_com_set *rcs;
9b6d8fcf 2189 struct bgp_path_info *path;
d62a17ae 2190 struct attr *attr;
2191 struct community *new = NULL;
2192 struct community *old;
2193 struct community *merge;
2194
1782514f
DS
2195 rcs = rule;
2196 path = object;
2197 attr = path->attr;
9a706b42 2198 old = bgp_attr_get_community(attr);
1782514f
DS
2199
2200 /* "none" case. */
2201 if (rcs->none) {
2202 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
9a706b42 2203 bgp_attr_set_community(attr, NULL);
1782514f
DS
2204 /* See the longer comment down below. */
2205 if (old && old->refcnt == 0)
2206 community_free(&old);
2207 return RMAP_OKAY;
2208 }
718e3744 2209
1782514f
DS
2210 /* "additive" case. */
2211 if (rcs->additive && old) {
2212 merge = community_merge(community_dup(old), rcs->com);
d62a17ae 2213
1782514f
DS
2214 new = community_uniq_sort(merge);
2215 community_free(&merge);
2216 } else
2217 new = community_dup(rcs->com);
d62a17ae 2218
1782514f
DS
2219 /* HACK: if the old community is not intern'd,
2220 * we should free it here, or all reference to it may be
2221 * lost.
2222 * Really need to cleanup attribute caching sometime.
2223 */
2224 if (old && old->refcnt == 0)
2225 community_free(&old);
f24804f4 2226
1782514f 2227 /* will be interned by caller if required */
9a706b42 2228 bgp_attr_set_community(attr, new);
d62a17ae 2229
1782514f 2230 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
718e3744 2231
d62a17ae 2232 return RMAP_OKAY;
718e3744 2233}
2234
2235/* Compile function for set community. */
d62a17ae 2236static void *route_set_community_compile(const char *arg)
2237{
2238 struct rmap_com_set *rcs;
2239 struct community *com = NULL;
2240 char *sp;
2241 int additive = 0;
2242 int none = 0;
2243
2244 if (strcmp(arg, "none") == 0)
2245 none = 1;
2246 else {
2247 sp = strstr(arg, "additive");
2248
2249 if (sp && sp > arg) {
770817b4 2250 /* "additive" keyword is included. */
d62a17ae 2251 additive = 1;
2252 *(sp - 1) = '\0';
2253 }
718e3744 2254
d62a17ae 2255 com = community_str2com(arg);
718e3744 2256
d62a17ae 2257 if (additive)
2258 *(sp - 1) = ' ';
718e3744 2259
d62a17ae 2260 if (!com)
2261 return NULL;
2262 }
e52702f2 2263
d62a17ae 2264 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2265 rcs->com = com;
2266 rcs->additive = additive;
2267 rcs->none = none;
e52702f2 2268
d62a17ae 2269 return rcs;
718e3744 2270}
2271
2272/* Free function for set community. */
d62a17ae 2273static void route_set_community_free(void *rule)
718e3744 2274{
d62a17ae 2275 struct rmap_com_set *rcs = rule;
718e3744 2276
d62a17ae 2277 if (rcs->com)
3c1f53de 2278 community_free(&rcs->com);
d62a17ae 2279 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2280}
2281
2282/* Set community rule structure. */
364deb04
DL
2283static const struct route_map_rule_cmd route_set_community_cmd = {
2284 "community",
2285 route_set_community,
2286 route_set_community_compile,
d62a17ae 2287 route_set_community_free,
718e3744 2288};
6b0655a2 2289
57d187bc 2290/* `set community COMMUNITY' */
d62a17ae 2291struct rmap_lcom_set {
2292 struct lcommunity *lcom;
2293 int additive;
2294 int none;
57d187bc
JS
2295};
2296
2297
2298/* For lcommunity set mechanism. */
b68885f9 2299static enum route_map_cmd_result_t
1782514f 2300route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2301{
2302 struct rmap_lcom_set *rcs;
9b6d8fcf 2303 struct bgp_path_info *path;
d62a17ae 2304 struct attr *attr;
2305 struct lcommunity *new = NULL;
2306 struct lcommunity *old;
2307 struct lcommunity *merge;
2308
1782514f
DS
2309 rcs = rule;
2310 path = object;
2311 attr = path->attr;
1bcf3a96 2312 old = bgp_attr_get_lcommunity(attr);
d62a17ae 2313
1782514f
DS
2314 /* "none" case. */
2315 if (rcs->none) {
2316 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
1bcf3a96 2317 bgp_attr_set_lcommunity(attr, NULL);
d62a17ae 2318
1782514f 2319 /* See the longer comment down below. */
4265a53e
NK
2320 if (old && old->refcnt == 0)
2321 lcommunity_free(&old);
1782514f
DS
2322 return RMAP_OKAY;
2323 }
4265a53e 2324
1782514f
DS
2325 if (rcs->additive && old) {
2326 merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
d62a17ae 2327
1782514f
DS
2328 new = lcommunity_uniq_sort(merge);
2329 lcommunity_free(&merge);
2330 } else
2331 new = lcommunity_dup(rcs->lcom);
2332
2333 /* HACK: if the old large-community is not intern'd,
2334 * we should free it here, or all reference to it may be
2335 * lost.
2336 * Really need to cleanup attribute caching sometime.
2337 */
2338 if (old && old->refcnt == 0)
2339 lcommunity_free(&old);
2340
2341 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1bcf3a96 2342 bgp_attr_set_lcommunity(attr, new);
1782514f
DS
2343
2344 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
57d187bc 2345
d62a17ae 2346 return RMAP_OKAY;
2347}
57d187bc 2348
d62a17ae 2349/* Compile function for set community. */
2350static void *route_set_lcommunity_compile(const char *arg)
2351{
2352 struct rmap_lcom_set *rcs;
2353 struct lcommunity *lcom = NULL;
2354 char *sp;
2355 int additive = 0;
2356 int none = 0;
2357
2358 if (strcmp(arg, "none") == 0)
2359 none = 1;
2360 else {
2361 sp = strstr(arg, "additive");
2362
2363 if (sp && sp > arg) {
2364 /* "additive" keyworkd is included. */
2365 additive = 1;
2366 *(sp - 1) = '\0';
2367 }
57d187bc 2368
d62a17ae 2369 lcom = lcommunity_str2com(arg);
57d187bc 2370
d62a17ae 2371 if (additive)
2372 *(sp - 1) = ' ';
57d187bc 2373
d62a17ae 2374 if (!lcom)
2375 return NULL;
2376 }
57d187bc 2377
d62a17ae 2378 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2379 rcs->lcom = lcom;
2380 rcs->additive = additive;
2381 rcs->none = none;
57d187bc 2382
d62a17ae 2383 return rcs;
57d187bc
JS
2384}
2385
2386/* Free function for set lcommunity. */
d62a17ae 2387static void route_set_lcommunity_free(void *rule)
57d187bc 2388{
d62a17ae 2389 struct rmap_lcom_set *rcs = rule;
57d187bc 2390
d62a17ae 2391 if (rcs->lcom) {
2392 lcommunity_free(&rcs->lcom);
2393 }
2394 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
57d187bc
JS
2395}
2396
2397/* Set community rule structure. */
364deb04
DL
2398static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2399 "large-community",
2400 route_set_lcommunity,
2401 route_set_lcommunity_compile,
d62a17ae 2402 route_set_lcommunity_free,
57d187bc
JS
2403};
2404
2405/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2406
2407/* For large community set mechanism. */
b68885f9 2408static enum route_map_cmd_result_t
1782514f 2409route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
d62a17ae 2410{
2411 struct community_list *list;
2412 struct lcommunity *merge;
2413 struct lcommunity *new;
2414 struct lcommunity *old;
9b6d8fcf 2415 struct bgp_path_info *path;
e9a223ac 2416 struct rmap_community *rcom = rule;
d62a17ae 2417
1782514f
DS
2418 if (!rcom)
2419 return RMAP_OKAY;
d62a17ae 2420
1782514f
DS
2421 path = object;
2422 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2423 LARGE_COMMUNITY_LIST_MASTER);
1bcf3a96 2424 old = bgp_attr_get_lcommunity(path->attr);
1782514f
DS
2425
2426 if (list && old) {
2427 merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
2428 new = lcommunity_uniq_sort(merge);
2429 lcommunity_free(&merge);
2430
2431 /* HACK: if the old community is not intern'd,
2432 * we should free it here, or all reference to it may be
2433 * lost.
2434 * Really need to cleanup attribute caching sometime.
2435 */
2436 if (old->refcnt == 0)
2437 lcommunity_free(&old);
2438
2439 if (new->size == 0) {
1bcf3a96 2440 bgp_attr_set_lcommunity(path->attr, NULL);
1782514f
DS
2441 path->attr->flag &=
2442 ~ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
2443 lcommunity_free(&new);
2444 } else {
1bcf3a96 2445 bgp_attr_set_lcommunity(path->attr, new);
1782514f
DS
2446 path->attr->flag |=
2447 ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
d62a17ae 2448 }
2449 }
2450
2451 return RMAP_OKAY;
57d187bc
JS
2452}
2453
2454/* Compile function for set lcommunity. */
d62a17ae 2455static void *route_set_lcommunity_delete_compile(const char *arg)
57d187bc 2456{
e9a223ac 2457 struct rmap_community *rcom;
caa5af30
DA
2458 char **splits;
2459 int num;
57d187bc 2460
caa5af30 2461 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2462
caa5af30
DA
2463 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2464 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2465 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2466
caa5af30
DA
2467 for (int i = 0; i < num; i++)
2468 XFREE(MTYPE_TMP, splits[i]);
2469 XFREE(MTYPE_TMP, splits);
2470
e9a223ac 2471 return rcom;
57d187bc
JS
2472}
2473
2474/* Free function for set lcommunity. */
d62a17ae 2475static void route_set_lcommunity_delete_free(void *rule)
57d187bc 2476{
e9a223ac
DS
2477 struct rmap_community *rcom = rule;
2478
2479 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2480 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
2481}
2482
2483/* Set lcommunity rule structure. */
364deb04
DL
2484static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2485 "large-comm-list",
2486 route_set_lcommunity_delete,
2487 route_set_lcommunity_delete_compile,
2488 route_set_lcommunity_delete_free,
57d187bc
JS
2489};
2490
2491
fee6e4e4 2492/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 2493
2494/* For community set mechanism. */
b68885f9
LK
2495static enum route_map_cmd_result_t
2496route_set_community_delete(void *rule, const struct prefix *prefix,
1782514f 2497 void *object)
d62a17ae 2498{
2499 struct community_list *list;
2500 struct community *merge;
2501 struct community *new;
2502 struct community *old;
9b6d8fcf 2503 struct bgp_path_info *path;
e9a223ac 2504 struct rmap_community *rcom = rule;
d62a17ae 2505
1782514f
DS
2506 if (!rcom)
2507 return RMAP_OKAY;
d62a17ae 2508
1782514f
DS
2509 path = object;
2510 list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2511 COMMUNITY_LIST_MASTER);
9a706b42 2512 old = bgp_attr_get_community(path->attr);
1782514f
DS
2513
2514 if (list && old) {
2515 merge = community_list_match_delete(community_dup(old), list);
2516 new = community_uniq_sort(merge);
2517 community_free(&merge);
2518
2519 /* HACK: if the old community is not intern'd,
2520 * we should free it here, or all reference to it may be
2521 * lost.
2522 * Really need to cleanup attribute caching sometime.
2523 */
2524 if (old->refcnt == 0)
2525 community_free(&old);
2526
2527 if (new->size == 0) {
9a706b42 2528 bgp_attr_set_community(path->attr, NULL);
1782514f
DS
2529 path->attr->flag &=
2530 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
2531 community_free(&new);
2532 } else {
9a706b42 2533 bgp_attr_set_community(path->attr, new);
1782514f 2534 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
d62a17ae 2535 }
718e3744 2536 }
718e3744 2537
d62a17ae 2538 return RMAP_OKAY;
718e3744 2539}
2540
2541/* Compile function for set community. */
d62a17ae 2542static void *route_set_community_delete_compile(const char *arg)
718e3744 2543{
e9a223ac 2544 struct rmap_community *rcom;
60762f8f
DA
2545 char **splits;
2546 int num;
718e3744 2547
60762f8f 2548 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2549
60762f8f
DA
2550 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2551 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2552 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2553
60762f8f
DA
2554 for (int i = 0; i < num; i++)
2555 XFREE(MTYPE_TMP, splits[i]);
2556 XFREE(MTYPE_TMP, splits);
2557
e9a223ac 2558 return rcom;
718e3744 2559}
2560
2561/* Free function for set community. */
d62a17ae 2562static void route_set_community_delete_free(void *rule)
718e3744 2563{
e9a223ac
DS
2564 struct rmap_community *rcom = rule;
2565
2566 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2567 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 2568}
2569
2570/* Set community rule structure. */
364deb04
DL
2571static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2572 "comm-list",
2573 route_set_community_delete,
2574 route_set_community_delete_compile,
2575 route_set_community_delete_free,
718e3744 2576};
6b0655a2 2577
718e3744 2578/* `set extcommunity rt COMMUNITY' */
2579
bb4dcdd1
DA
2580struct rmap_ecom_set {
2581 struct ecommunity *ecom;
2582 bool none;
2583};
2584
73d78ea0 2585/* For community set mechanism. Used by _rt and _soo. */
b68885f9 2586static enum route_map_cmd_result_t
1782514f 2587route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
d62a17ae 2588{
bb4dcdd1 2589 struct rmap_ecom_set *rcs;
d62a17ae 2590 struct ecommunity *new_ecom;
2591 struct ecommunity *old_ecom;
9b6d8fcf 2592 struct bgp_path_info *path;
bb4dcdd1 2593 struct attr *attr;
d62a17ae 2594
bb4dcdd1 2595 rcs = rule;
1782514f 2596 path = object;
bb4dcdd1 2597 attr = path->attr;
d62a17ae 2598
bb4dcdd1
DA
2599 if (rcs->none) {
2600 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
b53e67a3 2601 bgp_attr_set_ecommunity(attr, NULL);
bb4dcdd1
DA
2602 return RMAP_OKAY;
2603 }
2604
2605 if (!rcs->ecom)
1782514f 2606 return RMAP_OKAY;
d62a17ae 2607
1782514f 2608 /* We assume additive for Extended Community. */
b53e67a3 2609 old_ecom = bgp_attr_get_ecommunity(path->attr);
1782514f
DS
2610
2611 if (old_ecom) {
bb4dcdd1
DA
2612 new_ecom =
2613 ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
d62a17ae 2614
1782514f
DS
2615 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2616 * bgp_update_receive()
2617 * ->refcnt = 0 => set by a previous route-map
2618 * statement */
2619 if (!old_ecom->refcnt)
2620 ecommunity_free(&old_ecom);
2621 } else
bb4dcdd1 2622 new_ecom = ecommunity_dup(rcs->ecom);
d62a17ae 2623
1782514f 2624 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
b53e67a3 2625 bgp_attr_set_ecommunity(path->attr, new_ecom);
d62a17ae 2626
1782514f 2627 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
d62a17ae 2628
d62a17ae 2629 return RMAP_OKAY;
718e3744 2630}
2631
bb4dcdd1
DA
2632static void *route_set_ecommunity_none_compile(const char *arg)
2633{
2634 struct rmap_ecom_set *rcs;
2635 bool none = false;
2636
2637 if (strncmp(arg, "none", 4) == 0)
2638 none = true;
2639
2640 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2641 rcs->ecom = NULL;
2642 rcs->none = none;
2643
2644 return rcs;
2645}
2646
d62a17ae 2647static void *route_set_ecommunity_rt_compile(const char *arg)
718e3744 2648{
bb4dcdd1 2649 struct rmap_ecom_set *rcs;
d62a17ae 2650 struct ecommunity *ecom;
718e3744 2651
d62a17ae 2652 ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2653 if (!ecom)
2654 return NULL;
bb4dcdd1
DA
2655
2656 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2657 rcs->ecom = ecommunity_intern(ecom);
2658 rcs->none = false;
2659
2660 return rcs;
718e3744 2661}
2662
73d78ea0 2663/* Free function for set community. Used by _rt and _soo */
d62a17ae 2664static void route_set_ecommunity_free(void *rule)
718e3744 2665{
bb4dcdd1
DA
2666 struct rmap_ecom_set *rcs = rule;
2667
2668 if (rcs->ecom)
2669 ecommunity_unintern(&rcs->ecom);
2670
2671 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2672}
2673
bb4dcdd1
DA
2674static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
2675 "extcommunity",
2676 route_set_ecommunity,
2677 route_set_ecommunity_none_compile,
2678 route_set_ecommunity_free,
2679};
2680
718e3744 2681/* Set community rule structure. */
364deb04
DL
2682static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2683 "extcommunity rt",
2684 route_set_ecommunity,
2685 route_set_ecommunity_rt_compile,
2686 route_set_ecommunity_free,
718e3744 2687};
2688
2689/* `set extcommunity soo COMMUNITY' */
2690
718e3744 2691/* Compile function for set community. */
d62a17ae 2692static void *route_set_ecommunity_soo_compile(const char *arg)
718e3744 2693{
bb4dcdd1 2694 struct rmap_ecom_set *rcs;
d62a17ae 2695 struct ecommunity *ecom;
718e3744 2696
d62a17ae 2697 ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2698 if (!ecom)
2699 return NULL;
e52702f2 2700
bb4dcdd1
DA
2701 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2702 rcs->ecom = ecommunity_intern(ecom);
2703 rcs->none = false;
2704
2705 return rcs;
718e3744 2706}
2707
718e3744 2708/* Set community rule structure. */
364deb04
DL
2709static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2710 "extcommunity soo",
2711 route_set_ecommunity,
2712 route_set_ecommunity_soo_compile,
2713 route_set_ecommunity_free,
718e3744 2714};
6b0655a2 2715
ca9ac3ef 2716/* `set extcommunity bandwidth' */
2717
2718struct rmap_ecomm_lb_set {
2719 uint8_t lb_type;
2720#define RMAP_ECOMM_LB_SET_VALUE 1
2721#define RMAP_ECOMM_LB_SET_CUMUL 2
2722#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2723 bool non_trans;
2724 uint32_t bw;
2725};
2726
2727static enum route_map_cmd_result_t
1782514f 2728route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
ca9ac3ef 2729{
2730 struct rmap_ecomm_lb_set *rels = rule;
2731 struct bgp_path_info *path;
2732 struct peer *peer;
2733 struct ecommunity ecom_lb = {0};
2734 struct ecommunity_val lb_eval;
2735 uint32_t bw_bytes = 0;
b1875e65 2736 uint16_t mpath_count = 0;
ca9ac3ef 2737 struct ecommunity *new_ecom;
2738 struct ecommunity *old_ecom;
2739 as_t as;
2740
ca9ac3ef 2741 path = object;
2742 peer = path->peer;
2743 if (!peer || !peer->bgp)
2744 return RMAP_ERROR;
2745
2746 /* Build link bandwidth extended community */
2747 as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
b1875e65 2748 if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
87b42e3b 2749 bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
b1875e65 2750 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2751 /* process this only for the best path. */
2752 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2753 return RMAP_OKAY;
2754
2755 bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2756 if (!bw_bytes)
2757 return RMAP_OKAY;
2758
2759 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2760
2761 /* process this only for the best path. */
2762 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2763 return RMAP_OKAY;
2764
87b42e3b 2765 bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
b1875e65 2766 mpath_count = bgp_path_info_mpath_count(path) + 1;
2767 bw_bytes *= mpath_count;
2768 }
ca9ac3ef 2769
27aa23a4
DA
2770 encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
2771 CHECK_FLAG(peer->flags,
2772 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
ca9ac3ef 2773
2774 /* add to route or merge with existing */
b53e67a3 2775 old_ecom = bgp_attr_get_ecommunity(path->attr);
ca9ac3ef 2776 if (old_ecom) {
f6ca545a 2777 new_ecom = ecommunity_dup(old_ecom);
2778 ecommunity_add_val(new_ecom, &lb_eval, true, true);
ca9ac3ef 2779 if (!old_ecom->refcnt)
2780 ecommunity_free(&old_ecom);
f6ca545a 2781 } else {
2782 ecom_lb.size = 1;
7659ad68 2783 ecom_lb.unit_size = ECOMMUNITY_SIZE;
f6ca545a 2784 ecom_lb.val = (uint8_t *)lb_eval.val;
ca9ac3ef 2785 new_ecom = ecommunity_dup(&ecom_lb);
f6ca545a 2786 }
ca9ac3ef 2787
2788 /* new_ecom will be intern()'d or attr_flush()'d in call stack */
b53e67a3 2789 bgp_attr_set_ecommunity(path->attr, new_ecom);
ca9ac3ef 2790 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
2791
7b651a32 2792 /* Mark that route-map has set link bandwidth; used in attribute
2793 * setting decisions.
2794 */
2795 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
ca9ac3ef 2796
2797 return RMAP_OKAY;
2798}
2799
2800static void *route_set_ecommunity_lb_compile(const char *arg)
2801{
2802 struct rmap_ecomm_lb_set *rels;
2803 uint8_t lb_type;
2804 uint32_t bw = 0;
4c13ffe4 2805 char bw_str[40] = {0};
2806 char *p, *str;
2807 bool non_trans = false;
ca9ac3ef 2808
4c13ffe4 2809 str = (char *)arg;
2810 p = strchr(arg, ' ');
2811 if (p) {
2812 int len;
2813
2814 len = p - arg;
2815 memcpy(bw_str, arg, len);
2816 non_trans = true;
2817 str = bw_str;
2818 }
2819
2820 if (strcmp(str, "cumulative") == 0)
ca9ac3ef 2821 lb_type = RMAP_ECOMM_LB_SET_CUMUL;
4c13ffe4 2822 else if (strcmp(str, "num-multipaths") == 0)
ca9ac3ef 2823 lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
2824 else {
2825 char *end = NULL;
2826
4c13ffe4 2827 bw = strtoul(str, &end, 10);
ca9ac3ef 2828 if (*end != '\0')
2829 return NULL;
2830 lb_type = RMAP_ECOMM_LB_SET_VALUE;
2831 }
2832
2833 rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2834 sizeof(struct rmap_ecomm_lb_set));
2835 rels->lb_type = lb_type;
2836 rels->bw = bw;
4c13ffe4 2837 rels->non_trans = non_trans;
ca9ac3ef 2838
2839 return rels;
2840}
2841
2842static void route_set_ecommunity_lb_free(void *rule)
2843{
2844 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2845}
2846
2847/* Set community rule structure. */
2848struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
2849 "extcommunity bandwidth",
2850 route_set_ecommunity_lb,
2851 route_set_ecommunity_lb_compile,
2852 route_set_ecommunity_lb_free,
2853};
2854
718e3744 2855/* `set origin ORIGIN' */
2856
2857/* For origin set. */
b68885f9 2858static enum route_map_cmd_result_t
1782514f 2859route_set_origin(void *rule, const struct prefix *prefix, void *object)
718e3744 2860{
d7c0a89a 2861 uint8_t *origin;
9b6d8fcf 2862 struct bgp_path_info *path;
718e3744 2863
1782514f
DS
2864 origin = rule;
2865 path = object;
e52702f2 2866
1782514f 2867 path->attr->origin = *origin;
718e3744 2868
d62a17ae 2869 return RMAP_OKAY;
718e3744 2870}
2871
2872/* Compile function for origin set. */
d62a17ae 2873static void *route_set_origin_compile(const char *arg)
718e3744 2874{
d7c0a89a 2875 uint8_t *origin;
718e3744 2876
d7c0a89a 2877 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 2878
d62a17ae 2879 if (strcmp(arg, "igp") == 0)
2880 *origin = 0;
2881 else if (strcmp(arg, "egp") == 0)
2882 *origin = 1;
2883 else
2884 *origin = 2;
718e3744 2885
d62a17ae 2886 return origin;
718e3744 2887}
2888
2889/* Compile function for origin set. */
d62a17ae 2890static void route_set_origin_free(void *rule)
718e3744 2891{
d62a17ae 2892 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2893}
2894
515e500c 2895/* Set origin rule structure. */
364deb04
DL
2896static const struct route_map_rule_cmd route_set_origin_cmd = {
2897 "origin",
2898 route_set_origin,
2899 route_set_origin_compile,
d62a17ae 2900 route_set_origin_free,
718e3744 2901};
6b0655a2 2902
718e3744 2903/* `set atomic-aggregate' */
2904
2905/* For atomic aggregate set. */
b68885f9 2906static enum route_map_cmd_result_t
1782514f 2907route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
718e3744 2908{
9b6d8fcf 2909 struct bgp_path_info *path;
718e3744 2910
1782514f
DS
2911 path = object;
2912 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
718e3744 2913
d62a17ae 2914 return RMAP_OKAY;
718e3744 2915}
2916
2917/* Compile function for atomic aggregate. */
d62a17ae 2918static void *route_set_atomic_aggregate_compile(const char *arg)
718e3744 2919{
d62a17ae 2920 return (void *)1;
718e3744 2921}
2922
2923/* Compile function for atomic aggregate. */
d62a17ae 2924static void route_set_atomic_aggregate_free(void *rule)
718e3744 2925{
d62a17ae 2926 return;
718e3744 2927}
2928
2929/* Set atomic aggregate rule structure. */
364deb04
DL
2930static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
2931 "atomic-aggregate",
2932 route_set_atomic_aggregate,
2933 route_set_atomic_aggregate_compile,
2934 route_set_atomic_aggregate_free,
718e3744 2935};
6b0655a2 2936
718e3744 2937/* `set aggregator as AS A.B.C.D' */
d62a17ae 2938struct aggregator {
2939 as_t as;
2940 struct in_addr address;
718e3744 2941};
2942
b68885f9 2943static enum route_map_cmd_result_t
1782514f 2944route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
718e3744 2945{
9b6d8fcf 2946 struct bgp_path_info *path;
d62a17ae 2947 struct aggregator *aggregator;
718e3744 2948
1782514f
DS
2949 path = object;
2950 aggregator = rule;
e52702f2 2951
1782514f
DS
2952 path->attr->aggregator_as = aggregator->as;
2953 path->attr->aggregator_addr = aggregator->address;
2954 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
718e3744 2955
d62a17ae 2956 return RMAP_OKAY;
718e3744 2957}
2958
d62a17ae 2959static void *route_set_aggregator_as_compile(const char *arg)
718e3744 2960{
d62a17ae 2961 struct aggregator *aggregator;
2962 char as[10];
2963 char address[20];
2964 int ret;
718e3744 2965
d62a17ae 2966 aggregator =
2967 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
116e176d
DS
2968 if (sscanf(arg, "%s %s", as, address) != 2) {
2969 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2970 return NULL;
2971 }
718e3744 2972
d62a17ae 2973 aggregator->as = strtoul(as, NULL, 10);
2974 ret = inet_aton(address, &aggregator->address);
2975 if (ret == 0) {
2976 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2977 return NULL;
2978 }
2979 return aggregator;
718e3744 2980}
2981
d62a17ae 2982static void route_set_aggregator_as_free(void *rule)
718e3744 2983{
d62a17ae 2984 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2985}
2986
364deb04
DL
2987static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
2988 "aggregator as",
2989 route_set_aggregator_as,
2990 route_set_aggregator_as_compile,
2991 route_set_aggregator_as_free,
718e3744 2992};
6b0655a2 2993
4b7e6066 2994/* Set tag to object. object must be pointer to struct bgp_path_info */
b68885f9 2995static enum route_map_cmd_result_t
1782514f 2996route_set_tag(void *rule, const struct prefix *prefix, void *object)
0d9551dc 2997{
d62a17ae 2998 route_tag_t *tag;
9b6d8fcf 2999 struct bgp_path_info *path;
0d9551dc 3000
1782514f
DS
3001 tag = rule;
3002 path = object;
0d9551dc 3003
1782514f
DS
3004 /* Set tag value */
3005 path->attr->tag = *tag;
0d9551dc 3006
d62a17ae 3007 return RMAP_OKAY;
0d9551dc
DS
3008}
3009
0d9551dc 3010/* Route map commands for tag set. */
364deb04
DL
3011static const struct route_map_rule_cmd route_set_tag_cmd = {
3012 "tag",
3013 route_set_tag,
3014 route_map_rule_tag_compile,
d62a17ae 3015 route_map_rule_tag_free,
0d9551dc
DS
3016};
3017
4b7e6066 3018/* Set label-index to object. object must be pointer to struct bgp_path_info */
b68885f9 3019static enum route_map_cmd_result_t
1782514f 3020route_set_label_index(void *rule, const struct prefix *prefix, void *object)
d62a17ae 3021{
3022 struct rmap_value *rv;
9b6d8fcf 3023 struct bgp_path_info *path;
d7c0a89a 3024 uint32_t label_index;
d62a17ae 3025
1782514f
DS
3026 /* Fetch routemap's rule information. */
3027 rv = rule;
3028 path = object;
d62a17ae 3029
1782514f
DS
3030 /* Set label-index value. */
3031 label_index = rv->value;
3032 if (label_index) {
3033 path->attr->label_index = label_index;
3034 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
d62a17ae 3035 }
d990e384 3036
d62a17ae 3037 return RMAP_OKAY;
d990e384
DS
3038}
3039
3040/* Route map commands for label-index set. */
364deb04
DL
3041static const struct route_map_rule_cmd route_set_label_index_cmd = {
3042 "label-index",
3043 route_set_label_index,
3044 route_value_compile,
d62a17ae 3045 route_value_free,
d990e384 3046};
0d9551dc 3047
718e3744 3048/* `match ipv6 address IP_ACCESS_LIST' */
3049
b68885f9 3050static enum route_map_cmd_result_t
1782514f 3051route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
718e3744 3052{
d62a17ae 3053 struct access_list *alist;
718e3744 3054
1782514f 3055 if (prefix->family == AF_INET6) {
d62a17ae 3056 alist = access_list_lookup(AFI_IP6, (char *)rule);
3057 if (alist == NULL)
3058 return RMAP_NOMATCH;
e52702f2 3059
d62a17ae 3060 return (access_list_apply(alist, prefix) == FILTER_DENY
3061 ? RMAP_NOMATCH
3062 : RMAP_MATCH);
3063 }
3064 return RMAP_NOMATCH;
718e3744 3065}
3066
d62a17ae 3067static void *route_match_ipv6_address_compile(const char *arg)
718e3744 3068{
d62a17ae 3069 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3070}
3071
d62a17ae 3072static void route_match_ipv6_address_free(void *rule)
718e3744 3073{
d62a17ae 3074 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3075}
3076
3077/* Route map commands for ip address matching. */
364deb04
DL
3078static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
3079 "ipv6 address",
3080 route_match_ipv6_address,
3081 route_match_ipv6_address_compile,
3082 route_match_ipv6_address_free
3083};
6b0655a2 3084
bc63ba98
DA
3085/* `match ipv6 next-hop ACCESSLIST6_NAME' */
3086static enum route_map_cmd_result_t
3087route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
3088{
3089 struct bgp_path_info *path;
3090 struct access_list *alist;
3091 struct prefix_ipv6 p;
3092
3093 if (prefix->family == AF_INET6) {
3094 path = object;
3095 p.family = AF_INET6;
3096 p.prefix = path->attr->mp_nexthop_global;
3097 p.prefixlen = IPV6_MAX_BITLEN;
3098
3099 alist = access_list_lookup(AFI_IP6, (char *)rule);
3100 if (!alist)
3101 return RMAP_NOMATCH;
3102
3103 if (access_list_apply(alist, &p) == FILTER_PERMIT)
3104 return RMAP_MATCH;
3105
3106 if (path->attr->mp_nexthop_len
3107 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3108 p.prefix = path->attr->mp_nexthop_local;
3109 if (access_list_apply(alist, &p) == FILTER_PERMIT)
3110 return RMAP_MATCH;
3111 }
3112 }
3113
3114 return RMAP_NOMATCH;
3115}
3116
3117static void *route_match_ipv6_next_hop_compile(const char *arg)
3118{
3119 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3120}
3121
3122static void route_match_ipv6_next_hop_free(void *rule)
3123{
3124 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3125}
3126
3127static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
3128 "ipv6 next-hop",
3129 route_match_ipv6_next_hop,
3130 route_match_ipv6_next_hop_compile,
3131 route_match_ipv6_next_hop_free
3132};
3133
718e3744 3134/* `match ipv6 next-hop IP_ADDRESS' */
3135
b68885f9 3136static enum route_map_cmd_result_t
bc63ba98
DA
3137route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
3138 void *object)
718e3744 3139{
d62a17ae 3140 struct in6_addr *addr = rule;
9b6d8fcf 3141 struct bgp_path_info *path;
718e3744 3142
1782514f 3143 path = object;
718e3744 3144
1782514f
DS
3145 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
3146 return RMAP_MATCH;
718e3744 3147
1782514f
DS
3148 if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
3149 && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
3150 return RMAP_MATCH;
718e3744 3151
d62a17ae 3152 return RMAP_NOMATCH;
718e3744 3153}
3154
bc63ba98 3155static void *route_match_ipv6_next_hop_address_compile(const char *arg)
718e3744 3156{
d62a17ae 3157 struct in6_addr *address;
3158 int ret;
718e3744 3159
d62a17ae 3160 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3161
d62a17ae 3162 ret = inet_pton(AF_INET6, arg, address);
3163 if (!ret) {
3164 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3165 return NULL;
3166 }
718e3744 3167
d62a17ae 3168 return address;
718e3744 3169}
3170
bc63ba98 3171static void route_match_ipv6_next_hop_address_free(void *rule)
718e3744 3172{
d62a17ae 3173 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3174}
3175
bc63ba98 3176static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
03030106 3177 "ipv6 next-hop address",
bc63ba98
DA
3178 route_match_ipv6_next_hop_address,
3179 route_match_ipv6_next_hop_address_compile,
3180 route_match_ipv6_next_hop_address_free
364deb04 3181};
6b0655a2 3182
be7735b3
PG
3183/* `match ip next-hop IP_ADDRESS' */
3184
3185static enum route_map_cmd_result_t
1782514f 3186route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
be7735b3
PG
3187{
3188 struct in_addr *addr = rule;
3189 struct bgp_path_info *path;
3190
1782514f 3191 path = object;
be7735b3 3192
1782514f
DS
3193 if (path->attr->nexthop.s_addr == addr->s_addr
3194 || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
3195 && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
3196 return RMAP_MATCH;
be7735b3
PG
3197
3198 return RMAP_NOMATCH;
3199}
3200
3201static void *route_match_ipv4_next_hop_compile(const char *arg)
3202{
3203 struct in_addr *address;
3204 int ret;
3205
3206 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3207
3208 ret = inet_pton(AF_INET, arg, address);
3209 if (!ret) {
3210 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3211 return NULL;
3212 }
3213
3214 return address;
3215}
3216
3217static void route_match_ipv4_next_hop_free(void *rule)
3218{
3219 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3220}
3221
3222static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
3223 "ip next-hop address",
3224 route_match_ipv4_next_hop,
3225 route_match_ipv4_next_hop_compile,
3226 route_match_ipv4_next_hop_free
3227};
3228
718e3744 3229/* `match ipv6 address prefix-list PREFIX_LIST' */
3230
b68885f9 3231static enum route_map_cmd_result_t
123214ef 3232route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1782514f 3233 void *object)
718e3744 3234{
1782514f 3235 return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
718e3744 3236}
3237
d62a17ae 3238static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 3239{
d62a17ae 3240 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3241}
3242
d62a17ae 3243static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 3244{
d62a17ae 3245 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3246}
3247
364deb04
DL
3248static const struct route_map_rule_cmd
3249 route_match_ipv6_address_prefix_list_cmd = {
3250 "ipv6 address prefix-list",
3251 route_match_ipv6_address_prefix_list,
d62a17ae 3252 route_match_ipv6_address_prefix_list_compile,
364deb04
DL
3253 route_match_ipv6_address_prefix_list_free
3254};
6b0655a2 3255
61ad901e
DA
3256/* `match ipv6 next-hop type <TYPE>' */
3257
b68885f9 3258static enum route_map_cmd_result_t
61ad901e 3259route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1782514f 3260 void *object)
61ad901e 3261{
9b6d8fcf 3262 struct bgp_path_info *path;
61ad901e
DA
3263 struct in6_addr *addr = rule;
3264
1782514f 3265 if (prefix->family == AF_INET6) {
9b6d8fcf 3266 path = (struct bgp_path_info *)object;
05864da7 3267 if (!path)
b68885f9 3268 return RMAP_NOMATCH;
61ad901e 3269
9b6d8fcf
DS
3270 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
3271 && !path->attr->nh_ifindex)
61ad901e
DA
3272 return RMAP_MATCH;
3273 }
1782514f 3274
61ad901e
DA
3275 return RMAP_NOMATCH;
3276}
3277
3278static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3279{
3280 struct in6_addr *address;
3281 int ret;
3282
3283 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3284
3285 ret = inet_pton(AF_INET6, "::0", address);
3286 if (!ret) {
3287 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3288 return NULL;
3289 }
3290
3291 return address;
3292}
3293
3294static void route_match_ipv6_next_hop_type_free(void *rule)
3295{
3296 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3297}
3298
364deb04
DL
3299static const struct route_map_rule_cmd
3300 route_match_ipv6_next_hop_type_cmd = {
3301 "ipv6 next-hop type",
3302 route_match_ipv6_next_hop_type,
61ad901e 3303 route_match_ipv6_next_hop_type_compile,
364deb04
DL
3304 route_match_ipv6_next_hop_type_free
3305};
61ad901e 3306
718e3744 3307/* `set ipv6 nexthop global IP_ADDRESS' */
3308
3309/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9 3310static enum route_map_cmd_result_t
1782514f 3311route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
718e3744 3312{
d62a17ae 3313 struct in6_addr *address;
9b6d8fcf 3314 struct bgp_path_info *path;
718e3744 3315
1782514f
DS
3316 /* Fetch routemap's rule information. */
3317 address = rule;
3318 path = object;
e52702f2 3319
1782514f
DS
3320 /* Set next hop value. */
3321 path->attr->mp_nexthop_global = *address;
3f9c7369 3322
1782514f
DS
3323 /* Set nexthop length. */
3324 if (path->attr->mp_nexthop_len == 0)
3325 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 3326
1782514f
DS
3327 SET_FLAG(path->attr->rmap_change_flags,
3328 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
718e3744 3329
d62a17ae 3330 return RMAP_OKAY;
718e3744 3331}
3332
3333/* Route map `ip next-hop' compile function. Given string is converted
3334 to struct in_addr structure. */
d62a17ae 3335static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 3336{
d62a17ae 3337 int ret;
3338 struct in6_addr *address;
718e3744 3339
d62a17ae 3340 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3341
d62a17ae 3342 ret = inet_pton(AF_INET6, arg, address);
718e3744 3343
d62a17ae 3344 if (ret == 0) {
3345 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3346 return NULL;
3347 }
718e3744 3348
d62a17ae 3349 return address;
718e3744 3350}
3351
3352/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3353static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 3354{
d62a17ae 3355 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3356}
3357
3358/* Route map commands for ip nexthop set. */
364deb04
DL
3359static const struct route_map_rule_cmd
3360 route_set_ipv6_nexthop_global_cmd = {
3361 "ipv6 next-hop global",
3362 route_set_ipv6_nexthop_global,
d62a17ae 3363 route_set_ipv6_nexthop_global_compile,
364deb04
DL
3364 route_set_ipv6_nexthop_global_free
3365};
6b0655a2 3366
161995ea 3367/* Set next-hop preference value. */
b68885f9 3368static enum route_map_cmd_result_t
123214ef 3369route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
1782514f 3370 void *object)
d62a17ae 3371{
9b6d8fcf 3372 struct bgp_path_info *path;
d62a17ae 3373 struct peer *peer;
3374
1782514f
DS
3375 /* Fetch routemap's rule information. */
3376 path = object;
3377 peer = path->peer;
d62a17ae 3378
1782514f
DS
3379 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3380 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
3381 /* Set next hop preference to global */
3382 path->attr->mp_nexthop_prefer_global = true;
3383 SET_FLAG(path->attr->rmap_change_flags,
3384 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3385 } else {
3386 path->attr->mp_nexthop_prefer_global = false;
3387 SET_FLAG(path->attr->rmap_change_flags,
3388 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
161995ea 3389 }
1782514f 3390
d62a17ae 3391 return RMAP_OKAY;
161995ea
DS
3392}
3393
d62a17ae 3394static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 3395{
d62a17ae 3396 int *rins = NULL;
161995ea 3397
d62a17ae 3398 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3399 *rins = 1;
161995ea 3400
d62a17ae 3401 return rins;
161995ea
DS
3402}
3403
3404/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3405static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 3406{
d62a17ae 3407 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
3408}
3409
3410/* Route map commands for ip nexthop set preferred. */
364deb04
DL
3411static const struct route_map_rule_cmd
3412 route_set_ipv6_nexthop_prefer_global_cmd = {
3413 "ipv6 next-hop prefer-global",
3414 route_set_ipv6_nexthop_prefer_global,
d62a17ae 3415 route_set_ipv6_nexthop_prefer_global_compile,
364deb04
DL
3416 route_set_ipv6_nexthop_prefer_global_free
3417};
161995ea 3418
718e3744 3419/* `set ipv6 nexthop local IP_ADDRESS' */
3420
3421/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9 3422static enum route_map_cmd_result_t
1782514f 3423route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
d62a17ae 3424{
3425 struct in6_addr *address;
9b6d8fcf 3426 struct bgp_path_info *path;
d62a17ae 3427
1782514f
DS
3428 /* Fetch routemap's rule information. */
3429 address = rule;
3430 path = object;
d62a17ae 3431
1782514f
DS
3432 /* Set next hop value. */
3433 path->attr->mp_nexthop_local = *address;
d62a17ae 3434
1782514f
DS
3435 /* Set nexthop length. */
3436 if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3437 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 3438
1782514f
DS
3439 SET_FLAG(path->attr->rmap_change_flags,
3440 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 3441
d62a17ae 3442 return RMAP_OKAY;
718e3744 3443}
3444
3445/* Route map `ip nexthop' compile function. Given string is converted
3446 to struct in_addr structure. */
d62a17ae 3447static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 3448{
d62a17ae 3449 int ret;
3450 struct in6_addr *address;
718e3744 3451
d62a17ae 3452 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3453
d62a17ae 3454 ret = inet_pton(AF_INET6, arg, address);
718e3744 3455
d62a17ae 3456 if (ret == 0) {
3457 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3458 return NULL;
3459 }
718e3744 3460
d62a17ae 3461 return address;
718e3744 3462}
3463
3464/* Free route map's compiled `ip nexthop' value. */
d62a17ae 3465static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 3466{
d62a17ae 3467 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3468}
3469
3470/* Route map commands for ip nexthop set. */
364deb04
DL
3471static const struct route_map_rule_cmd
3472 route_set_ipv6_nexthop_local_cmd = {
3473 "ipv6 next-hop local",
3474 route_set_ipv6_nexthop_local,
d62a17ae 3475 route_set_ipv6_nexthop_local_compile,
364deb04
DL
3476 route_set_ipv6_nexthop_local_free
3477};
90916ac2
DS
3478
3479/* `set ipv6 nexthop peer-address' */
3480
3481/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9 3482static enum route_map_cmd_result_t
1782514f 3483route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
d62a17ae 3484{
3485 struct in6_addr peer_address;
9b6d8fcf 3486 struct bgp_path_info *path;
d62a17ae 3487 struct peer *peer;
3488
1782514f
DS
3489 /* Fetch routemap's rule information. */
3490 path = object;
3491 peer = path->peer;
d62a17ae 3492
1782514f
DS
3493 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3494 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3495 && peer->su_remote
3496 && sockunion_family(peer->su_remote) == AF_INET6) {
3497 peer_address = peer->su_remote->sin6.sin6_addr;
3498 /* Set next hop value and length in attribute. */
3499 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3500 path->attr->mp_nexthop_local = peer_address;
3501 if (path->attr->mp_nexthop_len
3502 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3503 path->attr->mp_nexthop_len =
3504 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3505 } else {
3506 path->attr->mp_nexthop_global = peer_address;
3507 if (path->attr->mp_nexthop_len == 0)
3508 path->attr->mp_nexthop_len =
3509 BGP_ATTR_NHLEN_IPV6_GLOBAL;
d62a17ae 3510 }
1782514f
DS
3511
3512 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3513 /* The next hop value will be set as part of packet
3514 * rewrite.
3515 * Set the flags here to indicate that rewrite needs to
3516 * be done.
3517 * Also, clear the value - we clear both global and
3518 * link-local
3519 * nexthops, whether we send one or both is determined
3520 * elsewhere.
3521 */
3522 SET_FLAG(path->attr->rmap_change_flags,
3523 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3524 /* clear next hop value. */
3525 memset(&(path->attr->mp_nexthop_global), 0,
3526 sizeof(struct in6_addr));
3527 memset(&(path->attr->mp_nexthop_local), 0,
3528 sizeof(struct in6_addr));
90916ac2 3529 }
90916ac2 3530
d62a17ae 3531 return RMAP_OKAY;
90916ac2
DS
3532}
3533
3534/* Route map `ip next-hop' compile function. Given string is converted
3535 to struct in_addr structure. */
d62a17ae 3536static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 3537{
d62a17ae 3538 int *rins = NULL;
90916ac2 3539
d62a17ae 3540 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3541 *rins = 1;
90916ac2 3542
d62a17ae 3543 return rins;
90916ac2
DS
3544}
3545
3546/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3547static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 3548{
d62a17ae 3549 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
3550}
3551
3552/* Route map commands for ip nexthop set. */
364deb04
DL
3553static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3554 "ipv6 next-hop peer-address",
3555 route_set_ipv6_nexthop_peer,
3556 route_set_ipv6_nexthop_peer_compile,
3557 route_set_ipv6_nexthop_peer_free
3558};
90916ac2 3559
69ba6dd7 3560/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 3561
b68885f9 3562static enum route_map_cmd_result_t
1782514f 3563route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
718e3744 3564{
d62a17ae 3565 struct in_addr *address;
9b6d8fcf 3566 struct bgp_path_info *path;
718e3744 3567
1782514f
DS
3568 /* Fetch routemap's rule information. */
3569 address = rule;
3570 path = object;
e52702f2 3571
1782514f
DS
3572 /* Set next hop value. */
3573 path->attr->mp_nexthop_global_in = *address;
3574 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
718e3744 3575
d62a17ae 3576 return RMAP_OKAY;
718e3744 3577}
3578
d62a17ae 3579static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 3580{
d62a17ae 3581 int ret;
3582 struct in_addr *address;
718e3744 3583
d62a17ae 3584 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3585
d62a17ae 3586 ret = inet_aton(arg, address);
718e3744 3587
d62a17ae 3588 if (ret == 0) {
3589 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3590 return NULL;
3591 }
718e3744 3592
d62a17ae 3593 return address;
718e3744 3594}
3595
69ba6dd7 3596/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 3597
b68885f9 3598static enum route_map_cmd_result_t
1782514f 3599route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
d6902373 3600{
d62a17ae 3601 struct in6_addr *address;
9b6d8fcf 3602 struct bgp_path_info *path;
d6902373 3603
1782514f
DS
3604 /* Fetch routemap's rule information. */
3605 address = rule;
3606 path = object;
d6902373 3607
1782514f
DS
3608 /* Set next hop value. */
3609 memcpy(&path->attr->mp_nexthop_global, address,
3610 sizeof(struct in6_addr));
3611 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
d6902373 3612
d62a17ae 3613 return RMAP_OKAY;
d6902373
PG
3614}
3615
d62a17ae 3616static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 3617{
d62a17ae 3618 int ret;
3619 struct in6_addr *address;
d6902373 3620
d62a17ae 3621 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3622 ret = inet_pton(AF_INET6, arg, address);
d6902373 3623
d62a17ae 3624 if (ret == 0) {
3625 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3626 return NULL;
3627 }
d6902373 3628
d62a17ae 3629 return address;
d6902373
PG
3630}
3631
d62a17ae 3632static void route_set_vpn_nexthop_free(void *rule)
718e3744 3633{
d62a17ae 3634 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3635}
3636
69ba6dd7 3637/* Route map commands for ipv4 next-hop set. */
364deb04
DL
3638static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3639 "ipv4 vpn next-hop",
3640 route_set_vpnv4_nexthop,
3641 route_set_vpnv4_nexthop_compile,
3642 route_set_vpn_nexthop_free
3643};
d6902373 3644
69ba6dd7 3645/* Route map commands for ipv6 next-hop set. */
364deb04
DL
3646static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3647 "ipv6 vpn next-hop",
3648 route_set_vpnv6_nexthop,
3649 route_set_vpnv6_nexthop_compile,
3650 route_set_vpn_nexthop_free
3651};
6b0655a2 3652
718e3744 3653/* `set originator-id' */
3654
3655/* For origin set. */
b68885f9 3656static enum route_map_cmd_result_t
1782514f 3657route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
718e3744 3658{
d62a17ae 3659 struct in_addr *address;
9b6d8fcf 3660 struct bgp_path_info *path;
718e3744 3661
1782514f
DS
3662 address = rule;
3663 path = object;
e52702f2 3664
1782514f
DS
3665 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3666 path->attr->originator_id = *address;
718e3744 3667
d62a17ae 3668 return RMAP_OKAY;
718e3744 3669}
3670
3671/* Compile function for originator-id set. */
d62a17ae 3672static void *route_set_originator_id_compile(const char *arg)
718e3744 3673{
d62a17ae 3674 int ret;
3675 struct in_addr *address;
718e3744 3676
d62a17ae 3677 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3678
d62a17ae 3679 ret = inet_aton(arg, address);
718e3744 3680
d62a17ae 3681 if (ret == 0) {
3682 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3683 return NULL;
3684 }
718e3744 3685
d62a17ae 3686 return address;
718e3744 3687}
3688
3689/* Compile function for originator_id set. */
d62a17ae 3690static void route_set_originator_id_free(void *rule)
718e3744 3691{
d62a17ae 3692 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3693}
3694
515e500c 3695/* Set originator-id rule structure. */
364deb04
DL
3696static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3697 "originator-id",
3698 route_set_originator_id,
3699 route_set_originator_id_compile,
3700 route_set_originator_id_free,
718e3744 3701};
6b0655a2 3702
518f0eb1 3703/*
2a3d5731 3704 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
3705 * modifications.
3706 */
d62a17ae 3707static void bgp_route_map_process_peer(const char *rmap_name,
3708 struct route_map *map, struct peer *peer,
3709 int afi, int safi, int route_update)
3710{
d62a17ae 3711 struct bgp_filter *filter;
3712
3713 if (!peer || !rmap_name)
3714 return;
3715
3716 filter = &peer->filter[afi][safi];
3717 /*
3718 * in is for non-route-server clients,
3719 * out is for all peers
3720 */
db77a501
DS
3721 if (filter->map[RMAP_IN].name
3722 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3723 filter->map[RMAP_IN].map = map;
d62a17ae 3724
feb17238 3725 if (route_update && peer_established(peer)) {
d62a17ae 3726 if (CHECK_FLAG(peer->af_flags[afi][safi],
3727 PEER_FLAG_SOFT_RECONFIG)) {
3728 if (bgp_debug_update(peer, NULL, NULL, 1))
3729 zlog_debug(
11b228cd
DS
3730 "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
3731 rmap_name, afi2str(afi),
3732 safi2str(safi), peer->host);
d62a17ae 3733
3734 bgp_soft_reconfig_in(peer, afi, safi);
3735 } else if (CHECK_FLAG(peer->cap,
3736 PEER_CAP_REFRESH_OLD_RCV)
3737 || CHECK_FLAG(peer->cap,
3738 PEER_CAP_REFRESH_NEW_RCV)) {
3739 if (bgp_debug_update(peer, NULL, NULL, 1))
3740 zlog_debug(
11b228cd
DS
3741 "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
3742 rmap_name, afi2str(afi),
3743 safi2str(safi), peer->host);
9af52ccf
DA
3744 bgp_route_refresh_send(
3745 peer, afi, safi, 0, 0, 0,
3746 BGP_ROUTE_REFRESH_NORMAL);
d62a17ae 3747 }
d62a17ae 3748 }
518f0eb1 3749 }
d62a17ae 3750
3751 /*
3752 * For outbound, unsuppress and default-originate map change (content or
3753 * map created), merely update the "config" here, the actual route
3754 * announcement happens at the group level.
3755 */
3756 if (filter->map[RMAP_OUT].name
3757 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3758 filter->map[RMAP_OUT].map = map;
3759
3760 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3761 filter->usmap.map = map;
3762
7f7940e6
MK
3763 if (filter->advmap.aname
3764 && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
3765 filter->advmap.amap = map;
7f7940e6
MK
3766 }
3767
3768 if (filter->advmap.cname
3769 && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
3770 filter->advmap.cmap = map;
7f7940e6
MK
3771 }
3772
d62a17ae 3773 if (peer->default_rmap[afi][safi].name
3774 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
3775 peer->default_rmap[afi][safi].map = map;
c5aec50b
MK
3776
3777 /* Notify BGP conditional advertisement scanner percess */
c385f82a 3778 peer->advmap_config_change[afi][safi] = true;
d62a17ae 3779}
3780
3781static void bgp_route_map_update_peer_group(const char *rmap_name,
3782 struct route_map *map,
3783 struct bgp *bgp)
3784{
3785 struct peer_group *group;
3786 struct listnode *node, *nnode;
3787 struct bgp_filter *filter;
3788 int afi, safi;
3789 int direct;
3790
3791 if (!bgp)
3792 return;
3793
3794 /* All the peers have been updated correctly already. This is
3795 * just updating the placeholder data. No real update required.
3796 */
05c7a1cc
QY
3797 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
3798 FOREACH_AFI_SAFI (afi, safi) {
3799 filter = &group->conf->filter[afi][safi];
3800
3801 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
3802 if ((filter->map[direct].name)
3803 && (strcmp(rmap_name,
3804 filter->map[direct].name)
d62a17ae 3805 == 0))
05c7a1cc 3806 filter->map[direct].map = map;
d62a17ae 3807 }
05c7a1cc
QY
3808
3809 if (filter->usmap.name
3810 && (strcmp(rmap_name, filter->usmap.name) == 0))
3811 filter->usmap.map = map;
3812 }
3813 }
518f0eb1
DS
3814}
3815
a6e0d253
DW
3816/*
3817 * Note that if an extreme number (tens of thousands) of route-maps are in use
3818 * and if bgp has an extreme number of peers, network statements, etc then this
3819 * function can consume a lot of cycles. This is due to this function being
3820 * called for each route-map and within this function we walk the list of peers,
3821 * network statements, etc looking to see if they use this route-map.
3822 */
d62a17ae 3823static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
3824 int route_update)
3825{
3826 int i;
4056a5f6 3827 bool matched;
d62a17ae 3828 afi_t afi;
3829 safi_t safi;
3830 struct peer *peer;
9bcb3eef 3831 struct bgp_dest *bn;
d62a17ae 3832 struct bgp_static *bgp_static;
20894f50 3833 struct bgp_aggregate *aggregate;
d62a17ae 3834 struct listnode *node, *nnode;
3835 struct route_map *map;
3836 char buf[INET6_ADDRSTRLEN];
3837
3838 map = route_map_lookup_by_name(rmap_name);
3839
3840 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
3841
3842 /* Ignore dummy peer-group structure */
3843 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3844 continue;
3845
05c7a1cc
QY
3846 FOREACH_AFI_SAFI (afi, safi) {
3847 /* process in/out/import/export/default-orig
3848 * route-maps */
3849 bgp_route_map_process_peer(rmap_name, map, peer, afi,
3850 safi, route_update);
3851 }
d62a17ae 3852 }
3853
3854 /* for outbound/default-orig route-maps, process for groups */
3855 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
3856 route_update, 0);
3857
3858 /* update peer-group config (template) */
3859 bgp_route_map_update_peer_group(rmap_name, map, bgp);
3860
05c7a1cc
QY
3861 FOREACH_AFI_SAFI (afi, safi) {
3862 /* For table route-map updates. */
3863 if (!bgp_fibupd_safi(safi))
3864 continue;
d62a17ae 3865
05c7a1cc
QY
3866 if (bgp->table_map[afi][safi].name
3867 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
3868 == 0)) {
b4897fa5 3869
3870 /* bgp->table_map[afi][safi].map is NULL.
3871 * i.e Route map creation event.
3872 * So update applied_counter.
3873 * If it is not NULL, i.e It may be routemap updation or
3874 * deletion. so no need to update the counter.
3875 */
3876 if (!bgp->table_map[afi][safi].map)
3877 route_map_counter_increment(map);
05c7a1cc
QY
3878 bgp->table_map[afi][safi].map = map;
3879
3880 if (BGP_DEBUG(zebra, ZEBRA))
3881 zlog_debug(
11b228cd
DS
3882 "Processing route_map %s(%s:%s) update on table map",
3883 rmap_name, afi2str(afi),
3884 safi2str(safi));
05c7a1cc
QY
3885 if (route_update)
3886 bgp_zebra_announce_table(bgp, afi, safi);
3887 }
d62a17ae 3888
05c7a1cc
QY
3889 /* For network route-map updates. */
3890 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
96f10e1e 3891 bn = bgp_route_next(bn)) {
9bcb3eef 3892 bgp_static = bgp_dest_get_bgp_static_info(bn);
c9837105
DS
3893 if (!bgp_static)
3894 continue;
3895
3896 if (!bgp_static->rmap.name
3897 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
3898 continue;
3899
b4897fa5 3900 if (!bgp_static->rmap.map)
3901 route_map_counter_increment(map);
3902
c9837105
DS
3903 bgp_static->rmap.map = map;
3904
3905 if (route_update && !bgp_static->backdoor) {
b54892e0 3906 const struct prefix *bn_p =
9bcb3eef 3907 bgp_dest_get_prefix(bn);
b54892e0
DS
3908
3909 if (bgp_debug_zebra(bn_p))
c9837105 3910 zlog_debug(
11b228cd
DS
3911 "Processing route_map %s(%s:%s) update on static route %s",
3912 rmap_name, afi2str(afi),
3913 safi2str(safi),
b54892e0
DS
3914 inet_ntop(bn_p->family,
3915 &bn_p->u.prefix, buf,
c9837105 3916 INET6_ADDRSTRLEN));
b54892e0 3917 bgp_static_update(bgp, bn_p, bgp_static, afi,
c9837105 3918 safi);
05c7a1cc 3919 }
96f10e1e 3920 }
20894f50
DA
3921
3922 /* For aggregate-address route-map updates. */
3923 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
3924 bn = bgp_route_next(bn)) {
9bcb3eef 3925 aggregate = bgp_dest_get_bgp_aggregate_info(bn);
20894f50
DA
3926 if (!aggregate)
3927 continue;
3928
4056a5f6 3929 matched = false;
20894f50 3930
365ab2e7
RZ
3931 /* Update suppress map pointer. */
3932 if (aggregate->suppress_map_name
3933 && strmatch(aggregate->suppress_map_name,
3934 rmap_name)) {
4056a5f6 3935 if (aggregate->rmap.map == NULL)
365ab2e7 3936 route_map_counter_increment(map);
20894f50 3937
365ab2e7 3938 aggregate->suppress_map = map;
4056a5f6
RZ
3939
3940 bgp_aggregate_toggle_suppressed(
3941 aggregate, bgp, bgp_dest_get_prefix(bn),
3942 afi, safi, false);
3943
3944 matched = true;
365ab2e7
RZ
3945 }
3946
4056a5f6
RZ
3947 if (aggregate->rmap.name
3948 && strmatch(rmap_name, aggregate->rmap.name)) {
3949 if (aggregate->rmap.map == NULL)
3950 route_map_counter_increment(map);
20894f50 3951
4056a5f6 3952 aggregate->rmap.map = map;
20894f50 3953
4056a5f6
RZ
3954 matched = true;
3955 }
20894f50 3956
4056a5f6 3957 if (matched && route_update) {
b54892e0 3958 const struct prefix *bn_p =
9bcb3eef 3959 bgp_dest_get_prefix(bn);
b54892e0
DS
3960
3961 if (bgp_debug_zebra(bn_p))
20894f50 3962 zlog_debug(
11b228cd
DS
3963 "Processing route_map %s(%s:%s) update on aggregate-address route %s",
3964 rmap_name, afi2str(afi),
3965 safi2str(safi),
b54892e0
DS
3966 inet_ntop(bn_p->family,
3967 &bn_p->u.prefix, buf,
20894f50 3968 INET6_ADDRSTRLEN));
b54892e0 3969 bgp_aggregate_route(bgp, bn_p, afi, safi,
20894f50
DA
3970 aggregate);
3971 }
3972 }
05c7a1cc 3973 }
d62a17ae 3974
3975 /* For redistribute route-map updates. */
3976 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3977 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3978 struct list *red_list;
d62a17ae 3979 struct bgp_redist *red;
3980
3981 red_list = bgp->redist[afi][i];
3982 if (!red_list)
3983 continue;
3984
3985 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
c9837105
DS
3986 if (!red->rmap.name
3987 || (strcmp(rmap_name, red->rmap.name) != 0))
3988 continue;
3989
b4897fa5 3990 if (!red->rmap.map)
3991 route_map_counter_increment(map);
3992
c9837105
DS
3993 red->rmap.map = map;
3994
3995 if (!route_update)
3996 continue;
3997
3998 if (BGP_DEBUG(zebra, ZEBRA))
3999 zlog_debug(
11b228cd
DS
4000 "Processing route_map %s(%s:%s) update on redistributed routes",
4001 rmap_name, afi2str(afi),
4002 safi2str(safi));
c9837105
DS
4003
4004 bgp_redistribute_resend(bgp, afi, i,
d62a17ae 4005 red->instance);
d62a17ae 4006 }
4007 }
53c84f78
MK
4008
4009 /* for type5 command route-maps */
4010 FOREACH_AFI_SAFI (afi, safi) {
c9837105
DS
4011 if (!bgp->adv_cmd_rmap[afi][safi].name
4012 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4013 != 0)
4014 continue;
4015
2686df6a
NS
4016 /* Make sure the route-map is populated here if not already done */
4017 bgp->adv_cmd_rmap[afi][safi].map = map;
4018
c9837105
DS
4019 if (BGP_DEBUG(zebra, ZEBRA))
4020 zlog_debug(
11b228cd
DS
4021 "Processing route_map %s(%s:%s) update on advertise type5 route command",
4022 rmap_name, afi2str(afi), safi2str(safi));
2686df6a 4023
456a4697 4024 if (route_update && advertise_type5_routes(bgp, afi)) {
2686df6a
NS
4025 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4026 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4027 }
53c84f78 4028 }
d62a17ae 4029}
4030
46a69f10 4031static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 4032{
4033 struct listnode *node, *nnode;
4034 struct bgp *bgp;
4035
ddb5b488 4036 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
d62a17ae 4037 bgp_route_map_process_update(bgp, rmap_name, 1);
5fe9f963 4038
49e5a4a0 4039#ifdef ENABLE_BGP_VNC
ddb5b488 4040 vnc_routemap_update(bgp, __func__);
65efcfce 4041#endif
ddb5b488
PZ
4042 }
4043
4044 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
4045}
4046
cc9f21da 4047void bgp_route_map_update_timer(struct thread *thread)
518f0eb1 4048{
d62a17ae 4049 bm->t_rmap_update = NULL;
518f0eb1 4050
d62a17ae 4051 route_map_walk_update_list(bgp_route_map_process_update_cb);
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}