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