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