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