]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_routemap.c
d00bdd2571a2c835845596fe1b3f2fccbac0fce6
[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_VPNV6_GLOBAL_AND_LL)
3590 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3591
3592 SET_FLAG(path->attr->rmap_change_flags,
3593 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
3594
3595 return RMAP_OKAY;
3596 }
3597
3598 /* Route map `ip nexthop' compile function. Given string is converted
3599 to struct in_addr structure. */
3600 static void *route_set_ipv6_nexthop_local_compile(const char *arg)
3601 {
3602 int ret;
3603 struct in6_addr *address;
3604
3605 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3606
3607 ret = inet_pton(AF_INET6, arg, address);
3608
3609 if (ret == 0) {
3610 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3611 return NULL;
3612 }
3613
3614 return address;
3615 }
3616
3617 /* Free route map's compiled `ip nexthop' value. */
3618 static void route_set_ipv6_nexthop_local_free(void *rule)
3619 {
3620 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3621 }
3622
3623 /* Route map commands for ip nexthop set. */
3624 static const struct route_map_rule_cmd
3625 route_set_ipv6_nexthop_local_cmd = {
3626 "ipv6 next-hop local",
3627 route_set_ipv6_nexthop_local,
3628 route_set_ipv6_nexthop_local_compile,
3629 route_set_ipv6_nexthop_local_free
3630 };
3631
3632 /* `set ipv6 nexthop peer-address' */
3633
3634 /* Set nexthop to object. object must be pointer to struct attr. */
3635 static enum route_map_cmd_result_t
3636 route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
3637 {
3638 struct in6_addr peer_address;
3639 struct bgp_path_info *path;
3640 struct peer *peer;
3641
3642 /* Fetch routemap's rule information. */
3643 path = object;
3644 peer = path->peer;
3645
3646 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3647 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3648 && peer->su_remote
3649 && sockunion_family(peer->su_remote) == AF_INET6) {
3650 peer_address = peer->su_remote->sin6.sin6_addr;
3651 /* Set next hop value and length in attribute. */
3652 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3653 path->attr->mp_nexthop_local = peer_address;
3654 if (path->attr->mp_nexthop_len
3655 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3656 path->attr->mp_nexthop_len =
3657 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3658 } else {
3659 path->attr->mp_nexthop_global = peer_address;
3660 if (path->attr->mp_nexthop_len == 0)
3661 path->attr->mp_nexthop_len =
3662 BGP_ATTR_NHLEN_IPV6_GLOBAL;
3663 }
3664
3665 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3666 /* The next hop value will be set as part of packet
3667 * rewrite.
3668 * Set the flags here to indicate that rewrite needs to
3669 * be done.
3670 * Also, clear the value - we clear both global and
3671 * link-local
3672 * nexthops, whether we send one or both is determined
3673 * elsewhere.
3674 */
3675 SET_FLAG(path->attr->rmap_change_flags,
3676 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3677 /* clear next hop value. */
3678 memset(&(path->attr->mp_nexthop_global), 0,
3679 sizeof(struct in6_addr));
3680 memset(&(path->attr->mp_nexthop_local), 0,
3681 sizeof(struct in6_addr));
3682 }
3683
3684 return RMAP_OKAY;
3685 }
3686
3687 /* Route map `ip next-hop' compile function. Given string is converted
3688 to struct in_addr structure. */
3689 static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
3690 {
3691 int *rins = NULL;
3692
3693 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3694 *rins = 1;
3695
3696 return rins;
3697 }
3698
3699 /* Free route map's compiled `ip next-hop' value. */
3700 static void route_set_ipv6_nexthop_peer_free(void *rule)
3701 {
3702 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3703 }
3704
3705 /* Route map commands for ip nexthop set. */
3706 static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3707 "ipv6 next-hop peer-address",
3708 route_set_ipv6_nexthop_peer,
3709 route_set_ipv6_nexthop_peer_compile,
3710 route_set_ipv6_nexthop_peer_free
3711 };
3712
3713 /* `set ipv4 vpn next-hop A.B.C.D' */
3714
3715 static enum route_map_cmd_result_t
3716 route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
3717 {
3718 struct in_addr *address;
3719 struct bgp_path_info *path;
3720
3721 /* Fetch routemap's rule information. */
3722 address = rule;
3723 path = object;
3724
3725 /* Set next hop value. */
3726 path->attr->mp_nexthop_global_in = *address;
3727 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
3728
3729 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_VPNV4_NHOP_CHANGED);
3730
3731 return RMAP_OKAY;
3732 }
3733
3734 static void *route_set_vpnv4_nexthop_compile(const char *arg)
3735 {
3736 int ret;
3737 struct in_addr *address;
3738
3739 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3740
3741 ret = inet_aton(arg, address);
3742
3743 if (ret == 0) {
3744 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3745 return NULL;
3746 }
3747
3748 return address;
3749 }
3750
3751 /* `set ipv6 vpn next-hop A.B.C.D' */
3752
3753 static enum route_map_cmd_result_t
3754 route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
3755 {
3756 struct in6_addr *address;
3757 struct bgp_path_info *path;
3758
3759 /* Fetch routemap's rule information. */
3760 address = rule;
3761 path = object;
3762
3763 /* Set next hop value. */
3764 memcpy(&path->attr->mp_nexthop_global, address,
3765 sizeof(struct in6_addr));
3766 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
3767
3768 SET_FLAG(path->attr->rmap_change_flags,
3769 BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED);
3770
3771 return RMAP_OKAY;
3772 }
3773
3774 static void *route_set_vpnv6_nexthop_compile(const char *arg)
3775 {
3776 int ret;
3777 struct in6_addr *address;
3778
3779 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3780 ret = inet_pton(AF_INET6, arg, address);
3781
3782 if (ret == 0) {
3783 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3784 return NULL;
3785 }
3786
3787 return address;
3788 }
3789
3790 static void route_set_vpn_nexthop_free(void *rule)
3791 {
3792 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3793 }
3794
3795 /* Route map commands for ipv4 next-hop set. */
3796 static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3797 "ipv4 vpn next-hop",
3798 route_set_vpnv4_nexthop,
3799 route_set_vpnv4_nexthop_compile,
3800 route_set_vpn_nexthop_free
3801 };
3802
3803 /* Route map commands for ipv6 next-hop set. */
3804 static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3805 "ipv6 vpn next-hop",
3806 route_set_vpnv6_nexthop,
3807 route_set_vpnv6_nexthop_compile,
3808 route_set_vpn_nexthop_free
3809 };
3810
3811 /* `set originator-id' */
3812
3813 /* For origin set. */
3814 static enum route_map_cmd_result_t
3815 route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
3816 {
3817 struct in_addr *address;
3818 struct bgp_path_info *path;
3819
3820 address = rule;
3821 path = object;
3822
3823 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3824 path->attr->originator_id = *address;
3825
3826 return RMAP_OKAY;
3827 }
3828
3829 /* Compile function for originator-id set. */
3830 static void *route_set_originator_id_compile(const char *arg)
3831 {
3832 int ret;
3833 struct in_addr *address;
3834
3835 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3836
3837 ret = inet_aton(arg, address);
3838
3839 if (ret == 0) {
3840 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3841 return NULL;
3842 }
3843
3844 return address;
3845 }
3846
3847 /* Compile function for originator_id set. */
3848 static void route_set_originator_id_free(void *rule)
3849 {
3850 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3851 }
3852
3853 /* Set originator-id rule structure. */
3854 static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3855 "originator-id",
3856 route_set_originator_id,
3857 route_set_originator_id_compile,
3858 route_set_originator_id_free,
3859 };
3860
3861 static enum route_map_cmd_result_t
3862 route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
3863 void *object)
3864 {
3865 struct bgp_path_info *path;
3866 struct ecommunity *ecomm;
3867 struct ecommunity_val *ecomm_val;
3868 enum rpki_states *rpki_status = rule;
3869 enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
3870
3871 path = object;
3872
3873 ecomm = bgp_attr_get_ecommunity(path->attr);
3874 if (!ecomm)
3875 return RMAP_NOMATCH;
3876
3877 ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
3878 ECOMMUNITY_ORIGIN_VALIDATION_STATE);
3879 if (!ecomm_val)
3880 return RMAP_NOMATCH;
3881
3882 /* The Origin Validation State is encoded in the last octet of
3883 * the extended community.
3884 */
3885 switch (ecomm_val->val[7]) {
3886 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
3887 ecomm_rpki_status = RPKI_VALID;
3888 break;
3889 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
3890 ecomm_rpki_status = RPKI_NOTFOUND;
3891 break;
3892 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
3893 ecomm_rpki_status = RPKI_INVALID;
3894 break;
3895 case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
3896 break;
3897 }
3898
3899 if (ecomm_rpki_status == *rpki_status)
3900 return RMAP_MATCH;
3901
3902 return RMAP_NOMATCH;
3903 }
3904
3905 static void *route_match_extcommunity_compile(const char *arg)
3906 {
3907 int *rpki_status;
3908
3909 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3910
3911 if (strcmp(arg, "valid") == 0)
3912 *rpki_status = RPKI_VALID;
3913 else if (strcmp(arg, "invalid") == 0)
3914 *rpki_status = RPKI_INVALID;
3915 else
3916 *rpki_status = RPKI_NOTFOUND;
3917
3918 return rpki_status;
3919 }
3920
3921 static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
3922 "rpki-extcommunity",
3923 route_match_rpki_extcommunity,
3924 route_match_extcommunity_compile,
3925 route_value_free
3926 };
3927
3928 /*
3929 * This is the workhorse routine for processing in/out routemap
3930 * modifications.
3931 */
3932 static void bgp_route_map_process_peer(const char *rmap_name,
3933 struct route_map *map, struct peer *peer,
3934 int afi, int safi, int route_update)
3935 {
3936 struct bgp_filter *filter;
3937
3938 if (!peer || !rmap_name)
3939 return;
3940
3941 filter = &peer->filter[afi][safi];
3942 /*
3943 * in is for non-route-server clients,
3944 * out is for all peers
3945 */
3946 if (filter->map[RMAP_IN].name
3947 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3948 filter->map[RMAP_IN].map = map;
3949
3950 if (route_update && peer_established(peer)) {
3951 if (CHECK_FLAG(peer->af_flags[afi][safi],
3952 PEER_FLAG_SOFT_RECONFIG)) {
3953 if (bgp_debug_update(peer, NULL, NULL, 1))
3954 zlog_debug(
3955 "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
3956 rmap_name, afi2str(afi),
3957 safi2str(safi), peer->host);
3958
3959 bgp_soft_reconfig_in(peer, afi, safi);
3960 } else if (CHECK_FLAG(peer->cap,
3961 PEER_CAP_REFRESH_OLD_RCV)
3962 || CHECK_FLAG(peer->cap,
3963 PEER_CAP_REFRESH_NEW_RCV)) {
3964 if (bgp_debug_update(peer, NULL, NULL, 1))
3965 zlog_debug(
3966 "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
3967 rmap_name, afi2str(afi),
3968 safi2str(safi), peer->host);
3969 bgp_route_refresh_send(
3970 peer, afi, safi, 0, 0, 0,
3971 BGP_ROUTE_REFRESH_NORMAL);
3972 }
3973 }
3974 }
3975
3976 /*
3977 * For outbound, unsuppress and default-originate map change (content or
3978 * map created), merely update the "config" here, the actual route
3979 * announcement happens at the group level.
3980 */
3981 if (filter->map[RMAP_OUT].name
3982 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3983 filter->map[RMAP_OUT].map = map;
3984
3985 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3986 filter->usmap.map = map;
3987
3988 if (filter->advmap.aname
3989 && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
3990 filter->advmap.amap = map;
3991 }
3992
3993 if (filter->advmap.cname
3994 && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
3995 filter->advmap.cmap = map;
3996 }
3997
3998 if (peer->default_rmap[afi][safi].name
3999 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
4000 peer->default_rmap[afi][safi].map = map;
4001
4002 /* Notify BGP conditional advertisement scanner percess */
4003 peer->advmap_config_change[afi][safi] = true;
4004 }
4005
4006 static void bgp_route_map_update_peer_group(const char *rmap_name,
4007 struct route_map *map,
4008 struct bgp *bgp)
4009 {
4010 struct peer_group *group;
4011 struct listnode *node, *nnode;
4012 struct bgp_filter *filter;
4013 int afi, safi;
4014 int direct;
4015
4016 if (!bgp)
4017 return;
4018
4019 /* All the peers have been updated correctly already. This is
4020 * just updating the placeholder data. No real update required.
4021 */
4022 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
4023 FOREACH_AFI_SAFI (afi, safi) {
4024 filter = &group->conf->filter[afi][safi];
4025
4026 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
4027 if ((filter->map[direct].name)
4028 && (strcmp(rmap_name,
4029 filter->map[direct].name)
4030 == 0))
4031 filter->map[direct].map = map;
4032 }
4033
4034 if (filter->usmap.name
4035 && (strcmp(rmap_name, filter->usmap.name) == 0))
4036 filter->usmap.map = map;
4037
4038 if (filter->advmap.aname &&
4039 (strcmp(rmap_name, filter->advmap.aname) == 0))
4040 filter->advmap.amap = map;
4041
4042 if (filter->advmap.cname &&
4043 (strcmp(rmap_name, filter->advmap.cname) == 0))
4044 filter->advmap.cmap = map;
4045 }
4046 }
4047 }
4048
4049 /*
4050 * Note that if an extreme number (tens of thousands) of route-maps are in use
4051 * and if bgp has an extreme number of peers, network statements, etc then this
4052 * function can consume a lot of cycles. This is due to this function being
4053 * called for each route-map and within this function we walk the list of peers,
4054 * network statements, etc looking to see if they use this route-map.
4055 */
4056 static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
4057 bool route_update)
4058 {
4059 int i;
4060 bool matched;
4061 afi_t afi;
4062 safi_t safi;
4063 struct peer *peer;
4064 struct bgp_dest *bn;
4065 struct bgp_static *bgp_static;
4066 struct bgp_aggregate *aggregate;
4067 struct listnode *node, *nnode;
4068 struct route_map *map;
4069 char buf[INET6_ADDRSTRLEN];
4070
4071 map = route_map_lookup_by_name(rmap_name);
4072
4073 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
4074
4075 /* Ignore dummy peer-group structure */
4076 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4077 continue;
4078
4079 FOREACH_AFI_SAFI (afi, safi) {
4080 /* process in/out/import/export/default-orig
4081 * route-maps */
4082 bgp_route_map_process_peer(rmap_name, map, peer, afi,
4083 safi, route_update);
4084 }
4085 }
4086
4087 /* for outbound/default-orig route-maps, process for groups */
4088 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
4089 route_update, 0);
4090
4091 /* update peer-group config (template) */
4092 bgp_route_map_update_peer_group(rmap_name, map, bgp);
4093
4094 FOREACH_AFI_SAFI (afi, safi) {
4095 /* For table route-map updates. */
4096 if (!bgp_fibupd_safi(safi))
4097 continue;
4098
4099 if (bgp->table_map[afi][safi].name
4100 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
4101 == 0)) {
4102
4103 /* bgp->table_map[afi][safi].map is NULL.
4104 * i.e Route map creation event.
4105 * So update applied_counter.
4106 * If it is not NULL, i.e It may be routemap updation or
4107 * deletion. so no need to update the counter.
4108 */
4109 if (!bgp->table_map[afi][safi].map)
4110 route_map_counter_increment(map);
4111 bgp->table_map[afi][safi].map = map;
4112
4113 if (BGP_DEBUG(zebra, ZEBRA))
4114 zlog_debug(
4115 "Processing route_map %s(%s:%s) update on table map",
4116 rmap_name, afi2str(afi),
4117 safi2str(safi));
4118 if (route_update)
4119 bgp_zebra_announce_table(bgp, afi, safi);
4120 }
4121
4122 /* For network route-map updates. */
4123 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
4124 bn = bgp_route_next(bn)) {
4125 bgp_static = bgp_dest_get_bgp_static_info(bn);
4126 if (!bgp_static)
4127 continue;
4128
4129 if (!bgp_static->rmap.name
4130 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
4131 continue;
4132
4133 if (!bgp_static->rmap.map)
4134 route_map_counter_increment(map);
4135
4136 bgp_static->rmap.map = map;
4137
4138 if (route_update && !bgp_static->backdoor) {
4139 const struct prefix *bn_p =
4140 bgp_dest_get_prefix(bn);
4141
4142 if (bgp_debug_zebra(bn_p))
4143 zlog_debug(
4144 "Processing route_map %s(%s:%s) update on static route %s",
4145 rmap_name, afi2str(afi),
4146 safi2str(safi),
4147 inet_ntop(bn_p->family,
4148 &bn_p->u.prefix, buf,
4149 sizeof(buf)));
4150 bgp_static_update(bgp, bn_p, bgp_static, afi,
4151 safi);
4152 }
4153 }
4154
4155 /* For aggregate-address route-map updates. */
4156 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
4157 bn = bgp_route_next(bn)) {
4158 aggregate = bgp_dest_get_bgp_aggregate_info(bn);
4159 if (!aggregate)
4160 continue;
4161
4162 matched = false;
4163
4164 /* Update suppress map pointer. */
4165 if (aggregate->suppress_map_name
4166 && strmatch(aggregate->suppress_map_name,
4167 rmap_name)) {
4168 if (aggregate->rmap.map == NULL)
4169 route_map_counter_increment(map);
4170
4171 aggregate->suppress_map = map;
4172
4173 bgp_aggregate_toggle_suppressed(
4174 aggregate, bgp, bgp_dest_get_prefix(bn),
4175 afi, safi, false);
4176
4177 matched = true;
4178 }
4179
4180 if (aggregate->rmap.name
4181 && strmatch(rmap_name, aggregate->rmap.name)) {
4182 if (aggregate->rmap.map == NULL)
4183 route_map_counter_increment(map);
4184
4185 aggregate->rmap.map = map;
4186
4187 matched = true;
4188 }
4189
4190 if (matched && route_update) {
4191 const struct prefix *bn_p =
4192 bgp_dest_get_prefix(bn);
4193
4194 if (bgp_debug_zebra(bn_p))
4195 zlog_debug(
4196 "Processing route_map %s(%s:%s) update on aggregate-address route %s",
4197 rmap_name, afi2str(afi),
4198 safi2str(safi),
4199 inet_ntop(bn_p->family,
4200 &bn_p->u.prefix, buf,
4201 sizeof(buf)));
4202 bgp_aggregate_route(bgp, bn_p, afi, safi,
4203 aggregate);
4204 }
4205 }
4206 }
4207
4208 /* For redistribute route-map updates. */
4209 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4210 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
4211 struct list *red_list;
4212 struct bgp_redist *red;
4213
4214 red_list = bgp->redist[afi][i];
4215 if (!red_list)
4216 continue;
4217
4218 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
4219 if (!red->rmap.name
4220 || (strcmp(rmap_name, red->rmap.name) != 0))
4221 continue;
4222
4223 if (!red->rmap.map)
4224 route_map_counter_increment(map);
4225
4226 red->rmap.map = map;
4227
4228 if (!route_update)
4229 continue;
4230
4231 if (BGP_DEBUG(zebra, ZEBRA))
4232 zlog_debug(
4233 "Processing route_map %s(%s:%s) update on redistributed routes",
4234 rmap_name, afi2str(afi),
4235 safi2str(safi));
4236
4237 bgp_redistribute_resend(bgp, afi, i,
4238 red->instance);
4239 }
4240 }
4241
4242 /* for type5 command route-maps */
4243 FOREACH_AFI_SAFI (afi, safi) {
4244 if (!bgp->adv_cmd_rmap[afi][safi].name
4245 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4246 != 0)
4247 continue;
4248
4249 /* Make sure the route-map is populated here if not already done */
4250 bgp->adv_cmd_rmap[afi][safi].map = map;
4251
4252 if (BGP_DEBUG(zebra, ZEBRA))
4253 zlog_debug(
4254 "Processing route_map %s(%s:%s) update on advertise type5 route command",
4255 rmap_name, afi2str(afi), safi2str(safi));
4256
4257 if (route_update && advertise_type5_routes(bgp, afi)) {
4258 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4259 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4260 }
4261 }
4262 }
4263
4264 static void bgp_route_map_process_update_cb(char *rmap_name)
4265 {
4266 struct listnode *node, *nnode;
4267 struct bgp *bgp;
4268
4269 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
4270 bgp_route_map_process_update(bgp, rmap_name, true);
4271
4272 #ifdef ENABLE_BGP_VNC
4273 vnc_routemap_update(bgp, __func__);
4274 #endif
4275 }
4276
4277 vpn_policy_routemap_event(rmap_name);
4278 }
4279
4280 void bgp_route_map_update_timer(struct thread *thread)
4281 {
4282 route_map_walk_update_list(bgp_route_map_process_update_cb);
4283 }
4284
4285 static void bgp_route_map_mark_update(const char *rmap_name)
4286 {
4287 struct listnode *node, *nnode;
4288 struct bgp *bgp;
4289
4290 /* If new update is received before the current timer timed out,
4291 * turn it off and start a new timer.
4292 */
4293 THREAD_OFF(bm->t_rmap_update);
4294
4295 /* rmap_update_timer of 0 means don't do route updates */
4296 if (bm->rmap_update_timer) {
4297 thread_add_timer(bm->master, bgp_route_map_update_timer,
4298 NULL, bm->rmap_update_timer,
4299 &bm->t_rmap_update);
4300
4301 /* Signal the groups that a route-map update event has
4302 * started */
4303 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
4304 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
4305 rmap_name, true, 1);
4306 } else {
4307 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
4308 bgp_route_map_process_update(bgp, rmap_name, false);
4309 #ifdef ENABLE_BGP_VNC
4310 vnc_routemap_update(bgp, __func__);
4311 #endif
4312 }
4313
4314 vpn_policy_routemap_event(rmap_name);
4315 }
4316 }
4317
4318 static void bgp_route_map_add(const char *rmap_name)
4319 {
4320 if (route_map_mark_updated(rmap_name) == 0)
4321 bgp_route_map_mark_update(rmap_name);
4322
4323 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
4324 }
4325
4326 static void bgp_route_map_delete(const char *rmap_name)
4327 {
4328 if (route_map_mark_updated(rmap_name) == 0)
4329 bgp_route_map_mark_update(rmap_name);
4330
4331 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
4332 }
4333
4334 static void bgp_route_map_event(const char *rmap_name)
4335 {
4336 if (route_map_mark_updated(rmap_name) == 0)
4337 bgp_route_map_mark_update(rmap_name);
4338
4339 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
4340 }
4341
4342 DEFUN_YANG (match_mac_address,
4343 match_mac_address_cmd,
4344 "match mac address ACCESSLIST_MAC_NAME",
4345 MATCH_STR
4346 "mac address\n"
4347 "Match address of route\n"
4348 "MAC Access-list name\n")
4349 {
4350 const char *xpath =
4351 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4352 char xpath_value[XPATH_MAXLEN];
4353
4354 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4355 snprintf(xpath_value, sizeof(xpath_value),
4356 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4357 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4358
4359 return nb_cli_apply_changes(vty, NULL);
4360 }
4361
4362 DEFUN_YANG (no_match_mac_address,
4363 no_match_mac_address_cmd,
4364 "no match mac address ACCESSLIST_MAC_NAME",
4365 NO_STR
4366 MATCH_STR
4367 "mac\n"
4368 "Match address of route\n"
4369 "MAC acess-list name\n")
4370 {
4371 const char *xpath =
4372 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4373
4374 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4375 return nb_cli_apply_changes(vty, NULL);
4376 }
4377
4378 /*
4379 * Helper to handle the case of the user passing in a number or type string
4380 */
4381 static const char *parse_evpn_rt_type(const char *num_rt_type)
4382 {
4383 switch (num_rt_type[0]) {
4384 case '1':
4385 return "ead";
4386 case '2':
4387 return "macip";
4388 case '3':
4389 return "multicast";
4390 case '4':
4391 return "es";
4392 case '5':
4393 return "prefix";
4394 default:
4395 break;
4396 }
4397
4398 /* Was already full type string */
4399 return num_rt_type;
4400 }
4401
4402 DEFUN_YANG (match_evpn_route_type,
4403 match_evpn_route_type_cmd,
4404 "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
4405 MATCH_STR
4406 EVPN_HELP_STR
4407 EVPN_TYPE_HELP_STR
4408 EVPN_TYPE_1_HELP_STR
4409 EVPN_TYPE_1_HELP_STR
4410 EVPN_TYPE_2_HELP_STR
4411 EVPN_TYPE_2_HELP_STR
4412 EVPN_TYPE_3_HELP_STR
4413 EVPN_TYPE_3_HELP_STR
4414 EVPN_TYPE_4_HELP_STR
4415 EVPN_TYPE_4_HELP_STR
4416 EVPN_TYPE_5_HELP_STR
4417 EVPN_TYPE_5_HELP_STR)
4418 {
4419 const char *xpath =
4420 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4421 char xpath_value[XPATH_MAXLEN];
4422
4423 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4424 snprintf(xpath_value, sizeof(xpath_value),
4425 "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4426 xpath);
4427 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4428 parse_evpn_rt_type(argv[3]->arg));
4429
4430 return nb_cli_apply_changes(vty, NULL);
4431 }
4432
4433 DEFUN_YANG (no_match_evpn_route_type,
4434 no_match_evpn_route_type_cmd,
4435 "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
4436 NO_STR
4437 MATCH_STR
4438 EVPN_HELP_STR
4439 EVPN_TYPE_HELP_STR
4440 EVPN_TYPE_1_HELP_STR
4441 EVPN_TYPE_1_HELP_STR
4442 EVPN_TYPE_2_HELP_STR
4443 EVPN_TYPE_2_HELP_STR
4444 EVPN_TYPE_3_HELP_STR
4445 EVPN_TYPE_3_HELP_STR
4446 EVPN_TYPE_4_HELP_STR
4447 EVPN_TYPE_4_HELP_STR
4448 EVPN_TYPE_5_HELP_STR
4449 EVPN_TYPE_5_HELP_STR)
4450 {
4451 const char *xpath =
4452 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4453
4454 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4455
4456 return nb_cli_apply_changes(vty, NULL);
4457 }
4458
4459
4460 DEFUN_YANG (match_evpn_vni,
4461 match_evpn_vni_cmd,
4462 "match evpn vni " CMD_VNI_RANGE,
4463 MATCH_STR
4464 EVPN_HELP_STR
4465 "Match VNI\n"
4466 "VNI ID\n")
4467 {
4468 const char *xpath =
4469 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4470 char xpath_value[XPATH_MAXLEN];
4471
4472 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4473 snprintf(xpath_value, sizeof(xpath_value),
4474 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4475 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4476
4477 return nb_cli_apply_changes(vty, NULL);
4478 }
4479
4480 DEFUN_YANG (no_match_evpn_vni,
4481 no_match_evpn_vni_cmd,
4482 "no match evpn vni " CMD_VNI_RANGE,
4483 NO_STR
4484 MATCH_STR
4485 EVPN_HELP_STR
4486 "Match VNI\n"
4487 "VNI ID\n")
4488 {
4489 const char *xpath =
4490 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4491 char xpath_value[XPATH_MAXLEN];
4492
4493 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4494 snprintf(xpath_value, sizeof(xpath_value),
4495 "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4496 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4497
4498 return nb_cli_apply_changes(vty, NULL);
4499 }
4500
4501 DEFUN_YANG (match_evpn_default_route,
4502 match_evpn_default_route_cmd,
4503 "match evpn default-route",
4504 MATCH_STR
4505 EVPN_HELP_STR
4506 "default EVPN type-5 route\n")
4507 {
4508 const char *xpath =
4509 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4510 char xpath_value[XPATH_MAXLEN];
4511
4512 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4513
4514 snprintf(xpath_value, sizeof(xpath_value),
4515 "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4516 xpath);
4517 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4518
4519 return nb_cli_apply_changes(vty, NULL);
4520 }
4521
4522 DEFUN_YANG (no_match_evpn_default_route,
4523 no_match_evpn_default_route_cmd,
4524 "no match evpn default-route",
4525 NO_STR
4526 MATCH_STR
4527 EVPN_HELP_STR
4528 "default EVPN type-5 route\n")
4529 {
4530 const char *xpath =
4531 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4532
4533 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4534
4535 return nb_cli_apply_changes(vty, NULL);
4536 }
4537
4538 DEFUN_YANG (match_evpn_rd,
4539 match_evpn_rd_cmd,
4540 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4541 MATCH_STR
4542 EVPN_HELP_STR
4543 "Route Distinguisher\n"
4544 "ASN:XX or A.B.C.D:XX\n")
4545 {
4546 const char *xpath =
4547 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4548 char xpath_value[XPATH_MAXLEN];
4549
4550 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4551 snprintf(
4552 xpath_value, sizeof(xpath_value),
4553 "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4554 xpath);
4555 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4556
4557 return nb_cli_apply_changes(vty, NULL);
4558 }
4559
4560 DEFUN_YANG (no_match_evpn_rd,
4561 no_match_evpn_rd_cmd,
4562 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4563 NO_STR
4564 MATCH_STR
4565 EVPN_HELP_STR
4566 "Route Distinguisher\n"
4567 "ASN:XX or A.B.C.D:XX\n")
4568 {
4569 const char *xpath =
4570 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4571
4572 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4573 return nb_cli_apply_changes(vty, NULL);
4574 }
4575
4576 DEFUN_YANG (set_evpn_gw_ip_ipv4,
4577 set_evpn_gw_ip_ipv4_cmd,
4578 "set evpn gateway-ip ipv4 A.B.C.D",
4579 SET_STR
4580 EVPN_HELP_STR
4581 "Set gateway IP for prefix advertisement route\n"
4582 "IPv4 address\n"
4583 "Gateway IP address in IPv4 format\n")
4584 {
4585 int ret;
4586 union sockunion su;
4587 const char *xpath =
4588 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4589 char xpath_value[XPATH_MAXLEN];
4590
4591 ret = str2sockunion(argv[4]->arg, &su);
4592 if (ret < 0) {
4593 vty_out(vty, "%% Malformed gateway IP\n");
4594 return CMD_WARNING_CONFIG_FAILED;
4595 }
4596
4597 if (su.sin.sin_addr.s_addr == 0 ||
4598 !ipv4_unicast_valid(&su.sin.sin_addr)) {
4599 vty_out(vty,
4600 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4601 return CMD_WARNING_CONFIG_FAILED;
4602 }
4603
4604 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4605
4606 snprintf(xpath_value, sizeof(xpath_value),
4607 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4608 xpath);
4609
4610 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4611 return nb_cli_apply_changes(vty, NULL);
4612 }
4613
4614 DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4615 no_set_evpn_gw_ip_ipv4_cmd,
4616 "no set evpn gateway-ip ipv4 A.B.C.D",
4617 NO_STR
4618 SET_STR
4619 EVPN_HELP_STR
4620 "Set gateway IP for prefix advertisement route\n"
4621 "IPv4 address\n"
4622 "Gateway IP address in IPv4 format\n")
4623 {
4624 int ret;
4625 union sockunion su;
4626 const char *xpath =
4627 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4628
4629 ret = str2sockunion(argv[5]->arg, &su);
4630 if (ret < 0) {
4631 vty_out(vty, "%% Malformed gateway IP\n");
4632 return CMD_WARNING_CONFIG_FAILED;
4633 }
4634
4635 if (su.sin.sin_addr.s_addr == 0 ||
4636 !ipv4_unicast_valid(&su.sin.sin_addr)) {
4637 vty_out(vty,
4638 "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4639 return CMD_WARNING_CONFIG_FAILED;
4640 }
4641
4642 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4643
4644 return nb_cli_apply_changes(vty, NULL);
4645 }
4646
4647 DEFUN_YANG (set_evpn_gw_ip_ipv6,
4648 set_evpn_gw_ip_ipv6_cmd,
4649 "set evpn gateway-ip ipv6 X:X::X:X",
4650 SET_STR
4651 EVPN_HELP_STR
4652 "Set gateway IP for prefix advertisement route\n"
4653 "IPv6 address\n"
4654 "Gateway IP address in IPv6 format\n")
4655 {
4656 int ret;
4657 union sockunion su;
4658 const char *xpath =
4659 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4660 char xpath_value[XPATH_MAXLEN];
4661
4662 ret = str2sockunion(argv[4]->arg, &su);
4663 if (ret < 0) {
4664 vty_out(vty, "%% Malformed gateway IP\n");
4665 return CMD_WARNING_CONFIG_FAILED;
4666 }
4667
4668 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4669 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4670 vty_out(vty,
4671 "%% Gateway IP cannot be a linklocal or multicast address\n");
4672 return CMD_WARNING_CONFIG_FAILED;
4673 }
4674
4675 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4676
4677 snprintf(xpath_value, sizeof(xpath_value),
4678 "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4679 xpath);
4680
4681 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4682 return nb_cli_apply_changes(vty, NULL);
4683 }
4684
4685 DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4686 no_set_evpn_gw_ip_ipv6_cmd,
4687 "no set evpn gateway-ip ipv6 X:X::X:X",
4688 NO_STR
4689 SET_STR
4690 EVPN_HELP_STR
4691 "Set gateway IP for prefix advertisement route\n"
4692 "IPv4 address\n"
4693 "Gateway IP address in IPv4 format\n")
4694 {
4695 int ret;
4696 union sockunion su;
4697 const char *xpath =
4698 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4699
4700 ret = str2sockunion(argv[5]->arg, &su);
4701 if (ret < 0) {
4702 vty_out(vty, "%% Malformed gateway IP\n");
4703 return CMD_WARNING_CONFIG_FAILED;
4704 }
4705
4706 if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4707 || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4708 vty_out(vty,
4709 "%% Gateway IP cannot be a linklocal or multicast address\n");
4710 return CMD_WARNING_CONFIG_FAILED;
4711 }
4712
4713 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4714
4715 return nb_cli_apply_changes(vty, NULL);
4716 }
4717
4718 DEFPY_YANG(match_vrl_source_vrf,
4719 match_vrl_source_vrf_cmd,
4720 "match source-vrf NAME$vrf_name",
4721 MATCH_STR
4722 "source vrf\n"
4723 "The VRF name\n")
4724 {
4725 const char *xpath =
4726 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4727 char xpath_value[XPATH_MAXLEN];
4728
4729 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4730 snprintf(xpath_value, sizeof(xpath_value),
4731 "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4732 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4733
4734 return nb_cli_apply_changes(vty, NULL);
4735 }
4736
4737 DEFPY_YANG(no_match_vrl_source_vrf,
4738 no_match_vrl_source_vrf_cmd,
4739 "no match source-vrf NAME$vrf_name",
4740 NO_STR MATCH_STR
4741 "source vrf\n"
4742 "The VRF name\n")
4743 {
4744 const char *xpath =
4745 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4746
4747 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4748 return nb_cli_apply_changes(vty, NULL);
4749 }
4750
4751 DEFPY_YANG (match_peer,
4752 match_peer_cmd,
4753 "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
4754 MATCH_STR
4755 "Match peer address\n"
4756 "IP address of peer\n"
4757 "IPv6 address of peer\n"
4758 "Interface name of peer or peer group name\n")
4759 {
4760 const char *xpath =
4761 "./match-condition[condition='frr-bgp-route-map:peer']";
4762 char xpath_value[XPATH_MAXLEN];
4763
4764 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4765
4766 if (addrv4_str) {
4767 snprintf(
4768 xpath_value, sizeof(xpath_value),
4769 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4770 xpath);
4771 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4772 addrv4_str);
4773 } else if (addrv6_str) {
4774 snprintf(
4775 xpath_value, sizeof(xpath_value),
4776 "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4777 xpath);
4778 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4779 addrv6_str);
4780 } else {
4781 snprintf(
4782 xpath_value, sizeof(xpath_value),
4783 "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4784 xpath);
4785 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4786 }
4787
4788 return nb_cli_apply_changes(vty, NULL);
4789 }
4790
4791 DEFUN_YANG (match_peer_local,
4792 match_peer_local_cmd,
4793 "match peer local",
4794 MATCH_STR
4795 "Match peer address\n"
4796 "Static or Redistributed routes\n")
4797 {
4798 const char *xpath =
4799 "./match-condition[condition='frr-bgp-route-map:peer']";
4800 char xpath_value[XPATH_MAXLEN];
4801
4802 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4803
4804 snprintf(xpath_value, sizeof(xpath_value),
4805 "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4806 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4807
4808 return nb_cli_apply_changes(vty, NULL);
4809 }
4810
4811 DEFUN_YANG (no_match_peer,
4812 no_match_peer_cmd,
4813 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4814 NO_STR
4815 MATCH_STR
4816 "Match peer address\n"
4817 "Static or Redistributed routes\n"
4818 "IP address of peer\n"
4819 "IPv6 address of peer\n"
4820 "Interface name of peer\n")
4821 {
4822 const char *xpath =
4823 "./match-condition[condition='frr-bgp-route-map:peer']";
4824
4825 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4826
4827 return nb_cli_apply_changes(vty, NULL);
4828 }
4829
4830 #ifdef HAVE_SCRIPTING
4831 DEFUN_YANG (match_script,
4832 match_script_cmd,
4833 "[no] match script WORD",
4834 NO_STR
4835 MATCH_STR
4836 "Execute script to determine match\n"
4837 "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
4838 {
4839 bool no = strmatch(argv[0]->text, "no");
4840 int i = 0;
4841 argv_find(argv, argc, "WORD", &i);
4842 const char *script = argv[i]->arg;
4843 const char *xpath =
4844 "./match-condition[condition='frr-bgp-route-map:match-script']";
4845 char xpath_value[XPATH_MAXLEN];
4846
4847 if (no) {
4848 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4849 snprintf(xpath_value, sizeof(xpath_value),
4850 "%s/rmap-match-condition/frr-bgp-route-map:script",
4851 xpath);
4852 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4853 script);
4854
4855 return nb_cli_apply_changes(vty, NULL);
4856 }
4857
4858 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4859 snprintf(xpath_value, sizeof(xpath_value),
4860 "%s/rmap-match-condition/frr-bgp-route-map:script",
4861 xpath);
4862 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4863 script);
4864
4865 return nb_cli_apply_changes(vty, NULL);
4866 }
4867 #endif /* HAVE_SCRIPTING */
4868
4869 /* match probability */
4870 DEFUN_YANG (match_probability,
4871 match_probability_cmd,
4872 "match probability (0-100)",
4873 MATCH_STR
4874 "Match portion of routes defined by percentage value\n"
4875 "Percentage of routes\n")
4876 {
4877 int idx_number = 2;
4878
4879 const char *xpath =
4880 "./match-condition[condition='frr-bgp-route-map:probability']";
4881 char xpath_value[XPATH_MAXLEN];
4882
4883 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4884 snprintf(xpath_value, sizeof(xpath_value),
4885 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4886 xpath);
4887 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4888 argv[idx_number]->arg);
4889
4890 return nb_cli_apply_changes(vty, NULL);
4891 }
4892
4893
4894 DEFUN_YANG (no_match_probability,
4895 no_match_probability_cmd,
4896 "no match probability [(1-99)]",
4897 NO_STR
4898 MATCH_STR
4899 "Match portion of routes defined by percentage value\n"
4900 "Percentage of routes\n")
4901 {
4902 int idx_number = 3;
4903 const char *xpath =
4904 "./match-condition[condition='frr-bgp-route-map:probability']";
4905 char xpath_value[XPATH_MAXLEN];
4906
4907 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4908
4909 if (argc <= idx_number)
4910 return nb_cli_apply_changes(vty, NULL);
4911
4912 snprintf(xpath_value, sizeof(xpath_value),
4913 "%s/rmap-match-condition/frr-bgp-route-map:probability",
4914 xpath);
4915 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4916 argv[idx_number]->arg);
4917
4918 return nb_cli_apply_changes(vty, NULL);
4919 }
4920
4921
4922 DEFPY_YANG (match_ip_route_source,
4923 match_ip_route_source_cmd,
4924 "match ip route-source ACCESSLIST4_NAME",
4925 MATCH_STR
4926 IP_STR
4927 "Match advertising source address of route\n"
4928 "IP Access-list name\n")
4929 {
4930 const char *xpath =
4931 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4932 char xpath_value[XPATH_MAXLEN + 32];
4933 int idx_acl = 3;
4934
4935 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4936 snprintf(xpath_value, sizeof(xpath_value),
4937 "%s/rmap-match-condition/frr-bgp-route-map:list-name",
4938 xpath);
4939 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4940 argv[idx_acl]->arg);
4941
4942 return nb_cli_apply_changes(vty, NULL);
4943 }
4944
4945
4946 DEFUN_YANG (no_match_ip_route_source,
4947 no_match_ip_route_source_cmd,
4948 "no match ip route-source [ACCESSLIST4_NAME]",
4949 NO_STR
4950 MATCH_STR
4951 IP_STR
4952 "Match advertising source address of route\n"
4953 "IP Access-list name\n")
4954 {
4955 const char *xpath =
4956 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4957
4958 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4959 return nb_cli_apply_changes(vty, NULL);
4960 }
4961
4962 DEFUN_YANG (match_ip_route_source_prefix_list,
4963 match_ip_route_source_prefix_list_cmd,
4964 "match ip route-source prefix-list PREFIXLIST_NAME",
4965 MATCH_STR
4966 IP_STR
4967 "Match advertising source address of route\n"
4968 "Match entries of prefix-lists\n"
4969 "IP prefix-list name\n")
4970 {
4971 int idx_word = 4;
4972 const char *xpath =
4973 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4974 char xpath_value[XPATH_MAXLEN + 32];
4975
4976 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4977 snprintf(xpath_value, sizeof(xpath_value),
4978 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4979 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4980 argv[idx_word]->arg);
4981
4982 return nb_cli_apply_changes(vty, NULL);
4983 }
4984
4985
4986 DEFUN_YANG (no_match_ip_route_source_prefix_list,
4987 no_match_ip_route_source_prefix_list_cmd,
4988 "no match ip route-source prefix-list [PREFIXLIST_NAME]",
4989 NO_STR
4990 MATCH_STR
4991 IP_STR
4992 "Match advertising source address of route\n"
4993 "Match entries of prefix-lists\n"
4994 "IP prefix-list name\n")
4995 {
4996 const char *xpath =
4997 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4998
4999 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5000 return nb_cli_apply_changes(vty, NULL);
5001 }
5002
5003 DEFUN_YANG (match_local_pref,
5004 match_local_pref_cmd,
5005 "match local-preference (0-4294967295)",
5006 MATCH_STR
5007 "Match local-preference of route\n"
5008 "Metric value\n")
5009 {
5010 int idx_number = 2;
5011
5012 const char *xpath =
5013 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5014 char xpath_value[XPATH_MAXLEN];
5015
5016 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5017 snprintf(xpath_value, sizeof(xpath_value),
5018 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5019 xpath);
5020 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5021 argv[idx_number]->arg);
5022
5023 return nb_cli_apply_changes(vty, NULL);
5024 }
5025
5026
5027 DEFUN_YANG (no_match_local_pref,
5028 no_match_local_pref_cmd,
5029 "no match local-preference [(0-4294967295)]",
5030 NO_STR
5031 MATCH_STR
5032 "Match local preference of route\n"
5033 "Local preference value\n")
5034 {
5035 int idx_localpref = 3;
5036 const char *xpath =
5037 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5038 char xpath_value[XPATH_MAXLEN];
5039
5040 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5041
5042 if (argc <= idx_localpref)
5043 return nb_cli_apply_changes(vty, NULL);
5044
5045 snprintf(xpath_value, sizeof(xpath_value),
5046 "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5047 xpath);
5048 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5049 argv[idx_localpref]->arg);
5050
5051 return nb_cli_apply_changes(vty, NULL);
5052 }
5053
5054 DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
5055 MATCH_STR
5056 "Match BGP community alias name\n"
5057 "BGP community alias name\n")
5058 {
5059 const char *alias = argv[2]->arg;
5060 struct community_alias ca1;
5061 struct community_alias *lookup_alias;
5062
5063 const char *xpath =
5064 "./match-condition[condition='frr-bgp-route-map:match-alias']";
5065 char xpath_value[XPATH_MAXLEN];
5066
5067 memset(&ca1, 0, sizeof(ca1));
5068 strlcpy(ca1.alias, alias, sizeof(ca1.alias));
5069 lookup_alias = bgp_ca_alias_lookup(&ca1);
5070 if (!lookup_alias) {
5071 vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
5072 return CMD_WARNING_CONFIG_FAILED;
5073 }
5074
5075 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5076 snprintf(xpath_value, sizeof(xpath_value),
5077 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5078 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
5079
5080 return nb_cli_apply_changes(vty, NULL);
5081 }
5082
5083
5084 DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
5085 NO_STR MATCH_STR
5086 "Match BGP community alias name\n"
5087 "BGP community alias name\n")
5088 {
5089 int idx_alias = 3;
5090 const char *xpath =
5091 "./match-condition[condition='frr-bgp-route-map:match-alias']";
5092 char xpath_value[XPATH_MAXLEN];
5093
5094 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5095
5096 if (argc <= idx_alias)
5097 return nb_cli_apply_changes(vty, NULL);
5098
5099 snprintf(xpath_value, sizeof(xpath_value),
5100 "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5101 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5102 argv[idx_alias]->arg);
5103
5104 return nb_cli_apply_changes(vty, NULL);
5105 }
5106
5107 DEFPY_YANG (match_community,
5108 match_community_cmd,
5109 "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
5110 MATCH_STR
5111 "Match BGP community list\n"
5112 "Community-list number (standard)\n"
5113 "Community-list number (expanded)\n"
5114 "Community-list name\n"
5115 "Do exact matching of communities\n")
5116 {
5117 const char *xpath =
5118 "./match-condition[condition='frr-bgp-route-map:match-community']";
5119 char xpath_value[XPATH_MAXLEN];
5120 char xpath_match[XPATH_MAXLEN];
5121 int idx_comm_list = 2;
5122
5123 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5124
5125 snprintf(
5126 xpath_value, sizeof(xpath_value),
5127 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5128 xpath);
5129 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5130
5131 if (argc == 4) {
5132 snprintf(
5133 xpath_match, sizeof(xpath_match),
5134 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5135 xpath);
5136 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5137 "true");
5138 } else {
5139 snprintf(
5140 xpath_match, sizeof(xpath_match),
5141 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5142 xpath);
5143 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5144 "false");
5145 }
5146
5147 return nb_cli_apply_changes(vty, NULL);
5148 }
5149
5150 DEFUN_YANG (no_match_community,
5151 no_match_community_cmd,
5152 "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
5153 NO_STR
5154 MATCH_STR
5155 "Match BGP community list\n"
5156 "Community-list number (standard)\n"
5157 "Community-list number (expanded)\n"
5158 "Community-list name\n"
5159 "Do exact matching of communities\n")
5160 {
5161 const char *xpath =
5162 "./match-condition[condition='frr-bgp-route-map:match-community']";
5163
5164 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5165 return nb_cli_apply_changes(vty, NULL);
5166 }
5167
5168 DEFPY_YANG (match_lcommunity,
5169 match_lcommunity_cmd,
5170 "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
5171 MATCH_STR
5172 "Match BGP large community list\n"
5173 "Large Community-list number (standard)\n"
5174 "Large Community-list number (expanded)\n"
5175 "Large Community-list name\n"
5176 "Do exact matching of communities\n")
5177 {
5178 const char *xpath =
5179 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5180 char xpath_value[XPATH_MAXLEN];
5181 char xpath_match[XPATH_MAXLEN];
5182 int idx_lcomm_list = 2;
5183
5184 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5185
5186 snprintf(
5187 xpath_value, sizeof(xpath_value),
5188 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5189 xpath);
5190 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
5191
5192 if (argc == 4) {
5193 snprintf(
5194 xpath_match, sizeof(xpath_match),
5195 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5196 xpath);
5197 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5198 "true");
5199 } else {
5200 snprintf(
5201 xpath_match, sizeof(xpath_match),
5202 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5203 xpath);
5204 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5205 "false");
5206 }
5207
5208 return nb_cli_apply_changes(vty, NULL);
5209 }
5210
5211 DEFUN_YANG (no_match_lcommunity,
5212 no_match_lcommunity_cmd,
5213 "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
5214 NO_STR
5215 MATCH_STR
5216 "Match BGP large community list\n"
5217 "Large Community-list number (standard)\n"
5218 "Large Community-list number (expanded)\n"
5219 "Large Community-list name\n"
5220 "Do exact matching of communities\n")
5221 {
5222 const char *xpath =
5223 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5224
5225 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5226 return nb_cli_apply_changes(vty, NULL);
5227 }
5228
5229 DEFPY_YANG (match_ecommunity,
5230 match_ecommunity_cmd,
5231 "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
5232 MATCH_STR
5233 "Match BGP/VPN extended community list\n"
5234 "Extended community-list number (standard)\n"
5235 "Extended community-list number (expanded)\n"
5236 "Extended community-list name\n")
5237 {
5238 const char *xpath =
5239 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5240 char xpath_value[XPATH_MAXLEN];
5241 int idx_comm_list = 2;
5242
5243 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5244
5245 snprintf(
5246 xpath_value, sizeof(xpath_value),
5247 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5248 xpath);
5249 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5250
5251 return nb_cli_apply_changes(vty, NULL);
5252 }
5253
5254
5255 DEFUN_YANG (no_match_ecommunity,
5256 no_match_ecommunity_cmd,
5257 "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
5258 NO_STR
5259 MATCH_STR
5260 "Match BGP/VPN extended community list\n"
5261 "Extended community-list number (standard)\n"
5262 "Extended community-list number (expanded)\n"
5263 "Extended community-list name\n")
5264 {
5265 const char *xpath =
5266 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5267
5268 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5269 return nb_cli_apply_changes(vty, NULL);
5270 }
5271
5272
5273 DEFUN_YANG (match_aspath,
5274 match_aspath_cmd,
5275 "match as-path AS_PATH_FILTER_NAME",
5276 MATCH_STR
5277 "Match BGP AS path list\n"
5278 "AS path access-list name\n")
5279 {
5280 int idx_word = 2;
5281
5282 const char *xpath =
5283 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5284 char xpath_value[XPATH_MAXLEN];
5285
5286 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5287 snprintf(xpath_value, sizeof(xpath_value),
5288 "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5289 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5290 argv[idx_word]->arg);
5291
5292 return nb_cli_apply_changes(vty, NULL);
5293 }
5294
5295
5296 DEFUN_YANG (no_match_aspath,
5297 no_match_aspath_cmd,
5298 "no match as-path [AS_PATH_FILTER_NAME]",
5299 NO_STR
5300 MATCH_STR
5301 "Match BGP AS path list\n"
5302 "AS path access-list name\n")
5303 {
5304 const char *xpath =
5305 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5306
5307 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5308
5309 return nb_cli_apply_changes(vty, NULL);
5310 }
5311
5312 DEFUN_YANG (match_origin,
5313 match_origin_cmd,
5314 "match origin <egp|igp|incomplete>",
5315 MATCH_STR
5316 "BGP origin code\n"
5317 "remote EGP\n"
5318 "local IGP\n"
5319 "unknown heritage\n")
5320 {
5321 int idx_origin = 2;
5322 const char *origin_type;
5323 const char *xpath =
5324 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5325 char xpath_value[XPATH_MAXLEN];
5326
5327 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
5328 origin_type = "igp";
5329 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5330 origin_type = "egp";
5331 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5332 origin_type = "incomplete";
5333 else {
5334 vty_out(vty, "%% Invalid match origin type\n");
5335 return CMD_WARNING_CONFIG_FAILED;
5336 }
5337
5338 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5339 snprintf(xpath_value, sizeof(xpath_value),
5340 "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5341 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
5342
5343 return nb_cli_apply_changes(vty, NULL);
5344 }
5345
5346
5347 DEFUN_YANG (no_match_origin,
5348 no_match_origin_cmd,
5349 "no match origin [<egp|igp|incomplete>]",
5350 NO_STR
5351 MATCH_STR
5352 "BGP origin code\n"
5353 "remote EGP\n"
5354 "local IGP\n"
5355 "unknown heritage\n")
5356 {
5357 const char *xpath =
5358 "./match-condition[condition='frr-bgp-route-map:match-origin']";
5359 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5360 return nb_cli_apply_changes(vty, NULL);
5361 }
5362
5363 DEFUN_YANG (set_table_id,
5364 set_table_id_cmd,
5365 "set table (1-4294967295)",
5366 SET_STR
5367 "export route to non-main kernel table\n"
5368 "Kernel routing table id\n")
5369 {
5370 int idx_number = 2;
5371 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5372 char xpath_value[XPATH_MAXLEN];
5373
5374 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5375 snprintf(xpath_value, sizeof(xpath_value),
5376 "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5377 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5378 argv[idx_number]->arg);
5379 return nb_cli_apply_changes(vty, NULL);
5380 }
5381
5382 DEFUN_YANG (no_set_table_id,
5383 no_set_table_id_cmd,
5384 "no set table",
5385 NO_STR
5386 SET_STR
5387 "export route to non-main kernel table\n")
5388 {
5389 const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5390 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5391 return nb_cli_apply_changes(vty, NULL);
5392 }
5393
5394 DEFUN_YANG (set_ip_nexthop_peer,
5395 set_ip_nexthop_peer_cmd,
5396 "[no] set ip next-hop peer-address",
5397 NO_STR
5398 SET_STR
5399 IP_STR
5400 "Next hop address\n"
5401 "Use peer address (for BGP only)\n")
5402 {
5403 char xpath_value[XPATH_MAXLEN];
5404 const char *xpath =
5405 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5406
5407 if (strmatch(argv[0]->text, "no"))
5408 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5409 else {
5410 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5411 snprintf(xpath_value, sizeof(xpath_value),
5412 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5413 xpath);
5414 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5415 "peer-address");
5416 }
5417 return nb_cli_apply_changes(vty, NULL);
5418 }
5419
5420 DEFUN_YANG (set_ip_nexthop_unchanged,
5421 set_ip_nexthop_unchanged_cmd,
5422 "[no] set ip next-hop unchanged",
5423 NO_STR
5424 SET_STR
5425 IP_STR
5426 "Next hop address\n"
5427 "Don't modify existing Next hop address\n")
5428 {
5429 char xpath_value[XPATH_MAXLEN];
5430 const char *xpath =
5431 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5432
5433 if (strmatch(argv[0]->text, "no"))
5434 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5435 else {
5436 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5437 snprintf(xpath_value, sizeof(xpath_value),
5438 "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5439 xpath);
5440 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5441 "unchanged");
5442 }
5443 return nb_cli_apply_changes(vty, NULL);
5444 }
5445
5446 DEFUN_YANG (set_distance,
5447 set_distance_cmd,
5448 "set distance (0-255)",
5449 SET_STR
5450 "BGP Administrative Distance to use\n"
5451 "Distance value\n")
5452 {
5453 int idx_number = 2;
5454 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5455 char xpath_value[XPATH_MAXLEN];
5456
5457 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5458 snprintf(xpath_value, sizeof(xpath_value),
5459 "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5460 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5461 argv[idx_number]->arg);
5462 return nb_cli_apply_changes(vty, NULL);
5463 }
5464
5465 DEFUN_YANG (no_set_distance,
5466 no_set_distance_cmd,
5467 "no set distance [(0-255)]",
5468 NO_STR SET_STR
5469 "BGP Administrative Distance to use\n"
5470 "Distance value\n")
5471 {
5472 const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5473
5474 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5475 return nb_cli_apply_changes(vty, NULL);
5476 }
5477
5478 DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
5479 "[no] set l3vpn next-hop encapsulation gre",
5480 NO_STR SET_STR
5481 "L3VPN operations\n"
5482 "Next hop Information\n"
5483 "Encapsulation options (for BGP only)\n"
5484 "Accept L3VPN traffic over GRE encapsulation\n")
5485 {
5486 const char *xpath =
5487 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
5488 const char *xpath_value =
5489 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
5490 enum nb_operation operation;
5491
5492 if (no)
5493 operation = NB_OP_DESTROY;
5494 else
5495 operation = NB_OP_CREATE;
5496
5497 nb_cli_enqueue_change(vty, xpath, operation, NULL);
5498 if (operation == NB_OP_DESTROY)
5499 return nb_cli_apply_changes(vty, NULL);
5500
5501 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
5502
5503 return nb_cli_apply_changes(vty, NULL);
5504 }
5505
5506 DEFUN_YANG (set_local_pref,
5507 set_local_pref_cmd,
5508 "set local-preference WORD",
5509 SET_STR
5510 "BGP local preference path attribute\n"
5511 "Preference value (0-4294967295)\n")
5512 {
5513 int idx_number = 2;
5514 const char *xpath =
5515 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5516 char xpath_value[XPATH_MAXLEN];
5517
5518 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5519 snprintf(xpath_value, sizeof(xpath_value),
5520 "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5521 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5522 argv[idx_number]->arg);
5523 return nb_cli_apply_changes(vty, NULL);
5524 }
5525
5526 DEFUN_YANG (no_set_local_pref,
5527 no_set_local_pref_cmd,
5528 "no set local-preference [WORD]",
5529 NO_STR
5530 SET_STR
5531 "BGP local preference path attribute\n"
5532 "Preference value (0-4294967295)\n")
5533 {
5534 const char *xpath =
5535 "./set-action[action='frr-bgp-route-map:set-local-preference']";
5536
5537 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5538 return nb_cli_apply_changes(vty, NULL);
5539 }
5540
5541 DEFUN_YANG (set_weight,
5542 set_weight_cmd,
5543 "set weight (0-4294967295)",
5544 SET_STR
5545 "BGP weight for routing table\n"
5546 "Weight value\n")
5547 {
5548 int idx_number = 2;
5549 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5550 char xpath_value[XPATH_MAXLEN];
5551
5552 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5553 snprintf(xpath_value, sizeof(xpath_value),
5554 "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5555 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5556 argv[idx_number]->arg);
5557 return nb_cli_apply_changes(vty, NULL);
5558 }
5559
5560 DEFUN_YANG (no_set_weight,
5561 no_set_weight_cmd,
5562 "no set weight [(0-4294967295)]",
5563 NO_STR
5564 SET_STR
5565 "BGP weight for routing table\n"
5566 "Weight value\n")
5567 {
5568 const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5569
5570 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5571 return nb_cli_apply_changes(vty, NULL);
5572 }
5573
5574 DEFUN_YANG (set_label_index,
5575 set_label_index_cmd,
5576 "set label-index (0-1048560)",
5577 SET_STR
5578 "Label index to associate with the prefix\n"
5579 "Label index value\n")
5580 {
5581 int idx_number = 2;
5582 const char *xpath =
5583 "./set-action[action='frr-bgp-route-map:label-index']";
5584 char xpath_value[XPATH_MAXLEN];
5585
5586 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5587 snprintf(xpath_value, sizeof(xpath_value),
5588 "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5589 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5590 argv[idx_number]->arg);
5591 return nb_cli_apply_changes(vty, NULL);
5592 }
5593
5594 DEFUN_YANG (no_set_label_index,
5595 no_set_label_index_cmd,
5596 "no set label-index [(0-1048560)]",
5597 NO_STR
5598 SET_STR
5599 "Label index to associate with the prefix\n"
5600 "Label index value\n")
5601 {
5602 const char *xpath =
5603 "./set-action[action='frr-bgp-route-map:label-index']";
5604
5605 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5606 return nb_cli_apply_changes(vty, NULL);
5607 }
5608
5609 DEFUN_YANG (set_aspath_prepend_asn,
5610 set_aspath_prepend_asn_cmd,
5611 "set as-path prepend (1-4294967295)...",
5612 SET_STR
5613 "Transform BGP AS_PATH attribute\n"
5614 "Prepend to the as-path\n"
5615 "AS number\n")
5616 {
5617 int idx_asn = 3;
5618 int ret;
5619 char *str;
5620
5621 str = argv_concat(argv, argc, idx_asn);
5622
5623 const char *xpath =
5624 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5625 char xpath_value[XPATH_MAXLEN];
5626
5627 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5628 snprintf(xpath_value, sizeof(xpath_value),
5629 "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5630 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5631 ret = nb_cli_apply_changes(vty, NULL);
5632 XFREE(MTYPE_TMP, str);
5633 return ret;
5634 }
5635
5636 DEFUN_YANG (set_aspath_prepend_lastas,
5637 set_aspath_prepend_lastas_cmd,
5638 "set as-path prepend last-as (1-10)",
5639 SET_STR
5640 "Transform BGP AS_PATH attribute\n"
5641 "Prepend to the as-path\n"
5642 "Use the last AS-number in the as-path\n"
5643 "Number of times to insert\n")
5644 {
5645 int idx_num = 4;
5646
5647 const char *xpath =
5648 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5649 char xpath_value[XPATH_MAXLEN];
5650
5651 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5652 snprintf(xpath_value, sizeof(xpath_value),
5653 "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5654 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5655 argv[idx_num]->arg);
5656 return nb_cli_apply_changes(vty, NULL);
5657 }
5658
5659 DEFPY_YANG (set_aspath_replace_asn,
5660 set_aspath_replace_asn_cmd,
5661 "set as-path replace <any|(1-4294967295)>$replace",
5662 SET_STR
5663 "Transform BGP AS_PATH attribute\n"
5664 "Replace AS number to local AS number\n"
5665 "Replace any AS number to local AS number\n"
5666 "Replace a specific AS number to local AS number\n")
5667 {
5668 const char *xpath =
5669 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5670 char xpath_value[XPATH_MAXLEN];
5671
5672 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5673 snprintf(xpath_value, sizeof(xpath_value),
5674 "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5675 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5676 return nb_cli_apply_changes(vty, NULL);
5677 }
5678
5679 DEFPY_YANG (no_set_aspath_replace_asn,
5680 no_set_aspath_replace_asn_cmd,
5681 "no set as-path replace [<any|(1-4294967295)>]",
5682 NO_STR
5683 SET_STR
5684 "Transform BGP AS_PATH attribute\n"
5685 "Replace AS number to local AS number\n"
5686 "Replace any AS number to local AS number\n"
5687 "Replace a specific AS number to local AS number\n")
5688 {
5689 const char *xpath =
5690 "./set-action[action='frr-bgp-route-map:as-path-replace']";
5691
5692 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5693 return nb_cli_apply_changes(vty, NULL);
5694 }
5695
5696 DEFUN_YANG (no_set_aspath_prepend,
5697 no_set_aspath_prepend_cmd,
5698 "no set as-path prepend [(1-4294967295)]",
5699 NO_STR
5700 SET_STR
5701 "Transform BGP AS_PATH attribute\n"
5702 "Prepend to the as-path\n"
5703 "AS number\n")
5704 {
5705 const char *xpath =
5706 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5707
5708 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5709 return nb_cli_apply_changes(vty, NULL);
5710 }
5711
5712 DEFUN_YANG (no_set_aspath_prepend_lastas,
5713 no_set_aspath_prepend_lastas_cmd,
5714 "no set as-path prepend last-as [(1-10)]",
5715 NO_STR
5716 SET_STR
5717 "Transform BGP AS_PATH attribute\n"
5718 "Prepend to the as-path\n"
5719 "Use the peers AS-number\n"
5720 "Number of times to insert\n")
5721 {
5722 const char *xpath =
5723 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5724
5725 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5726 return nb_cli_apply_changes(vty, NULL);
5727 }
5728
5729 DEFUN_YANG (set_aspath_exclude,
5730 set_aspath_exclude_cmd,
5731 "set as-path exclude (1-4294967295)...",
5732 SET_STR
5733 "Transform BGP AS-path attribute\n"
5734 "Exclude from the as-path\n"
5735 "AS number\n")
5736 {
5737 int idx_asn = 3;
5738 int ret;
5739 char *str;
5740
5741 str = argv_concat(argv, argc, idx_asn);
5742
5743 const char *xpath =
5744 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5745 char xpath_value[XPATH_MAXLEN];
5746
5747 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5748 snprintf(xpath_value, sizeof(xpath_value),
5749 "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5750 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5751 ret = nb_cli_apply_changes(vty, NULL);
5752 XFREE(MTYPE_TMP, str);
5753 return ret;
5754 }
5755
5756 DEFUN_YANG (no_set_aspath_exclude,
5757 no_set_aspath_exclude_cmd,
5758 "no set as-path exclude (1-4294967295)...",
5759 NO_STR
5760 SET_STR
5761 "Transform BGP AS_PATH attribute\n"
5762 "Exclude from the as-path\n"
5763 "AS number\n")
5764 {
5765 const char *xpath =
5766 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5767
5768 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5769 return nb_cli_apply_changes(vty, NULL);
5770 }
5771
5772 ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5773 "no set as-path exclude",
5774 NO_STR SET_STR
5775 "Transform BGP AS_PATH attribute\n"
5776 "Exclude from the as-path\n")
5777
5778 DEFUN_YANG (set_community,
5779 set_community_cmd,
5780 "set community AA:NN...",
5781 SET_STR
5782 "BGP community attribute\n"
5783 COMMUNITY_VAL_STR)
5784 {
5785 int idx_aa_nn = 2;
5786 int i;
5787 int first = 0;
5788 int additive = 0;
5789 struct buffer *b;
5790 struct community *com = NULL;
5791 char *str;
5792 char *argstr = NULL;
5793 int ret;
5794
5795 const char *xpath =
5796 "./set-action[action='frr-bgp-route-map:set-community']";
5797 char xpath_value[XPATH_MAXLEN];
5798
5799 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5800 snprintf(xpath_value, sizeof(xpath_value),
5801 "%s/rmap-set-action/frr-bgp-route-map:community-string",
5802 xpath);
5803
5804 b = buffer_new(1024);
5805
5806 for (i = idx_aa_nn; i < argc; i++) {
5807 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5808 == 0) {
5809 additive = 1;
5810 continue;
5811 }
5812
5813 if (first)
5814 buffer_putc(b, ' ');
5815 else
5816 first = 1;
5817
5818 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5819 == 0) {
5820 buffer_putstr(b, "internet");
5821 continue;
5822 }
5823 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5824 == 0) {
5825 buffer_putstr(b, "local-AS");
5826 continue;
5827 }
5828 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5829 && strncmp(argv[i]->arg, "no-advertise",
5830 strlen(argv[i]->arg))
5831 == 0) {
5832 buffer_putstr(b, "no-advertise");
5833 continue;
5834 }
5835 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5836 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5837 == 0) {
5838 buffer_putstr(b, "no-export");
5839 continue;
5840 }
5841 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
5842 == 0) {
5843 buffer_putstr(b, "blackhole");
5844 continue;
5845 }
5846 if (strncmp(argv[i]->arg, "graceful-shutdown",
5847 strlen(argv[i]->arg))
5848 == 0) {
5849 buffer_putstr(b, "graceful-shutdown");
5850 continue;
5851 }
5852 buffer_putstr(b, argv[i]->arg);
5853 }
5854 buffer_putc(b, '\0');
5855
5856 /* Fetch result string then compile it to communities attribute. */
5857 str = buffer_getstr(b);
5858 buffer_free(b);
5859
5860 if (str)
5861 com = community_str2com(str);
5862
5863 /* Can't compile user input into communities attribute. */
5864 if (!com) {
5865 vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
5866 XFREE(MTYPE_TMP, str);
5867 return CMD_WARNING_CONFIG_FAILED;
5868 }
5869 XFREE(MTYPE_TMP, str);
5870
5871 /* Set communites attribute string. */
5872 str = community_str(com, false, false);
5873
5874 if (additive) {
5875 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
5876 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
5877 strlcpy(argstr, str, argstr_sz);
5878 strlcat(argstr, " additive", argstr_sz);
5879 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
5880 } else
5881 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5882
5883 ret = nb_cli_apply_changes(vty, NULL);
5884
5885 if (argstr)
5886 XFREE(MTYPE_TMP, argstr);
5887 community_free(&com);
5888
5889 return ret;
5890 }
5891
5892 DEFUN_YANG (set_community_none,
5893 set_community_none_cmd,
5894 "set community none",
5895 SET_STR
5896 "BGP community attribute\n"
5897 "No community attribute\n")
5898 {
5899 const char *xpath =
5900 "./set-action[action='frr-bgp-route-map:set-community']";
5901 char xpath_value[XPATH_MAXLEN];
5902
5903 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5904
5905 snprintf(xpath_value, sizeof(xpath_value),
5906 "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
5907 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5908 return nb_cli_apply_changes(vty, NULL);
5909 }
5910
5911 DEFUN_YANG (no_set_community,
5912 no_set_community_cmd,
5913 "no set community AA:NN...",
5914 NO_STR
5915 SET_STR
5916 "BGP community attribute\n"
5917 COMMUNITY_VAL_STR)
5918 {
5919 const char *xpath =
5920 "./set-action[action='frr-bgp-route-map:set-community']";
5921
5922 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5923 return nb_cli_apply_changes(vty, NULL);
5924 }
5925
5926 ALIAS_YANG (no_set_community,
5927 no_set_community_short_cmd,
5928 "no set community",
5929 NO_STR
5930 SET_STR
5931 "BGP community attribute\n")
5932
5933 DEFPY_YANG (set_community_delete,
5934 set_community_delete_cmd,
5935 "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
5936 SET_STR
5937 "set BGP community list (for deletion)\n"
5938 "Community-list number (standard)\n"
5939 "Community-list number (expanded)\n"
5940 "Community-list name\n"
5941 "Delete matching communities\n")
5942 {
5943 const char *xpath =
5944 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5945 char xpath_value[XPATH_MAXLEN];
5946 int idx_comm_list = 2;
5947
5948 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5949
5950 snprintf(xpath_value, sizeof(xpath_value),
5951 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5952 xpath);
5953 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5954 argv[idx_comm_list]->arg);
5955
5956 return nb_cli_apply_changes(vty, NULL);
5957
5958 }
5959
5960 DEFUN_YANG (no_set_community_delete,
5961 no_set_community_delete_cmd,
5962 "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
5963 NO_STR
5964 SET_STR
5965 "set BGP community list (for deletion)\n"
5966 "Community-list number (standard)\n"
5967 "Community-list number (expanded)\n"
5968 "Community-list name\n"
5969 "Delete matching communities\n")
5970 {
5971 const char *xpath =
5972 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5973
5974 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5975 return nb_cli_apply_changes(vty, NULL);
5976 }
5977
5978 DEFUN_YANG (set_lcommunity,
5979 set_lcommunity_cmd,
5980 "set large-community AA:BB:CC...",
5981 SET_STR
5982 "BGP large community attribute\n"
5983 "Large Community number in aa:bb:cc format or additive\n")
5984 {
5985 char *str;
5986 int ret;
5987 const char *xpath =
5988 "./set-action[action='frr-bgp-route-map:set-large-community']";
5989 char xpath_value[XPATH_MAXLEN];
5990
5991 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5992
5993 snprintf(xpath_value, sizeof(xpath_value),
5994 "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
5995 xpath);
5996 str = argv_concat(argv, argc, 2);
5997 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5998 ret = nb_cli_apply_changes(vty, NULL);
5999 XFREE(MTYPE_TMP, str);
6000 return ret;
6001 }
6002
6003 DEFUN_YANG (set_lcommunity_none,
6004 set_lcommunity_none_cmd,
6005 "set large-community none",
6006 SET_STR
6007 "BGP large community attribute\n"
6008 "No large community attribute\n")
6009 {
6010 const char *xpath =
6011 "./set-action[action='frr-bgp-route-map:set-large-community']";
6012 char xpath_value[XPATH_MAXLEN];
6013
6014 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6015
6016 snprintf(xpath_value, sizeof(xpath_value),
6017 "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
6018 xpath);
6019 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6020 return nb_cli_apply_changes(vty, NULL);
6021 }
6022
6023 DEFUN_YANG (no_set_lcommunity,
6024 no_set_lcommunity_cmd,
6025 "no set large-community none",
6026 NO_STR
6027 SET_STR
6028 "BGP large community attribute\n"
6029 "No community attribute\n")
6030 {
6031 const char *xpath =
6032 "./set-action[action='frr-bgp-route-map:set-large-community']";
6033
6034 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6035 return nb_cli_apply_changes(vty, NULL);
6036 }
6037
6038 DEFUN_YANG (no_set_lcommunity1,
6039 no_set_lcommunity1_cmd,
6040 "no set large-community AA:BB:CC...",
6041 NO_STR
6042 SET_STR
6043 "BGP large community attribute\n"
6044 "Large community in AA:BB:CC... format or additive\n")
6045 {
6046 const char *xpath =
6047 "./set-action[action='frr-bgp-route-map:set-large-community']";
6048
6049 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6050 return nb_cli_apply_changes(vty, NULL);
6051 }
6052
6053 ALIAS_YANG (no_set_lcommunity1,
6054 no_set_lcommunity1_short_cmd,
6055 "no set large-community",
6056 NO_STR
6057 SET_STR
6058 "BGP large community attribute\n")
6059
6060 DEFPY_YANG (set_lcommunity_delete,
6061 set_lcommunity_delete_cmd,
6062 "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
6063 SET_STR
6064 "set BGP large community list (for deletion)\n"
6065 "Large Community-list number (standard)\n"
6066 "Large Communitly-list number (expanded)\n"
6067 "Large Community-list name\n"
6068 "Delete matching large communities\n")
6069 {
6070 const char *xpath =
6071 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6072 char xpath_value[XPATH_MAXLEN];
6073 int idx_lcomm_list = 2;
6074
6075 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6076
6077 snprintf(xpath_value, sizeof(xpath_value),
6078 "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6079 xpath);
6080 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6081 argv[idx_lcomm_list]->arg);
6082
6083 return nb_cli_apply_changes(vty, NULL);
6084 }
6085
6086 DEFUN_YANG (no_set_lcommunity_delete,
6087 no_set_lcommunity_delete_cmd,
6088 "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
6089 NO_STR
6090 SET_STR
6091 "set BGP large community list (for deletion)\n"
6092 "Large Community-list number (standard)\n"
6093 "Large Communitly-list number (expanded)\n"
6094 "Large Community-list name\n"
6095 "Delete matching large communities\n")
6096 {
6097 const char *xpath =
6098 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6099
6100 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6101 return nb_cli_apply_changes(vty, NULL);
6102 }
6103
6104 ALIAS_YANG (no_set_lcommunity_delete,
6105 no_set_lcommunity_delete_short_cmd,
6106 "no set large-comm-list",
6107 NO_STR
6108 SET_STR
6109 "set BGP large community list (for deletion)\n")
6110
6111 DEFUN_YANG (set_ecommunity_rt,
6112 set_ecommunity_rt_cmd,
6113 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6114 SET_STR
6115 "BGP extended community attribute\n"
6116 "Route Target extended community\n"
6117 "VPN extended community\n")
6118 {
6119 int idx_asn_nn = 3;
6120 char *str;
6121 int ret;
6122 const char *xpath =
6123 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6124 char xpath_value[XPATH_MAXLEN];
6125
6126 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6127
6128 snprintf(xpath_value, sizeof(xpath_value),
6129 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
6130 str = argv_concat(argv, argc, idx_asn_nn);
6131 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6132 ret = nb_cli_apply_changes(vty, NULL);
6133 XFREE(MTYPE_TMP, str);
6134 return ret;
6135 }
6136
6137 DEFUN_YANG (no_set_ecommunity_rt,
6138 no_set_ecommunity_rt_cmd,
6139 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6140 NO_STR
6141 SET_STR
6142 "BGP extended community attribute\n"
6143 "Route Target extended community\n"
6144 "VPN extended community\n")
6145 {
6146 const char *xpath =
6147 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6148 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6149 return nb_cli_apply_changes(vty, NULL);
6150 }
6151
6152 ALIAS_YANG (no_set_ecommunity_rt,
6153 no_set_ecommunity_rt_short_cmd,
6154 "no set extcommunity rt",
6155 NO_STR
6156 SET_STR
6157 "BGP extended community attribute\n"
6158 "Route Target extended community\n")
6159
6160 DEFUN_YANG (set_ecommunity_soo,
6161 set_ecommunity_soo_cmd,
6162 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6163 SET_STR
6164 "BGP extended community attribute\n"
6165 "Site-of-Origin extended community\n"
6166 "VPN extended community\n")
6167 {
6168 int idx_asn_nn = 3;
6169 char *str;
6170 int ret;
6171 const char *xpath =
6172 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6173 char xpath_value[XPATH_MAXLEN];
6174
6175 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6176
6177 snprintf(xpath_value, sizeof(xpath_value),
6178 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
6179 xpath);
6180 str = argv_concat(argv, argc, idx_asn_nn);
6181 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6182 ret = nb_cli_apply_changes(vty, NULL);
6183 XFREE(MTYPE_TMP, str);
6184 return ret;
6185 }
6186
6187 DEFUN_YANG (no_set_ecommunity_soo,
6188 no_set_ecommunity_soo_cmd,
6189 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6190 NO_STR
6191 SET_STR
6192 "BGP extended community attribute\n"
6193 "Site-of-Origin extended community\n"
6194 "VPN extended community\n")
6195 {
6196 const char *xpath =
6197 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6198 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6199 return nb_cli_apply_changes(vty, NULL);
6200 }
6201
6202 ALIAS_YANG (no_set_ecommunity_soo,
6203 no_set_ecommunity_soo_short_cmd,
6204 "no set extcommunity soo",
6205 NO_STR
6206 SET_STR
6207 "GP extended community attribute\n"
6208 "Site-of-Origin extended community\n")
6209
6210 DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
6211 "set extcommunity none",
6212 SET_STR
6213 "BGP extended community attribute\n"
6214 "No extended community attribute\n")
6215 {
6216 const char *xpath =
6217 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6218 char xpath_value[XPATH_MAXLEN];
6219
6220 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6221
6222 snprintf(xpath_value, sizeof(xpath_value),
6223 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6224 xpath);
6225 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6226 return nb_cli_apply_changes(vty, NULL);
6227 }
6228
6229 DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6230 "no set extcommunity none",
6231 NO_STR SET_STR
6232 "BGP extended community attribute\n"
6233 "No extended community attribute\n")
6234 {
6235 const char *xpath =
6236 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6237 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6238 return nb_cli_apply_changes(vty, NULL);
6239 }
6240
6241 DEFUN_YANG (set_ecommunity_lb,
6242 set_ecommunity_lb_cmd,
6243 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6244 SET_STR
6245 "BGP extended community attribute\n"
6246 "Link bandwidth extended community\n"
6247 "Bandwidth value in Mbps\n"
6248 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6249 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6250 "Attribute is set as non-transitive\n")
6251 {
6252 int idx_lb = 3;
6253 int idx_non_transitive = 0;
6254 const char *xpath =
6255 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6256 char xpath_lb_type[XPATH_MAXLEN];
6257 char xpath_bandwidth[XPATH_MAXLEN];
6258 char xpath_non_transitive[XPATH_MAXLEN];
6259
6260 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6261
6262 snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6263 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6264 xpath);
6265 snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6266 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6267 xpath);
6268 snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6269 "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6270 xpath);
6271
6272 if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6273 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6274 "cumulative-bandwidth");
6275 else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6276 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6277 "computed-bandwidth");
6278 else {
6279 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6280 "explicit-bandwidth");
6281 nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6282 argv[idx_lb]->arg);
6283 }
6284
6285 if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
6286 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6287 "true");
6288 else
6289 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6290 "false");
6291
6292 return nb_cli_apply_changes(vty, NULL);
6293 }
6294
6295 DEFUN_YANG (no_set_ecommunity_lb,
6296 no_set_ecommunity_lb_cmd,
6297 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6298 NO_STR
6299 SET_STR
6300 "BGP extended community attribute\n"
6301 "Link bandwidth extended community\n"
6302 "Bandwidth value in Mbps\n"
6303 "Cumulative bandwidth of all multipaths (outbound-only)\n"
6304 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6305 "Attribute is set as non-transitive\n")
6306 {
6307 const char *xpath =
6308 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6309
6310 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6311 return nb_cli_apply_changes(vty, NULL);
6312 }
6313
6314 ALIAS_YANG (no_set_ecommunity_lb,
6315 no_set_ecommunity_lb_short_cmd,
6316 "no set extcommunity bandwidth",
6317 NO_STR
6318 SET_STR
6319 "BGP extended community attribute\n"
6320 "Link bandwidth extended community\n")
6321
6322 DEFUN_YANG (set_origin,
6323 set_origin_cmd,
6324 "set origin <egp|igp|incomplete>",
6325 SET_STR
6326 "BGP origin code\n"
6327 "remote EGP\n"
6328 "local IGP\n"
6329 "unknown heritage\n")
6330 {
6331 int idx_origin = 2;
6332 const char *origin_type;
6333 const char *xpath =
6334 "./set-action[action='frr-bgp-route-map:set-origin']";
6335 char xpath_value[XPATH_MAXLEN];
6336
6337 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6338 origin_type = "igp";
6339 else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6340 origin_type = "egp";
6341 else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6342 origin_type = "incomplete";
6343 else {
6344 vty_out(vty, "%% Invalid match origin type\n");
6345 return CMD_WARNING_CONFIG_FAILED;
6346 }
6347
6348 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6349 snprintf(xpath_value, sizeof(xpath_value),
6350 "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6351 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
6352
6353 return nb_cli_apply_changes(vty, NULL);
6354 }
6355
6356 DEFUN_YANG (no_set_origin,
6357 no_set_origin_cmd,
6358 "no set origin [<egp|igp|incomplete>]",
6359 NO_STR
6360 SET_STR
6361 "BGP origin code\n"
6362 "remote EGP\n"
6363 "local IGP\n"
6364 "unknown heritage\n")
6365 {
6366 const char *xpath =
6367 "./set-action[action='frr-bgp-route-map:set-origin']";
6368
6369 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6370 return nb_cli_apply_changes(vty, NULL);
6371 }
6372
6373 DEFUN_YANG (set_atomic_aggregate,
6374 set_atomic_aggregate_cmd,
6375 "set atomic-aggregate",
6376 SET_STR
6377 "BGP atomic aggregate attribute\n" )
6378 {
6379 const char *xpath =
6380 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6381 char xpath_value[XPATH_MAXLEN];
6382
6383 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6384 snprintf(xpath_value, sizeof(xpath_value),
6385 "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6386 xpath);
6387 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
6388
6389 return nb_cli_apply_changes(vty, NULL);
6390 }
6391
6392 DEFUN_YANG (no_set_atomic_aggregate,
6393 no_set_atomic_aggregate_cmd,
6394 "no set atomic-aggregate",
6395 NO_STR
6396 SET_STR
6397 "BGP atomic aggregate attribute\n" )
6398 {
6399 const char *xpath =
6400 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6401
6402 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6403 return nb_cli_apply_changes(vty, NULL);
6404 }
6405
6406 DEFPY_YANG (set_aigp_metric,
6407 set_aigp_metric_cmd,
6408 "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
6409 SET_STR
6410 "BGP AIGP attribute (AIGP Metric TLV)\n"
6411 "AIGP Metric value from IGP protocol\n"
6412 "Manual AIGP Metric value\n")
6413 {
6414 const char *xpath =
6415 "./set-action[action='frr-bgp-route-map:aigp-metric']";
6416 char xpath_value[XPATH_MAXLEN];
6417
6418 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6419 snprintf(xpath_value, sizeof(xpath_value),
6420 "%s/rmap-set-action/frr-bgp-route-map:aigp-metric", xpath);
6421 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, aigp_metric);
6422
6423 return nb_cli_apply_changes(vty, NULL);
6424 }
6425
6426 DEFPY_YANG (no_set_aigp_metric,
6427 no_set_aigp_metric_cmd,
6428 "no set aigp-metric [<igp-metric|(1-4294967295)>]",
6429 NO_STR
6430 SET_STR
6431 "BGP AIGP attribute (AIGP Metric TLV)\n"
6432 "AIGP Metric value from IGP protocol\n"
6433 "Manual AIGP Metric value\n")
6434 {
6435 const char *xpath =
6436 "./set-action[action='frr-bgp-route-map:aigp-metric']";
6437
6438 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6439 return nb_cli_apply_changes(vty, NULL);
6440 }
6441
6442 DEFUN_YANG (set_aggregator_as,
6443 set_aggregator_as_cmd,
6444 "set aggregator as (1-4294967295) A.B.C.D",
6445 SET_STR
6446 "BGP aggregator attribute\n"
6447 "AS number of aggregator\n"
6448 "AS number\n"
6449 "IP address of aggregator\n")
6450 {
6451 int idx_number = 3;
6452 int idx_ipv4 = 4;
6453 char xpath_asn[XPATH_MAXLEN];
6454 char xpath_addr[XPATH_MAXLEN];
6455 const char *xpath =
6456 "./set-action[action='frr-bgp-route-map:aggregator']";
6457
6458 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6459
6460 snprintf(
6461 xpath_asn, sizeof(xpath_asn),
6462 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6463 xpath);
6464 nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6465 argv[idx_number]->arg);
6466
6467 snprintf(
6468 xpath_addr, sizeof(xpath_addr),
6469 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6470 xpath);
6471 nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6472 argv[idx_ipv4]->arg);
6473
6474 return nb_cli_apply_changes(vty, NULL);
6475 }
6476
6477 DEFUN_YANG (no_set_aggregator_as,
6478 no_set_aggregator_as_cmd,
6479 "no set aggregator as [(1-4294967295) A.B.C.D]",
6480 NO_STR
6481 SET_STR
6482 "BGP aggregator attribute\n"
6483 "AS number of aggregator\n"
6484 "AS number\n"
6485 "IP address of aggregator\n")
6486 {
6487 const char *xpath =
6488 "./set-action[action='frr-bgp-route-map:aggregator']";
6489
6490 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6491 return nb_cli_apply_changes(vty, NULL);
6492 }
6493
6494 DEFUN_YANG (match_ipv6_next_hop,
6495 match_ipv6_next_hop_cmd,
6496 "match ipv6 next-hop ACCESSLIST6_NAME",
6497 MATCH_STR
6498 IPV6_STR
6499 "Match IPv6 next-hop address of route\n"
6500 "IPv6 access-list name\n")
6501 {
6502 const char *xpath =
6503 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6504 char xpath_value[XPATH_MAXLEN];
6505
6506 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6507 snprintf(xpath_value, sizeof(xpath_value),
6508 "%s/rmap-match-condition/list-name", xpath);
6509 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6510 argv[argc - 1]->arg);
6511
6512 return nb_cli_apply_changes(vty, NULL);
6513 }
6514
6515 DEFUN_YANG (no_match_ipv6_next_hop,
6516 no_match_ipv6_next_hop_cmd,
6517 "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6518 NO_STR
6519 MATCH_STR
6520 IPV6_STR
6521 "Match IPv6 next-hop address of route\n"
6522 "IPv6 access-list name\n")
6523 {
6524 const char *xpath =
6525 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6526
6527 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6528 return nb_cli_apply_changes(vty, NULL);
6529 }
6530
6531 DEFUN_YANG (match_ipv6_next_hop_address,
6532 match_ipv6_next_hop_address_cmd,
6533 "match ipv6 next-hop address X:X::X:X",
6534 MATCH_STR
6535 IPV6_STR
6536 "Match IPv6 next-hop address of route\n"
6537 "IPv6 address\n"
6538 "IPv6 address of next hop\n")
6539 {
6540 const char *xpath =
6541 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6542 char xpath_value[XPATH_MAXLEN];
6543
6544 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6545 snprintf(xpath_value, sizeof(xpath_value),
6546 "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6547 xpath);
6548 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6549 argv[argc - 1]->arg);
6550
6551 return nb_cli_apply_changes(vty, NULL);
6552 }
6553
6554 DEFUN_YANG (no_match_ipv6_next_hop_address,
6555 no_match_ipv6_next_hop_address_cmd,
6556 "no match ipv6 next-hop address X:X::X:X",
6557 NO_STR
6558 MATCH_STR
6559 IPV6_STR
6560 "Match IPv6 next-hop address of route\n"
6561 "IPv6 address\n"
6562 "IPv6 address of next hop\n")
6563 {
6564 const char *xpath =
6565 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6566
6567 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6568 return nb_cli_apply_changes(vty, NULL);
6569 }
6570
6571 ALIAS_HIDDEN (match_ipv6_next_hop_address,
6572 match_ipv6_next_hop_old_cmd,
6573 "match ipv6 next-hop X:X::X:X",
6574 MATCH_STR
6575 IPV6_STR
6576 "Match IPv6 next-hop address of route\n"
6577 "IPv6 address of next hop\n")
6578
6579 ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
6580 no_match_ipv6_next_hop_old_cmd,
6581 "no match ipv6 next-hop X:X::X:X",
6582 NO_STR
6583 MATCH_STR
6584 IPV6_STR
6585 "Match IPv6 next-hop address of route\n"
6586 "IPv6 address of next hop\n")
6587
6588 DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6589 match_ipv6_next_hop_prefix_list_cmd,
6590 "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6591 MATCH_STR
6592 IPV6_STR
6593 "Match IPv6 next-hop address of route\n"
6594 "Match entries by prefix-list\n"
6595 "IPv6 prefix-list name\n")
6596 {
6597 const char *xpath =
6598 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6599 char xpath_value[XPATH_MAXLEN];
6600
6601 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6602 snprintf(xpath_value, sizeof(xpath_value),
6603 "%s/rmap-match-condition/list-name", xpath);
6604 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6605 argv[argc - 1]->arg);
6606
6607 return nb_cli_apply_changes(vty, NULL);
6608 }
6609
6610 DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6611 no_match_ipv6_next_hop_prefix_list_cmd,
6612 "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6613 NO_STR
6614 MATCH_STR
6615 IPV6_STR
6616 "Match IPv6 next-hop address of route\n"
6617 "Match entries by prefix-list\n"
6618 "IPv6 prefix-list name\n")
6619 {
6620 const char *xpath =
6621 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6622
6623 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6624 return nb_cli_apply_changes(vty, NULL);
6625 }
6626
6627 DEFPY_YANG (match_ipv4_next_hop,
6628 match_ipv4_next_hop_cmd,
6629 "match ip next-hop address A.B.C.D",
6630 MATCH_STR
6631 IP_STR
6632 "Match IP next-hop address of route\n"
6633 "IP address\n"
6634 "IP address of next-hop\n")
6635 {
6636 const char *xpath =
6637 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6638 char xpath_value[XPATH_MAXLEN];
6639
6640 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6641 snprintf(xpath_value, sizeof(xpath_value),
6642 "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6643 xpath);
6644 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
6645
6646 return nb_cli_apply_changes(vty, NULL);
6647 }
6648
6649 DEFPY_YANG (no_match_ipv4_next_hop,
6650 no_match_ipv4_next_hop_cmd,
6651 "no match ip next-hop address [A.B.C.D]",
6652 NO_STR
6653 MATCH_STR
6654 IP_STR
6655 "Match IP next-hop address of route\n"
6656 "IP address\n"
6657 "IP address of next-hop\n")
6658 {
6659 const char *xpath =
6660 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6661
6662 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6663 return nb_cli_apply_changes(vty, NULL);
6664 }
6665
6666 DEFUN_YANG (set_ipv6_nexthop_peer,
6667 set_ipv6_nexthop_peer_cmd,
6668 "set ipv6 next-hop peer-address",
6669 SET_STR
6670 IPV6_STR
6671 "Next hop address\n"
6672 "Use peer address (for BGP only)\n")
6673 {
6674 const char *xpath =
6675 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6676 char xpath_value[XPATH_MAXLEN];
6677
6678 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6679 snprintf(xpath_value, sizeof(xpath_value),
6680 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6681 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6682
6683 return nb_cli_apply_changes(vty, NULL);
6684 }
6685
6686 DEFUN_YANG (no_set_ipv6_nexthop_peer,
6687 no_set_ipv6_nexthop_peer_cmd,
6688 "no set ipv6 next-hop peer-address",
6689 NO_STR
6690 SET_STR
6691 IPV6_STR
6692 "IPv6 next-hop address\n"
6693 "Use peer address (for BGP only)\n")
6694 {
6695 const char *xpath =
6696 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6697
6698 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6699 return nb_cli_apply_changes(vty, NULL);
6700 }
6701
6702 DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6703 set_ipv6_nexthop_prefer_global_cmd,
6704 "set ipv6 next-hop prefer-global",
6705 SET_STR
6706 IPV6_STR
6707 "IPv6 next-hop address\n"
6708 "Prefer global over link-local if both exist\n")
6709 {
6710 const char *xpath =
6711 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6712 char xpath_value[XPATH_MAXLEN];
6713
6714 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6715 snprintf(xpath_value, sizeof(xpath_value),
6716 "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6717 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6718
6719 return nb_cli_apply_changes(vty, NULL);
6720 }
6721
6722 DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6723 no_set_ipv6_nexthop_prefer_global_cmd,
6724 "no set ipv6 next-hop prefer-global",
6725 NO_STR
6726 SET_STR
6727 IPV6_STR
6728 "IPv6 next-hop address\n"
6729 "Prefer global over link-local if both exist\n")
6730 {
6731 const char *xpath =
6732 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6733
6734 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6735 return nb_cli_apply_changes(vty, NULL);
6736 }
6737
6738 DEFUN_YANG (set_ipv6_nexthop_global,
6739 set_ipv6_nexthop_global_cmd,
6740 "set ipv6 next-hop global X:X::X:X",
6741 SET_STR
6742 IPV6_STR
6743 "IPv6 next-hop address\n"
6744 "IPv6 global address\n"
6745 "IPv6 address of next hop\n")
6746 {
6747 int idx_ipv6 = 4;
6748 const char *xpath =
6749 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6750 char xpath_value[XPATH_MAXLEN];
6751
6752 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6753 snprintf(xpath_value, sizeof(xpath_value),
6754 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6755 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6756 argv[idx_ipv6]->arg);
6757
6758 return nb_cli_apply_changes(vty, NULL);
6759 }
6760
6761 DEFUN_YANG (no_set_ipv6_nexthop_global,
6762 no_set_ipv6_nexthop_global_cmd,
6763 "no set ipv6 next-hop global X:X::X:X",
6764 NO_STR
6765 SET_STR
6766 IPV6_STR
6767 "IPv6 next-hop address\n"
6768 "IPv6 global address\n"
6769 "IPv6 address of next hop\n")
6770 {
6771 const char *xpath =
6772 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6773
6774 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6775 return nb_cli_apply_changes(vty, NULL);
6776 }
6777
6778 #ifdef KEEP_OLD_VPN_COMMANDS
6779 DEFUN_YANG (set_vpn_nexthop,
6780 set_vpn_nexthop_cmd,
6781 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6782 SET_STR
6783 "VPNv4 information\n"
6784 "VPN next-hop address\n"
6785 "IP address of next hop\n"
6786 "VPNv6 information\n"
6787 "VPN next-hop address\n"
6788 "IPv6 address of next hop\n")
6789 {
6790 int idx_ip = 3;
6791 afi_t afi;
6792 int idx = 0;
6793 char xpath_value[XPATH_MAXLEN];
6794
6795 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
6796 if (afi == AFI_IP) {
6797 const char *xpath =
6798 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6799
6800 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6801 snprintf(
6802 xpath_value, sizeof(xpath_value),
6803 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6804 xpath);
6805 } else {
6806 const char *xpath =
6807 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6808
6809 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6810 snprintf(
6811 xpath_value, sizeof(xpath_value),
6812 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6813 xpath);
6814 }
6815
6816 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6817 argv[idx_ip]->arg);
6818
6819 return nb_cli_apply_changes(vty, NULL);
6820 }
6821
6822 return CMD_SUCCESS;
6823 }
6824
6825 DEFUN_YANG (no_set_vpn_nexthop,
6826 no_set_vpn_nexthop_cmd,
6827 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6828 NO_STR
6829 SET_STR
6830 "VPNv4 information\n"
6831 "VPN next-hop address\n"
6832 "IP address of next hop\n"
6833 "VPNv6 information\n"
6834 "VPN next-hop address\n"
6835 "IPv6 address of next hop\n")
6836 {
6837 afi_t afi;
6838 int idx = 0;
6839
6840 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
6841 if (afi == AFI_IP) {
6842 const char *xpath =
6843 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6844 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6845 } else {
6846 const char *xpath =
6847 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6848 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6849 }
6850 return nb_cli_apply_changes(vty, NULL);
6851 }
6852 return CMD_SUCCESS;
6853 }
6854 #endif /* KEEP_OLD_VPN_COMMANDS */
6855
6856 DEFPY_YANG (set_ipx_vpn_nexthop,
6857 set_ipx_vpn_nexthop_cmd,
6858 "set <ipv4|ipv6> vpn next-hop <A.B.C.D$addrv4|X:X::X:X$addrv6>",
6859 SET_STR
6860 "IPv4 information\n"
6861 "IPv6 information\n"
6862 "VPN information\n"
6863 "VPN next-hop address\n"
6864 "IP address of next hop\n"
6865 "IPv6 address of next hop\n")
6866 {
6867 int idx_ip = 4;
6868 afi_t afi;
6869 int idx = 0;
6870 char xpath_value[XPATH_MAXLEN];
6871
6872 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
6873 if (afi == AFI_IP) {
6874 if (addrv6_str) {
6875 vty_out(vty, "%% IPv4 next-hop expected\n");
6876 return CMD_WARNING_CONFIG_FAILED;
6877 }
6878
6879 const char *xpath =
6880 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6881
6882 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6883 snprintf(
6884 xpath_value, sizeof(xpath_value),
6885 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6886 xpath);
6887 } else {
6888 if (addrv4_str) {
6889 vty_out(vty, "%% IPv6 next-hop expected\n");
6890 return CMD_WARNING_CONFIG_FAILED;
6891 }
6892
6893 const char *xpath =
6894 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6895
6896 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6897 snprintf(
6898 xpath_value, sizeof(xpath_value),
6899 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6900 xpath);
6901 }
6902 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6903 argv[idx_ip]->arg);
6904 return nb_cli_apply_changes(vty, NULL);
6905 }
6906 return CMD_SUCCESS;
6907 }
6908
6909 DEFUN_YANG (no_set_ipx_vpn_nexthop,
6910 no_set_ipx_vpn_nexthop_cmd,
6911 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
6912 NO_STR
6913 SET_STR
6914 "IPv4 information\n"
6915 "IPv6 information\n"
6916 "VPN information\n"
6917 "VPN next-hop address\n"
6918 "IP address of next hop\n"
6919 "IPv6 address of next hop\n")
6920 {
6921 afi_t afi;
6922 int idx = 0;
6923
6924 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
6925 if (afi == AFI_IP) {
6926 const char *xpath =
6927 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6928 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6929 } else {
6930 const char *xpath =
6931 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6932 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6933 }
6934 return nb_cli_apply_changes(vty, NULL);
6935 }
6936 return CMD_SUCCESS;
6937 }
6938
6939 DEFUN_YANG (set_originator_id,
6940 set_originator_id_cmd,
6941 "set originator-id A.B.C.D",
6942 SET_STR
6943 "BGP originator ID attribute\n"
6944 "IP address of originator\n")
6945 {
6946 int idx_ipv4 = 2;
6947 const char *xpath =
6948 "./set-action[action='frr-bgp-route-map:originator-id']";
6949 char xpath_value[XPATH_MAXLEN];
6950
6951 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6952 snprintf(xpath_value, sizeof(xpath_value),
6953 "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
6954 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6955 argv[idx_ipv4]->arg);
6956
6957 return nb_cli_apply_changes(vty, NULL);
6958 }
6959
6960 DEFUN_YANG (no_set_originator_id,
6961 no_set_originator_id_cmd,
6962 "no set originator-id [A.B.C.D]",
6963 NO_STR
6964 SET_STR
6965 "BGP originator ID attribute\n"
6966 "IP address of originator\n")
6967 {
6968 const char *xpath =
6969 "./set-action[action='frr-bgp-route-map:originator-id']";
6970
6971 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6972 return nb_cli_apply_changes(vty, NULL);
6973 }
6974
6975 DEFPY_YANG (match_rpki_extcommunity,
6976 match_rpki_extcommunity_cmd,
6977 "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
6978 NO_STR
6979 MATCH_STR
6980 "BGP RPKI (Origin Validation State) extended community attribute\n"
6981 "Valid prefix\n"
6982 "Invalid prefix\n"
6983 "Prefix not found\n")
6984 {
6985 const char *xpath =
6986 "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
6987 char xpath_value[XPATH_MAXLEN];
6988
6989 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6990
6991 if (!no) {
6992 snprintf(
6993 xpath_value, sizeof(xpath_value),
6994 "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
6995 xpath);
6996 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6997 argv[2]->arg);
6998 }
6999
7000 return nb_cli_apply_changes(vty, NULL);
7001 }
7002
7003 /* Initialization of route map. */
7004 void bgp_route_map_init(void)
7005 {
7006 route_map_init();
7007
7008 route_map_add_hook(bgp_route_map_add);
7009 route_map_delete_hook(bgp_route_map_delete);
7010 route_map_event_hook(bgp_route_map_event);
7011
7012 route_map_match_interface_hook(generic_match_add);
7013 route_map_no_match_interface_hook(generic_match_delete);
7014
7015 route_map_match_ip_address_hook(generic_match_add);
7016 route_map_no_match_ip_address_hook(generic_match_delete);
7017
7018 route_map_match_ip_address_prefix_list_hook(generic_match_add);
7019 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
7020
7021 route_map_match_ip_next_hop_hook(generic_match_add);
7022 route_map_no_match_ip_next_hop_hook(generic_match_delete);
7023
7024 route_map_match_ipv6_next_hop_hook(generic_match_add);
7025 route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
7026
7027 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
7028 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
7029
7030 route_map_match_ip_next_hop_type_hook(generic_match_add);
7031 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
7032
7033 route_map_match_ipv6_address_hook(generic_match_add);
7034 route_map_no_match_ipv6_address_hook(generic_match_delete);
7035
7036 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
7037 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
7038
7039 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
7040 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
7041
7042 route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
7043 route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
7044
7045 route_map_match_metric_hook(generic_match_add);
7046 route_map_no_match_metric_hook(generic_match_delete);
7047
7048 route_map_match_tag_hook(generic_match_add);
7049 route_map_no_match_tag_hook(generic_match_delete);
7050
7051 route_map_set_srte_color_hook(generic_set_add);
7052 route_map_no_set_srte_color_hook(generic_set_delete);
7053
7054 route_map_set_ip_nexthop_hook(generic_set_add);
7055 route_map_no_set_ip_nexthop_hook(generic_set_delete);
7056
7057 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
7058 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
7059
7060 route_map_set_metric_hook(generic_set_add);
7061 route_map_no_set_metric_hook(generic_set_delete);
7062
7063 route_map_set_tag_hook(generic_set_add);
7064 route_map_no_set_tag_hook(generic_set_delete);
7065
7066 route_map_install_match(&route_match_peer_cmd);
7067 route_map_install_match(&route_match_alias_cmd);
7068 route_map_install_match(&route_match_local_pref_cmd);
7069 #ifdef HAVE_SCRIPTING
7070 route_map_install_match(&route_match_script_cmd);
7071 #endif
7072 route_map_install_match(&route_match_ip_address_cmd);
7073 route_map_install_match(&route_match_ip_next_hop_cmd);
7074 route_map_install_match(&route_match_ip_route_source_cmd);
7075 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
7076 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
7077 route_map_install_match(&route_match_ip_next_hop_type_cmd);
7078 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
7079 route_map_install_match(&route_match_aspath_cmd);
7080 route_map_install_match(&route_match_community_cmd);
7081 route_map_install_match(&route_match_lcommunity_cmd);
7082 route_map_install_match(&route_match_ecommunity_cmd);
7083 route_map_install_match(&route_match_local_pref_cmd);
7084 route_map_install_match(&route_match_metric_cmd);
7085 route_map_install_match(&route_match_origin_cmd);
7086 route_map_install_match(&route_match_probability_cmd);
7087 route_map_install_match(&route_match_interface_cmd);
7088 route_map_install_match(&route_match_tag_cmd);
7089 route_map_install_match(&route_match_mac_address_cmd);
7090 route_map_install_match(&route_match_evpn_vni_cmd);
7091 route_map_install_match(&route_match_evpn_route_type_cmd);
7092 route_map_install_match(&route_match_evpn_rd_cmd);
7093 route_map_install_match(&route_match_evpn_default_route_cmd);
7094 route_map_install_match(&route_match_vrl_source_vrf_cmd);
7095
7096 route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
7097 route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
7098 route_map_install_set(&route_set_table_id_cmd);
7099 route_map_install_set(&route_set_srte_color_cmd);
7100 route_map_install_set(&route_set_ip_nexthop_cmd);
7101 route_map_install_set(&route_set_local_pref_cmd);
7102 route_map_install_set(&route_set_weight_cmd);
7103 route_map_install_set(&route_set_label_index_cmd);
7104 route_map_install_set(&route_set_metric_cmd);
7105 route_map_install_set(&route_set_distance_cmd);
7106 route_map_install_set(&route_set_aspath_prepend_cmd);
7107 route_map_install_set(&route_set_aspath_exclude_cmd);
7108 route_map_install_set(&route_set_aspath_replace_cmd);
7109 route_map_install_set(&route_set_origin_cmd);
7110 route_map_install_set(&route_set_atomic_aggregate_cmd);
7111 route_map_install_set(&route_set_aigp_metric_cmd);
7112 route_map_install_set(&route_set_aggregator_as_cmd);
7113 route_map_install_set(&route_set_community_cmd);
7114 route_map_install_set(&route_set_community_delete_cmd);
7115 route_map_install_set(&route_set_lcommunity_cmd);
7116 route_map_install_set(&route_set_lcommunity_delete_cmd);
7117 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
7118 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
7119 route_map_install_set(&route_set_originator_id_cmd);
7120 route_map_install_set(&route_set_ecommunity_rt_cmd);
7121 route_map_install_set(&route_set_ecommunity_soo_cmd);
7122 route_map_install_set(&route_set_ecommunity_lb_cmd);
7123 route_map_install_set(&route_set_ecommunity_none_cmd);
7124 route_map_install_set(&route_set_tag_cmd);
7125 route_map_install_set(&route_set_label_index_cmd);
7126 route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
7127
7128 install_element(RMAP_NODE, &match_peer_cmd);
7129 install_element(RMAP_NODE, &match_peer_local_cmd);
7130 install_element(RMAP_NODE, &no_match_peer_cmd);
7131 install_element(RMAP_NODE, &match_ip_route_source_cmd);
7132 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
7133 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
7134 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
7135 install_element(RMAP_NODE, &match_mac_address_cmd);
7136 install_element(RMAP_NODE, &no_match_mac_address_cmd);
7137 install_element(RMAP_NODE, &match_evpn_vni_cmd);
7138 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
7139 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
7140 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
7141 install_element(RMAP_NODE, &match_evpn_rd_cmd);
7142 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
7143 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
7144 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
7145 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
7146 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
7147 install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
7148 install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
7149 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
7150 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
7151
7152 install_element(RMAP_NODE, &match_aspath_cmd);
7153 install_element(RMAP_NODE, &no_match_aspath_cmd);
7154 install_element(RMAP_NODE, &match_local_pref_cmd);
7155 install_element(RMAP_NODE, &no_match_local_pref_cmd);
7156 install_element(RMAP_NODE, &match_alias_cmd);
7157 install_element(RMAP_NODE, &no_match_alias_cmd);
7158 install_element(RMAP_NODE, &match_community_cmd);
7159 install_element(RMAP_NODE, &no_match_community_cmd);
7160 install_element(RMAP_NODE, &match_lcommunity_cmd);
7161 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
7162 install_element(RMAP_NODE, &match_ecommunity_cmd);
7163 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
7164 install_element(RMAP_NODE, &match_origin_cmd);
7165 install_element(RMAP_NODE, &no_match_origin_cmd);
7166 install_element(RMAP_NODE, &match_probability_cmd);
7167 install_element(RMAP_NODE, &no_match_probability_cmd);
7168
7169 install_element(RMAP_NODE, &no_set_table_id_cmd);
7170 install_element(RMAP_NODE, &set_table_id_cmd);
7171 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
7172 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
7173 install_element(RMAP_NODE, &set_local_pref_cmd);
7174 install_element(RMAP_NODE, &set_distance_cmd);
7175 install_element(RMAP_NODE, &no_set_distance_cmd);
7176 install_element(RMAP_NODE, &no_set_local_pref_cmd);
7177 install_element(RMAP_NODE, &set_weight_cmd);
7178 install_element(RMAP_NODE, &set_label_index_cmd);
7179 install_element(RMAP_NODE, &no_set_weight_cmd);
7180 install_element(RMAP_NODE, &no_set_label_index_cmd);
7181 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
7182 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
7183 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
7184 install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
7185 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
7186 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
7187 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
7188 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
7189 install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
7190 install_element(RMAP_NODE, &set_origin_cmd);
7191 install_element(RMAP_NODE, &no_set_origin_cmd);
7192 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
7193 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
7194 install_element(RMAP_NODE, &set_aigp_metric_cmd);
7195 install_element(RMAP_NODE, &no_set_aigp_metric_cmd);
7196 install_element(RMAP_NODE, &set_aggregator_as_cmd);
7197 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
7198 install_element(RMAP_NODE, &set_community_cmd);
7199 install_element(RMAP_NODE, &set_community_none_cmd);
7200 install_element(RMAP_NODE, &no_set_community_cmd);
7201 install_element(RMAP_NODE, &no_set_community_short_cmd);
7202 install_element(RMAP_NODE, &set_community_delete_cmd);
7203 install_element(RMAP_NODE, &no_set_community_delete_cmd);
7204 install_element(RMAP_NODE, &set_lcommunity_cmd);
7205 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
7206 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
7207 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
7208 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
7209 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
7210 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
7211 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
7212 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
7213 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
7214 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
7215 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
7216 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
7217 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
7218 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
7219 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
7220 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
7221 install_element(RMAP_NODE, &set_ecommunity_none_cmd);
7222 install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
7223 #ifdef KEEP_OLD_VPN_COMMANDS
7224 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
7225 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
7226 #endif /* KEEP_OLD_VPN_COMMANDS */
7227 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
7228 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
7229 install_element(RMAP_NODE, &set_originator_id_cmd);
7230 install_element(RMAP_NODE, &no_set_originator_id_cmd);
7231 install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
7232
7233 route_map_install_match(&route_match_ipv6_address_cmd);
7234 route_map_install_match(&route_match_ipv6_next_hop_cmd);
7235 route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
7236 route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
7237 route_map_install_match(&route_match_ipv4_next_hop_cmd);
7238 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
7239 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
7240 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
7241 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
7242 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
7243 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
7244 route_map_install_match(&route_match_rpki_extcommunity_cmd);
7245
7246 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
7247 install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
7248 install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
7249 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
7250 install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
7251 install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
7252 install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
7253 install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
7254 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
7255 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
7256 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
7257 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
7258 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
7259 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
7260 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
7261 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
7262 install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
7263 #ifdef HAVE_SCRIPTING
7264 install_element(RMAP_NODE, &match_script_cmd);
7265 #endif
7266 }
7267
7268 void bgp_route_map_terminate(void)
7269 {
7270 /* ToDo: Cleanup all the used memory */
7271 route_map_finish();
7272 }