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