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