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