1 /* Route map function of bgpd.
2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #ifdef HAVE_LIBPCREPOSIX
32 #include <pcreposix.h>
35 #endif /* HAVE_LIBPCREPOSIX */
37 #include "sockunion.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_attr.h"
45 #include "bgpd/bgp_aspath.h"
46 #include "bgpd/bgp_packet.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_zebra.h"
49 #include "bgpd/bgp_regex.h"
50 #include "bgpd/bgp_community.h"
51 #include "bgpd/bgp_clist.h"
52 #include "bgpd/bgp_filter.h"
53 #include "bgpd/bgp_mplsvpn.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_vty.h"
57 #include "bgpd/bgp_debug.h"
58 #include "bgpd/bgp_evpn.h"
59 #include "bgpd/bgp_evpn_private.h"
60 #include "bgpd/bgp_evpn_vty.h"
61 #include "bgpd/bgp_mplsvpn.h"
64 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
67 /* Memo of route-map commands.
76 ip route-source : Done
80 ipv6 route-source: (This will not be implemented by bgpd)
81 ipv6 prefix-list : Done
82 length : (This will not be implemented by bgpd)
84 route-type : (This will not be implemented by bgpd)
86 local-preference : Done
88 set as-path prepend : Done
90 automatic-tag : (This will not be implemented by bgpd)
92 large-community : Done
93 large-comm-list : Done
96 default : (This will not be implemented by bgpd)
97 interface : (This will not be implemented by bgpd)
98 ip default : (This will not be implemented by bgpd)
100 ip precedence : (This will not be implemented by bgpd)
101 ip tos : (This will not be implemented by bgpd)
102 level : (This will not be implemented by bgpd)
103 local-preference : Done
105 metric-type : Not yet
112 set ipv6 next-hop global: Done
113 set ipv6 next-hop prefer-global: Done
114 set ipv6 next-hop local : Done
115 set as-path exclude : Done
119 /* generic value manipulation to be shared in multiple rules */
121 #define RMAP_VALUE_SET 0
122 #define RMAP_VALUE_ADD 1
123 #define RMAP_VALUE_SUB 2
131 static int route_value_match(struct rmap_value
*rv
, uint32_t value
)
133 if (rv
->variable
== 0 && value
== rv
->value
)
139 static uint32_t route_value_adjust(struct rmap_value
*rv
, uint32_t current
,
144 switch (rv
->variable
) {
153 switch (rv
->action
) {
155 if (current
> UINT32_MAX
- value
)
157 return current
+ value
;
159 if (current
<= value
)
161 return current
- value
;
167 static void *route_value_compile(const char *arg
)
169 uint8_t action
= RMAP_VALUE_SET
, var
= 0;
170 unsigned long larg
= 0;
172 struct rmap_value
*rv
;
175 action
= RMAP_VALUE_ADD
;
177 } else if (arg
[0] == '-') {
178 action
= RMAP_VALUE_SUB
;
182 if (all_digit(arg
)) {
184 larg
= strtoul(arg
, &endptr
, 10);
185 if (*arg
== 0 || *endptr
!= 0 || errno
|| larg
> UINT32_MAX
)
188 if (strcmp(arg
, "rtt") == 0)
194 rv
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_value
));
204 static void route_value_free(void *rule
)
206 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
209 /* generic as path object to be shared in multiple rules */
211 static void *route_aspath_compile(const char *arg
)
213 struct aspath
*aspath
;
215 aspath
= aspath_str2aspath(arg
);
221 static void route_aspath_free(void *rule
)
223 struct aspath
*aspath
= rule
;
227 struct bgp_match_peer_compiled
{
232 /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
234 /* Compares the peer specified in the 'match peer' clause with the peer
235 received in bgp_info->peer. If it is the same, or if the peer structure
236 received is a peer_group containing it, returns RMAP_MATCH. */
237 static route_map_result_t
route_match_peer(void *rule
,
238 const struct prefix
*prefix
,
239 route_map_object_t type
,
242 struct bgp_match_peer_compiled
*pc
;
244 union sockunion su_def
= {
245 .sin
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= INADDR_ANY
}};
246 struct peer_group
*group
;
248 struct listnode
*node
, *nnode
;
250 if (type
== RMAP_BGP
) {
253 peer
= ((struct bgp_info
*)object
)->peer
;
259 if (strcmp(peer
->conf_if
, pc
->interface
) == 0)
265 /* If su='0.0.0.0' (command 'match peer local'), and it's a
267 REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH
269 if (sockunion_same(su
, &su_def
)) {
271 if (CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_NETWORK
)
272 || CHECK_FLAG(peer
->rmap_type
,
273 PEER_RMAP_TYPE_REDISTRIBUTE
)
274 || CHECK_FLAG(peer
->rmap_type
,
275 PEER_RMAP_TYPE_DEFAULT
))
282 if (!CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
283 if (sockunion_same(su
, &peer
->su
))
289 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
,
291 if (sockunion_same(su
, &peer
->su
))
300 static void *route_match_peer_compile(const char *arg
)
302 struct bgp_match_peer_compiled
*pc
;
305 pc
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
,
306 sizeof(struct bgp_match_peer_compiled
));
308 ret
= str2sockunion(strcmp(arg
, "local") ? arg
: "0.0.0.0", &pc
->su
);
310 pc
->interface
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
317 /* Free route map's compiled `ip address' value. */
318 static void route_match_peer_free(void *rule
)
320 struct bgp_match_peer_compiled
*pc
= rule
;
323 XFREE(MTYPE_ROUTE_MAP_COMPILED
, pc
->interface
);
325 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
328 /* Route map commands for ip address matching. */
329 struct route_map_rule_cmd route_match_peer_cmd
= {"peer", route_match_peer
,
330 route_match_peer_compile
,
331 route_match_peer_free
};
333 /* `match ip address IP_ACCESS_LIST' */
335 /* Match function should return 1 if match is success else return
337 static route_map_result_t
route_match_ip_address(void *rule
,
338 const struct prefix
*prefix
,
339 route_map_object_t type
,
342 struct access_list
*alist
;
344 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
345 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
349 return (access_list_apply(alist
, prefix
) == FILTER_DENY
356 /* Route map `ip address' match statement. `arg' should be
358 static void *route_match_ip_address_compile(const char *arg
)
360 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
363 /* Free route map's compiled `ip address' value. */
364 static void route_match_ip_address_free(void *rule
)
366 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
369 /* Route map commands for ip address matching. */
370 struct route_map_rule_cmd route_match_ip_address_cmd
= {
371 "ip address", route_match_ip_address
, route_match_ip_address_compile
,
372 route_match_ip_address_free
};
374 /* `match ip next-hop IP_ADDRESS' */
376 /* Match function return 1 if match is success else return zero. */
377 static route_map_result_t
route_match_ip_next_hop(void *rule
,
378 const struct prefix
*prefix
,
379 route_map_object_t type
,
382 struct access_list
*alist
;
383 struct bgp_info
*bgp_info
;
384 struct prefix_ipv4 p
;
386 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
389 p
.prefix
= bgp_info
->attr
->nexthop
;
390 p
.prefixlen
= IPV4_MAX_BITLEN
;
392 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
396 return (access_list_apply(alist
, &p
) == FILTER_DENY
403 /* Route map `ip next-hop' match statement. `arg' is
405 static void *route_match_ip_next_hop_compile(const char *arg
)
407 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
410 /* Free route map's compiled `ip address' value. */
411 static void route_match_ip_next_hop_free(void *rule
)
413 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
416 /* Route map commands for ip next-hop matching. */
417 struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
418 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
419 route_match_ip_next_hop_free
};
421 /* `match ip route-source ACCESS-LIST' */
423 /* Match function return 1 if match is success else return zero. */
424 static route_map_result_t
route_match_ip_route_source(void *rule
,
425 const struct prefix
*pfx
,
426 route_map_object_t type
,
429 struct access_list
*alist
;
430 struct bgp_info
*bgp_info
;
432 struct prefix_ipv4 p
;
434 if (type
== RMAP_BGP
&& pfx
->family
== AF_INET
) {
436 peer
= bgp_info
->peer
;
438 if (!peer
|| sockunion_family(&peer
->su
) != AF_INET
)
442 p
.prefix
= peer
->su
.sin
.sin_addr
;
443 p
.prefixlen
= IPV4_MAX_BITLEN
;
445 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
449 return (access_list_apply(alist
, &p
) == FILTER_DENY
456 /* Route map `ip route-source' match statement. `arg' is
458 static void *route_match_ip_route_source_compile(const char *arg
)
460 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
463 /* Free route map's compiled `ip address' value. */
464 static void route_match_ip_route_source_free(void *rule
)
466 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
469 /* Route map commands for ip route-source matching. */
470 struct route_map_rule_cmd route_match_ip_route_source_cmd
= {
471 "ip route-source", route_match_ip_route_source
,
472 route_match_ip_route_source_compile
, route_match_ip_route_source_free
};
474 /* `match ip address prefix-list PREFIX_LIST' */
476 static route_map_result_t
477 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
478 route_map_object_t type
, void *object
)
480 struct prefix_list
*plist
;
482 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
483 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
487 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
494 static void *route_match_ip_address_prefix_list_compile(const char *arg
)
496 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
499 static void route_match_ip_address_prefix_list_free(void *rule
)
501 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
504 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
505 "ip address prefix-list", route_match_ip_address_prefix_list
,
506 route_match_ip_address_prefix_list_compile
,
507 route_match_ip_address_prefix_list_free
};
509 /* `match ip next-hop prefix-list PREFIX_LIST' */
511 static route_map_result_t
512 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
513 route_map_object_t type
, void *object
)
515 struct prefix_list
*plist
;
516 struct bgp_info
*bgp_info
;
517 struct prefix_ipv4 p
;
519 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
522 p
.prefix
= bgp_info
->attr
->nexthop
;
523 p
.prefixlen
= IPV4_MAX_BITLEN
;
525 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
529 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
536 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
538 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
541 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
543 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
546 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
547 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
548 route_match_ip_next_hop_prefix_list_compile
,
549 route_match_ip_next_hop_prefix_list_free
};
551 /* `match ip route-source prefix-list PREFIX_LIST' */
553 static route_map_result_t
554 route_match_ip_route_source_prefix_list(void *rule
,
555 const struct prefix
*prefix
,
556 route_map_object_t type
, void *object
)
558 struct prefix_list
*plist
;
559 struct bgp_info
*bgp_info
;
561 struct prefix_ipv4 p
;
563 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
565 peer
= bgp_info
->peer
;
567 if (!peer
|| sockunion_family(&peer
->su
) != AF_INET
)
571 p
.prefix
= peer
->su
.sin
.sin_addr
;
572 p
.prefixlen
= IPV4_MAX_BITLEN
;
574 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
578 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
585 static void *route_match_ip_route_source_prefix_list_compile(const char *arg
)
587 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
590 static void route_match_ip_route_source_prefix_list_free(void *rule
)
592 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
595 struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd
= {
596 "ip route-source prefix-list", route_match_ip_route_source_prefix_list
,
597 route_match_ip_route_source_prefix_list_compile
,
598 route_match_ip_route_source_prefix_list_free
};
600 /* `match evpn default-route' */
602 /* Match function should return 1 if match is success else 0 */
603 static route_map_result_t
route_match_evpn_default_route(void *rule
,
604 const struct prefix
*p
,
608 if (type
== RMAP_BGP
&& is_evpn_prefix_default(p
))
614 /* Route map commands for default-route matching. */
615 struct route_map_rule_cmd route_match_evpn_default_route_cmd
= {
616 "evpn default-route", route_match_evpn_default_route
, NULL
, NULL
};
618 /* `match mac address MAC_ACCESS_LIST' */
620 /* Match function should return 1 if match is success else return
622 static route_map_result_t
route_match_mac_address(void *rule
,
623 const struct prefix
*prefix
,
624 route_map_object_t type
,
627 struct access_list
*alist
;
630 if (type
== RMAP_BGP
) {
631 alist
= access_list_lookup(AFI_L2VPN
, (char *)rule
);
635 if (prefix
->u
.prefix_evpn
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
638 p
.family
= AF_ETHERNET
;
639 p
.prefixlen
= ETH_ALEN
* 8;
640 p
.u
.prefix_eth
= prefix
->u
.prefix_evpn
.macip_addr
.mac
;
642 return (access_list_apply(alist
, &p
) == FILTER_DENY
650 /* Route map `mac address' match statement. `arg' should be
652 static void *route_match_mac_address_compile(const char *arg
)
654 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
657 /* Free route map's compiled `ip address' value. */
658 static void route_match_mac_address_free(void *rule
)
660 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
663 /* Route map commands for mac address matching. */
664 struct route_map_rule_cmd route_match_mac_address_cmd
= {
665 "mac address", route_match_mac_address
, route_match_mac_address_compile
,
666 route_match_mac_address_free
};
670 /* Match function should return 1 if match is success else return
672 static route_map_result_t
route_match_vni(void *rule
,
673 const struct prefix
*prefix
,
674 route_map_object_t type
, void *object
)
677 struct bgp_info
*bgp_info
= NULL
;
679 if (type
== RMAP_BGP
) {
680 vni
= *((vni_t
*)rule
);
681 bgp_info
= (struct bgp_info
*)object
;
683 if (bgp_info
->extra
== NULL
)
686 if (vni
== label2vni(&bgp_info
->extra
->label
[0]))
693 /* Route map `vni' match statement. */
694 static void *route_match_vni_compile(const char *arg
)
699 vni
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(vni_t
));
703 *vni
= strtoul(arg
, &end
, 10);
705 XFREE(MTYPE_ROUTE_MAP_COMPILED
, vni
);
712 /* Free route map's compiled `vni' value. */
713 static void route_match_vni_free(void *rule
)
715 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
718 /* Route map commands for vni matching. */
719 struct route_map_rule_cmd route_match_evpn_vni_cmd
= {
720 "evpn vni", route_match_vni
, route_match_vni_compile
,
721 route_match_vni_free
};
723 /* `match evpn route-type' */
725 /* Match function should return 1 if match is success else return
727 static route_map_result_t
route_match_evpn_route_type(void *rule
,
728 const struct prefix
*pfx
,
729 route_map_object_t type
,
732 uint8_t route_type
= 0;
734 if (type
== RMAP_BGP
) {
735 route_type
= *((uint8_t *)rule
);
737 if (route_type
== pfx
->u
.prefix_evpn
.route_type
)
744 /* Route map `route-type' match statement. */
745 static void *route_match_evpn_route_type_compile(const char *arg
)
747 uint8_t *route_type
= NULL
;
749 route_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
751 if (strncmp(arg
, "ma", 2) == 0)
752 *route_type
= BGP_EVPN_MAC_IP_ROUTE
;
753 else if (strncmp(arg
, "mu", 2) == 0)
754 *route_type
= BGP_EVPN_IMET_ROUTE
;
756 *route_type
= BGP_EVPN_IP_PREFIX_ROUTE
;
761 /* Free route map's compiled `route-type' value. */
762 static void route_match_evpn_route_type_free(void *rule
)
764 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
767 /* Route map commands for evpn route-type matching. */
768 struct route_map_rule_cmd route_match_evpn_route_type_cmd
= {
769 "evpn route-type", route_match_evpn_route_type
,
770 route_match_evpn_route_type_compile
, route_match_evpn_route_type_free
};
772 /* `match local-preference LOCAL-PREF' */
774 /* Match function return 1 if match is success else return zero. */
775 static route_map_result_t
route_match_local_pref(void *rule
,
776 const struct prefix
*prefix
,
777 route_map_object_t type
,
780 uint32_t *local_pref
;
781 struct bgp_info
*bgp_info
;
783 if (type
== RMAP_BGP
) {
787 if (bgp_info
->attr
->local_pref
== *local_pref
)
795 /* Route map `match local-preference' match statement.
796 `arg' is local-pref value */
797 static void *route_match_local_pref_compile(const char *arg
)
799 uint32_t *local_pref
;
801 unsigned long tmpval
;
803 /* Locpref value shoud be integer. */
808 tmpval
= strtoul(arg
, &endptr
, 10);
809 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
812 local_pref
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
817 *local_pref
= tmpval
;
821 /* Free route map's compiled `match local-preference' value. */
822 static void route_match_local_pref_free(void *rule
)
824 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
827 /* Route map commands for metric matching. */
828 struct route_map_rule_cmd route_match_local_pref_cmd
= {
829 "local-preference", route_match_local_pref
,
830 route_match_local_pref_compile
, route_match_local_pref_free
};
832 /* `match metric METRIC' */
834 /* Match function return 1 if match is success else return zero. */
835 static route_map_result_t
route_match_metric(void *rule
,
836 const struct prefix
*prefix
,
837 route_map_object_t type
,
840 struct rmap_value
*rv
;
841 struct bgp_info
*bgp_info
;
843 if (type
== RMAP_BGP
) {
846 return route_value_match(rv
, bgp_info
->attr
->med
);
851 /* Route map commands for metric matching. */
852 struct route_map_rule_cmd route_match_metric_cmd
= {
853 "metric", route_match_metric
, route_value_compile
, route_value_free
,
856 /* `match as-path ASPATH' */
858 /* Match function for as-path match. I assume given object is */
859 static route_map_result_t
route_match_aspath(void *rule
,
860 const struct prefix
*prefix
,
861 route_map_object_t type
,
865 struct as_list
*as_list
;
866 struct bgp_info
*bgp_info
;
868 if (type
== RMAP_BGP
) {
869 as_list
= as_list_lookup((char *)rule
);
876 return ((as_list_apply(as_list
, bgp_info
->attr
->aspath
)
884 /* Compile function for as-path match. */
885 static void *route_match_aspath_compile(const char *arg
)
887 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
890 /* Compile function for as-path match. */
891 static void route_match_aspath_free(void *rule
)
893 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
896 /* Route map commands for aspath matching. */
897 struct route_map_rule_cmd route_match_aspath_cmd
= {
898 "as-path", route_match_aspath
, route_match_aspath_compile
,
899 route_match_aspath_free
};
901 /* `match community COMMUNIY' */
902 struct rmap_community
{
907 /* Match function for community match. */
908 static route_map_result_t
route_match_community(void *rule
,
909 const struct prefix
*prefix
,
910 route_map_object_t type
,
913 struct community_list
*list
;
914 struct bgp_info
*bgp_info
;
915 struct rmap_community
*rcom
;
917 if (type
== RMAP_BGP
) {
921 list
= community_list_lookup(bgp_clist
, rcom
->name
,
922 COMMUNITY_LIST_MASTER
);
927 if (community_list_exact_match(
928 bgp_info
->attr
->community
, list
))
931 if (community_list_match(bgp_info
->attr
->community
,
939 /* Compile function for community match. */
940 static void *route_match_community_compile(const char *arg
)
942 struct rmap_community
*rcom
;
946 rcom
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_community
));
948 p
= strchr(arg
, ' ');
951 rcom
->name
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
952 memcpy(rcom
->name
, arg
, len
);
955 rcom
->name
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
961 /* Compile function for community match. */
962 static void route_match_community_free(void *rule
)
964 struct rmap_community
*rcom
= rule
;
966 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
->name
);
967 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
);
970 /* Route map commands for community matching. */
971 struct route_map_rule_cmd route_match_community_cmd
= {
972 "community", route_match_community
, route_match_community_compile
,
973 route_match_community_free
};
975 /* Match function for lcommunity match. */
976 static route_map_result_t
route_match_lcommunity(void *rule
,
977 const struct prefix
*prefix
,
978 route_map_object_t type
,
981 struct community_list
*list
;
982 struct bgp_info
*bgp_info
;
983 struct rmap_community
*rcom
;
985 if (type
== RMAP_BGP
) {
989 list
= community_list_lookup(bgp_clist
, rcom
->name
,
990 LARGE_COMMUNITY_LIST_MASTER
);
994 if (lcommunity_list_match(bgp_info
->attr
->lcommunity
, list
))
1000 /* Compile function for community match. */
1001 static void *route_match_lcommunity_compile(const char *arg
)
1003 struct rmap_community
*rcom
;
1007 rcom
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_community
));
1009 p
= strchr(arg
, ' ');
1012 rcom
->name
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1013 memcpy(rcom
->name
, arg
, len
);
1015 rcom
->name
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1021 /* Compile function for community match. */
1022 static void route_match_lcommunity_free(void *rule
)
1024 struct rmap_community
*rcom
= rule
;
1026 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
->name
);
1027 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
);
1030 /* Route map commands for community matching. */
1031 struct route_map_rule_cmd route_match_lcommunity_cmd
= {
1032 "large-community", route_match_lcommunity
,
1033 route_match_lcommunity_compile
, route_match_lcommunity_free
};
1036 /* Match function for extcommunity match. */
1037 static route_map_result_t
route_match_ecommunity(void *rule
,
1038 const struct prefix
*prefix
,
1039 route_map_object_t type
,
1042 struct community_list
*list
;
1043 struct bgp_info
*bgp_info
;
1045 if (type
== RMAP_BGP
) {
1048 list
= community_list_lookup(bgp_clist
, (char *)rule
,
1049 EXTCOMMUNITY_LIST_MASTER
);
1051 return RMAP_NOMATCH
;
1053 if (ecommunity_list_match(bgp_info
->attr
->ecommunity
, list
))
1056 return RMAP_NOMATCH
;
1059 /* Compile function for extcommunity match. */
1060 static void *route_match_ecommunity_compile(const char *arg
)
1062 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1065 /* Compile function for extcommunity match. */
1066 static void route_match_ecommunity_free(void *rule
)
1068 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1071 /* Route map commands for community matching. */
1072 struct route_map_rule_cmd route_match_ecommunity_cmd
= {
1073 "extcommunity", route_match_ecommunity
, route_match_ecommunity_compile
,
1074 route_match_ecommunity_free
};
1076 /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1077 and `address-family vpnv4'. */
1079 /* `match origin' */
1080 static route_map_result_t
route_match_origin(void *rule
,
1081 const struct prefix
*prefix
,
1082 route_map_object_t type
,
1086 struct bgp_info
*bgp_info
;
1088 if (type
== RMAP_BGP
) {
1092 if (bgp_info
->attr
->origin
== *origin
)
1096 return RMAP_NOMATCH
;
1099 static void *route_match_origin_compile(const char *arg
)
1103 origin
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1105 if (strcmp(arg
, "igp") == 0)
1107 else if (strcmp(arg
, "egp") == 0)
1115 /* Free route map's compiled `ip address' value. */
1116 static void route_match_origin_free(void *rule
)
1118 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1121 /* Route map commands for origin matching. */
1122 struct route_map_rule_cmd route_match_origin_cmd
= {
1123 "origin", route_match_origin
, route_match_origin_compile
,
1124 route_match_origin_free
};
1126 /* match probability { */
1128 static route_map_result_t
route_match_probability(void *rule
,
1129 const struct prefix
*prefix
,
1130 route_map_object_t type
,
1135 switch (*(long *)rule
) {
1141 if (r
< *(long *)rule
) {
1146 return RMAP_NOMATCH
;
1149 static void *route_match_probability_compile(const char *arg
)
1155 lobule
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(long));
1165 *lobule
= RAND_MAX
/ 100 * perc
;
1171 static void route_match_probability_free(void *rule
)
1173 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1176 struct route_map_rule_cmd route_match_probability_cmd
= {
1177 "probability", route_match_probability
, route_match_probability_compile
,
1178 route_match_probability_free
};
1180 /* `match interface IFNAME' */
1181 /* Match function should return 1 if match is success else return
1183 static route_map_result_t
route_match_interface(void *rule
,
1184 const struct prefix
*prefix
,
1185 route_map_object_t type
,
1188 struct interface
*ifp
;
1189 struct bgp_info
*info
;
1191 if (type
== RMAP_BGP
) {
1194 if (!info
|| !info
->attr
)
1195 return RMAP_NOMATCH
;
1197 ifp
= if_lookup_by_name_all_vrf((char *)rule
);
1199 if (ifp
== NULL
|| ifp
->ifindex
!= info
->attr
->nh_ifindex
)
1200 return RMAP_NOMATCH
;
1204 return RMAP_NOMATCH
;
1207 /* Route map `interface' match statement. `arg' should be
1209 static void *route_match_interface_compile(const char *arg
)
1211 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1214 /* Free route map's compiled `interface' value. */
1215 static void route_match_interface_free(void *rule
)
1217 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1220 /* Route map commands for ip address matching. */
1221 struct route_map_rule_cmd route_match_interface_cmd
= {
1222 "interface", route_match_interface
, route_match_interface_compile
,
1223 route_match_interface_free
};
1227 /* `set ip next-hop IP_ADDRESS' */
1229 /* Match function return 1 if match is success else return zero. */
1230 static route_map_result_t
route_match_tag(void *rule
,
1231 const struct prefix
*prefix
,
1232 route_map_object_t type
, void *object
)
1235 struct bgp_info
*bgp_info
;
1237 if (type
== RMAP_BGP
) {
1241 return ((bgp_info
->attr
->tag
== *tag
) ? RMAP_MATCH
1245 return RMAP_NOMATCH
;
1249 /* Route map commands for tag matching. */
1250 static struct route_map_rule_cmd route_match_tag_cmd
= {
1251 "tag", route_match_tag
, route_map_rule_tag_compile
,
1252 route_map_rule_tag_free
,
1256 /* Set nexthop to object. ojbect must be pointer to struct attr. */
1257 struct rmap_ip_nexthop_set
{
1258 struct in_addr
*address
;
1263 static route_map_result_t
route_set_ip_nexthop(void *rule
,
1264 const struct prefix
*prefix
,
1265 route_map_object_t type
,
1268 struct rmap_ip_nexthop_set
*rins
= rule
;
1269 struct bgp_info
*bgp_info
;
1272 if (type
== RMAP_BGP
) {
1274 peer
= bgp_info
->peer
;
1276 if (rins
->unchanged
) {
1277 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1278 BATTR_RMAP_NEXTHOP_UNCHANGED
);
1279 } else if (rins
->peer_address
) {
1280 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
1281 || CHECK_FLAG(peer
->rmap_type
,
1282 PEER_RMAP_TYPE_IMPORT
))
1284 && sockunion_family(peer
->su_remote
) == AF_INET
) {
1285 bgp_info
->attr
->nexthop
.s_addr
=
1286 sockunion2ip(peer
->su_remote
);
1287 bgp_info
->attr
->flag
|=
1288 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1289 } else if (CHECK_FLAG(peer
->rmap_type
,
1290 PEER_RMAP_TYPE_OUT
)) {
1291 /* The next hop value will be set as part of
1293 * Set the flags here to indicate that rewrite
1295 * Also, clear the value.
1297 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1298 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
);
1299 bgp_info
->attr
->nexthop
.s_addr
= 0;
1302 /* Set next hop value. */
1303 bgp_info
->attr
->flag
|=
1304 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1305 bgp_info
->attr
->nexthop
= *rins
->address
;
1306 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1307 BATTR_RMAP_IPV4_NHOP_CHANGED
);
1308 /* case for MP-BGP : MPLS VPN */
1309 bgp_info
->attr
->mp_nexthop_global_in
= *rins
->address
;
1310 bgp_info
->attr
->mp_nexthop_len
= sizeof(*rins
->address
);
1317 /* Route map `ip nexthop' compile function. Given string is converted
1318 to struct in_addr structure. */
1319 static void *route_set_ip_nexthop_compile(const char *arg
)
1321 struct rmap_ip_nexthop_set
*rins
;
1322 struct in_addr
*address
= NULL
;
1323 int peer_address
= 0;
1327 if (strcmp(arg
, "peer-address") == 0)
1329 else if (strcmp(arg
, "unchanged") == 0)
1332 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
1333 sizeof(struct in_addr
));
1334 ret
= inet_aton(arg
, address
);
1337 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
1342 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
,
1343 sizeof(struct rmap_ip_nexthop_set
));
1345 rins
->address
= address
;
1346 rins
->peer_address
= peer_address
;
1347 rins
->unchanged
= unchanged
;
1352 /* Free route map's compiled `ip nexthop' value. */
1353 static void route_set_ip_nexthop_free(void *rule
)
1355 struct rmap_ip_nexthop_set
*rins
= rule
;
1358 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rins
->address
);
1360 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rins
);
1363 /* Route map commands for ip nexthop set. */
1364 struct route_map_rule_cmd route_set_ip_nexthop_cmd
= {
1365 "ip next-hop", route_set_ip_nexthop
, route_set_ip_nexthop_compile
,
1366 route_set_ip_nexthop_free
};
1368 /* `set local-preference LOCAL_PREF' */
1370 /* Set local preference. */
1371 static route_map_result_t
route_set_local_pref(void *rule
,
1372 const struct prefix
*prefix
,
1373 route_map_object_t type
,
1376 struct rmap_value
*rv
;
1377 struct bgp_info
*bgp_info
;
1378 uint32_t locpref
= 0;
1380 if (type
== RMAP_BGP
) {
1381 /* Fetch routemap's rule information. */
1385 /* Set local preference value. */
1386 if (bgp_info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
1387 locpref
= bgp_info
->attr
->local_pref
;
1389 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1390 bgp_info
->attr
->local_pref
=
1391 route_value_adjust(rv
, locpref
, bgp_info
->peer
);
1397 /* Set local preference rule structure. */
1398 struct route_map_rule_cmd route_set_local_pref_cmd
= {
1399 "local-preference", route_set_local_pref
, route_value_compile
,
1403 /* `set weight WEIGHT' */
1406 static route_map_result_t
route_set_weight(void *rule
,
1407 const struct prefix
*prefix
,
1408 route_map_object_t type
,
1411 struct rmap_value
*rv
;
1412 struct bgp_info
*bgp_info
;
1414 if (type
== RMAP_BGP
) {
1415 /* Fetch routemap's rule information. */
1419 /* Set weight value. */
1420 bgp_info
->attr
->weight
=
1421 route_value_adjust(rv
, 0, bgp_info
->peer
);
1427 /* Set local preference rule structure. */
1428 struct route_map_rule_cmd route_set_weight_cmd
= {
1429 "weight", route_set_weight
, route_value_compile
, route_value_free
,
1432 /* `set metric METRIC' */
1434 /* Set metric to attribute. */
1435 static route_map_result_t
route_set_metric(void *rule
,
1436 const struct prefix
*prefix
,
1437 route_map_object_t type
,
1440 struct rmap_value
*rv
;
1441 struct bgp_info
*bgp_info
;
1444 if (type
== RMAP_BGP
) {
1445 /* Fetch routemap's rule information. */
1449 if (bgp_info
->attr
->flag
1450 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1451 med
= bgp_info
->attr
->med
;
1453 bgp_info
->attr
->med
=
1454 route_value_adjust(rv
, med
, bgp_info
->peer
);
1455 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1460 /* Set metric rule structure. */
1461 struct route_map_rule_cmd route_set_metric_cmd
= {
1462 "metric", route_set_metric
, route_value_compile
, route_value_free
,
1465 /* `set as-path prepend ASPATH' */
1467 /* For AS path prepend mechanism. */
1468 static route_map_result_t
route_set_aspath_prepend(void *rule
,
1469 const struct prefix
*prefix
,
1470 route_map_object_t type
,
1473 struct aspath
*aspath
;
1475 struct bgp_info
*binfo
;
1477 if (type
== RMAP_BGP
) {
1480 if (binfo
->attr
->aspath
->refcnt
)
1481 new = aspath_dup(binfo
->attr
->aspath
);
1483 new = binfo
->attr
->aspath
;
1485 if ((uintptr_t)rule
> 10) {
1487 aspath_prepend(aspath
, new);
1489 as_t as
= aspath_leftmost(new);
1491 as
= binfo
->peer
->as
;
1492 new = aspath_add_seq_n(new, as
, (uintptr_t)rule
);
1495 binfo
->attr
->aspath
= new;
1501 static void *route_set_aspath_prepend_compile(const char *arg
)
1505 if (sscanf(arg
, "last-as %u", &num
) == 1 && num
> 0 && num
<= 10)
1506 return (void *)(uintptr_t)num
;
1508 return route_aspath_compile(arg
);
1511 static void route_set_aspath_prepend_free(void *rule
)
1513 if ((uintptr_t)rule
> 10)
1514 route_aspath_free(rule
);
1518 /* Set as-path prepend rule structure. */
1519 struct route_map_rule_cmd route_set_aspath_prepend_cmd
= {
1520 "as-path prepend", route_set_aspath_prepend
,
1521 route_set_aspath_prepend_compile
, route_set_aspath_prepend_free
,
1524 /* `set as-path exclude ASn' */
1526 /* For ASN exclude mechanism.
1527 * Iterate over ASns requested and filter them from the given AS_PATH one by
1529 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1531 static route_map_result_t
route_set_aspath_exclude(void *rule
,
1532 const struct prefix
*dummy
,
1533 route_map_object_t type
,
1536 struct aspath
*new_path
, *exclude_path
;
1537 struct bgp_info
*binfo
;
1539 if (type
== RMAP_BGP
) {
1540 exclude_path
= rule
;
1542 if (binfo
->attr
->aspath
->refcnt
)
1543 new_path
= aspath_dup(binfo
->attr
->aspath
);
1545 new_path
= binfo
->attr
->aspath
;
1546 binfo
->attr
->aspath
=
1547 aspath_filter_exclude(new_path
, exclude_path
);
1552 /* Set ASn exlude rule structure. */
1553 struct route_map_rule_cmd route_set_aspath_exclude_cmd
= {
1554 "as-path exclude", route_set_aspath_exclude
, route_aspath_compile
,
1558 /* `set community COMMUNITY' */
1559 struct rmap_com_set
{
1560 struct community
*com
;
1565 /* For community set mechanism. */
1566 static route_map_result_t
route_set_community(void *rule
,
1567 const struct prefix
*prefix
,
1568 route_map_object_t type
,
1571 struct rmap_com_set
*rcs
;
1572 struct bgp_info
*binfo
;
1574 struct community
*new = NULL
;
1575 struct community
*old
;
1576 struct community
*merge
;
1578 if (type
== RMAP_BGP
) {
1582 old
= attr
->community
;
1586 attr
->flag
&= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1587 attr
->community
= NULL
;
1588 /* See the longer comment down below. */
1589 if (old
&& old
->refcnt
== 0)
1590 community_free(old
);
1594 /* "additive" case. */
1595 if (rcs
->additive
&& old
) {
1596 merge
= community_merge(community_dup(old
), rcs
->com
);
1598 new = community_uniq_sort(merge
);
1599 community_free(merge
);
1601 new = community_dup(rcs
->com
);
1603 /* HACK: if the old community is not intern'd,
1604 * we should free it here, or all reference to it may be
1606 * Really need to cleanup attribute caching sometime.
1608 if (old
&& old
->refcnt
== 0)
1609 community_free(old
);
1611 /* will be interned by caller if required */
1612 attr
->community
= new;
1614 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1620 /* Compile function for set community. */
1621 static void *route_set_community_compile(const char *arg
)
1623 struct rmap_com_set
*rcs
;
1624 struct community
*com
= NULL
;
1629 if (strcmp(arg
, "none") == 0)
1632 sp
= strstr(arg
, "additive");
1634 if (sp
&& sp
> arg
) {
1635 /* "additive" keyword is included. */
1640 com
= community_str2com(arg
);
1649 rcs
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_com_set
));
1651 rcs
->additive
= additive
;
1657 /* Free function for set community. */
1658 static void route_set_community_free(void *rule
)
1660 struct rmap_com_set
*rcs
= rule
;
1663 community_free(rcs
->com
);
1664 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcs
);
1667 /* Set community rule structure. */
1668 struct route_map_rule_cmd route_set_community_cmd
= {
1669 "community", route_set_community
, route_set_community_compile
,
1670 route_set_community_free
,
1673 /* `set community COMMUNITY' */
1674 struct rmap_lcom_set
{
1675 struct lcommunity
*lcom
;
1681 /* For lcommunity set mechanism. */
1682 static route_map_result_t
route_set_lcommunity(void *rule
,
1683 const struct prefix
*prefix
,
1684 route_map_object_t type
,
1687 struct rmap_lcom_set
*rcs
;
1688 struct bgp_info
*binfo
;
1690 struct lcommunity
*new = NULL
;
1691 struct lcommunity
*old
;
1692 struct lcommunity
*merge
;
1694 if (type
== RMAP_BGP
) {
1698 old
= attr
->lcommunity
;
1703 ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1704 attr
->lcommunity
= NULL
;
1706 /* See the longer comment down below. */
1707 if (old
&& old
->refcnt
== 0)
1708 lcommunity_free(&old
);
1712 if (rcs
->additive
&& old
) {
1713 merge
= lcommunity_merge(lcommunity_dup(old
),
1716 new = lcommunity_uniq_sort(merge
);
1717 lcommunity_free(&merge
);
1719 new = lcommunity_dup(rcs
->lcom
);
1721 /* HACK: if the old large-community is not intern'd,
1722 * we should free it here, or all reference to it may be
1724 * Really need to cleanup attribute caching sometime.
1726 if (old
&& old
->refcnt
== 0)
1727 lcommunity_free(&old
);
1729 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1730 attr
->lcommunity
= new;
1732 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1738 /* Compile function for set community. */
1739 static void *route_set_lcommunity_compile(const char *arg
)
1741 struct rmap_lcom_set
*rcs
;
1742 struct lcommunity
*lcom
= NULL
;
1747 if (strcmp(arg
, "none") == 0)
1750 sp
= strstr(arg
, "additive");
1752 if (sp
&& sp
> arg
) {
1753 /* "additive" keyworkd is included. */
1758 lcom
= lcommunity_str2com(arg
);
1767 rcs
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_com_set
));
1769 rcs
->additive
= additive
;
1775 /* Free function for set lcommunity. */
1776 static void route_set_lcommunity_free(void *rule
)
1778 struct rmap_lcom_set
*rcs
= rule
;
1781 lcommunity_free(&rcs
->lcom
);
1783 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcs
);
1786 /* Set community rule structure. */
1787 struct route_map_rule_cmd route_set_lcommunity_cmd
= {
1788 "large-community", route_set_lcommunity
, route_set_lcommunity_compile
,
1789 route_set_lcommunity_free
,
1792 /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
1794 /* For large community set mechanism. */
1795 static route_map_result_t
route_set_lcommunity_delete(void *rule
,
1796 const struct prefix
*pfx
,
1797 route_map_object_t type
,
1800 struct community_list
*list
;
1801 struct lcommunity
*merge
;
1802 struct lcommunity
*new;
1803 struct lcommunity
*old
;
1804 struct bgp_info
*binfo
;
1806 if (type
== RMAP_BGP
) {
1811 list
= community_list_lookup(bgp_clist
, rule
,
1812 LARGE_COMMUNITY_LIST_MASTER
);
1813 old
= binfo
->attr
->lcommunity
;
1816 merge
= lcommunity_list_match_delete(
1817 lcommunity_dup(old
), list
);
1818 new = lcommunity_uniq_sort(merge
);
1819 lcommunity_free(&merge
);
1821 /* HACK: if the old community is not intern'd,
1822 * we should free it here, or all reference to it may be
1824 * Really need to cleanup attribute caching sometime.
1826 if (old
->refcnt
== 0)
1827 lcommunity_free(&old
);
1829 if (new->size
== 0) {
1830 binfo
->attr
->lcommunity
= NULL
;
1831 binfo
->attr
->flag
&= ~ATTR_FLAG_BIT(
1832 BGP_ATTR_LARGE_COMMUNITIES
);
1833 lcommunity_free(&new);
1835 binfo
->attr
->lcommunity
= new;
1836 binfo
->attr
->flag
|= ATTR_FLAG_BIT(
1837 BGP_ATTR_LARGE_COMMUNITIES
);
1845 /* Compile function for set lcommunity. */
1846 static void *route_set_lcommunity_delete_compile(const char *arg
)
1852 p
= strchr(arg
, ' ');
1855 str
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1856 memcpy(str
, arg
, len
);
1863 /* Free function for set lcommunity. */
1864 static void route_set_lcommunity_delete_free(void *rule
)
1866 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1869 /* Set lcommunity rule structure. */
1870 struct route_map_rule_cmd route_set_lcommunity_delete_cmd
= {
1871 "large-comm-list", route_set_lcommunity_delete
,
1872 route_set_lcommunity_delete_compile
, route_set_lcommunity_delete_free
,
1876 /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
1878 /* For community set mechanism. */
1879 static route_map_result_t
route_set_community_delete(
1881 const struct prefix
*prefix
,
1882 route_map_object_t type
,
1885 struct community_list
*list
;
1886 struct community
*merge
;
1887 struct community
*new;
1888 struct community
*old
;
1889 struct bgp_info
*binfo
;
1891 if (type
== RMAP_BGP
) {
1896 list
= community_list_lookup(bgp_clist
, rule
,
1897 COMMUNITY_LIST_MASTER
);
1898 old
= binfo
->attr
->community
;
1901 merge
= community_list_match_delete(community_dup(old
),
1903 new = community_uniq_sort(merge
);
1904 community_free(merge
);
1906 /* HACK: if the old community is not intern'd,
1907 * we should free it here, or all reference to it may be
1909 * Really need to cleanup attribute caching sometime.
1911 if (old
->refcnt
== 0)
1912 community_free(old
);
1914 if (new->size
== 0) {
1915 binfo
->attr
->community
= NULL
;
1916 binfo
->attr
->flag
&=
1917 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1918 community_free(new);
1920 binfo
->attr
->community
= new;
1921 binfo
->attr
->flag
|=
1922 ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1930 /* Compile function for set community. */
1931 static void *route_set_community_delete_compile(const char *arg
)
1937 p
= strchr(arg
, ' ');
1940 str
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1941 memcpy(str
, arg
, len
);
1948 /* Free function for set community. */
1949 static void route_set_community_delete_free(void *rule
)
1951 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1954 /* Set community rule structure. */
1955 struct route_map_rule_cmd route_set_community_delete_cmd
= {
1956 "comm-list", route_set_community_delete
,
1957 route_set_community_delete_compile
, route_set_community_delete_free
,
1960 /* `set extcommunity rt COMMUNITY' */
1962 /* For community set mechanism. Used by _rt and _soo. */
1963 static route_map_result_t
route_set_ecommunity(void *rule
,
1964 const struct prefix
*prefix
,
1965 route_map_object_t type
,
1968 struct ecommunity
*ecom
;
1969 struct ecommunity
*new_ecom
;
1970 struct ecommunity
*old_ecom
;
1971 struct bgp_info
*bgp_info
;
1973 if (type
== RMAP_BGP
) {
1980 /* We assume additive for Extended Community. */
1981 old_ecom
= bgp_info
->attr
->ecommunity
;
1984 new_ecom
= ecommunity_merge(ecommunity_dup(old_ecom
),
1987 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
1988 * bgp_update_receive()
1989 * ->refcnt = 0 => set by a previous route-map
1991 if (!old_ecom
->refcnt
)
1992 ecommunity_free(&old_ecom
);
1994 new_ecom
= ecommunity_dup(ecom
);
1996 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1997 bgp_info
->attr
->ecommunity
= new_ecom
;
1999 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2004 /* Compile function for set community. */
2005 static void *route_set_ecommunity_rt_compile(const char *arg
)
2007 struct ecommunity
*ecom
;
2009 ecom
= ecommunity_str2com(arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
2012 return ecommunity_intern(ecom
);
2015 /* Free function for set community. Used by _rt and _soo */
2016 static void route_set_ecommunity_free(void *rule
)
2018 struct ecommunity
*ecom
= rule
;
2019 ecommunity_unintern(&ecom
);
2022 /* Set community rule structure. */
2023 struct route_map_rule_cmd route_set_ecommunity_rt_cmd
= {
2024 "extcommunity rt", route_set_ecommunity
,
2025 route_set_ecommunity_rt_compile
, route_set_ecommunity_free
,
2028 /* `set extcommunity soo COMMUNITY' */
2030 /* Compile function for set community. */
2031 static void *route_set_ecommunity_soo_compile(const char *arg
)
2033 struct ecommunity
*ecom
;
2035 ecom
= ecommunity_str2com(arg
, ECOMMUNITY_SITE_ORIGIN
, 0);
2039 return ecommunity_intern(ecom
);
2042 /* Set community rule structure. */
2043 struct route_map_rule_cmd route_set_ecommunity_soo_cmd
= {
2044 "extcommunity soo", route_set_ecommunity
,
2045 route_set_ecommunity_soo_compile
, route_set_ecommunity_free
,
2048 /* `set origin ORIGIN' */
2050 /* For origin set. */
2051 static route_map_result_t
route_set_origin(void *rule
,
2052 const struct prefix
*prefix
,
2053 route_map_object_t type
,
2057 struct bgp_info
*bgp_info
;
2059 if (type
== RMAP_BGP
) {
2063 bgp_info
->attr
->origin
= *origin
;
2069 /* Compile function for origin set. */
2070 static void *route_set_origin_compile(const char *arg
)
2074 origin
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
2076 if (strcmp(arg
, "igp") == 0)
2078 else if (strcmp(arg
, "egp") == 0)
2086 /* Compile function for origin set. */
2087 static void route_set_origin_free(void *rule
)
2089 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2092 /* Set origin rule structure. */
2093 struct route_map_rule_cmd route_set_origin_cmd
= {
2094 "origin", route_set_origin
, route_set_origin_compile
,
2095 route_set_origin_free
,
2098 /* `set atomic-aggregate' */
2100 /* For atomic aggregate set. */
2101 static route_map_result_t
route_set_atomic_aggregate(void *rule
,
2102 const struct prefix
*pfx
,
2103 route_map_object_t type
,
2106 struct bgp_info
*bgp_info
;
2108 if (type
== RMAP_BGP
) {
2110 bgp_info
->attr
->flag
|=
2111 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
2117 /* Compile function for atomic aggregate. */
2118 static void *route_set_atomic_aggregate_compile(const char *arg
)
2123 /* Compile function for atomic aggregate. */
2124 static void route_set_atomic_aggregate_free(void *rule
)
2129 /* Set atomic aggregate rule structure. */
2130 struct route_map_rule_cmd route_set_atomic_aggregate_cmd
= {
2131 "atomic-aggregate", route_set_atomic_aggregate
,
2132 route_set_atomic_aggregate_compile
, route_set_atomic_aggregate_free
,
2135 /* `set aggregator as AS A.B.C.D' */
2138 struct in_addr address
;
2141 static route_map_result_t
route_set_aggregator_as(void *rule
,
2142 const struct prefix
*prefix
,
2143 route_map_object_t type
,
2146 struct bgp_info
*bgp_info
;
2147 struct aggregator
*aggregator
;
2149 if (type
== RMAP_BGP
) {
2153 bgp_info
->attr
->aggregator_as
= aggregator
->as
;
2154 bgp_info
->attr
->aggregator_addr
= aggregator
->address
;
2155 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
2161 static void *route_set_aggregator_as_compile(const char *arg
)
2163 struct aggregator
*aggregator
;
2169 XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct aggregator
));
2170 if (sscanf(arg
, "%s %s", as
, address
) != 2) {
2171 XFREE(MTYPE_ROUTE_MAP_COMPILED
, aggregator
);
2175 aggregator
->as
= strtoul(as
, NULL
, 10);
2176 ret
= inet_aton(address
, &aggregator
->address
);
2178 XFREE(MTYPE_ROUTE_MAP_COMPILED
, aggregator
);
2184 static void route_set_aggregator_as_free(void *rule
)
2186 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2189 struct route_map_rule_cmd route_set_aggregator_as_cmd
= {
2190 "aggregator as", route_set_aggregator_as
,
2191 route_set_aggregator_as_compile
, route_set_aggregator_as_free
,
2194 /* Set tag to object. object must be pointer to struct bgp_info */
2195 static route_map_result_t
route_set_tag(void *rule
,
2196 const struct prefix
*prefix
,
2197 route_map_object_t type
, void *object
)
2200 struct bgp_info
*bgp_info
;
2202 if (type
== RMAP_BGP
) {
2207 bgp_info
->attr
->tag
= *tag
;
2213 /* Route map commands for tag set. */
2214 static struct route_map_rule_cmd route_set_tag_cmd
= {
2215 "tag", route_set_tag
, route_map_rule_tag_compile
,
2216 route_map_rule_tag_free
,
2219 /* Set label-index to object. object must be pointer to struct bgp_info */
2220 static route_map_result_t
route_set_label_index(void *rule
,
2221 const struct prefix
*prefix
,
2222 route_map_object_t type
,
2225 struct rmap_value
*rv
;
2226 struct bgp_info
*bgp_info
;
2227 uint32_t label_index
;
2229 if (type
== RMAP_BGP
) {
2230 /* Fetch routemap's rule information. */
2234 /* Set label-index value. */
2235 label_index
= rv
->value
;
2237 bgp_info
->attr
->label_index
= label_index
;
2238 bgp_info
->attr
->flag
|=
2239 ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2246 /* Route map commands for label-index set. */
2247 static struct route_map_rule_cmd route_set_label_index_cmd
= {
2248 "label-index", route_set_label_index
, route_value_compile
,
2252 /* `match ipv6 address IP_ACCESS_LIST' */
2254 static route_map_result_t
route_match_ipv6_address(void *rule
,
2255 const struct prefix
*prefix
,
2256 route_map_object_t type
,
2259 struct access_list
*alist
;
2261 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET6
) {
2262 alist
= access_list_lookup(AFI_IP6
, (char *)rule
);
2264 return RMAP_NOMATCH
;
2266 return (access_list_apply(alist
, prefix
) == FILTER_DENY
2270 return RMAP_NOMATCH
;
2273 static void *route_match_ipv6_address_compile(const char *arg
)
2275 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
2278 static void route_match_ipv6_address_free(void *rule
)
2280 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2283 /* Route map commands for ip address matching. */
2284 struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
2285 "ipv6 address", route_match_ipv6_address
,
2286 route_match_ipv6_address_compile
, route_match_ipv6_address_free
};
2288 /* `match ipv6 next-hop IP_ADDRESS' */
2290 static route_map_result_t
route_match_ipv6_next_hop(void *rule
,
2291 const struct prefix
*prefix
,
2292 route_map_object_t type
,
2295 struct in6_addr
*addr
= rule
;
2296 struct bgp_info
*bgp_info
;
2298 if (type
== RMAP_BGP
) {
2301 if (IPV6_ADDR_SAME(&bgp_info
->attr
->mp_nexthop_global
, addr
))
2304 if (bgp_info
->attr
->mp_nexthop_len
2305 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
2306 && IPV6_ADDR_SAME(&bgp_info
->attr
->mp_nexthop_local
, rule
))
2309 return RMAP_NOMATCH
;
2312 return RMAP_NOMATCH
;
2315 static void *route_match_ipv6_next_hop_compile(const char *arg
)
2317 struct in6_addr
*address
;
2320 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2322 ret
= inet_pton(AF_INET6
, arg
, address
);
2324 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2331 static void route_match_ipv6_next_hop_free(void *rule
)
2333 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2336 struct route_map_rule_cmd route_match_ipv6_next_hop_cmd
= {
2337 "ipv6 next-hop", route_match_ipv6_next_hop
,
2338 route_match_ipv6_next_hop_compile
, route_match_ipv6_next_hop_free
};
2340 /* `match ipv6 address prefix-list PREFIX_LIST' */
2342 static route_map_result_t
2343 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
2344 route_map_object_t type
, void *object
)
2346 struct prefix_list
*plist
;
2348 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET6
) {
2349 plist
= prefix_list_lookup(AFI_IP6
, (char *)rule
);
2351 return RMAP_NOMATCH
;
2353 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
2357 return RMAP_NOMATCH
;
2360 static void *route_match_ipv6_address_prefix_list_compile(const char *arg
)
2362 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
2365 static void route_match_ipv6_address_prefix_list_free(void *rule
)
2367 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2370 struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
2371 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
2372 route_match_ipv6_address_prefix_list_compile
,
2373 route_match_ipv6_address_prefix_list_free
};
2375 /* `set ipv6 nexthop global IP_ADDRESS' */
2377 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2378 static route_map_result_t
route_set_ipv6_nexthop_global(void *rule
,
2379 const struct prefix
*p
,
2380 route_map_object_t type
,
2383 struct in6_addr
*address
;
2384 struct bgp_info
*bgp_info
;
2386 if (type
== RMAP_BGP
) {
2387 /* Fetch routemap's rule information. */
2391 /* Set next hop value. */
2392 bgp_info
->attr
->mp_nexthop_global
= *address
;
2394 /* Set nexthop length. */
2395 if (bgp_info
->attr
->mp_nexthop_len
== 0)
2396 bgp_info
->attr
->mp_nexthop_len
=
2397 BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2399 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2400 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
);
2406 /* Route map `ip next-hop' compile function. Given string is converted
2407 to struct in_addr structure. */
2408 static void *route_set_ipv6_nexthop_global_compile(const char *arg
)
2411 struct in6_addr
*address
;
2413 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2415 ret
= inet_pton(AF_INET6
, arg
, address
);
2418 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2425 /* Free route map's compiled `ip next-hop' value. */
2426 static void route_set_ipv6_nexthop_global_free(void *rule
)
2428 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2431 /* Route map commands for ip nexthop set. */
2432 struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd
= {
2433 "ipv6 next-hop global", route_set_ipv6_nexthop_global
,
2434 route_set_ipv6_nexthop_global_compile
,
2435 route_set_ipv6_nexthop_global_free
};
2437 /* Set next-hop preference value. */
2438 static route_map_result_t
2439 route_set_ipv6_nexthop_prefer_global(void *rule
, const struct prefix
*prefix
,
2440 route_map_object_t type
, void *object
)
2442 struct bgp_info
*bgp_info
;
2445 if (type
== RMAP_BGP
) {
2446 /* Fetch routemap's rule information. */
2448 peer
= bgp_info
->peer
;
2450 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
2451 || CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IMPORT
))
2453 && sockunion_family(peer
->su_remote
) == AF_INET6
) {
2454 /* Set next hop preference to global */
2455 bgp_info
->attr
->mp_nexthop_prefer_global
= TRUE
;
2456 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2457 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED
);
2459 bgp_info
->attr
->mp_nexthop_prefer_global
= FALSE
;
2460 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2461 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED
);
2467 static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg
)
2471 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
2477 /* Free route map's compiled `ip next-hop' value. */
2478 static void route_set_ipv6_nexthop_prefer_global_free(void *rule
)
2480 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2483 /* Route map commands for ip nexthop set preferred. */
2484 struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd
= {
2485 "ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global
,
2486 route_set_ipv6_nexthop_prefer_global_compile
,
2487 route_set_ipv6_nexthop_prefer_global_free
};
2489 /* `set ipv6 nexthop local IP_ADDRESS' */
2491 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2492 static route_map_result_t
route_set_ipv6_nexthop_local(void *rule
,
2493 const struct prefix
*p
,
2494 route_map_object_t type
,
2497 struct in6_addr
*address
;
2498 struct bgp_info
*bgp_info
;
2500 if (type
== RMAP_BGP
) {
2501 /* Fetch routemap's rule information. */
2505 /* Set next hop value. */
2506 bgp_info
->attr
->mp_nexthop_local
= *address
;
2508 /* Set nexthop length. */
2509 if (bgp_info
->attr
->mp_nexthop_len
2510 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2511 bgp_info
->attr
->mp_nexthop_len
=
2512 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2514 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2515 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
);
2521 /* Route map `ip nexthop' compile function. Given string is converted
2522 to struct in_addr structure. */
2523 static void *route_set_ipv6_nexthop_local_compile(const char *arg
)
2526 struct in6_addr
*address
;
2528 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2530 ret
= inet_pton(AF_INET6
, arg
, address
);
2533 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2540 /* Free route map's compiled `ip nexthop' value. */
2541 static void route_set_ipv6_nexthop_local_free(void *rule
)
2543 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2546 /* Route map commands for ip nexthop set. */
2547 struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd
= {
2548 "ipv6 next-hop local", route_set_ipv6_nexthop_local
,
2549 route_set_ipv6_nexthop_local_compile
,
2550 route_set_ipv6_nexthop_local_free
};
2552 /* `set ipv6 nexthop peer-address' */
2554 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2555 static route_map_result_t
route_set_ipv6_nexthop_peer(void *rule
,
2556 const struct prefix
*pfx
,
2557 route_map_object_t type
,
2560 struct in6_addr peer_address
;
2561 struct bgp_info
*bgp_info
;
2564 if (type
== RMAP_BGP
) {
2565 /* Fetch routemap's rule information. */
2567 peer
= bgp_info
->peer
;
2569 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
2570 || CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IMPORT
))
2572 && sockunion_family(peer
->su_remote
) == AF_INET6
) {
2573 peer_address
= peer
->su_remote
->sin6
.sin6_addr
;
2574 /* Set next hop value and length in attribute. */
2575 if (IN6_IS_ADDR_LINKLOCAL(&peer_address
)) {
2576 bgp_info
->attr
->mp_nexthop_local
= peer_address
;
2577 if (bgp_info
->attr
->mp_nexthop_len
!= 32)
2578 bgp_info
->attr
->mp_nexthop_len
= 32;
2580 bgp_info
->attr
->mp_nexthop_global
=
2582 if (bgp_info
->attr
->mp_nexthop_len
== 0)
2583 bgp_info
->attr
->mp_nexthop_len
= 16;
2586 } else if (CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
)) {
2587 /* The next hop value will be set as part of packet
2589 * Set the flags here to indicate that rewrite needs to
2591 * Also, clear the value - we clear both global and
2593 * nexthops, whether we send one or both is determined
2596 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2597 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
);
2598 /* clear next hop value. */
2599 memset(&(bgp_info
->attr
->mp_nexthop_global
), 0,
2600 sizeof(struct in6_addr
));
2601 memset(&(bgp_info
->attr
->mp_nexthop_local
), 0,
2602 sizeof(struct in6_addr
));
2609 /* Route map `ip next-hop' compile function. Given string is converted
2610 to struct in_addr structure. */
2611 static void *route_set_ipv6_nexthop_peer_compile(const char *arg
)
2615 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
2621 /* Free route map's compiled `ip next-hop' value. */
2622 static void route_set_ipv6_nexthop_peer_free(void *rule
)
2624 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2627 /* Route map commands for ip nexthop set. */
2628 struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd
= {
2629 "ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer
,
2630 route_set_ipv6_nexthop_peer_compile
, route_set_ipv6_nexthop_peer_free
};
2632 /* `set ipv4 vpn next-hop A.B.C.D' */
2634 static route_map_result_t
route_set_vpnv4_nexthop(void *rule
,
2635 const struct prefix
*prefix
,
2636 route_map_object_t type
,
2639 struct in_addr
*address
;
2640 struct bgp_info
*bgp_info
;
2642 if (type
== RMAP_BGP
) {
2643 /* Fetch routemap's rule information. */
2647 /* Set next hop value. */
2648 bgp_info
->attr
->mp_nexthop_global_in
= *address
;
2649 bgp_info
->attr
->mp_nexthop_len
= 4;
2655 static void *route_set_vpnv4_nexthop_compile(const char *arg
)
2658 struct in_addr
*address
;
2660 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in_addr
));
2662 ret
= inet_aton(arg
, address
);
2665 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2672 /* `set ipv6 vpn next-hop A.B.C.D' */
2674 static route_map_result_t
route_set_vpnv6_nexthop(void *rule
,
2675 const struct prefix
*prefix
,
2676 route_map_object_t type
,
2679 struct in6_addr
*address
;
2680 struct bgp_info
*bgp_info
;
2682 if (type
== RMAP_BGP
) {
2683 /* Fetch routemap's rule information. */
2687 /* Set next hop value. */
2688 memcpy(&bgp_info
->attr
->mp_nexthop_global
, address
,
2689 sizeof(struct in6_addr
));
2690 bgp_info
->attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_VPNV6_GLOBAL
;
2696 static void *route_set_vpnv6_nexthop_compile(const char *arg
)
2699 struct in6_addr
*address
;
2701 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2702 ret
= inet_pton(AF_INET6
, arg
, address
);
2705 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2712 static void route_set_vpn_nexthop_free(void *rule
)
2714 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2717 /* Route map commands for ipv4 next-hop set. */
2718 struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd
= {
2719 "ipv4 vpn next-hop", route_set_vpnv4_nexthop
,
2720 route_set_vpnv4_nexthop_compile
, route_set_vpn_nexthop_free
};
2722 /* Route map commands for ipv6 next-hop set. */
2723 struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd
= {
2724 "ipv6 vpn next-hop", route_set_vpnv6_nexthop
,
2725 route_set_vpnv6_nexthop_compile
, route_set_vpn_nexthop_free
};
2727 /* `set originator-id' */
2729 /* For origin set. */
2730 static route_map_result_t
route_set_originator_id(void *rule
,
2731 const struct prefix
*prefix
,
2732 route_map_object_t type
,
2735 struct in_addr
*address
;
2736 struct bgp_info
*bgp_info
;
2738 if (type
== RMAP_BGP
) {
2742 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2743 bgp_info
->attr
->originator_id
= *address
;
2749 /* Compile function for originator-id set. */
2750 static void *route_set_originator_id_compile(const char *arg
)
2753 struct in_addr
*address
;
2755 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in_addr
));
2757 ret
= inet_aton(arg
, address
);
2760 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2767 /* Compile function for originator_id set. */
2768 static void route_set_originator_id_free(void *rule
)
2770 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2773 /* Set originator-id rule structure. */
2774 struct route_map_rule_cmd route_set_originator_id_cmd
= {
2775 "originator-id", route_set_originator_id
,
2776 route_set_originator_id_compile
, route_set_originator_id_free
,
2779 /* Add bgp route map rule. */
2780 static int bgp_route_match_add(struct vty
*vty
, const char *command
,
2781 const char *arg
, route_map_event_t type
)
2783 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
2784 int retval
= CMD_SUCCESS
;
2787 ret
= route_map_add_match(index
, command
, arg
);
2789 case RMAP_RULE_MISSING
:
2790 vty_out(vty
, "%% BGP Can't find rule.\n");
2791 retval
= CMD_WARNING_CONFIG_FAILED
;
2793 case RMAP_COMPILE_ERROR
:
2794 vty_out(vty
, "%% BGP Argument is malformed.\n");
2795 retval
= CMD_WARNING_CONFIG_FAILED
;
2797 case RMAP_COMPILE_SUCCESS
:
2798 if (type
!= RMAP_EVENT_MATCH_ADDED
) {
2799 route_map_upd8_dependency(type
, arg
, index
->map
->name
);
2807 /* Delete bgp route map rule. */
2808 static int bgp_route_match_delete(struct vty
*vty
, const char *command
,
2809 const char *arg
, route_map_event_t type
)
2811 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
2813 int retval
= CMD_SUCCESS
;
2814 char *dep_name
= NULL
;
2816 char *rmap_name
= NULL
;
2818 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
2819 /* ignore the mundane, the types without any dependency */
2821 if ((tmpstr
= route_map_get_match_arg(index
, command
))
2824 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
2826 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
2828 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
2831 ret
= route_map_delete_match(index
, command
, dep_name
);
2833 case RMAP_RULE_MISSING
:
2834 vty_out(vty
, "%% BGP Can't find rule.\n");
2835 retval
= CMD_WARNING_CONFIG_FAILED
;
2837 case RMAP_COMPILE_ERROR
:
2838 vty_out(vty
, "%% BGP Argument is malformed.\n");
2839 retval
= CMD_WARNING_CONFIG_FAILED
;
2841 case RMAP_COMPILE_SUCCESS
:
2842 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
2843 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
2848 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
2850 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
2856 * This is the workhorse routine for processing in/out routemap
2859 static void bgp_route_map_process_peer(const char *rmap_name
,
2860 struct route_map
*map
, struct peer
*peer
,
2861 int afi
, int safi
, int route_update
)
2865 struct bgp_filter
*filter
;
2867 if (!peer
|| !rmap_name
)
2870 filter
= &peer
->filter
[afi
][safi
];
2872 * in is for non-route-server clients,
2873 * out is for all peers
2875 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_RSERVER_CLIENT
)) {
2876 if (filter
->map
[RMAP_IN
].name
2877 && (strcmp(rmap_name
, filter
->map
[RMAP_IN
].name
) == 0)) {
2878 filter
->map
[RMAP_IN
].map
= map
;
2880 if (route_update
&& peer
->status
== Established
) {
2881 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2882 PEER_FLAG_SOFT_RECONFIG
)) {
2883 if (bgp_debug_update(peer
, NULL
, NULL
,
2886 "Processing route_map %s update on "
2887 "peer %s (inbound, soft-reconfig)",
2888 rmap_name
, peer
->host
);
2890 bgp_soft_reconfig_in(peer
, afi
, safi
);
2892 CHECK_FLAG(peer
->cap
,
2893 PEER_CAP_REFRESH_OLD_RCV
)
2896 PEER_CAP_REFRESH_NEW_RCV
)) {
2898 if (bgp_debug_update(peer
, NULL
, NULL
,
2901 "Processing route_map %s update on "
2902 "peer %s (inbound, route-refresh)",
2903 rmap_name
, peer
->host
);
2904 bgp_route_refresh_send(peer
, afi
, safi
,
2911 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_RSERVER_CLIENT
)) {
2914 if (update
&& route_update
&& peer
->status
== Established
) {
2915 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2916 PEER_FLAG_SOFT_RECONFIG
)) {
2917 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2919 "Processing route_map %s update on "
2920 "peer %s (import, soft-reconfig)",
2921 rmap_name
, peer
->host
);
2923 bgp_soft_reconfig_in(peer
, afi
, safi
);
2924 } else if (CHECK_FLAG(peer
->cap
,
2925 PEER_CAP_REFRESH_OLD_RCV
)
2926 || CHECK_FLAG(peer
->cap
,
2927 PEER_CAP_REFRESH_NEW_RCV
)) {
2928 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2930 "Processing route_map %s update on "
2931 "peer %s (import, route-refresh)",
2932 rmap_name
, peer
->host
);
2933 bgp_route_refresh_send(peer
, afi
, safi
, 0, 0,
2936 /* DD: Else, what else do we do ? Reset peer ? */
2941 * For outbound, unsuppress and default-originate map change (content or
2942 * map created), merely update the "config" here, the actual route
2943 * announcement happens at the group level.
2945 if (filter
->map
[RMAP_OUT
].name
2946 && (strcmp(rmap_name
, filter
->map
[RMAP_OUT
].name
) == 0))
2947 filter
->map
[RMAP_OUT
].map
= map
;
2949 if (filter
->usmap
.name
&& (strcmp(rmap_name
, filter
->usmap
.name
) == 0))
2950 filter
->usmap
.map
= map
;
2952 if (peer
->default_rmap
[afi
][safi
].name
2953 && (strcmp(rmap_name
, peer
->default_rmap
[afi
][safi
].name
) == 0))
2954 peer
->default_rmap
[afi
][safi
].map
= map
;
2957 static void bgp_route_map_update_peer_group(const char *rmap_name
,
2958 struct route_map
*map
,
2961 struct peer_group
*group
;
2962 struct listnode
*node
, *nnode
;
2963 struct bgp_filter
*filter
;
2970 /* All the peers have been updated correctly already. This is
2971 * just updating the placeholder data. No real update required.
2973 for (ALL_LIST_ELEMENTS(bgp
->group
, node
, nnode
, group
)) {
2974 FOREACH_AFI_SAFI (afi
, safi
) {
2975 filter
= &group
->conf
->filter
[afi
][safi
];
2977 for (direct
= RMAP_IN
; direct
< RMAP_MAX
; direct
++) {
2978 if ((filter
->map
[direct
].name
)
2979 && (strcmp(rmap_name
,
2980 filter
->map
[direct
].name
)
2982 filter
->map
[direct
].map
= map
;
2985 if (filter
->usmap
.name
2986 && (strcmp(rmap_name
, filter
->usmap
.name
) == 0))
2987 filter
->usmap
.map
= map
;
2993 * Note that if an extreme number (tens of thousands) of route-maps are in use
2994 * and if bgp has an extreme number of peers, network statements, etc then this
2995 * function can consume a lot of cycles. This is due to this function being
2996 * called for each route-map and within this function we walk the list of peers,
2997 * network statements, etc looking to see if they use this route-map.
2999 static void bgp_route_map_process_update(struct bgp
*bgp
, const char *rmap_name
,
3006 struct bgp_node
*bn
;
3007 struct bgp_static
*bgp_static
;
3008 struct listnode
*node
, *nnode
;
3009 struct route_map
*map
;
3010 char buf
[INET6_ADDRSTRLEN
];
3012 map
= route_map_lookup_by_name(rmap_name
);
3014 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
3016 /* Ignore dummy peer-group structure */
3017 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
))
3020 FOREACH_AFI_SAFI (afi
, safi
) {
3021 /* process in/out/import/export/default-orig
3023 bgp_route_map_process_peer(rmap_name
, map
, peer
, afi
,
3024 safi
, route_update
);
3028 /* for outbound/default-orig route-maps, process for groups */
3029 update_group_policy_update(bgp
, BGP_POLICY_ROUTE_MAP
, rmap_name
,
3032 /* update peer-group config (template) */
3033 bgp_route_map_update_peer_group(rmap_name
, map
, bgp
);
3035 FOREACH_AFI_SAFI (afi
, safi
) {
3036 /* For table route-map updates. */
3037 if (!bgp_fibupd_safi(safi
))
3040 if (bgp
->table_map
[afi
][safi
].name
3041 && (strcmp(rmap_name
, bgp
->table_map
[afi
][safi
].name
)
3043 bgp
->table_map
[afi
][safi
].map
= map
;
3045 if (BGP_DEBUG(zebra
, ZEBRA
))
3047 "Processing route_map %s update on "
3051 bgp_zebra_announce_table(bgp
, afi
, safi
);
3054 /* For network route-map updates. */
3055 for (bn
= bgp_table_top(bgp
->route
[afi
][safi
]); bn
;
3056 bn
= bgp_route_next(bn
))
3057 if ((bgp_static
= bn
->info
) != NULL
) {
3058 if (bgp_static
->rmap
.name
3059 && (strcmp(rmap_name
, bgp_static
->rmap
.name
)
3061 bgp_static
->rmap
.map
= map
;
3064 if (!bgp_static
->backdoor
) {
3065 if (bgp_debug_zebra(
3068 "Processing route_map %s update on "
3085 /* For redistribute route-map updates. */
3086 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3087 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
3088 struct list
*red_list
;
3089 struct bgp_redist
*red
;
3091 red_list
= bgp
->redist
[afi
][i
];
3095 for (ALL_LIST_ELEMENTS_RO(red_list
, node
, red
)) {
3097 && (strcmp(rmap_name
, red
->rmap
.name
)
3099 red
->rmap
.map
= map
;
3102 if (BGP_DEBUG(zebra
, ZEBRA
))
3104 "Processing route_map %s update on "
3105 "redistributed routes",
3108 bgp_redistribute_resend(
3116 /* for type5 command route-maps */
3117 FOREACH_AFI_SAFI (afi
, safi
) {
3118 if (bgp
->adv_cmd_rmap
[afi
][safi
].name
3119 && strcmp(rmap_name
, bgp
->adv_cmd_rmap
[afi
][safi
].name
)
3121 if (BGP_DEBUG(zebra
, ZEBRA
))
3123 "Processing route_map %s update on advertise type5 route command",
3125 bgp_evpn_withdraw_type5_routes(bgp
, afi
, safi
);
3126 bgp_evpn_advertise_type5_routes(bgp
, afi
, safi
);
3131 static void bgp_route_map_process_update_cb(char *rmap_name
)
3133 struct listnode
*node
, *nnode
;
3136 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3137 bgp_route_map_process_update(bgp
, rmap_name
, 1);
3140 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3141 vnc_routemap_update(bgp
, __func__
);
3145 vpn_policy_routemap_event(rmap_name
);
3148 int bgp_route_map_update_timer(struct thread
*thread
)
3150 bm
->t_rmap_update
= NULL
;
3152 route_map_walk_update_list(bgp_route_map_process_update_cb
);
3157 static void bgp_route_map_mark_update(const char *rmap_name
)
3159 if (bm
->t_rmap_update
== NULL
) {
3160 struct listnode
*node
, *nnode
;
3163 /* rmap_update_timer of 0 means don't do route updates */
3164 if (bm
->rmap_update_timer
) {
3165 bm
->t_rmap_update
= NULL
;
3166 thread_add_timer(bm
->master
, bgp_route_map_update_timer
,
3167 NULL
, bm
->rmap_update_timer
,
3168 &bm
->t_rmap_update
);
3170 /* Signal the groups that a route-map update event has
3172 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3173 update_group_policy_update(bgp
,
3174 BGP_POLICY_ROUTE_MAP
,
3177 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3178 bgp_route_map_process_update(bgp
, rmap_name
, 0);
3180 zlog_debug("%s: calling vnc_routemap_update", __func__
);
3181 vnc_routemap_update(bgp
, __func__
);
3187 static void bgp_route_map_add(const char *rmap_name
)
3189 if (route_map_mark_updated(rmap_name
) == 0)
3190 bgp_route_map_mark_update(rmap_name
);
3192 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
3195 static void bgp_route_map_delete(const char *rmap_name
)
3197 if (route_map_mark_updated(rmap_name
) == 0)
3198 bgp_route_map_mark_update(rmap_name
);
3200 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
3203 static void bgp_route_map_event(route_map_event_t event
, const char *rmap_name
)
3205 if (route_map_mark_updated(rmap_name
) == 0)
3206 bgp_route_map_mark_update(rmap_name
);
3208 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
3211 DEFUN (match_mac_address
,
3212 match_mac_address_cmd
,
3213 "match mac address WORD",
3216 "Match address of route\n"
3217 "MAC Access-list name\n")
3219 return bgp_route_match_add(vty
, "mac address", argv
[3]->arg
,
3220 RMAP_EVENT_FILTER_ADDED
);
3223 DEFUN (no_match_mac_address
,
3224 no_match_mac_address_cmd
,
3225 "no match mac address WORD",
3229 "Match address of route\n"
3230 "MAC acess-list name\n")
3232 return bgp_route_match_delete(vty
, "mac address", argv
[4]->arg
,
3233 RMAP_EVENT_FILTER_DELETED
);
3236 DEFUN (match_evpn_route_type
,
3237 match_evpn_route_type_cmd
,
3238 "match evpn route-type <macip | multicast | prefix>",
3241 "Match route-type\n"
3246 return bgp_route_match_add(vty
, "evpn route-type", argv
[3]->arg
,
3247 RMAP_EVENT_MATCH_ADDED
);
3250 DEFUN (no_match_evpn_route_type
,
3251 no_match_evpn_route_type_cmd
,
3252 "no match evpn route-type <macip | multicast | prefix>",
3256 "Match route-type\n"
3261 return bgp_route_match_delete(vty
, "evpn route-type", argv
[4]->arg
,
3262 RMAP_EVENT_MATCH_DELETED
);
3266 DEFUN (match_evpn_vni
,
3268 "match evpn vni (1-16777215)",
3274 return bgp_route_match_add(vty
, "evpn vni", argv
[3]->arg
,
3275 RMAP_EVENT_MATCH_ADDED
);
3278 DEFUN (no_match_evpn_vni
,
3279 no_match_evpn_vni_cmd
,
3280 "no match evpn vni (1-16777215)",
3287 return bgp_route_match_delete(vty
, "evpn vni", argv
[4]->arg
,
3288 RMAP_EVENT_MATCH_DELETED
);
3291 DEFUN (match_evpn_default_route
,
3292 match_evpn_default_route_cmd
,
3293 "match evpn default-route",
3296 "default EVPN type-5 route\n")
3298 return bgp_route_match_add(vty
, "evpn default-route", NULL
,
3299 RMAP_EVENT_MATCH_ADDED
);
3302 DEFUN (no_match_evpn_default_route
,
3303 no_match_evpn_default_route_cmd
,
3304 "no match evpn default-route",
3308 "default EVPN type-5 route\n")
3310 return bgp_route_match_delete(vty
, "evpn default-route", NULL
,
3311 RMAP_EVENT_MATCH_DELETED
);
3316 "match peer <A.B.C.D|X:X::X:X|WORD>",
3318 "Match peer address\n"
3319 "IP address of peer\n"
3320 "IPv6 address of peer\n"
3321 "Interface name of peer\n")
3324 return bgp_route_match_add(vty
, "peer", argv
[idx_ip
]->arg
,
3325 RMAP_EVENT_MATCH_ADDED
);
3328 DEFUN (match_peer_local
,
3329 match_peer_local_cmd
,
3332 "Match peer address\n"
3333 "Static or Redistributed routes\n")
3335 return bgp_route_match_add(vty
, "peer", "local",
3336 RMAP_EVENT_MATCH_DELETED
);
3339 DEFUN (no_match_peer
,
3341 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
3344 "Match peer address\n"
3345 "Static or Redistributed routes\n"
3346 "IP address of peer\n"
3347 "IPv6 address of peer\n"
3348 "Interface name of peer\n")
3352 if (argc
<= idx_peer
)
3353 return bgp_route_match_delete(vty
, "peer", NULL
,
3354 RMAP_EVENT_MATCH_DELETED
);
3355 return bgp_route_match_delete(vty
, "peer", argv
[idx_peer
]->arg
,
3356 RMAP_EVENT_MATCH_DELETED
);
3360 /* match probability */
3361 DEFUN (match_probability
,
3362 match_probability_cmd
,
3363 "match probability (0-100)",
3365 "Match portion of routes defined by percentage value\n"
3366 "Percentage of routes\n")
3369 return bgp_route_match_add(vty
, "probability", argv
[idx_number
]->arg
,
3370 RMAP_EVENT_MATCH_ADDED
);
3374 DEFUN (no_match_probability
,
3375 no_match_probability_cmd
,
3376 "no match probability [(1-99)]",
3379 "Match portion of routes defined by percentage value\n"
3380 "Percentage of routes\n")
3383 if (argc
<= idx_number
)
3384 return bgp_route_match_delete(vty
, "probability", NULL
,
3385 RMAP_EVENT_MATCH_DELETED
);
3386 return bgp_route_match_delete(vty
, "probability", argv
[idx_number
]->arg
,
3387 RMAP_EVENT_MATCH_DELETED
);
3391 DEFUN (match_ip_route_source
,
3392 match_ip_route_source_cmd
,
3393 "match ip route-source <(1-199)|(1300-2699)|WORD>",
3396 "Match advertising source address of route\n"
3397 "IP access-list number\n"
3398 "IP access-list number (expanded range)\n"
3399 "IP standard access-list name\n")
3402 return bgp_route_match_add(vty
, "ip route-source", argv
[idx_acl
]->arg
,
3403 RMAP_EVENT_FILTER_ADDED
);
3407 DEFUN (no_match_ip_route_source
,
3408 no_match_ip_route_source_cmd
,
3409 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
3413 "Match advertising source address of route\n"
3414 "IP access-list number\n"
3415 "IP access-list number (expanded range)\n"
3416 "IP standard access-list name\n")
3419 if (argc
<= idx_number
)
3420 return bgp_route_match_delete(vty
, "ip route-source", NULL
,
3421 RMAP_EVENT_FILTER_DELETED
);
3422 return bgp_route_match_delete(vty
, "ip route-source",
3423 argv
[idx_number
]->arg
,
3424 RMAP_EVENT_FILTER_DELETED
);
3428 DEFUN (match_ip_route_source_prefix_list
,
3429 match_ip_route_source_prefix_list_cmd
,
3430 "match ip route-source prefix-list WORD",
3433 "Match advertising source address of route\n"
3434 "Match entries of prefix-lists\n"
3435 "IP prefix-list name\n")
3438 return bgp_route_match_add(vty
, "ip route-source prefix-list",
3439 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
3443 DEFUN (no_match_ip_route_source_prefix_list
,
3444 no_match_ip_route_source_prefix_list_cmd
,
3445 "no match ip route-source prefix-list [WORD]",
3449 "Match advertising source address of route\n"
3450 "Match entries of prefix-lists\n"
3451 "IP prefix-list name\n")
3454 if (argc
<= idx_word
)
3455 return bgp_route_match_delete(vty
,
3456 "ip route-source prefix-list",
3457 NULL
, RMAP_EVENT_PLIST_DELETED
);
3458 return bgp_route_match_delete(vty
, "ip route-source prefix-list",
3459 argv
[idx_word
]->arg
,
3460 RMAP_EVENT_PLIST_DELETED
);
3464 DEFUN (match_local_pref
,
3465 match_local_pref_cmd
,
3466 "match local-preference (0-4294967295)",
3468 "Match local-preference of route\n"
3472 return bgp_route_match_add(vty
, "local-preference",
3473 argv
[idx_number
]->arg
,
3474 RMAP_EVENT_MATCH_ADDED
);
3478 DEFUN (no_match_local_pref
,
3479 no_match_local_pref_cmd
,
3480 "no match local-preference [(0-4294967295)]",
3483 "Match local preference of route\n"
3484 "Local preference value\n")
3486 int idx_localpref
= 3;
3487 if (argc
<= idx_localpref
)
3488 return bgp_route_match_delete(vty
, "local-preference", NULL
,
3489 RMAP_EVENT_MATCH_DELETED
);
3490 return bgp_route_match_delete(vty
, "local-preference",
3491 argv
[idx_localpref
]->arg
,
3492 RMAP_EVENT_MATCH_DELETED
);
3496 DEFUN (match_community
,
3497 match_community_cmd
,
3498 "match community <(1-99)|(100-500)|WORD> [exact-match]",
3500 "Match BGP community list\n"
3501 "Community-list number (standard)\n"
3502 "Community-list number (expanded)\n"
3503 "Community-list name\n"
3504 "Do exact matching of communities\n")
3506 int idx_comm_list
= 2;
3511 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
3512 strlen(argv
[idx_comm_list
]->arg
)
3513 + strlen("exact-match") + 2);
3515 sprintf(argstr
, "%s exact-match", argv
[idx_comm_list
]->arg
);
3517 argstr
= argv
[idx_comm_list
]->arg
;
3519 ret
= bgp_route_match_add(vty
, "community", argstr
,
3520 RMAP_EVENT_CLIST_ADDED
);
3522 if (argstr
!= argv
[idx_comm_list
]->arg
)
3523 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
3528 DEFUN (no_match_community
,
3529 no_match_community_cmd
,
3530 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
3533 "Match BGP community list\n"
3534 "Community-list number (standard)\n"
3535 "Community-list number (expanded)\n"
3536 "Community-list name\n"
3537 "Do exact matching of communities\n")
3539 return bgp_route_match_delete(vty
, "community", NULL
,
3540 RMAP_EVENT_CLIST_DELETED
);
3543 DEFUN (match_lcommunity
,
3544 match_lcommunity_cmd
,
3545 "match large-community <(1-99)|(100-500)|WORD>",
3547 "Match BGP large community list\n"
3548 "Large Community-list number (standard)\n"
3549 "Large Community-list number (expanded)\n"
3550 "Large Community-list name\n")
3552 return bgp_route_match_add(vty
, "large-community", argv
[2]->arg
,
3553 RMAP_EVENT_LLIST_ADDED
);
3556 DEFUN (no_match_lcommunity
,
3557 no_match_lcommunity_cmd
,
3558 "no match large-community [<(1-99)|(100-500)|WORD>]",
3561 "Match BGP large community list\n"
3562 "Large Community-list number (standard)\n"
3563 "Large Community-list number (expanded)\n"
3564 "Large Community-list name\n")
3566 return bgp_route_match_delete(vty
, "large-community", NULL
,
3567 RMAP_EVENT_LLIST_DELETED
);
3570 DEFUN (match_ecommunity
,
3571 match_ecommunity_cmd
,
3572 "match extcommunity <(1-99)|(100-500)|WORD>",
3574 "Match BGP/VPN extended community list\n"
3575 "Extended community-list number (standard)\n"
3576 "Extended community-list number (expanded)\n"
3577 "Extended community-list name\n")
3579 int idx_comm_list
= 2;
3580 return bgp_route_match_add(vty
, "extcommunity",
3581 argv
[idx_comm_list
]->arg
,
3582 RMAP_EVENT_ECLIST_ADDED
);
3586 DEFUN (no_match_ecommunity
,
3587 no_match_ecommunity_cmd
,
3588 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
3591 "Match BGP/VPN extended community list\n"
3592 "Extended community-list number (standard)\n"
3593 "Extended community-list number (expanded)\n"
3594 "Extended community-list name\n")
3596 return bgp_route_match_delete(vty
, "extcommunity", NULL
,
3597 RMAP_EVENT_ECLIST_DELETED
);
3601 DEFUN (match_aspath
,
3603 "match as-path WORD",
3605 "Match BGP AS path list\n"
3606 "AS path access-list name\n")
3609 return bgp_route_match_add(vty
, "as-path", argv
[idx_word
]->arg
,
3610 RMAP_EVENT_ASLIST_ADDED
);
3614 DEFUN (no_match_aspath
,
3615 no_match_aspath_cmd
,
3616 "no match as-path [WORD]",
3619 "Match BGP AS path list\n"
3620 "AS path access-list name\n")
3622 return bgp_route_match_delete(vty
, "as-path", NULL
,
3623 RMAP_EVENT_ASLIST_DELETED
);
3627 DEFUN (match_origin
,
3629 "match origin <egp|igp|incomplete>",
3634 "unknown heritage\n")
3637 if (strncmp(argv
[idx_origin
]->arg
, "igp", 2) == 0)
3638 return bgp_route_match_add(vty
, "origin", "igp",
3639 RMAP_EVENT_MATCH_ADDED
);
3640 if (strncmp(argv
[idx_origin
]->arg
, "egp", 1) == 0)
3641 return bgp_route_match_add(vty
, "origin", "egp",
3642 RMAP_EVENT_MATCH_ADDED
);
3643 if (strncmp(argv
[idx_origin
]->arg
, "incomplete", 2) == 0)
3644 return bgp_route_match_add(vty
, "origin", "incomplete",
3645 RMAP_EVENT_MATCH_ADDED
);
3647 vty_out(vty
, "%% Invalid match origin type\n");
3648 return CMD_WARNING_CONFIG_FAILED
;
3652 DEFUN (no_match_origin
,
3653 no_match_origin_cmd
,
3654 "no match origin [<egp|igp|incomplete>]",
3660 "unknown heritage\n")
3662 return bgp_route_match_delete(vty
, "origin", NULL
,
3663 RMAP_EVENT_MATCH_DELETED
);
3666 DEFUN (set_ip_nexthop_peer
,
3667 set_ip_nexthop_peer_cmd
,
3668 "[no] set ip next-hop peer-address",
3672 "Next hop address\n"
3673 "Use peer address (for BGP only)\n")
3675 int (*func
)(struct vty
*, struct route_map_index
*, const char *,
3676 const char *) = strmatch(argv
[0]->text
, "no")
3677 ? generic_set_delete
3680 return func(vty
, VTY_GET_CONTEXT(route_map_index
), "ip next-hop",
3684 DEFUN (set_ip_nexthop_unchanged
,
3685 set_ip_nexthop_unchanged_cmd
,
3686 "[no] set ip next-hop unchanged",
3690 "Next hop address\n"
3691 "Don't modify existing Next hop address\n")
3693 int (*func
)(struct vty
*, struct route_map_index
*, const char *,
3694 const char *) = strmatch(argv
[0]->text
, "no")
3695 ? generic_set_delete
3698 return func(vty
, VTY_GET_CONTEXT(route_map_index
), "ip next-hop",
3703 DEFUN (set_local_pref
,
3705 "set local-preference (0-4294967295)",
3707 "BGP local preference path attribute\n"
3708 "Preference value\n")
3711 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3712 "local-preference", argv
[idx_number
]->arg
);
3716 DEFUN (no_set_local_pref
,
3717 no_set_local_pref_cmd
,
3718 "no set local-preference [(0-4294967295)]",
3721 "BGP local preference path attribute\n"
3722 "Preference value\n")
3724 int idx_localpref
= 3;
3725 if (argc
<= idx_localpref
)
3726 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3727 "local-preference", NULL
);
3728 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3729 "local-preference", argv
[idx_localpref
]->arg
);
3735 "set weight (0-4294967295)",
3737 "BGP weight for routing table\n"
3741 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
), "weight",
3742 argv
[idx_number
]->arg
);
3746 DEFUN (no_set_weight
,
3748 "no set weight [(0-4294967295)]",
3751 "BGP weight for routing table\n"
3755 if (argc
<= idx_weight
)
3756 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3758 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3759 "weight", argv
[idx_weight
]->arg
);
3762 DEFUN (set_label_index
,
3763 set_label_index_cmd
,
3764 "set label-index (0-1048560)",
3766 "Label index to associate with the prefix\n"
3767 "Label index value\n")
3770 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3771 "label-index", argv
[idx_number
]->arg
);
3774 DEFUN (no_set_label_index
,
3775 no_set_label_index_cmd
,
3776 "no set label-index [(0-1048560)]",
3779 "Label index to associate with the prefix\n"
3780 "Label index value\n")
3782 int idx_label_index
= 3;
3783 if (argc
<= idx_label_index
)
3784 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3785 "label-index", NULL
);
3786 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3787 "label-index", argv
[idx_label_index
]->arg
);
3790 DEFUN (set_aspath_prepend_asn
,
3791 set_aspath_prepend_asn_cmd
,
3792 "set as-path prepend (1-4294967295)...",
3794 "Transform BGP AS_PATH attribute\n"
3795 "Prepend to the as-path\n"
3802 str
= argv_concat(argv
, argc
, idx_asn
);
3803 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3804 "as-path prepend", str
);
3805 XFREE(MTYPE_TMP
, str
);
3810 DEFUN (set_aspath_prepend_lastas
,
3811 set_aspath_prepend_lastas_cmd
,
3812 "set as-path prepend last-as (1-10)",
3814 "Transform BGP AS_PATH attribute\n"
3815 "Prepend to the as-path\n"
3816 "Use the peer's AS-number\n"
3817 "Number of times to insert\n")
3819 return set_aspath_prepend_asn(self
, vty
, argc
, argv
);
3822 DEFUN (no_set_aspath_prepend
,
3823 no_set_aspath_prepend_cmd
,
3824 "no set as-path prepend [(1-4294967295)]",
3827 "Transform BGP AS_PATH attribute\n"
3828 "Prepend to the as-path\n"
3835 str
= argv_concat(argv
, argc
, idx_asn
);
3836 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3837 "as-path prepend", str
);
3838 XFREE(MTYPE_TMP
, str
);
3843 DEFUN (set_aspath_exclude
,
3844 set_aspath_exclude_cmd
,
3845 "set as-path exclude (1-4294967295)...",
3847 "Transform BGP AS-path attribute\n"
3848 "Exclude from the as-path\n"
3855 str
= argv_concat(argv
, argc
, idx_asn
);
3856 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3857 "as-path exclude", str
);
3858 XFREE(MTYPE_TMP
, str
);
3862 DEFUN (no_set_aspath_exclude
,
3863 no_set_aspath_exclude_cmd
,
3864 "no set as-path exclude (1-4294967295)...",
3867 "Transform BGP AS_PATH attribute\n"
3868 "Exclude from the as-path\n"
3875 str
= argv_concat(argv
, argc
, idx_asn
);
3876 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3877 "as-path exclude", str
);
3878 XFREE(MTYPE_TMP
, str
);
3883 DEFUN (set_community
,
3885 "set community AA:NN...",
3887 "BGP community attribute\n"
3895 struct community
*com
= NULL
;
3900 b
= buffer_new(1024);
3902 for (i
= idx_aa_nn
; i
< argc
; i
++) {
3903 if (strncmp(argv
[i
]->arg
, "additive", strlen(argv
[i
]->arg
))
3910 buffer_putc(b
, ' ');
3914 if (strncmp(argv
[i
]->arg
, "internet", strlen(argv
[i
]->arg
))
3916 buffer_putstr(b
, "internet");
3919 if (strncmp(argv
[i
]->arg
, "local-AS", strlen(argv
[i
]->arg
))
3921 buffer_putstr(b
, "local-AS");
3924 if (strncmp(argv
[i
]->arg
, "no-a", strlen("no-a")) == 0
3925 && strncmp(argv
[i
]->arg
, "no-advertise",
3926 strlen(argv
[i
]->arg
))
3928 buffer_putstr(b
, "no-advertise");
3931 if (strncmp(argv
[i
]->arg
, "no-e", strlen("no-e")) == 0
3932 && strncmp(argv
[i
]->arg
, "no-export", strlen(argv
[i
]->arg
))
3934 buffer_putstr(b
, "no-export");
3937 if (strncmp(argv
[i
]->arg
, "graceful-shutdown",
3938 strlen(argv
[i
]->arg
))
3940 buffer_putstr(b
, "graceful-shutdown");
3943 buffer_putstr(b
, argv
[i
]->arg
);
3945 buffer_putc(b
, '\0');
3947 /* Fetch result string then compile it to communities attribute. */
3948 str
= buffer_getstr(b
);
3952 com
= community_str2com(str
);
3953 XFREE(MTYPE_TMP
, str
);
3956 /* Can't compile user input into communities attribute. */
3958 vty_out(vty
, "%% Malformed communities attribute\n");
3959 return CMD_WARNING_CONFIG_FAILED
;
3962 /* Set communites attribute string. */
3963 str
= community_str(com
, false);
3966 argstr
= XCALLOC(MTYPE_TMP
,
3967 strlen(str
) + strlen(" additive") + 1);
3968 strcpy(argstr
, str
);
3969 strcpy(argstr
+ strlen(str
), " additive");
3970 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3971 "community", argstr
);
3972 XFREE(MTYPE_TMP
, argstr
);
3974 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3977 community_free(com
);
3982 DEFUN (set_community_none
,
3983 set_community_none_cmd
,
3984 "set community none",
3986 "BGP community attribute\n"
3987 "No community attribute\n")
3989 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3990 "community", "none");
3993 DEFUN (no_set_community
,
3994 no_set_community_cmd
,
3995 "no set community AA:NN...",
3998 "BGP community attribute\n"
4001 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4006 DEFUN (set_community_delete
,
4007 set_community_delete_cmd
,
4008 "set comm-list <(1-99)|(100-500)|WORD> delete",
4010 "set BGP community list (for deletion)\n"
4011 "Community-list number (standard)\n"
4012 "Community-list number (expanded)\n"
4013 "Community-list name\n"
4014 "Delete matching communities\n")
4016 int idx_comm_list
= 2;
4019 str
= XCALLOC(MTYPE_TMP
,
4020 strlen(argv
[idx_comm_list
]->arg
) + strlen(" delete") + 1);
4021 strcpy(str
, argv
[idx_comm_list
]->arg
);
4022 strcpy(str
+ strlen(argv
[idx_comm_list
]->arg
), " delete");
4024 generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
), "comm-list",
4027 XFREE(MTYPE_TMP
, str
);
4031 DEFUN (no_set_community_delete
,
4032 no_set_community_delete_cmd
,
4033 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
4036 "set BGP community list (for deletion)\n"
4037 "Community-list number (standard)\n"
4038 "Community-list number (expanded)\n"
4039 "Community-list name\n"
4040 "Delete matching communities\n")
4042 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4046 DEFUN (set_lcommunity
,
4048 "set large-community AA:BB:CC...",
4050 "BGP large community attribute\n"
4051 "Large Community number in aa:bb:cc format or additive\n")
4056 str
= argv_concat(argv
, argc
, 2);
4057 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4058 "large-community", str
);
4059 XFREE(MTYPE_TMP
, str
);
4064 DEFUN (set_lcommunity_none
,
4065 set_lcommunity_none_cmd
,
4066 "set large-community none",
4068 "BGP large community attribute\n"
4069 "No large community attribute\n")
4071 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4072 "large-community", "none");
4075 DEFUN (no_set_lcommunity
,
4076 no_set_lcommunity_cmd
,
4077 "no set large-community none",
4080 "BGP large community attribute\n"
4081 "No community attribute\n")
4083 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4084 "large-community", NULL
);
4087 DEFUN (no_set_lcommunity1
,
4088 no_set_lcommunity1_cmd
,
4089 "no set large-community AA:BB:CC...",
4092 "BGP large community attribute\n"
4093 "Large community in AA:BB:CC... format or additive\n")
4095 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4096 "large-community", NULL
);
4099 DEFUN (set_lcommunity_delete
,
4100 set_lcommunity_delete_cmd
,
4101 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4103 "set BGP large community list (for deletion)\n"
4104 "Large Community-list number (standard)\n"
4105 "Large Communitly-list number (expanded)\n"
4106 "Large Community-list name\n"
4107 "Delete matching large communities\n")
4111 str
= XCALLOC(MTYPE_TMP
, strlen(argv
[2]->arg
) + strlen(" delete") + 1);
4112 strcpy(str
, argv
[2]->arg
);
4113 strcpy(str
+ strlen(argv
[2]->arg
), " delete");
4115 generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4116 "large-comm-list", str
);
4118 XFREE(MTYPE_TMP
, str
);
4122 DEFUN (no_set_lcommunity_delete
,
4123 no_set_lcommunity_delete_cmd
,
4124 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
4127 "set BGP large community list (for deletion)\n"
4128 "Large Community-list number (standard)\n"
4129 "Large Communitly-list number (expanded)\n"
4130 "Large Community-list name\n"
4131 "Delete matching large communities\n")
4133 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4134 "large-comm-list", NULL
);
4137 DEFUN (set_ecommunity_rt
,
4138 set_ecommunity_rt_cmd
,
4139 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4141 "BGP extended community attribute\n"
4142 "Route Target extended community\n"
4143 "VPN extended community\n")
4149 str
= argv_concat(argv
, argc
, idx_asn_nn
);
4150 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4151 "extcommunity rt", str
);
4152 XFREE(MTYPE_TMP
, str
);
4157 DEFUN (no_set_ecommunity_rt
,
4158 no_set_ecommunity_rt_cmd
,
4159 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4162 "BGP extended community attribute\n"
4163 "Route Target extended community\n"
4164 "VPN extended community\n")
4166 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4167 "extcommunity rt", NULL
);
4171 DEFUN (set_ecommunity_soo
,
4172 set_ecommunity_soo_cmd
,
4173 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4175 "BGP extended community attribute\n"
4176 "Site-of-Origin extended community\n"
4177 "VPN extended community\n")
4183 str
= argv_concat(argv
, argc
, idx_asn_nn
);
4184 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4185 "extcommunity soo", str
);
4186 XFREE(MTYPE_TMP
, str
);
4191 DEFUN (no_set_ecommunity_soo
,
4192 no_set_ecommunity_soo_cmd
,
4193 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4196 "BGP extended community attribute\n"
4197 "Site-of-Origin extended community\n"
4198 "VPN extended community\n")
4200 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4201 "extcommunity soo", NULL
);
4207 "set origin <egp|igp|incomplete>",
4212 "unknown heritage\n")
4215 if (strncmp(argv
[idx_origin
]->arg
, "igp", 2) == 0)
4216 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4218 if (strncmp(argv
[idx_origin
]->arg
, "egp", 1) == 0)
4219 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4221 if (strncmp(argv
[idx_origin
]->arg
, "incomplete", 2) == 0)
4222 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4223 "origin", "incomplete");
4225 vty_out(vty
, "%% Invalid set origin type\n");
4226 return CMD_WARNING_CONFIG_FAILED
;
4230 DEFUN (no_set_origin
,
4232 "no set origin [<egp|igp|incomplete>]",
4238 "unknown heritage\n")
4240 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4245 DEFUN (set_atomic_aggregate
,
4246 set_atomic_aggregate_cmd
,
4247 "set atomic-aggregate",
4249 "BGP atomic aggregate attribute\n" )
4251 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4252 "atomic-aggregate", NULL
);
4255 DEFUN (no_set_atomic_aggregate
,
4256 no_set_atomic_aggregate_cmd
,
4257 "no set atomic-aggregate",
4260 "BGP atomic aggregate attribute\n" )
4262 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4263 "atomic-aggregate", NULL
);
4266 DEFUN (set_aggregator_as
,
4267 set_aggregator_as_cmd
,
4268 "set aggregator as (1-4294967295) A.B.C.D",
4270 "BGP aggregator attribute\n"
4271 "AS number of aggregator\n"
4273 "IP address of aggregator\n")
4278 struct in_addr address
;
4281 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &address
);
4283 vty_out(vty
, "Aggregator IP address is invalid\n");
4284 return CMD_WARNING_CONFIG_FAILED
;
4287 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
4288 strlen(argv
[idx_number
]->arg
)
4289 + strlen(argv
[idx_ipv4
]->arg
) + 2);
4291 sprintf(argstr
, "%s %s", argv
[idx_number
]->arg
, argv
[idx_ipv4
]->arg
);
4293 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4294 "aggregator as", argstr
);
4296 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
4302 DEFUN (no_set_aggregator_as
,
4303 no_set_aggregator_as_cmd
,
4304 "no set aggregator as [(1-4294967295) A.B.C.D]",
4307 "BGP aggregator attribute\n"
4308 "AS number of aggregator\n"
4310 "IP address of aggregator\n")
4315 struct in_addr address
;
4318 if (argc
<= idx_asn
)
4319 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4320 "aggregator as", NULL
);
4322 ret
= inet_aton(argv
[idx_ip
]->arg
, &address
);
4324 vty_out(vty
, "Aggregator IP address is invalid\n");
4325 return CMD_WARNING_CONFIG_FAILED
;
4328 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
4329 strlen(argv
[idx_asn
]->arg
) + strlen(argv
[idx_ip
]->arg
)
4332 sprintf(argstr
, "%s %s", argv
[idx_asn
]->arg
, argv
[idx_ip
]->arg
);
4334 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4335 "aggregator as", argstr
);
4337 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
4342 DEFUN (match_ipv6_next_hop
,
4343 match_ipv6_next_hop_cmd
,
4344 "match ipv6 next-hop X:X::X:X",
4347 "Match IPv6 next-hop address of route\n"
4348 "IPv6 address of next hop\n")
4351 return bgp_route_match_add(vty
, "ipv6 next-hop", argv
[idx_ipv6
]->arg
,
4352 RMAP_EVENT_MATCH_ADDED
);
4355 DEFUN (no_match_ipv6_next_hop
,
4356 no_match_ipv6_next_hop_cmd
,
4357 "no match ipv6 next-hop X:X::X:X",
4361 "Match IPv6 next-hop address of route\n"
4362 "IPv6 address of next hop\n")
4365 return bgp_route_match_delete(vty
, "ipv6 next-hop", argv
[idx_ipv6
]->arg
,
4366 RMAP_EVENT_MATCH_DELETED
);
4370 DEFUN (set_ipv6_nexthop_peer
,
4371 set_ipv6_nexthop_peer_cmd
,
4372 "set ipv6 next-hop peer-address",
4375 "Next hop address\n"
4376 "Use peer address (for BGP only)\n")
4378 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4379 "ipv6 next-hop peer-address", NULL
);
4382 DEFUN (no_set_ipv6_nexthop_peer
,
4383 no_set_ipv6_nexthop_peer_cmd
,
4384 "no set ipv6 next-hop peer-address",
4388 "IPv6 next-hop address\n"
4389 "Use peer address (for BGP only)\n")
4391 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4392 "ipv6 next-hop peer-address", NULL
);
4395 DEFUN (set_ipv6_nexthop_prefer_global
,
4396 set_ipv6_nexthop_prefer_global_cmd
,
4397 "set ipv6 next-hop prefer-global",
4400 "IPv6 next-hop address\n"
4401 "Prefer global over link-local if both exist\n")
4403 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4404 "ipv6 next-hop prefer-global", NULL
);
4408 DEFUN (no_set_ipv6_nexthop_prefer_global
,
4409 no_set_ipv6_nexthop_prefer_global_cmd
,
4410 "no set ipv6 next-hop prefer-global",
4414 "IPv6 next-hop address\n"
4415 "Prefer global over link-local if both exist\n")
4417 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4418 "ipv6 next-hop prefer-global", NULL
);
4421 DEFUN (set_ipv6_nexthop_global
,
4422 set_ipv6_nexthop_global_cmd
,
4423 "set ipv6 next-hop global X:X::X:X",
4426 "IPv6 next-hop address\n"
4427 "IPv6 global address\n"
4428 "IPv6 address of next hop\n")
4431 struct in6_addr addr
;
4434 ret
= inet_pton(AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
4436 vty_out(vty
, "%% Malformed nexthop address\n");
4437 return CMD_WARNING_CONFIG_FAILED
;
4439 if (IN6_IS_ADDR_UNSPECIFIED(&addr
) || IN6_IS_ADDR_LOOPBACK(&addr
)
4440 || IN6_IS_ADDR_MULTICAST(&addr
) || IN6_IS_ADDR_LINKLOCAL(&addr
)) {
4441 vty_out(vty
, "%% Invalid global nexthop address\n");
4442 return CMD_WARNING_CONFIG_FAILED
;
4445 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4446 "ipv6 next-hop global", argv
[idx_ipv6
]->arg
);
4450 DEFUN (no_set_ipv6_nexthop_global
,
4451 no_set_ipv6_nexthop_global_cmd
,
4452 "no set ipv6 next-hop global X:X::X:X",
4456 "IPv6 next-hop address\n"
4457 "IPv6 global address\n"
4458 "IPv6 address of next hop\n")
4461 if (argc
<= idx_ipv6
)
4462 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4463 "ipv6 next-hop global", NULL
);
4464 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4465 "ipv6 next-hop global", argv
[idx_ipv6
]->arg
);
4468 #ifdef KEEP_OLD_VPN_COMMANDS
4469 DEFUN (set_vpn_nexthop
,
4470 set_vpn_nexthop_cmd
,
4471 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4473 "VPNv4 information\n"
4474 "VPN next-hop address\n"
4475 "IP address of next hop\n"
4476 "VPNv6 information\n"
4477 "VPN next-hop address\n"
4478 "IPv6 address of next hop\n")
4484 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
4486 return generic_set_add(
4487 vty
, VTY_GET_CONTEXT(route_map_index
),
4488 "ipv4 vpn next-hop", argv
[idx_ip
]->arg
);
4490 return generic_set_add(
4491 vty
, VTY_GET_CONTEXT(route_map_index
),
4492 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4497 DEFUN (no_set_vpn_nexthop
,
4498 no_set_vpn_nexthop_cmd
,
4499 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4502 "VPNv4 information\n"
4503 "VPN next-hop address\n"
4504 "IP address of next hop\n"
4505 "VPNv6 information\n"
4506 "VPN next-hop address\n"
4507 "IPv6 address of next hop\n")
4517 arg
= argv
[idx_ip
]->arg
;
4518 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
4520 return generic_set_delete(
4521 vty
, VTY_GET_CONTEXT(route_map_index
),
4522 "ipv4 vpn next-hop", arg
);
4524 return generic_set_delete(
4525 vty
, VTY_GET_CONTEXT(route_map_index
),
4526 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4530 #endif /* KEEP_OLD_VPN_COMMANDS */
4532 DEFUN (set_ipx_vpn_nexthop
,
4533 set_ipx_vpn_nexthop_cmd
,
4534 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
4536 "IPv4 information\n"
4537 "IPv6 information\n"
4539 "VPN next-hop address\n"
4540 "IP address of next hop\n"
4541 "IPv6 address of next hop\n")
4547 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
4549 return generic_set_add(
4550 vty
, VTY_GET_CONTEXT(route_map_index
),
4551 "ipv4 vpn next-hop", argv
[idx_ip
]->arg
);
4553 return generic_set_add(
4554 vty
, VTY_GET_CONTEXT(route_map_index
),
4555 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4560 DEFUN (no_set_ipx_vpn_nexthop
,
4561 no_set_ipx_vpn_nexthop_cmd
,
4562 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
4565 "IPv4 information\n"
4566 "IPv6 information\n"
4568 "VPN next-hop address\n"
4569 "IP address of next hop\n"
4570 "IPv6 address of next hop\n")
4580 arg
= argv
[idx_ip
]->arg
;
4581 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
4583 return generic_set_delete(
4584 vty
, VTY_GET_CONTEXT(route_map_index
),
4585 "ipv4 vpn next-hop", arg
);
4587 return generic_set_delete(
4588 vty
, VTY_GET_CONTEXT(route_map_index
),
4589 "ipv6 vpn next-hop", arg
);
4594 DEFUN (set_originator_id
,
4595 set_originator_id_cmd
,
4596 "set originator-id A.B.C.D",
4598 "BGP originator ID attribute\n"
4599 "IP address of originator\n")
4602 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4603 "originator-id", argv
[idx_ipv4
]->arg
);
4607 DEFUN (no_set_originator_id
,
4608 no_set_originator_id_cmd
,
4609 "no set originator-id [A.B.C.D]",
4612 "BGP originator ID attribute\n"
4613 "IP address of originator\n")
4617 argv_find(argv
, argc
, "A.B.C.D", &idx
) ? argv
[idx
]->arg
: NULL
;
4619 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4620 "originator-id", arg
);
4624 /* Initialization of route map. */
4625 void bgp_route_map_init(void)
4629 route_map_add_hook(bgp_route_map_add
);
4630 route_map_delete_hook(bgp_route_map_delete
);
4631 route_map_event_hook(bgp_route_map_event
);
4633 route_map_match_interface_hook(generic_match_add
);
4634 route_map_no_match_interface_hook(generic_match_delete
);
4636 route_map_match_ip_address_hook(generic_match_add
);
4637 route_map_no_match_ip_address_hook(generic_match_delete
);
4639 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
4640 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
4642 route_map_match_ip_next_hop_hook(generic_match_add
);
4643 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
4645 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
4646 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
4648 route_map_match_ipv6_address_hook(generic_match_add
);
4649 route_map_no_match_ipv6_address_hook(generic_match_delete
);
4651 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
4652 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
4654 route_map_match_metric_hook(generic_match_add
);
4655 route_map_no_match_metric_hook(generic_match_delete
);
4657 route_map_match_tag_hook(generic_match_add
);
4658 route_map_no_match_tag_hook(generic_match_delete
);
4660 route_map_set_ip_nexthop_hook(generic_set_add
);
4661 route_map_no_set_ip_nexthop_hook(generic_set_delete
);
4663 route_map_set_ipv6_nexthop_local_hook(generic_set_add
);
4664 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete
);
4666 route_map_set_metric_hook(generic_set_add
);
4667 route_map_no_set_metric_hook(generic_set_delete
);
4669 route_map_set_tag_hook(generic_set_add
);
4670 route_map_no_set_tag_hook(generic_set_delete
);
4672 route_map_install_match(&route_match_peer_cmd
);
4673 route_map_install_match(&route_match_local_pref_cmd
);
4674 route_map_install_match(&route_match_ip_address_cmd
);
4675 route_map_install_match(&route_match_ip_next_hop_cmd
);
4676 route_map_install_match(&route_match_ip_route_source_cmd
);
4677 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
4678 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
4679 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd
);
4680 route_map_install_match(&route_match_aspath_cmd
);
4681 route_map_install_match(&route_match_community_cmd
);
4682 route_map_install_match(&route_match_lcommunity_cmd
);
4683 route_map_install_match(&route_match_ecommunity_cmd
);
4684 route_map_install_match(&route_match_local_pref_cmd
);
4685 route_map_install_match(&route_match_metric_cmd
);
4686 route_map_install_match(&route_match_origin_cmd
);
4687 route_map_install_match(&route_match_probability_cmd
);
4688 route_map_install_match(&route_match_interface_cmd
);
4689 route_map_install_match(&route_match_tag_cmd
);
4690 route_map_install_match(&route_match_mac_address_cmd
);
4691 route_map_install_match(&route_match_evpn_vni_cmd
);
4692 route_map_install_match(&route_match_evpn_route_type_cmd
);
4693 route_map_install_match(&route_match_evpn_default_route_cmd
);
4695 route_map_install_set(&route_set_ip_nexthop_cmd
);
4696 route_map_install_set(&route_set_local_pref_cmd
);
4697 route_map_install_set(&route_set_weight_cmd
);
4698 route_map_install_set(&route_set_label_index_cmd
);
4699 route_map_install_set(&route_set_metric_cmd
);
4700 route_map_install_set(&route_set_aspath_prepend_cmd
);
4701 route_map_install_set(&route_set_aspath_exclude_cmd
);
4702 route_map_install_set(&route_set_origin_cmd
);
4703 route_map_install_set(&route_set_atomic_aggregate_cmd
);
4704 route_map_install_set(&route_set_aggregator_as_cmd
);
4705 route_map_install_set(&route_set_community_cmd
);
4706 route_map_install_set(&route_set_community_delete_cmd
);
4707 route_map_install_set(&route_set_lcommunity_cmd
);
4708 route_map_install_set(&route_set_lcommunity_delete_cmd
);
4709 route_map_install_set(&route_set_vpnv4_nexthop_cmd
);
4710 route_map_install_set(&route_set_vpnv6_nexthop_cmd
);
4711 route_map_install_set(&route_set_originator_id_cmd
);
4712 route_map_install_set(&route_set_ecommunity_rt_cmd
);
4713 route_map_install_set(&route_set_ecommunity_soo_cmd
);
4714 route_map_install_set(&route_set_tag_cmd
);
4715 route_map_install_set(&route_set_label_index_cmd
);
4717 install_element(RMAP_NODE
, &match_peer_cmd
);
4718 install_element(RMAP_NODE
, &match_peer_local_cmd
);
4719 install_element(RMAP_NODE
, &no_match_peer_cmd
);
4720 install_element(RMAP_NODE
, &match_ip_route_source_cmd
);
4721 install_element(RMAP_NODE
, &no_match_ip_route_source_cmd
);
4722 install_element(RMAP_NODE
, &match_ip_route_source_prefix_list_cmd
);
4723 install_element(RMAP_NODE
, &no_match_ip_route_source_prefix_list_cmd
);
4724 install_element(RMAP_NODE
, &match_mac_address_cmd
);
4725 install_element(RMAP_NODE
, &no_match_mac_address_cmd
);
4726 install_element(RMAP_NODE
, &match_evpn_vni_cmd
);
4727 install_element(RMAP_NODE
, &no_match_evpn_vni_cmd
);
4728 install_element(RMAP_NODE
, &match_evpn_route_type_cmd
);
4729 install_element(RMAP_NODE
, &no_match_evpn_route_type_cmd
);
4730 install_element(RMAP_NODE
, &match_evpn_default_route_cmd
);
4731 install_element(RMAP_NODE
, &no_match_evpn_default_route_cmd
);
4733 install_element(RMAP_NODE
, &match_aspath_cmd
);
4734 install_element(RMAP_NODE
, &no_match_aspath_cmd
);
4735 install_element(RMAP_NODE
, &match_local_pref_cmd
);
4736 install_element(RMAP_NODE
, &no_match_local_pref_cmd
);
4737 install_element(RMAP_NODE
, &match_community_cmd
);
4738 install_element(RMAP_NODE
, &no_match_community_cmd
);
4739 install_element(RMAP_NODE
, &match_lcommunity_cmd
);
4740 install_element(RMAP_NODE
, &no_match_lcommunity_cmd
);
4741 install_element(RMAP_NODE
, &match_ecommunity_cmd
);
4742 install_element(RMAP_NODE
, &no_match_ecommunity_cmd
);
4743 install_element(RMAP_NODE
, &match_origin_cmd
);
4744 install_element(RMAP_NODE
, &no_match_origin_cmd
);
4745 install_element(RMAP_NODE
, &match_probability_cmd
);
4746 install_element(RMAP_NODE
, &no_match_probability_cmd
);
4748 install_element(RMAP_NODE
, &set_ip_nexthop_peer_cmd
);
4749 install_element(RMAP_NODE
, &set_ip_nexthop_unchanged_cmd
);
4750 install_element(RMAP_NODE
, &set_local_pref_cmd
);
4751 install_element(RMAP_NODE
, &no_set_local_pref_cmd
);
4752 install_element(RMAP_NODE
, &set_weight_cmd
);
4753 install_element(RMAP_NODE
, &set_label_index_cmd
);
4754 install_element(RMAP_NODE
, &no_set_weight_cmd
);
4755 install_element(RMAP_NODE
, &no_set_label_index_cmd
);
4756 install_element(RMAP_NODE
, &set_aspath_prepend_asn_cmd
);
4757 install_element(RMAP_NODE
, &set_aspath_prepend_lastas_cmd
);
4758 install_element(RMAP_NODE
, &set_aspath_exclude_cmd
);
4759 install_element(RMAP_NODE
, &no_set_aspath_prepend_cmd
);
4760 install_element(RMAP_NODE
, &no_set_aspath_exclude_cmd
);
4761 install_element(RMAP_NODE
, &set_origin_cmd
);
4762 install_element(RMAP_NODE
, &no_set_origin_cmd
);
4763 install_element(RMAP_NODE
, &set_atomic_aggregate_cmd
);
4764 install_element(RMAP_NODE
, &no_set_atomic_aggregate_cmd
);
4765 install_element(RMAP_NODE
, &set_aggregator_as_cmd
);
4766 install_element(RMAP_NODE
, &no_set_aggregator_as_cmd
);
4767 install_element(RMAP_NODE
, &set_community_cmd
);
4768 install_element(RMAP_NODE
, &set_community_none_cmd
);
4769 install_element(RMAP_NODE
, &no_set_community_cmd
);
4770 install_element(RMAP_NODE
, &set_community_delete_cmd
);
4771 install_element(RMAP_NODE
, &no_set_community_delete_cmd
);
4772 install_element(RMAP_NODE
, &set_lcommunity_cmd
);
4773 install_element(RMAP_NODE
, &set_lcommunity_none_cmd
);
4774 install_element(RMAP_NODE
, &no_set_lcommunity_cmd
);
4775 install_element(RMAP_NODE
, &no_set_lcommunity1_cmd
);
4776 install_element(RMAP_NODE
, &set_lcommunity_delete_cmd
);
4777 install_element(RMAP_NODE
, &no_set_lcommunity_delete_cmd
);
4778 install_element(RMAP_NODE
, &set_ecommunity_rt_cmd
);
4779 install_element(RMAP_NODE
, &no_set_ecommunity_rt_cmd
);
4780 install_element(RMAP_NODE
, &set_ecommunity_soo_cmd
);
4781 install_element(RMAP_NODE
, &no_set_ecommunity_soo_cmd
);
4782 #ifdef KEEP_OLD_VPN_COMMANDS
4783 install_element(RMAP_NODE
, &set_vpn_nexthop_cmd
);
4784 install_element(RMAP_NODE
, &no_set_vpn_nexthop_cmd
);
4785 #endif /* KEEP_OLD_VPN_COMMANDS */
4786 install_element(RMAP_NODE
, &set_ipx_vpn_nexthop_cmd
);
4787 install_element(RMAP_NODE
, &no_set_ipx_vpn_nexthop_cmd
);
4788 install_element(RMAP_NODE
, &set_originator_id_cmd
);
4789 install_element(RMAP_NODE
, &no_set_originator_id_cmd
);
4791 route_map_install_match(&route_match_ipv6_address_cmd
);
4792 route_map_install_match(&route_match_ipv6_next_hop_cmd
);
4793 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
4794 route_map_install_set(&route_set_ipv6_nexthop_global_cmd
);
4795 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd
);
4796 route_map_install_set(&route_set_ipv6_nexthop_local_cmd
);
4797 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd
);
4799 install_element(RMAP_NODE
, &match_ipv6_next_hop_cmd
);
4800 install_element(RMAP_NODE
, &no_match_ipv6_next_hop_cmd
);
4801 install_element(RMAP_NODE
, &set_ipv6_nexthop_global_cmd
);
4802 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_global_cmd
);
4803 install_element(RMAP_NODE
, &set_ipv6_nexthop_prefer_global_cmd
);
4804 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_prefer_global_cmd
);
4805 install_element(RMAP_NODE
, &set_ipv6_nexthop_peer_cmd
);
4806 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_peer_cmd
);
4809 void bgp_route_map_terminate(void)
4811 /* ToDo: Cleanup all the used memory */