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