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