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"
41 #include "bgpd/bgpd.h"
42 #include "bgpd/bgp_table.h"
43 #include "bgpd/bgp_attr.h"
44 #include "bgpd/bgp_aspath.h"
45 #include "bgpd/bgp_packet.h"
46 #include "bgpd/bgp_route.h"
47 #include "bgpd/bgp_zebra.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_clist.h"
51 #include "bgpd/bgp_filter.h"
52 #include "bgpd/bgp_mplsvpn.h"
53 #include "bgpd/bgp_ecommunity.h"
54 #include "bgpd/bgp_lcommunity.h"
55 #include "bgpd/bgp_vty.h"
56 #include "bgpd/bgp_debug.h"
57 #include "bgpd/bgp_evpn.h"
58 #include "bgpd/bgp_evpn_private.h"
59 #include "bgpd/bgp_evpn_vty.h"
62 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
65 /* Memo of route-map commands.
74 ip route-source : Done
78 ipv6 route-source: (This will not be implemented by bgpd)
79 ipv6 prefix-list : Done
80 length : (This will not be implemented by bgpd)
82 route-type : (This will not be implemented by bgpd)
84 local-preference : Done
86 set as-path prepend : Done
88 automatic-tag : (This will not be implemented by bgpd)
90 large-community : Done
91 large-comm-list : Done
94 default : (This will not be implemented by bgpd)
95 interface : (This will not be implemented by bgpd)
96 ip default : (This will not be implemented by bgpd)
98 ip precedence : (This will not be implemented by bgpd)
99 ip tos : (This will not be implemented by bgpd)
100 level : (This will not be implemented by bgpd)
101 local-preference : Done
103 metric-type : Not yet
110 set ipv6 next-hop global: Done
111 set ipv6 next-hop prefer-global: Done
112 set ipv6 next-hop local : Done
113 set as-path exclude : Done
117 /* generic value manipulation to be shared in multiple rules */
119 #define RMAP_VALUE_SET 0
120 #define RMAP_VALUE_ADD 1
121 #define RMAP_VALUE_SUB 2
129 static int route_value_match(struct rmap_value
*rv
, u_int32_t value
)
131 if (rv
->variable
== 0 && value
== rv
->value
)
137 static u_int32_t
route_value_adjust(struct rmap_value
*rv
, u_int32_t current
,
142 switch (rv
->variable
) {
151 switch (rv
->action
) {
153 if (current
> UINT32_MAX
- value
)
155 return current
+ value
;
157 if (current
<= value
)
159 return current
- value
;
165 static void *route_value_compile(const char *arg
)
167 u_int8_t action
= RMAP_VALUE_SET
, var
= 0;
168 unsigned long larg
= 0;
170 struct rmap_value
*rv
;
173 action
= RMAP_VALUE_ADD
;
175 } else if (arg
[0] == '-') {
176 action
= RMAP_VALUE_SUB
;
180 if (all_digit(arg
)) {
182 larg
= strtoul(arg
, &endptr
, 10);
183 if (*arg
== 0 || *endptr
!= 0 || errno
|| larg
> UINT32_MAX
)
186 if (strcmp(arg
, "rtt") == 0)
192 rv
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_value
));
202 static void route_value_free(void *rule
)
204 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
207 /* generic as path object to be shared in multiple rules */
209 static void *route_aspath_compile(const char *arg
)
211 struct aspath
*aspath
;
213 aspath
= aspath_str2aspath(arg
);
219 static void route_aspath_free(void *rule
)
221 struct aspath
*aspath
= rule
;
225 struct bgp_match_peer_compiled
{
230 /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
232 /* Compares the peer specified in the 'match peer' clause with the peer
233 received in bgp_info->peer. If it is the same, or if the peer structure
234 received is a peer_group containing it, returns RMAP_MATCH. */
235 static route_map_result_t
route_match_peer(void *rule
, struct prefix
*prefix
,
236 route_map_object_t type
,
239 struct bgp_match_peer_compiled
*pc
;
241 union sockunion su_def
= {
242 .sin
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= INADDR_ANY
}};
243 struct peer_group
*group
;
245 struct listnode
*node
, *nnode
;
247 if (type
== RMAP_BGP
) {
250 peer
= ((struct bgp_info
*)object
)->peer
;
256 if (strcmp(peer
->conf_if
, pc
->interface
) == 0)
262 /* If su='0.0.0.0' (command 'match peer local'), and it's a
264 REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH
266 if (sockunion_same(su
, &su_def
)) {
268 if (CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_NETWORK
)
269 || CHECK_FLAG(peer
->rmap_type
,
270 PEER_RMAP_TYPE_REDISTRIBUTE
)
271 || CHECK_FLAG(peer
->rmap_type
,
272 PEER_RMAP_TYPE_DEFAULT
))
279 if (!CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
280 if (sockunion_same(su
, &peer
->su
))
286 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
,
288 if (sockunion_same(su
, &peer
->su
))
297 static void *route_match_peer_compile(const char *arg
)
299 struct bgp_match_peer_compiled
*pc
;
302 pc
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
,
303 sizeof(struct bgp_match_peer_compiled
));
305 ret
= str2sockunion(strcmp(arg
, "local") ? arg
: "0.0.0.0", &pc
->su
);
307 pc
->interface
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
314 /* Free route map's compiled `ip address' value. */
315 static void route_match_peer_free(void *rule
)
317 struct bgp_match_peer_compiled
*pc
= rule
;
320 XFREE(MTYPE_ROUTE_MAP_COMPILED
, pc
->interface
);
322 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
325 /* Route map commands for ip address matching. */
326 struct route_map_rule_cmd route_match_peer_cmd
= {"peer", route_match_peer
,
327 route_match_peer_compile
,
328 route_match_peer_free
};
330 /* `match ip address IP_ACCESS_LIST' */
332 /* Match function should return 1 if match is success else return
334 static route_map_result_t
route_match_ip_address(void *rule
,
335 struct prefix
*prefix
,
336 route_map_object_t type
,
339 struct access_list
*alist
;
340 /* struct prefix_ipv4 match; */
342 if (type
== RMAP_BGP
) {
343 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
347 return (access_list_apply(alist
, prefix
) == FILTER_DENY
354 /* Route map `ip address' match statement. `arg' should be
356 static void *route_match_ip_address_compile(const char *arg
)
358 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
361 /* Free route map's compiled `ip address' value. */
362 static void route_match_ip_address_free(void *rule
)
364 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
367 /* Route map commands for ip address matching. */
368 struct route_map_rule_cmd route_match_ip_address_cmd
= {
369 "ip address", route_match_ip_address
, route_match_ip_address_compile
,
370 route_match_ip_address_free
};
372 /* `match ip next-hop IP_ADDRESS' */
374 /* Match function return 1 if match is success else return zero. */
375 static route_map_result_t
route_match_ip_next_hop(void *rule
,
376 struct prefix
*prefix
,
377 route_map_object_t type
,
380 struct access_list
*alist
;
381 struct bgp_info
*bgp_info
;
382 struct prefix_ipv4 p
;
384 if (type
== RMAP_BGP
) {
387 p
.prefix
= bgp_info
->attr
->nexthop
;
388 p
.prefixlen
= IPV4_MAX_BITLEN
;
390 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
394 return (access_list_apply(alist
, &p
) == FILTER_DENY
401 /* Route map `ip next-hop' match statement. `arg' is
403 static void *route_match_ip_next_hop_compile(const char *arg
)
405 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
408 /* Free route map's compiled `ip address' value. */
409 static void route_match_ip_next_hop_free(void *rule
)
411 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
414 /* Route map commands for ip next-hop matching. */
415 struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
416 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
417 route_match_ip_next_hop_free
};
419 /* `match ip route-source ACCESS-LIST' */
421 /* Match function return 1 if match is success else return zero. */
422 static route_map_result_t
route_match_ip_route_source(void *rule
,
423 struct prefix
*prefix
,
424 route_map_object_t type
,
427 struct access_list
*alist
;
428 struct bgp_info
*bgp_info
;
430 struct prefix_ipv4 p
;
432 if (type
== RMAP_BGP
) {
434 peer
= bgp_info
->peer
;
436 if (!peer
|| sockunion_family(&peer
->su
) != AF_INET
)
440 p
.prefix
= peer
->su
.sin
.sin_addr
;
441 p
.prefixlen
= IPV4_MAX_BITLEN
;
443 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
447 return (access_list_apply(alist
, &p
) == FILTER_DENY
454 /* Route map `ip route-source' match statement. `arg' is
456 static void *route_match_ip_route_source_compile(const char *arg
)
458 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
461 /* Free route map's compiled `ip address' value. */
462 static void route_match_ip_route_source_free(void *rule
)
464 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
467 /* Route map commands for ip route-source matching. */
468 struct route_map_rule_cmd route_match_ip_route_source_cmd
= {
469 "ip route-source", route_match_ip_route_source
,
470 route_match_ip_route_source_compile
, route_match_ip_route_source_free
};
472 /* `match ip address prefix-list PREFIX_LIST' */
474 static route_map_result_t
475 route_match_ip_address_prefix_list(void *rule
, struct prefix
*prefix
,
476 route_map_object_t type
, void *object
)
478 struct prefix_list
*plist
;
480 if (type
== RMAP_BGP
) {
481 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
485 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
492 static void *route_match_ip_address_prefix_list_compile(const char *arg
)
494 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
497 static void route_match_ip_address_prefix_list_free(void *rule
)
499 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
502 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
503 "ip address prefix-list", route_match_ip_address_prefix_list
,
504 route_match_ip_address_prefix_list_compile
,
505 route_match_ip_address_prefix_list_free
};
507 /* `match ip next-hop prefix-list PREFIX_LIST' */
509 static route_map_result_t
510 route_match_ip_next_hop_prefix_list(void *rule
, struct prefix
*prefix
,
511 route_map_object_t type
, void *object
)
513 struct prefix_list
*plist
;
514 struct bgp_info
*bgp_info
;
515 struct prefix_ipv4 p
;
517 if (type
== RMAP_BGP
) {
520 p
.prefix
= bgp_info
->attr
->nexthop
;
521 p
.prefixlen
= IPV4_MAX_BITLEN
;
523 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
527 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
534 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
536 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
539 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
541 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
544 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
545 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
546 route_match_ip_next_hop_prefix_list_compile
,
547 route_match_ip_next_hop_prefix_list_free
};
549 /* `match ip route-source prefix-list PREFIX_LIST' */
551 static route_map_result_t
552 route_match_ip_route_source_prefix_list(void *rule
, struct prefix
*prefix
,
553 route_map_object_t type
, void *object
)
555 struct prefix_list
*plist
;
556 struct bgp_info
*bgp_info
;
558 struct prefix_ipv4 p
;
560 if (type
== RMAP_BGP
) {
562 peer
= bgp_info
->peer
;
564 if (!peer
|| sockunion_family(&peer
->su
) != AF_INET
)
568 p
.prefix
= peer
->su
.sin
.sin_addr
;
569 p
.prefixlen
= IPV4_MAX_BITLEN
;
571 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
575 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
582 static void *route_match_ip_route_source_prefix_list_compile(const char *arg
)
584 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
587 static void route_match_ip_route_source_prefix_list_free(void *rule
)
589 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
592 struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd
= {
593 "ip route-source prefix-list", route_match_ip_route_source_prefix_list
,
594 route_match_ip_route_source_prefix_list_compile
,
595 route_match_ip_route_source_prefix_list_free
};
597 /* `match mac address MAC_ACCESS_LIST' */
599 /* Match function should return 1 if match is success else return
601 static route_map_result_t
route_match_mac_address(void *rule
,
602 struct prefix
*prefix
,
603 route_map_object_t type
,
606 struct access_list
*alist
;
609 if (type
== RMAP_BGP
) {
610 alist
= access_list_lookup(AFI_L2VPN
, (char *)rule
);
614 if (prefix
->u
.prefix_evpn
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
617 p
.family
= AF_ETHERNET
;
618 p
.prefixlen
= ETH_ALEN
* 8;
619 p
.u
.prefix_eth
= prefix
->u
.prefix_evpn
.mac
;
621 return (access_list_apply(alist
, &p
) == FILTER_DENY
629 /* Route map `mac address' match statement. `arg' should be
631 static void *route_match_mac_address_compile(const char *arg
)
633 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
636 /* Free route map's compiled `ip address' value. */
637 static void route_match_mac_address_free(void *rule
)
639 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
642 /* Route map commands for mac address matching. */
643 struct route_map_rule_cmd route_match_mac_address_cmd
= {
644 "mac address", route_match_mac_address
, route_match_mac_address_compile
,
645 route_match_mac_address_free
};
649 /* Match function should return 1 if match is success else return
651 static route_map_result_t
route_match_vni(void *rule
, struct prefix
*prefix
,
652 route_map_object_t type
, void *object
)
655 struct bgp_info
*bgp_info
= NULL
;
657 if (type
== RMAP_BGP
) {
658 vni
= *((vni_t
*)rule
);
659 bgp_info
= (struct bgp_info
*)object
;
661 if (vni
== label2vni(&bgp_info
->extra
->label
[0]))
668 /* Route map `vni' match statement. */
669 static void *route_match_vni_compile(const char *arg
)
674 vni
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(vni_t
));
678 *vni
= strtoul(arg
, &end
, 10);
680 XFREE(MTYPE_ROUTE_MAP_COMPILED
, vni
);
687 /* Free route map's compiled `vni' value. */
688 static void route_match_vni_free(void *rule
)
690 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
693 /* Route map commands for vni matching. */
694 struct route_map_rule_cmd route_match_evpn_vni_cmd
= {
695 "evpn vni", route_match_vni
, route_match_vni_compile
,
696 route_match_vni_free
};
698 /* `match evpn route-type' */
700 /* Match function should return 1 if match is success else return
702 static route_map_result_t
route_match_evpn_route_type(void *rule
,
703 struct prefix
*prefix
,
704 route_map_object_t type
,
707 u_char route_type
= 0;
709 if (type
== RMAP_BGP
) {
710 route_type
= *((u_char
*)rule
);
712 if (route_type
== prefix
->u
.prefix_evpn
.route_type
)
719 /* Route map `route-type' match statement. */
720 static void *route_match_evpn_route_type_compile(const char *arg
)
722 u_char
*route_type
= NULL
;
724 route_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(u_char
));
726 if (strncmp(arg
, "ma", 2) == 0)
727 *route_type
= BGP_EVPN_MAC_IP_ROUTE
;
728 else if (strncmp(arg
, "mu", 2) == 0)
729 *route_type
= BGP_EVPN_IMET_ROUTE
;
731 *route_type
= BGP_EVPN_IP_PREFIX_ROUTE
;
736 /* Free route map's compiled `route-type' value. */
737 static void route_match_evpn_route_type_free(void *rule
)
739 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
742 /* Route map commands for evpn route-type matching. */
743 struct route_map_rule_cmd route_match_evpn_route_type_cmd
= {
744 "evpn route-type", route_match_evpn_route_type
,
745 route_match_evpn_route_type_compile
,
746 route_match_evpn_route_type_free
};
748 /* `match local-preference LOCAL-PREF' */
750 /* Match function return 1 if match is success else return zero. */
751 static route_map_result_t
route_match_local_pref(void *rule
,
752 struct prefix
*prefix
,
753 route_map_object_t type
,
756 u_int32_t
*local_pref
;
757 struct bgp_info
*bgp_info
;
759 if (type
== RMAP_BGP
) {
763 if (bgp_info
->attr
->local_pref
== *local_pref
)
771 /* Route map `match local-preference' match statement.
772 `arg' is local-pref value */
773 static void *route_match_local_pref_compile(const char *arg
)
775 u_int32_t
*local_pref
;
777 unsigned long tmpval
;
779 /* Locpref value shoud be integer. */
784 tmpval
= strtoul(arg
, &endptr
, 10);
785 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
788 local_pref
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(u_int32_t
));
793 *local_pref
= tmpval
;
797 /* Free route map's compiled `match local-preference' value. */
798 static void route_match_local_pref_free(void *rule
)
800 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
803 /* Route map commands for metric matching. */
804 struct route_map_rule_cmd route_match_local_pref_cmd
= {
805 "local-preference", route_match_local_pref
,
806 route_match_local_pref_compile
, route_match_local_pref_free
};
808 /* `match metric METRIC' */
810 /* Match function return 1 if match is success else return zero. */
811 static route_map_result_t
route_match_metric(void *rule
, struct prefix
*prefix
,
812 route_map_object_t type
,
815 struct rmap_value
*rv
;
816 struct bgp_info
*bgp_info
;
818 if (type
== RMAP_BGP
) {
821 return route_value_match(rv
, bgp_info
->attr
->med
);
826 /* Route map commands for metric matching. */
827 struct route_map_rule_cmd route_match_metric_cmd
= {
828 "metric", route_match_metric
, route_value_compile
, route_value_free
,
831 /* `match as-path ASPATH' */
833 /* Match function for as-path match. I assume given object is */
834 static route_map_result_t
route_match_aspath(void *rule
, struct prefix
*prefix
,
835 route_map_object_t type
,
839 struct as_list
*as_list
;
840 struct bgp_info
*bgp_info
;
842 if (type
== RMAP_BGP
) {
843 as_list
= as_list_lookup((char *)rule
);
850 return ((as_list_apply(as_list
, bgp_info
->attr
->aspath
)
858 /* Compile function for as-path match. */
859 static void *route_match_aspath_compile(const char *arg
)
861 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
864 /* Compile function for as-path match. */
865 static void route_match_aspath_free(void *rule
)
867 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
870 /* Route map commands for aspath matching. */
871 struct route_map_rule_cmd route_match_aspath_cmd
= {
872 "as-path", route_match_aspath
, route_match_aspath_compile
,
873 route_match_aspath_free
};
875 /* `match community COMMUNIY' */
876 struct rmap_community
{
881 /* Match function for community match. */
882 static route_map_result_t
route_match_community(void *rule
,
883 struct prefix
*prefix
,
884 route_map_object_t type
,
887 struct community_list
*list
;
888 struct bgp_info
*bgp_info
;
889 struct rmap_community
*rcom
;
891 if (type
== RMAP_BGP
) {
895 list
= community_list_lookup(bgp_clist
, rcom
->name
,
896 COMMUNITY_LIST_MASTER
);
901 if (community_list_exact_match(
902 bgp_info
->attr
->community
, list
))
905 if (community_list_match(bgp_info
->attr
->community
,
913 /* Compile function for community match. */
914 static void *route_match_community_compile(const char *arg
)
916 struct rmap_community
*rcom
;
920 rcom
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_community
));
922 p
= strchr(arg
, ' ');
925 rcom
->name
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
926 memcpy(rcom
->name
, arg
, len
);
929 rcom
->name
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
935 /* Compile function for community match. */
936 static void route_match_community_free(void *rule
)
938 struct rmap_community
*rcom
= rule
;
940 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
->name
);
941 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
);
944 /* Route map commands for community matching. */
945 struct route_map_rule_cmd route_match_community_cmd
= {
946 "community", route_match_community
, route_match_community_compile
,
947 route_match_community_free
};
949 /* Match function for lcommunity match. */
950 static route_map_result_t
route_match_lcommunity(void *rule
,
951 struct prefix
*prefix
,
952 route_map_object_t type
,
955 struct community_list
*list
;
956 struct bgp_info
*bgp_info
;
957 struct rmap_community
*rcom
;
959 if (type
== RMAP_BGP
) {
963 list
= community_list_lookup(bgp_clist
, rcom
->name
,
964 LARGE_COMMUNITY_LIST_MASTER
);
968 if (lcommunity_list_match(bgp_info
->attr
->lcommunity
, list
))
974 /* Compile function for community match. */
975 static void *route_match_lcommunity_compile(const char *arg
)
977 struct rmap_community
*rcom
;
981 rcom
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_community
));
983 p
= strchr(arg
, ' ');
986 rcom
->name
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
987 memcpy(rcom
->name
, arg
, len
);
989 rcom
->name
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
995 /* Compile function for community match. */
996 static void route_match_lcommunity_free(void *rule
)
998 struct rmap_community
*rcom
= rule
;
1000 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
->name
);
1001 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
);
1004 /* Route map commands for community matching. */
1005 struct route_map_rule_cmd route_match_lcommunity_cmd
= {
1006 "large-community", route_match_lcommunity
,
1007 route_match_lcommunity_compile
, route_match_lcommunity_free
};
1010 /* Match function for extcommunity match. */
1011 static route_map_result_t
route_match_ecommunity(void *rule
,
1012 struct prefix
*prefix
,
1013 route_map_object_t type
,
1016 struct community_list
*list
;
1017 struct bgp_info
*bgp_info
;
1019 if (type
== RMAP_BGP
) {
1022 list
= community_list_lookup(bgp_clist
, (char *)rule
,
1023 EXTCOMMUNITY_LIST_MASTER
);
1025 return RMAP_NOMATCH
;
1027 if (ecommunity_list_match(bgp_info
->attr
->ecommunity
, list
))
1030 return RMAP_NOMATCH
;
1033 /* Compile function for extcommunity match. */
1034 static void *route_match_ecommunity_compile(const char *arg
)
1036 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1039 /* Compile function for extcommunity match. */
1040 static void route_match_ecommunity_free(void *rule
)
1042 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1045 /* Route map commands for community matching. */
1046 struct route_map_rule_cmd route_match_ecommunity_cmd
= {
1047 "extcommunity", route_match_ecommunity
, route_match_ecommunity_compile
,
1048 route_match_ecommunity_free
};
1050 /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1051 and `address-family vpnv4'. */
1053 /* `match origin' */
1054 static route_map_result_t
route_match_origin(void *rule
, struct prefix
*prefix
,
1055 route_map_object_t type
,
1059 struct bgp_info
*bgp_info
;
1061 if (type
== RMAP_BGP
) {
1065 if (bgp_info
->attr
->origin
== *origin
)
1069 return RMAP_NOMATCH
;
1072 static void *route_match_origin_compile(const char *arg
)
1076 origin
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(u_char
));
1078 if (strcmp(arg
, "igp") == 0)
1080 else if (strcmp(arg
, "egp") == 0)
1088 /* Free route map's compiled `ip address' value. */
1089 static void route_match_origin_free(void *rule
)
1091 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1094 /* Route map commands for origin matching. */
1095 struct route_map_rule_cmd route_match_origin_cmd
= {
1096 "origin", route_match_origin
, route_match_origin_compile
,
1097 route_match_origin_free
};
1099 /* match probability { */
1101 static route_map_result_t
route_match_probability(void *rule
,
1102 struct prefix
*prefix
,
1103 route_map_object_t type
,
1108 switch (*(long *)rule
) {
1114 if (r
< *(long *)rule
) {
1119 return RMAP_NOMATCH
;
1122 static void *route_match_probability_compile(const char *arg
)
1128 lobule
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(long));
1138 *lobule
= RAND_MAX
/ 100 * perc
;
1144 static void route_match_probability_free(void *rule
)
1146 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1149 struct route_map_rule_cmd route_match_probability_cmd
= {
1150 "probability", route_match_probability
, route_match_probability_compile
,
1151 route_match_probability_free
};
1153 /* `match interface IFNAME' */
1154 /* Match function should return 1 if match is success else return
1156 static route_map_result_t
route_match_interface(void *rule
,
1157 struct prefix
*prefix
,
1158 route_map_object_t type
,
1161 struct interface
*ifp
;
1162 struct bgp_info
*info
;
1164 if (type
== RMAP_BGP
) {
1167 if (!info
|| !info
->attr
)
1168 return RMAP_NOMATCH
;
1170 ifp
= if_lookup_by_name_all_vrf((char *)rule
);
1172 if (ifp
== NULL
|| ifp
->ifindex
!= info
->attr
->nh_ifindex
)
1173 return RMAP_NOMATCH
;
1177 return RMAP_NOMATCH
;
1180 /* Route map `interface' match statement. `arg' should be
1182 static void *route_match_interface_compile(const char *arg
)
1184 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1187 /* Free route map's compiled `interface' value. */
1188 static void route_match_interface_free(void *rule
)
1190 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1193 /* Route map commands for ip address matching. */
1194 struct route_map_rule_cmd route_match_interface_cmd
= {
1195 "interface", route_match_interface
, route_match_interface_compile
,
1196 route_match_interface_free
};
1200 /* `set ip next-hop IP_ADDRESS' */
1202 /* Match function return 1 if match is success else return zero. */
1203 static route_map_result_t
route_match_tag(void *rule
, struct prefix
*prefix
,
1204 route_map_object_t type
, void *object
)
1207 struct bgp_info
*bgp_info
;
1209 if (type
== RMAP_BGP
) {
1213 return ((bgp_info
->attr
->tag
== *tag
) ? RMAP_MATCH
1217 return RMAP_NOMATCH
;
1221 /* Route map commands for tag matching. */
1222 static struct route_map_rule_cmd route_match_tag_cmd
= {
1223 "tag", route_match_tag
, route_map_rule_tag_compile
,
1224 route_map_rule_tag_free
,
1228 /* Set nexthop to object. ojbect must be pointer to struct attr. */
1229 struct rmap_ip_nexthop_set
{
1230 struct in_addr
*address
;
1235 static route_map_result_t
route_set_ip_nexthop(void *rule
,
1236 struct prefix
*prefix
,
1237 route_map_object_t type
,
1240 struct rmap_ip_nexthop_set
*rins
= rule
;
1241 struct bgp_info
*bgp_info
;
1244 if (type
== RMAP_BGP
) {
1246 peer
= bgp_info
->peer
;
1248 if (rins
->unchanged
) {
1249 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1250 BATTR_RMAP_NEXTHOP_UNCHANGED
);
1251 } else if (rins
->peer_address
) {
1252 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
1253 || CHECK_FLAG(peer
->rmap_type
,
1254 PEER_RMAP_TYPE_IMPORT
))
1256 && sockunion_family(peer
->su_remote
) == AF_INET
) {
1257 bgp_info
->attr
->nexthop
.s_addr
=
1258 sockunion2ip(peer
->su_remote
);
1259 bgp_info
->attr
->flag
|=
1260 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1261 } else if (CHECK_FLAG(peer
->rmap_type
,
1262 PEER_RMAP_TYPE_OUT
)) {
1263 /* The next hop value will be set as part of
1265 * Set the flags here to indicate that rewrite
1267 * Also, clear the value.
1269 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1270 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
);
1271 bgp_info
->attr
->nexthop
.s_addr
= 0;
1274 /* Set next hop value. */
1275 bgp_info
->attr
->flag
|=
1276 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1277 bgp_info
->attr
->nexthop
= *rins
->address
;
1278 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1279 BATTR_RMAP_IPV4_NHOP_CHANGED
);
1286 /* Route map `ip nexthop' compile function. Given string is converted
1287 to struct in_addr structure. */
1288 static void *route_set_ip_nexthop_compile(const char *arg
)
1290 struct rmap_ip_nexthop_set
*rins
;
1291 struct in_addr
*address
= NULL
;
1292 int peer_address
= 0;
1296 if (strcmp(arg
, "peer-address") == 0)
1298 else if (strcmp(arg
, "unchanged") == 0)
1301 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
1302 sizeof(struct in_addr
));
1303 ret
= inet_aton(arg
, address
);
1306 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
1311 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
,
1312 sizeof(struct rmap_ip_nexthop_set
));
1314 rins
->address
= address
;
1315 rins
->peer_address
= peer_address
;
1316 rins
->unchanged
= unchanged
;
1321 /* Free route map's compiled `ip nexthop' value. */
1322 static void route_set_ip_nexthop_free(void *rule
)
1324 struct rmap_ip_nexthop_set
*rins
= rule
;
1327 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rins
->address
);
1329 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rins
);
1332 /* Route map commands for ip nexthop set. */
1333 struct route_map_rule_cmd route_set_ip_nexthop_cmd
= {
1334 "ip next-hop", route_set_ip_nexthop
, route_set_ip_nexthop_compile
,
1335 route_set_ip_nexthop_free
};
1337 /* `set local-preference LOCAL_PREF' */
1339 /* Set local preference. */
1340 static route_map_result_t
route_set_local_pref(void *rule
,
1341 struct prefix
*prefix
,
1342 route_map_object_t type
,
1345 struct rmap_value
*rv
;
1346 struct bgp_info
*bgp_info
;
1347 u_int32_t locpref
= 0;
1349 if (type
== RMAP_BGP
) {
1350 /* Fetch routemap's rule information. */
1354 /* Set local preference value. */
1355 if (bgp_info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
1356 locpref
= bgp_info
->attr
->local_pref
;
1358 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1359 bgp_info
->attr
->local_pref
=
1360 route_value_adjust(rv
, locpref
, bgp_info
->peer
);
1366 /* Set local preference rule structure. */
1367 struct route_map_rule_cmd route_set_local_pref_cmd
= {
1368 "local-preference", route_set_local_pref
, route_value_compile
,
1372 /* `set weight WEIGHT' */
1375 static route_map_result_t
route_set_weight(void *rule
, struct prefix
*prefix
,
1376 route_map_object_t type
,
1379 struct rmap_value
*rv
;
1380 struct bgp_info
*bgp_info
;
1382 if (type
== RMAP_BGP
) {
1383 /* Fetch routemap's rule information. */
1387 /* Set weight value. */
1388 bgp_info
->attr
->weight
=
1389 route_value_adjust(rv
, 0, bgp_info
->peer
);
1395 /* Set local preference rule structure. */
1396 struct route_map_rule_cmd route_set_weight_cmd
= {
1397 "weight", route_set_weight
, route_value_compile
, route_value_free
,
1400 /* `set metric METRIC' */
1402 /* Set metric to attribute. */
1403 static route_map_result_t
route_set_metric(void *rule
, struct prefix
*prefix
,
1404 route_map_object_t type
,
1407 struct rmap_value
*rv
;
1408 struct bgp_info
*bgp_info
;
1411 if (type
== RMAP_BGP
) {
1412 /* Fetch routemap's rule information. */
1416 if (bgp_info
->attr
->flag
1417 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1418 med
= bgp_info
->attr
->med
;
1420 bgp_info
->attr
->med
=
1421 route_value_adjust(rv
, med
, bgp_info
->peer
);
1422 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1427 /* Set metric rule structure. */
1428 struct route_map_rule_cmd route_set_metric_cmd
= {
1429 "metric", route_set_metric
, route_value_compile
, route_value_free
,
1432 /* `set as-path prepend ASPATH' */
1434 /* For AS path prepend mechanism. */
1435 static route_map_result_t
route_set_aspath_prepend(void *rule
,
1436 struct prefix
*prefix
,
1437 route_map_object_t type
,
1440 struct aspath
*aspath
;
1442 struct bgp_info
*binfo
;
1444 if (type
== RMAP_BGP
) {
1447 if (binfo
->attr
->aspath
->refcnt
)
1448 new = aspath_dup(binfo
->attr
->aspath
);
1450 new = binfo
->attr
->aspath
;
1452 if ((uintptr_t)rule
> 10) {
1454 aspath_prepend(aspath
, new);
1456 as_t as
= aspath_leftmost(new);
1458 as
= binfo
->peer
->as
;
1459 new = aspath_add_seq_n(new, as
, (uintptr_t)rule
);
1462 binfo
->attr
->aspath
= new;
1468 static void *route_set_aspath_prepend_compile(const char *arg
)
1472 if (sscanf(arg
, "last-as %u", &num
) == 1 && num
> 0 && num
<= 10)
1473 return (void *)(uintptr_t)num
;
1475 return route_aspath_compile(arg
);
1478 static void route_set_aspath_prepend_free(void *rule
)
1480 if ((uintptr_t)rule
> 10)
1481 route_aspath_free(rule
);
1485 /* Set as-path prepend rule structure. */
1486 struct route_map_rule_cmd route_set_aspath_prepend_cmd
= {
1487 "as-path prepend", route_set_aspath_prepend
,
1488 route_set_aspath_prepend_compile
, route_set_aspath_prepend_free
,
1491 /* `set as-path exclude ASn' */
1493 /* For ASN exclude mechanism.
1494 * Iterate over ASns requested and filter them from the given AS_PATH one by
1496 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1498 static route_map_result_t
route_set_aspath_exclude(void *rule
,
1499 struct prefix
*dummy
,
1500 route_map_object_t type
,
1503 struct aspath
*new_path
, *exclude_path
;
1504 struct bgp_info
*binfo
;
1506 if (type
== RMAP_BGP
) {
1507 exclude_path
= rule
;
1509 if (binfo
->attr
->aspath
->refcnt
)
1510 new_path
= aspath_dup(binfo
->attr
->aspath
);
1512 new_path
= binfo
->attr
->aspath
;
1513 binfo
->attr
->aspath
=
1514 aspath_filter_exclude(new_path
, exclude_path
);
1519 /* Set ASn exlude rule structure. */
1520 struct route_map_rule_cmd route_set_aspath_exclude_cmd
= {
1521 "as-path exclude", route_set_aspath_exclude
, route_aspath_compile
,
1525 /* `set community COMMUNITY' */
1526 struct rmap_com_set
{
1527 struct community
*com
;
1532 /* For community set mechanism. */
1533 static route_map_result_t
route_set_community(void *rule
, struct prefix
*prefix
,
1534 route_map_object_t type
,
1537 struct rmap_com_set
*rcs
;
1538 struct bgp_info
*binfo
;
1540 struct community
*new = NULL
;
1541 struct community
*old
;
1542 struct community
*merge
;
1544 if (type
== RMAP_BGP
) {
1548 old
= attr
->community
;
1552 attr
->flag
&= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1553 attr
->community
= NULL
;
1554 /* See the longer comment down below. */
1555 if (old
&& old
->refcnt
== 0)
1556 community_free(old
);
1560 /* "additive" case. */
1561 if (rcs
->additive
&& old
) {
1562 merge
= community_merge(community_dup(old
), rcs
->com
);
1564 new = community_uniq_sort(merge
);
1565 community_free(merge
);
1567 new = community_dup(rcs
->com
);
1569 /* HACK: if the old community is not intern'd,
1570 * we should free it here, or all reference to it may be
1572 * Really need to cleanup attribute caching sometime.
1574 if (old
&& old
->refcnt
== 0)
1575 community_free(old
);
1577 /* will be interned by caller if required */
1578 attr
->community
= new;
1580 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1586 /* Compile function for set community. */
1587 static void *route_set_community_compile(const char *arg
)
1589 struct rmap_com_set
*rcs
;
1590 struct community
*com
= NULL
;
1595 if (strcmp(arg
, "none") == 0)
1598 sp
= strstr(arg
, "additive");
1600 if (sp
&& sp
> arg
) {
1601 /* "additive" keyword is included. */
1606 com
= community_str2com(arg
);
1615 rcs
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_com_set
));
1617 rcs
->additive
= additive
;
1623 /* Free function for set community. */
1624 static void route_set_community_free(void *rule
)
1626 struct rmap_com_set
*rcs
= rule
;
1629 community_free(rcs
->com
);
1630 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcs
);
1633 /* Set community rule structure. */
1634 struct route_map_rule_cmd route_set_community_cmd
= {
1635 "community", route_set_community
, route_set_community_compile
,
1636 route_set_community_free
,
1639 /* `set community COMMUNITY' */
1640 struct rmap_lcom_set
{
1641 struct lcommunity
*lcom
;
1647 /* For lcommunity set mechanism. */
1648 static route_map_result_t
route_set_lcommunity(void *rule
,
1649 struct prefix
*prefix
,
1650 route_map_object_t type
,
1653 struct rmap_lcom_set
*rcs
;
1654 struct bgp_info
*binfo
;
1656 struct lcommunity
*new = NULL
;
1657 struct lcommunity
*old
;
1658 struct lcommunity
*merge
;
1660 if (type
== RMAP_BGP
) {
1664 old
= attr
->lcommunity
;
1669 ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1670 attr
->lcommunity
= NULL
;
1672 /* See the longer comment down below. */
1673 if (old
&& old
->refcnt
== 0)
1674 lcommunity_free(&old
);
1678 if (rcs
->additive
&& old
) {
1679 merge
= lcommunity_merge(lcommunity_dup(old
),
1682 new = lcommunity_uniq_sort(merge
);
1683 lcommunity_free(&merge
);
1685 new = lcommunity_dup(rcs
->lcom
);
1687 /* HACK: if the old large-community is not intern'd,
1688 * we should free it here, or all reference to it may be
1690 * Really need to cleanup attribute caching sometime.
1692 if (old
&& old
->refcnt
== 0)
1693 lcommunity_free(&old
);
1695 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1696 attr
->lcommunity
= new;
1698 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1704 /* Compile function for set community. */
1705 static void *route_set_lcommunity_compile(const char *arg
)
1707 struct rmap_lcom_set
*rcs
;
1708 struct lcommunity
*lcom
= NULL
;
1713 if (strcmp(arg
, "none") == 0)
1716 sp
= strstr(arg
, "additive");
1718 if (sp
&& sp
> arg
) {
1719 /* "additive" keyworkd is included. */
1724 lcom
= lcommunity_str2com(arg
);
1733 rcs
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_com_set
));
1735 rcs
->additive
= additive
;
1741 /* Free function for set lcommunity. */
1742 static void route_set_lcommunity_free(void *rule
)
1744 struct rmap_lcom_set
*rcs
= rule
;
1747 lcommunity_free(&rcs
->lcom
);
1749 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcs
);
1752 /* Set community rule structure. */
1753 struct route_map_rule_cmd route_set_lcommunity_cmd
= {
1754 "large-community", route_set_lcommunity
, route_set_lcommunity_compile
,
1755 route_set_lcommunity_free
,
1758 /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
1760 /* For large community set mechanism. */
1761 static route_map_result_t
route_set_lcommunity_delete(void *rule
,
1762 struct prefix
*prefix
,
1763 route_map_object_t type
,
1766 struct community_list
*list
;
1767 struct lcommunity
*merge
;
1768 struct lcommunity
*new;
1769 struct lcommunity
*old
;
1770 struct bgp_info
*binfo
;
1772 if (type
== RMAP_BGP
) {
1777 list
= community_list_lookup(bgp_clist
, rule
,
1778 LARGE_COMMUNITY_LIST_MASTER
);
1779 old
= binfo
->attr
->lcommunity
;
1782 merge
= lcommunity_list_match_delete(
1783 lcommunity_dup(old
), list
);
1784 new = lcommunity_uniq_sort(merge
);
1785 lcommunity_free(&merge
);
1787 /* HACK: if the old community is not intern'd,
1788 * we should free it here, or all reference to it may be
1790 * Really need to cleanup attribute caching sometime.
1792 if (old
->refcnt
== 0)
1793 lcommunity_free(&old
);
1795 if (new->size
== 0) {
1796 binfo
->attr
->lcommunity
= NULL
;
1797 binfo
->attr
->flag
&= ~ATTR_FLAG_BIT(
1798 BGP_ATTR_LARGE_COMMUNITIES
);
1799 lcommunity_free(&new);
1801 binfo
->attr
->lcommunity
= new;
1802 binfo
->attr
->flag
|= ATTR_FLAG_BIT(
1803 BGP_ATTR_LARGE_COMMUNITIES
);
1811 /* Compile function for set lcommunity. */
1812 static void *route_set_lcommunity_delete_compile(const char *arg
)
1818 p
= strchr(arg
, ' ');
1821 str
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1822 memcpy(str
, arg
, len
);
1829 /* Free function for set lcommunity. */
1830 static void route_set_lcommunity_delete_free(void *rule
)
1832 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1835 /* Set lcommunity rule structure. */
1836 struct route_map_rule_cmd route_set_lcommunity_delete_cmd
= {
1837 "large-comm-list", route_set_lcommunity_delete
,
1838 route_set_lcommunity_delete_compile
, route_set_lcommunity_delete_free
,
1842 /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
1844 /* For community set mechanism. */
1845 static route_map_result_t
route_set_community_delete(void *rule
,
1846 struct prefix
*prefix
,
1847 route_map_object_t type
,
1850 struct community_list
*list
;
1851 struct community
*merge
;
1852 struct community
*new;
1853 struct community
*old
;
1854 struct bgp_info
*binfo
;
1856 if (type
== RMAP_BGP
) {
1861 list
= community_list_lookup(bgp_clist
, rule
,
1862 COMMUNITY_LIST_MASTER
);
1863 old
= binfo
->attr
->community
;
1866 merge
= community_list_match_delete(community_dup(old
),
1868 new = community_uniq_sort(merge
);
1869 community_free(merge
);
1871 /* HACK: if the old community is not intern'd,
1872 * we should free it here, or all reference to it may be
1874 * Really need to cleanup attribute caching sometime.
1876 if (old
->refcnt
== 0)
1877 community_free(old
);
1879 if (new->size
== 0) {
1880 binfo
->attr
->community
= NULL
;
1881 binfo
->attr
->flag
&=
1882 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1883 community_free(new);
1885 binfo
->attr
->community
= new;
1886 binfo
->attr
->flag
|=
1887 ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1895 /* Compile function for set community. */
1896 static void *route_set_community_delete_compile(const char *arg
)
1902 p
= strchr(arg
, ' ');
1905 str
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1906 memcpy(str
, arg
, len
);
1913 /* Free function for set community. */
1914 static void route_set_community_delete_free(void *rule
)
1916 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1919 /* Set community rule structure. */
1920 struct route_map_rule_cmd route_set_community_delete_cmd
= {
1921 "comm-list", route_set_community_delete
,
1922 route_set_community_delete_compile
, route_set_community_delete_free
,
1925 /* `set extcommunity rt COMMUNITY' */
1927 /* For community set mechanism. Used by _rt and _soo. */
1928 static route_map_result_t
route_set_ecommunity(void *rule
,
1929 struct prefix
*prefix
,
1930 route_map_object_t type
,
1933 struct ecommunity
*ecom
;
1934 struct ecommunity
*new_ecom
;
1935 struct ecommunity
*old_ecom
;
1936 struct bgp_info
*bgp_info
;
1938 if (type
== RMAP_BGP
) {
1945 /* We assume additive for Extended Community. */
1946 old_ecom
= bgp_info
->attr
->ecommunity
;
1949 new_ecom
= ecommunity_merge(ecommunity_dup(old_ecom
),
1952 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
1953 * bgp_update_receive()
1954 * ->refcnt = 0 => set by a previous route-map
1956 if (!old_ecom
->refcnt
)
1957 ecommunity_free(&old_ecom
);
1959 new_ecom
= ecommunity_dup(ecom
);
1961 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1962 bgp_info
->attr
->ecommunity
= new_ecom
;
1964 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
1969 /* Compile function for set community. */
1970 static void *route_set_ecommunity_rt_compile(const char *arg
)
1972 struct ecommunity
*ecom
;
1974 ecom
= ecommunity_str2com(arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
1977 return ecommunity_intern(ecom
);
1980 /* Free function for set community. Used by _rt and _soo */
1981 static void route_set_ecommunity_free(void *rule
)
1983 struct ecommunity
*ecom
= rule
;
1984 ecommunity_unintern(&ecom
);
1987 /* Set community rule structure. */
1988 struct route_map_rule_cmd route_set_ecommunity_rt_cmd
= {
1989 "extcommunity rt", route_set_ecommunity
,
1990 route_set_ecommunity_rt_compile
, route_set_ecommunity_free
,
1993 /* `set extcommunity soo COMMUNITY' */
1995 /* Compile function for set community. */
1996 static void *route_set_ecommunity_soo_compile(const char *arg
)
1998 struct ecommunity
*ecom
;
2000 ecom
= ecommunity_str2com(arg
, ECOMMUNITY_SITE_ORIGIN
, 0);
2004 return ecommunity_intern(ecom
);
2007 /* Set community rule structure. */
2008 struct route_map_rule_cmd route_set_ecommunity_soo_cmd
= {
2009 "extcommunity soo", route_set_ecommunity
,
2010 route_set_ecommunity_soo_compile
, route_set_ecommunity_free
,
2013 /* `set origin ORIGIN' */
2015 /* For origin set. */
2016 static route_map_result_t
route_set_origin(void *rule
, struct prefix
*prefix
,
2017 route_map_object_t type
,
2021 struct bgp_info
*bgp_info
;
2023 if (type
== RMAP_BGP
) {
2027 bgp_info
->attr
->origin
= *origin
;
2033 /* Compile function for origin set. */
2034 static void *route_set_origin_compile(const char *arg
)
2038 origin
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(u_char
));
2040 if (strcmp(arg
, "igp") == 0)
2042 else if (strcmp(arg
, "egp") == 0)
2050 /* Compile function for origin set. */
2051 static void route_set_origin_free(void *rule
)
2053 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2056 /* Set origin rule structure. */
2057 struct route_map_rule_cmd route_set_origin_cmd
= {
2058 "origin", route_set_origin
, route_set_origin_compile
,
2059 route_set_origin_free
,
2062 /* `set atomic-aggregate' */
2064 /* For atomic aggregate set. */
2065 static route_map_result_t
route_set_atomic_aggregate(void *rule
,
2066 struct prefix
*prefix
,
2067 route_map_object_t type
,
2070 struct bgp_info
*bgp_info
;
2072 if (type
== RMAP_BGP
) {
2074 bgp_info
->attr
->flag
|=
2075 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
2081 /* Compile function for atomic aggregate. */
2082 static void *route_set_atomic_aggregate_compile(const char *arg
)
2087 /* Compile function for atomic aggregate. */
2088 static void route_set_atomic_aggregate_free(void *rule
)
2093 /* Set atomic aggregate rule structure. */
2094 struct route_map_rule_cmd route_set_atomic_aggregate_cmd
= {
2095 "atomic-aggregate", route_set_atomic_aggregate
,
2096 route_set_atomic_aggregate_compile
, route_set_atomic_aggregate_free
,
2099 /* `set aggregator as AS A.B.C.D' */
2102 struct in_addr address
;
2105 static route_map_result_t
route_set_aggregator_as(void *rule
,
2106 struct prefix
*prefix
,
2107 route_map_object_t type
,
2110 struct bgp_info
*bgp_info
;
2111 struct aggregator
*aggregator
;
2113 if (type
== RMAP_BGP
) {
2117 bgp_info
->attr
->aggregator_as
= aggregator
->as
;
2118 bgp_info
->attr
->aggregator_addr
= aggregator
->address
;
2119 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
2125 static void *route_set_aggregator_as_compile(const char *arg
)
2127 struct aggregator
*aggregator
;
2133 XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct aggregator
));
2134 if (sscanf(arg
, "%s %s", as
, address
) != 2) {
2135 XFREE(MTYPE_ROUTE_MAP_COMPILED
, aggregator
);
2139 aggregator
->as
= strtoul(as
, NULL
, 10);
2140 ret
= inet_aton(address
, &aggregator
->address
);
2142 XFREE(MTYPE_ROUTE_MAP_COMPILED
, aggregator
);
2148 static void route_set_aggregator_as_free(void *rule
)
2150 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2153 struct route_map_rule_cmd route_set_aggregator_as_cmd
= {
2154 "aggregator as", route_set_aggregator_as
,
2155 route_set_aggregator_as_compile
, route_set_aggregator_as_free
,
2158 /* Set tag to object. object must be pointer to struct bgp_info */
2159 static route_map_result_t
route_set_tag(void *rule
, struct prefix
*prefix
,
2160 route_map_object_t type
, void *object
)
2163 struct bgp_info
*bgp_info
;
2165 if (type
== RMAP_BGP
) {
2170 bgp_info
->attr
->tag
= *tag
;
2176 /* Route map commands for tag set. */
2177 static struct route_map_rule_cmd route_set_tag_cmd
= {
2178 "tag", route_set_tag
, route_map_rule_tag_compile
,
2179 route_map_rule_tag_free
,
2182 /* Set label-index to object. object must be pointer to struct bgp_info */
2183 static route_map_result_t
route_set_label_index(void *rule
,
2184 struct prefix
*prefix
,
2185 route_map_object_t type
,
2188 struct rmap_value
*rv
;
2189 struct bgp_info
*bgp_info
;
2190 u_int32_t label_index
;
2192 if (type
== RMAP_BGP
) {
2193 /* Fetch routemap's rule information. */
2197 /* Set label-index value. */
2198 label_index
= rv
->value
;
2200 bgp_info
->attr
->label_index
= label_index
;
2201 bgp_info
->attr
->flag
|=
2202 ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2209 /* Route map commands for label-index set. */
2210 static struct route_map_rule_cmd route_set_label_index_cmd
= {
2211 "label-index", route_set_label_index
, route_value_compile
,
2215 /* `match ipv6 address IP_ACCESS_LIST' */
2217 static route_map_result_t
route_match_ipv6_address(void *rule
,
2218 struct prefix
*prefix
,
2219 route_map_object_t type
,
2222 struct access_list
*alist
;
2224 if (type
== RMAP_BGP
) {
2225 alist
= access_list_lookup(AFI_IP6
, (char *)rule
);
2227 return RMAP_NOMATCH
;
2229 return (access_list_apply(alist
, prefix
) == FILTER_DENY
2233 return RMAP_NOMATCH
;
2236 static void *route_match_ipv6_address_compile(const char *arg
)
2238 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
2241 static void route_match_ipv6_address_free(void *rule
)
2243 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2246 /* Route map commands for ip address matching. */
2247 struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
2248 "ipv6 address", route_match_ipv6_address
,
2249 route_match_ipv6_address_compile
, route_match_ipv6_address_free
};
2251 /* `match ipv6 next-hop IP_ADDRESS' */
2253 static route_map_result_t
route_match_ipv6_next_hop(void *rule
,
2254 struct prefix
*prefix
,
2255 route_map_object_t type
,
2258 struct in6_addr
*addr
= rule
;
2259 struct bgp_info
*bgp_info
;
2261 if (type
== RMAP_BGP
) {
2264 if (IPV6_ADDR_SAME(&bgp_info
->attr
->mp_nexthop_global
, addr
))
2267 if (bgp_info
->attr
->mp_nexthop_len
2268 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
2269 && IPV6_ADDR_SAME(&bgp_info
->attr
->mp_nexthop_local
, rule
))
2272 return RMAP_NOMATCH
;
2275 return RMAP_NOMATCH
;
2278 static void *route_match_ipv6_next_hop_compile(const char *arg
)
2280 struct in6_addr
*address
;
2283 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2285 ret
= inet_pton(AF_INET6
, arg
, address
);
2287 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2294 static void route_match_ipv6_next_hop_free(void *rule
)
2296 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2299 struct route_map_rule_cmd route_match_ipv6_next_hop_cmd
= {
2300 "ipv6 next-hop", route_match_ipv6_next_hop
,
2301 route_match_ipv6_next_hop_compile
, route_match_ipv6_next_hop_free
};
2303 /* `match ipv6 address prefix-list PREFIX_LIST' */
2305 static route_map_result_t
2306 route_match_ipv6_address_prefix_list(void *rule
, struct prefix
*prefix
,
2307 route_map_object_t type
, void *object
)
2309 struct prefix_list
*plist
;
2311 if (type
== RMAP_BGP
) {
2312 plist
= prefix_list_lookup(AFI_IP6
, (char *)rule
);
2314 return RMAP_NOMATCH
;
2316 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
2320 return RMAP_NOMATCH
;
2323 static void *route_match_ipv6_address_prefix_list_compile(const char *arg
)
2325 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
2328 static void route_match_ipv6_address_prefix_list_free(void *rule
)
2330 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2333 struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
2334 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
2335 route_match_ipv6_address_prefix_list_compile
,
2336 route_match_ipv6_address_prefix_list_free
};
2338 /* `set ipv6 nexthop global IP_ADDRESS' */
2340 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2341 static route_map_result_t
route_set_ipv6_nexthop_global(void *rule
,
2342 struct prefix
*prefix
,
2343 route_map_object_t type
,
2346 struct in6_addr
*address
;
2347 struct bgp_info
*bgp_info
;
2349 if (type
== RMAP_BGP
) {
2350 /* Fetch routemap's rule information. */
2354 /* Set next hop value. */
2355 bgp_info
->attr
->mp_nexthop_global
= *address
;
2357 /* Set nexthop length. */
2358 if (bgp_info
->attr
->mp_nexthop_len
== 0)
2359 bgp_info
->attr
->mp_nexthop_len
=
2360 BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2362 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2363 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
);
2369 /* Route map `ip next-hop' compile function. Given string is converted
2370 to struct in_addr structure. */
2371 static void *route_set_ipv6_nexthop_global_compile(const char *arg
)
2374 struct in6_addr
*address
;
2376 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2378 ret
= inet_pton(AF_INET6
, arg
, address
);
2381 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2388 /* Free route map's compiled `ip next-hop' value. */
2389 static void route_set_ipv6_nexthop_global_free(void *rule
)
2391 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2394 /* Route map commands for ip nexthop set. */
2395 struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd
= {
2396 "ipv6 next-hop global", route_set_ipv6_nexthop_global
,
2397 route_set_ipv6_nexthop_global_compile
,
2398 route_set_ipv6_nexthop_global_free
};
2400 /* Set next-hop preference value. */
2401 static route_map_result_t
2402 route_set_ipv6_nexthop_prefer_global(void *rule
, struct prefix
*prefix
,
2403 route_map_object_t type
, void *object
)
2405 struct bgp_info
*bgp_info
;
2408 if (type
== RMAP_BGP
) {
2409 /* Fetch routemap's rule information. */
2411 peer
= bgp_info
->peer
;
2413 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
2414 || CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IMPORT
))
2416 && sockunion_family(peer
->su_remote
) == AF_INET6
) {
2417 /* Set next hop preference to global */
2418 bgp_info
->attr
->mp_nexthop_prefer_global
= TRUE
;
2419 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2420 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED
);
2422 bgp_info
->attr
->mp_nexthop_prefer_global
= FALSE
;
2423 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2424 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED
);
2430 static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg
)
2434 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
2440 /* Free route map's compiled `ip next-hop' value. */
2441 static void route_set_ipv6_nexthop_prefer_global_free(void *rule
)
2443 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2446 /* Route map commands for ip nexthop set preferred. */
2447 struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd
= {
2448 "ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global
,
2449 route_set_ipv6_nexthop_prefer_global_compile
,
2450 route_set_ipv6_nexthop_prefer_global_free
};
2452 /* `set ipv6 nexthop local IP_ADDRESS' */
2454 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2455 static route_map_result_t
route_set_ipv6_nexthop_local(void *rule
,
2456 struct prefix
*prefix
,
2457 route_map_object_t type
,
2460 struct in6_addr
*address
;
2461 struct bgp_info
*bgp_info
;
2463 if (type
== RMAP_BGP
) {
2464 /* Fetch routemap's rule information. */
2468 /* Set next hop value. */
2469 bgp_info
->attr
->mp_nexthop_local
= *address
;
2471 /* Set nexthop length. */
2472 if (bgp_info
->attr
->mp_nexthop_len
2473 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2474 bgp_info
->attr
->mp_nexthop_len
=
2475 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2477 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2478 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
);
2484 /* Route map `ip nexthop' compile function. Given string is converted
2485 to struct in_addr structure. */
2486 static void *route_set_ipv6_nexthop_local_compile(const char *arg
)
2489 struct in6_addr
*address
;
2491 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2493 ret
= inet_pton(AF_INET6
, arg
, address
);
2496 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2503 /* Free route map's compiled `ip nexthop' value. */
2504 static void route_set_ipv6_nexthop_local_free(void *rule
)
2506 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2509 /* Route map commands for ip nexthop set. */
2510 struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd
= {
2511 "ipv6 next-hop local", route_set_ipv6_nexthop_local
,
2512 route_set_ipv6_nexthop_local_compile
,
2513 route_set_ipv6_nexthop_local_free
};
2515 /* `set ipv6 nexthop peer-address' */
2517 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2518 static route_map_result_t
route_set_ipv6_nexthop_peer(void *rule
,
2519 struct prefix
*prefix
,
2520 route_map_object_t type
,
2523 struct in6_addr peer_address
;
2524 struct bgp_info
*bgp_info
;
2527 if (type
== RMAP_BGP
) {
2528 /* Fetch routemap's rule information. */
2530 peer
= bgp_info
->peer
;
2532 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
2533 || CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IMPORT
))
2535 && sockunion_family(peer
->su_remote
) == AF_INET6
) {
2536 peer_address
= peer
->su_remote
->sin6
.sin6_addr
;
2537 /* Set next hop value and length in attribute. */
2538 if (IN6_IS_ADDR_LINKLOCAL(&peer_address
)) {
2539 bgp_info
->attr
->mp_nexthop_local
= peer_address
;
2540 if (bgp_info
->attr
->mp_nexthop_len
!= 32)
2541 bgp_info
->attr
->mp_nexthop_len
= 32;
2543 bgp_info
->attr
->mp_nexthop_global
=
2545 if (bgp_info
->attr
->mp_nexthop_len
== 0)
2546 bgp_info
->attr
->mp_nexthop_len
= 16;
2549 } else if (CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
)) {
2550 /* The next hop value will be set as part of packet
2552 * Set the flags here to indicate that rewrite needs to
2554 * Also, clear the value - we clear both global and
2556 * nexthops, whether we send one or both is determined
2559 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2560 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
);
2561 /* clear next hop value. */
2562 memset(&(bgp_info
->attr
->mp_nexthop_global
), 0,
2563 sizeof(struct in6_addr
));
2564 memset(&(bgp_info
->attr
->mp_nexthop_local
), 0,
2565 sizeof(struct in6_addr
));
2572 /* Route map `ip next-hop' compile function. Given string is converted
2573 to struct in_addr structure. */
2574 static void *route_set_ipv6_nexthop_peer_compile(const char *arg
)
2578 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
2584 /* Free route map's compiled `ip next-hop' value. */
2585 static void route_set_ipv6_nexthop_peer_free(void *rule
)
2587 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2590 /* Route map commands for ip nexthop set. */
2591 struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd
= {
2592 "ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer
,
2593 route_set_ipv6_nexthop_peer_compile
, route_set_ipv6_nexthop_peer_free
};
2595 /* `set ipv4 vpn next-hop A.B.C.D' */
2597 static route_map_result_t
route_set_vpnv4_nexthop(void *rule
,
2598 struct prefix
*prefix
,
2599 route_map_object_t type
,
2602 struct in_addr
*address
;
2603 struct bgp_info
*bgp_info
;
2605 if (type
== RMAP_BGP
) {
2606 /* Fetch routemap's rule information. */
2610 /* Set next hop value. */
2611 bgp_info
->attr
->mp_nexthop_global_in
= *address
;
2612 bgp_info
->attr
->mp_nexthop_len
= 4;
2618 static void *route_set_vpnv4_nexthop_compile(const char *arg
)
2621 struct in_addr
*address
;
2623 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in_addr
));
2625 ret
= inet_aton(arg
, address
);
2628 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2635 /* `set ipv6 vpn next-hop A.B.C.D' */
2637 static route_map_result_t
route_set_vpnv6_nexthop(void *rule
,
2638 struct prefix
*prefix
,
2639 route_map_object_t type
,
2642 struct in6_addr
*address
;
2643 struct bgp_info
*bgp_info
;
2645 if (type
== RMAP_BGP
) {
2646 /* Fetch routemap's rule information. */
2650 /* Set next hop value. */
2651 memcpy(&bgp_info
->attr
->mp_nexthop_global
, address
,
2652 sizeof(struct in6_addr
));
2653 bgp_info
->attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_VPNV6_GLOBAL
;
2659 static void *route_set_vpnv6_nexthop_compile(const char *arg
)
2662 struct in6_addr
*address
;
2664 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2665 ret
= inet_pton(AF_INET6
, arg
, address
);
2668 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2675 static void route_set_vpn_nexthop_free(void *rule
)
2677 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2680 /* Route map commands for ipv4 next-hop set. */
2681 struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd
= {
2682 "ipv4 vpn next-hop", route_set_vpnv4_nexthop
,
2683 route_set_vpnv4_nexthop_compile
, route_set_vpn_nexthop_free
};
2685 /* Route map commands for ipv6 next-hop set. */
2686 struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd
= {
2687 "ipv6 vpn next-hop", route_set_vpnv6_nexthop
,
2688 route_set_vpnv6_nexthop_compile
, route_set_vpn_nexthop_free
};
2690 /* `set originator-id' */
2692 /* For origin set. */
2693 static route_map_result_t
route_set_originator_id(void *rule
,
2694 struct prefix
*prefix
,
2695 route_map_object_t type
,
2698 struct in_addr
*address
;
2699 struct bgp_info
*bgp_info
;
2701 if (type
== RMAP_BGP
) {
2705 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2706 bgp_info
->attr
->originator_id
= *address
;
2712 /* Compile function for originator-id set. */
2713 static void *route_set_originator_id_compile(const char *arg
)
2716 struct in_addr
*address
;
2718 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in_addr
));
2720 ret
= inet_aton(arg
, address
);
2723 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2730 /* Compile function for originator_id set. */
2731 static void route_set_originator_id_free(void *rule
)
2733 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2736 /* Set originator-id rule structure. */
2737 struct route_map_rule_cmd route_set_originator_id_cmd
= {
2738 "originator-id", route_set_originator_id
,
2739 route_set_originator_id_compile
, route_set_originator_id_free
,
2742 /* Add bgp route map rule. */
2743 static int bgp_route_match_add(struct vty
*vty
, const char *command
,
2744 const char *arg
, route_map_event_t type
)
2746 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
2747 int retval
= CMD_SUCCESS
;
2750 ret
= route_map_add_match(index
, command
, arg
);
2752 case RMAP_RULE_MISSING
:
2753 vty_out(vty
, "%% BGP Can't find rule.\n");
2754 retval
= CMD_WARNING_CONFIG_FAILED
;
2756 case RMAP_COMPILE_ERROR
:
2757 vty_out(vty
, "%% BGP Argument is malformed.\n");
2758 retval
= CMD_WARNING_CONFIG_FAILED
;
2760 case RMAP_COMPILE_SUCCESS
:
2761 if (type
!= RMAP_EVENT_MATCH_ADDED
) {
2762 route_map_upd8_dependency(type
, arg
, index
->map
->name
);
2770 /* Delete bgp route map rule. */
2771 static int bgp_route_match_delete(struct vty
*vty
, const char *command
,
2772 const char *arg
, route_map_event_t type
)
2774 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
2776 int retval
= CMD_SUCCESS
;
2777 char *dep_name
= NULL
;
2779 char *rmap_name
= NULL
;
2781 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
2782 /* ignore the mundane, the types without any dependency */
2784 if ((tmpstr
= route_map_get_match_arg(index
, command
))
2787 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
2789 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
2791 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
2794 ret
= route_map_delete_match(index
, command
, dep_name
);
2796 case RMAP_RULE_MISSING
:
2797 vty_out(vty
, "%% BGP Can't find rule.\n");
2798 retval
= CMD_WARNING_CONFIG_FAILED
;
2800 case RMAP_COMPILE_ERROR
:
2801 vty_out(vty
, "%% BGP Argument is malformed.\n");
2802 retval
= CMD_WARNING_CONFIG_FAILED
;
2804 case RMAP_COMPILE_SUCCESS
:
2805 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
2806 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
2811 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
2813 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
2819 * This is the workhorse routine for processing in/out routemap
2822 static void bgp_route_map_process_peer(const char *rmap_name
,
2823 struct route_map
*map
, struct peer
*peer
,
2824 int afi
, int safi
, int route_update
)
2828 struct bgp_filter
*filter
;
2830 if (!peer
|| !rmap_name
)
2833 filter
= &peer
->filter
[afi
][safi
];
2835 * in is for non-route-server clients,
2836 * out is for all peers
2838 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_RSERVER_CLIENT
)) {
2839 if (filter
->map
[RMAP_IN
].name
2840 && (strcmp(rmap_name
, filter
->map
[RMAP_IN
].name
) == 0)) {
2841 filter
->map
[RMAP_IN
].map
= map
;
2843 if (route_update
&& peer
->status
== Established
) {
2844 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2845 PEER_FLAG_SOFT_RECONFIG
)) {
2846 if (bgp_debug_update(peer
, NULL
, NULL
,
2849 "Processing route_map %s update on "
2850 "peer %s (inbound, soft-reconfig)",
2851 rmap_name
, peer
->host
);
2853 bgp_soft_reconfig_in(peer
, afi
, safi
);
2855 CHECK_FLAG(peer
->cap
,
2856 PEER_CAP_REFRESH_OLD_RCV
)
2859 PEER_CAP_REFRESH_NEW_RCV
)) {
2861 if (bgp_debug_update(peer
, NULL
, NULL
,
2864 "Processing route_map %s update on "
2865 "peer %s (inbound, route-refresh)",
2866 rmap_name
, peer
->host
);
2867 bgp_route_refresh_send(peer
, afi
, safi
,
2874 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_RSERVER_CLIENT
)) {
2877 if (update
&& route_update
&& peer
->status
== Established
) {
2878 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2879 PEER_FLAG_SOFT_RECONFIG
)) {
2880 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2882 "Processing route_map %s update on "
2883 "peer %s (import, soft-reconfig)",
2884 rmap_name
, peer
->host
);
2886 bgp_soft_reconfig_in(peer
, afi
, safi
);
2887 } else if (CHECK_FLAG(peer
->cap
,
2888 PEER_CAP_REFRESH_OLD_RCV
)
2889 || CHECK_FLAG(peer
->cap
,
2890 PEER_CAP_REFRESH_NEW_RCV
)) {
2891 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
2893 "Processing route_map %s update on "
2894 "peer %s (import, route-refresh)",
2895 rmap_name
, peer
->host
);
2896 bgp_route_refresh_send(peer
, afi
, safi
, 0, 0,
2899 /* DD: Else, what else do we do ? Reset peer ? */
2904 * For outbound, unsuppress and default-originate map change (content or
2905 * map created), merely update the "config" here, the actual route
2906 * announcement happens at the group level.
2908 if (filter
->map
[RMAP_OUT
].name
2909 && (strcmp(rmap_name
, filter
->map
[RMAP_OUT
].name
) == 0))
2910 filter
->map
[RMAP_OUT
].map
= map
;
2912 if (filter
->usmap
.name
&& (strcmp(rmap_name
, filter
->usmap
.name
) == 0))
2913 filter
->usmap
.map
= map
;
2915 if (peer
->default_rmap
[afi
][safi
].name
2916 && (strcmp(rmap_name
, peer
->default_rmap
[afi
][safi
].name
) == 0))
2917 peer
->default_rmap
[afi
][safi
].map
= map
;
2920 static void bgp_route_map_update_peer_group(const char *rmap_name
,
2921 struct route_map
*map
,
2924 struct peer_group
*group
;
2925 struct listnode
*node
, *nnode
;
2926 struct bgp_filter
*filter
;
2933 /* All the peers have been updated correctly already. This is
2934 * just updating the placeholder data. No real update required.
2936 for (ALL_LIST_ELEMENTS(bgp
->group
, node
, nnode
, group
)) {
2937 FOREACH_AFI_SAFI (afi
, safi
) {
2938 filter
= &group
->conf
->filter
[afi
][safi
];
2940 for (direct
= RMAP_IN
; direct
< RMAP_MAX
; direct
++) {
2941 if ((filter
->map
[direct
].name
)
2942 && (strcmp(rmap_name
,
2943 filter
->map
[direct
].name
)
2945 filter
->map
[direct
].map
= map
;
2948 if (filter
->usmap
.name
2949 && (strcmp(rmap_name
, filter
->usmap
.name
) == 0))
2950 filter
->usmap
.map
= map
;
2956 * Note that if an extreme number (tens of thousands) of route-maps are in use
2957 * and if bgp has an extreme number of peers, network statements, etc then this
2958 * function can consume a lot of cycles. This is due to this function being
2959 * called for each route-map and within this function we walk the list of peers,
2960 * network statements, etc looking to see if they use this route-map.
2962 static void bgp_route_map_process_update(struct bgp
*bgp
, const char *rmap_name
,
2969 struct bgp_node
*bn
;
2970 struct bgp_static
*bgp_static
;
2971 struct listnode
*node
, *nnode
;
2972 struct route_map
*map
;
2973 char buf
[INET6_ADDRSTRLEN
];
2975 map
= route_map_lookup_by_name(rmap_name
);
2977 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
2979 /* Ignore dummy peer-group structure */
2980 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
))
2983 FOREACH_AFI_SAFI (afi
, safi
) {
2984 /* process in/out/import/export/default-orig
2986 bgp_route_map_process_peer(rmap_name
, map
, peer
, afi
,
2987 safi
, route_update
);
2991 /* for outbound/default-orig route-maps, process for groups */
2992 update_group_policy_update(bgp
, BGP_POLICY_ROUTE_MAP
, rmap_name
,
2995 /* update peer-group config (template) */
2996 bgp_route_map_update_peer_group(rmap_name
, map
, bgp
);
2998 FOREACH_AFI_SAFI (afi
, safi
) {
2999 /* For table route-map updates. */
3000 if (!bgp_fibupd_safi(safi
))
3003 if (bgp
->table_map
[afi
][safi
].name
3004 && (strcmp(rmap_name
, bgp
->table_map
[afi
][safi
].name
)
3006 bgp
->table_map
[afi
][safi
].map
= map
;
3008 if (BGP_DEBUG(zebra
, ZEBRA
))
3010 "Processing route_map %s update on "
3014 bgp_zebra_announce_table(bgp
, afi
, safi
);
3017 /* For network route-map updates. */
3018 for (bn
= bgp_table_top(bgp
->route
[afi
][safi
]); bn
;
3019 bn
= bgp_route_next(bn
))
3020 if ((bgp_static
= bn
->info
) != NULL
) {
3021 if (bgp_static
->rmap
.name
3022 && (strcmp(rmap_name
, bgp_static
->rmap
.name
)
3024 bgp_static
->rmap
.map
= map
;
3027 if (!bgp_static
->backdoor
) {
3028 if (bgp_debug_zebra(
3031 "Processing route_map %s update on "
3048 /* For redistribute route-map updates. */
3049 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3050 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
3051 struct list
*red_list
;
3052 struct listnode
*node
;
3053 struct bgp_redist
*red
;
3055 red_list
= bgp
->redist
[afi
][i
];
3059 for (ALL_LIST_ELEMENTS_RO(red_list
, node
, red
)) {
3061 && (strcmp(rmap_name
, red
->rmap
.name
)
3063 red
->rmap
.map
= map
;
3066 if (BGP_DEBUG(zebra
, ZEBRA
))
3068 "Processing route_map %s update on "
3069 "redistributed routes",
3072 bgp_redistribute_resend(
3080 /* for type5 command route-maps */
3081 FOREACH_AFI_SAFI (afi
, safi
) {
3082 if (bgp
->adv_cmd_rmap
[afi
][safi
].name
&&
3083 strcmp(rmap_name
, bgp
->adv_cmd_rmap
[afi
][safi
].name
) == 0) {
3084 if (BGP_DEBUG(zebra
, ZEBRA
))
3086 "Processing route_map %s update on advertise type5 route command",
3088 bgp_evpn_withdraw_type5_routes(bgp
, afi
, safi
);
3089 bgp_evpn_advertise_type5_routes(bgp
, afi
, safi
);
3094 static int bgp_route_map_process_update_cb(char *rmap_name
)
3096 struct listnode
*node
, *nnode
;
3099 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3100 bgp_route_map_process_update(bgp
, rmap_name
, 1);
3103 zlog_debug("%s: calling vnc_routemap_update", __func__
);
3104 vnc_routemap_update(bgp
, __func__
);
3109 int bgp_route_map_update_timer(struct thread
*thread
)
3111 bm
->t_rmap_update
= NULL
;
3113 route_map_walk_update_list(bgp_route_map_process_update_cb
);
3118 static void bgp_route_map_mark_update(const char *rmap_name
)
3120 if (bm
->t_rmap_update
== NULL
) {
3121 struct listnode
*node
, *nnode
;
3124 /* rmap_update_timer of 0 means don't do route updates */
3125 if (bm
->rmap_update_timer
) {
3126 bm
->t_rmap_update
= NULL
;
3127 thread_add_timer(bm
->master
, bgp_route_map_update_timer
,
3128 NULL
, bm
->rmap_update_timer
,
3129 &bm
->t_rmap_update
);
3131 /* Signal the groups that a route-map update event has
3133 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3134 update_group_policy_update(bgp
,
3135 BGP_POLICY_ROUTE_MAP
,
3138 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3139 bgp_route_map_process_update(bgp
, rmap_name
, 0);
3141 zlog_debug("%s: calling vnc_routemap_update", __func__
);
3142 vnc_routemap_update(bgp
, __func__
);
3148 static void bgp_route_map_add(const char *rmap_name
)
3150 if (route_map_mark_updated(rmap_name
, 0) == 0)
3151 bgp_route_map_mark_update(rmap_name
);
3153 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
3156 static void bgp_route_map_delete(const char *rmap_name
)
3158 if (route_map_mark_updated(rmap_name
, 1) == 0)
3159 bgp_route_map_mark_update(rmap_name
);
3161 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
3164 static void bgp_route_map_event(route_map_event_t event
, const char *rmap_name
)
3166 if (route_map_mark_updated(rmap_name
, 0) == 0)
3167 bgp_route_map_mark_update(rmap_name
);
3169 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
3172 DEFUN (match_mac_address
,
3173 match_mac_address_cmd
,
3174 "match mac address WORD",
3177 "Match address of route\n"
3178 "MAC Access-list name\n")
3180 return bgp_route_match_add(vty
, "mac address", argv
[3]->arg
,
3181 RMAP_EVENT_FILTER_ADDED
);
3184 DEFUN (no_match_mac_address
,
3185 no_match_mac_address_cmd
,
3186 "no match mac address WORD",
3190 "Match address of route\n"
3191 "MAC acess-list name\n")
3193 return bgp_route_match_delete(vty
, "mac address", argv
[4]->arg
,
3194 RMAP_EVENT_FILTER_DELETED
);
3197 DEFUN (match_evpn_route_type
,
3198 match_evpn_route_type_cmd
,
3199 "match evpn route-type <macip | multicast | prefix>",
3202 "Match route-type\n"
3207 return bgp_route_match_add(vty
, "evpn route-type", argv
[3]->arg
,
3208 RMAP_EVENT_MATCH_ADDED
);
3211 DEFUN (no_match_evpn_route_type
,
3212 no_match_evpn_route_type_cmd
,
3213 "no match evpn route-type <macip | multicast | prefix>",
3217 "Match route-type\n"
3222 return bgp_route_match_delete(vty
, "evpn route-type", argv
[4]->arg
,
3223 RMAP_EVENT_MATCH_DELETED
);
3227 DEFUN (match_evpn_vni
,
3229 "match evpn vni (1-16777215)",
3235 return bgp_route_match_add(vty
, "evpn vni", argv
[3]->arg
,
3236 RMAP_EVENT_MATCH_ADDED
);
3239 DEFUN (no_match_evpn_vni
,
3240 no_match_evpn_vni_cmd
,
3241 "no match evpn vni (1-16777215)",
3248 return bgp_route_match_delete(vty
, "evpn vni", argv
[4]->arg
,
3249 RMAP_EVENT_MATCH_DELETED
);
3254 "match peer <A.B.C.D|X:X::X:X|WORD>",
3256 "Match peer address\n"
3257 "IP address of peer\n"
3258 "IPv6 address of peer\n"
3259 "Interface name of peer\n")
3262 return bgp_route_match_add(vty
, "peer", argv
[idx_ip
]->arg
,
3263 RMAP_EVENT_MATCH_ADDED
);
3266 DEFUN (match_peer_local
,
3267 match_peer_local_cmd
,
3270 "Match peer address\n"
3271 "Static or Redistributed routes\n")
3273 return bgp_route_match_add(vty
, "peer", "local",
3274 RMAP_EVENT_MATCH_DELETED
);
3277 DEFUN (no_match_peer
,
3279 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
3282 "Match peer address\n"
3283 "Static or Redistributed routes\n"
3284 "IP address of peer\n"
3285 "IPv6 address of peer\n"
3286 "Interface name of peer\n")
3290 if (argc
<= idx_peer
)
3291 return bgp_route_match_delete(vty
, "peer", NULL
,
3292 RMAP_EVENT_MATCH_DELETED
);
3293 return bgp_route_match_delete(vty
, "peer", argv
[idx_peer
]->arg
,
3294 RMAP_EVENT_MATCH_DELETED
);
3298 /* match probability */
3299 DEFUN (match_probability
,
3300 match_probability_cmd
,
3301 "match probability (0-100)",
3303 "Match portion of routes defined by percentage value\n"
3304 "Percentage of routes\n")
3307 return bgp_route_match_add(vty
, "probability", argv
[idx_number
]->arg
,
3308 RMAP_EVENT_MATCH_ADDED
);
3312 DEFUN (no_match_probability
,
3313 no_match_probability_cmd
,
3314 "no match probability [(1-99)]",
3317 "Match portion of routes defined by percentage value\n"
3318 "Percentage of routes\n")
3321 if (argc
<= idx_number
)
3322 return bgp_route_match_delete(vty
, "probability", NULL
,
3323 RMAP_EVENT_MATCH_DELETED
);
3324 return bgp_route_match_delete(vty
, "probability", argv
[idx_number
]->arg
,
3325 RMAP_EVENT_MATCH_DELETED
);
3329 DEFUN (match_ip_route_source
,
3330 match_ip_route_source_cmd
,
3331 "match ip route-source <(1-199)|(1300-2699)|WORD>",
3334 "Match advertising source address of route\n"
3335 "IP access-list number\n"
3336 "IP access-list number (expanded range)\n"
3337 "IP standard access-list name\n")
3340 return bgp_route_match_add(vty
, "ip route-source", argv
[idx_acl
]->arg
,
3341 RMAP_EVENT_FILTER_ADDED
);
3345 DEFUN (no_match_ip_route_source
,
3346 no_match_ip_route_source_cmd
,
3347 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
3351 "Match advertising source address of route\n"
3352 "IP access-list number\n"
3353 "IP access-list number (expanded range)\n"
3354 "IP standard access-list name\n")
3357 if (argc
<= idx_number
)
3358 return bgp_route_match_delete(vty
, "ip route-source", NULL
,
3359 RMAP_EVENT_FILTER_DELETED
);
3360 return bgp_route_match_delete(vty
, "ip route-source",
3361 argv
[idx_number
]->arg
,
3362 RMAP_EVENT_FILTER_DELETED
);
3366 DEFUN (match_ip_route_source_prefix_list
,
3367 match_ip_route_source_prefix_list_cmd
,
3368 "match ip route-source prefix-list WORD",
3371 "Match advertising source address of route\n"
3372 "Match entries of prefix-lists\n"
3373 "IP prefix-list name\n")
3376 return bgp_route_match_add(vty
, "ip route-source prefix-list",
3377 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
3381 DEFUN (no_match_ip_route_source_prefix_list
,
3382 no_match_ip_route_source_prefix_list_cmd
,
3383 "no match ip route-source prefix-list [WORD]",
3387 "Match advertising source address of route\n"
3388 "Match entries of prefix-lists\n"
3389 "IP prefix-list name\n")
3392 if (argc
<= idx_word
)
3393 return bgp_route_match_delete(vty
,
3394 "ip route-source prefix-list",
3395 NULL
, RMAP_EVENT_PLIST_DELETED
);
3396 return bgp_route_match_delete(vty
, "ip route-source prefix-list",
3397 argv
[idx_word
]->arg
,
3398 RMAP_EVENT_PLIST_DELETED
);
3402 DEFUN (match_local_pref
,
3403 match_local_pref_cmd
,
3404 "match local-preference (0-4294967295)",
3406 "Match local-preference of route\n"
3410 return bgp_route_match_add(vty
, "local-preference",
3411 argv
[idx_number
]->arg
,
3412 RMAP_EVENT_MATCH_ADDED
);
3416 DEFUN (no_match_local_pref
,
3417 no_match_local_pref_cmd
,
3418 "no match local-preference [(0-4294967295)]",
3421 "Match local preference of route\n"
3422 "Local preference value\n")
3424 int idx_localpref
= 3;
3425 if (argc
<= idx_localpref
)
3426 return bgp_route_match_delete(vty
, "local-preference", NULL
,
3427 RMAP_EVENT_MATCH_DELETED
);
3428 return bgp_route_match_delete(vty
, "local-preference",
3429 argv
[idx_localpref
]->arg
,
3430 RMAP_EVENT_MATCH_DELETED
);
3434 DEFUN (match_community
,
3435 match_community_cmd
,
3436 "match community <(1-99)|(100-500)|WORD> [exact-match]",
3438 "Match BGP community list\n"
3439 "Community-list number (standard)\n"
3440 "Community-list number (expanded)\n"
3441 "Community-list name\n"
3442 "Do exact matching of communities\n")
3444 int idx_comm_list
= 2;
3449 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
3450 strlen(argv
[idx_comm_list
]->arg
)
3451 + strlen("exact-match") + 2);
3453 sprintf(argstr
, "%s exact-match", argv
[idx_comm_list
]->arg
);
3455 argstr
= argv
[idx_comm_list
]->arg
;
3457 ret
= bgp_route_match_add(vty
, "community", argstr
,
3458 RMAP_EVENT_CLIST_ADDED
);
3460 if (argstr
!= argv
[idx_comm_list
]->arg
)
3461 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
3466 DEFUN (no_match_community
,
3467 no_match_community_cmd
,
3468 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
3471 "Match BGP community list\n"
3472 "Community-list number (standard)\n"
3473 "Community-list number (expanded)\n"
3474 "Community-list name\n"
3475 "Do exact matching of communities\n")
3477 return bgp_route_match_delete(vty
, "community", NULL
,
3478 RMAP_EVENT_CLIST_DELETED
);
3481 DEFUN (match_lcommunity
,
3482 match_lcommunity_cmd
,
3483 "match large-community <(1-99)|(100-500)|WORD>",
3485 "Match BGP large community list\n"
3486 "Large Community-list number (standard)\n"
3487 "Large Community-list number (expanded)\n"
3488 "Large Community-list name\n")
3490 return bgp_route_match_add(vty
, "large-community", argv
[2]->arg
,
3491 RMAP_EVENT_LLIST_ADDED
);
3494 DEFUN (no_match_lcommunity
,
3495 no_match_lcommunity_cmd
,
3496 "no match large-community [<(1-99)|(100-500)|WORD>]",
3499 "Match BGP large community list\n"
3500 "Large Community-list number (standard)\n"
3501 "Large Community-list number (expanded)\n"
3502 "Large Community-list name\n")
3504 return bgp_route_match_delete(vty
, "large-community", NULL
,
3505 RMAP_EVENT_LLIST_DELETED
);
3508 DEFUN (match_ecommunity
,
3509 match_ecommunity_cmd
,
3510 "match extcommunity <(1-99)|(100-500)|WORD>",
3512 "Match BGP/VPN extended community list\n"
3513 "Extended community-list number (standard)\n"
3514 "Extended community-list number (expanded)\n"
3515 "Extended community-list name\n")
3517 int idx_comm_list
= 2;
3518 return bgp_route_match_add(vty
, "extcommunity",
3519 argv
[idx_comm_list
]->arg
,
3520 RMAP_EVENT_ECLIST_ADDED
);
3524 DEFUN (no_match_ecommunity
,
3525 no_match_ecommunity_cmd
,
3526 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
3529 "Match BGP/VPN extended community list\n"
3530 "Extended community-list number (standard)\n"
3531 "Extended community-list number (expanded)\n"
3532 "Extended community-list name\n")
3534 return bgp_route_match_delete(vty
, "extcommunity", NULL
,
3535 RMAP_EVENT_ECLIST_DELETED
);
3539 DEFUN (match_aspath
,
3541 "match as-path WORD",
3543 "Match BGP AS path list\n"
3544 "AS path access-list name\n")
3547 return bgp_route_match_add(vty
, "as-path", argv
[idx_word
]->arg
,
3548 RMAP_EVENT_ASLIST_ADDED
);
3552 DEFUN (no_match_aspath
,
3553 no_match_aspath_cmd
,
3554 "no match as-path [WORD]",
3557 "Match BGP AS path list\n"
3558 "AS path access-list name\n")
3560 return bgp_route_match_delete(vty
, "as-path", NULL
,
3561 RMAP_EVENT_ASLIST_DELETED
);
3565 DEFUN (match_origin
,
3567 "match origin <egp|igp|incomplete>",
3572 "unknown heritage\n")
3575 if (strncmp(argv
[idx_origin
]->arg
, "igp", 2) == 0)
3576 return bgp_route_match_add(vty
, "origin", "igp",
3577 RMAP_EVENT_MATCH_ADDED
);
3578 if (strncmp(argv
[idx_origin
]->arg
, "egp", 1) == 0)
3579 return bgp_route_match_add(vty
, "origin", "egp",
3580 RMAP_EVENT_MATCH_ADDED
);
3581 if (strncmp(argv
[idx_origin
]->arg
, "incomplete", 2) == 0)
3582 return bgp_route_match_add(vty
, "origin", "incomplete",
3583 RMAP_EVENT_MATCH_ADDED
);
3585 vty_out(vty
, "%% Invalid match origin type\n");
3586 return CMD_WARNING_CONFIG_FAILED
;
3590 DEFUN (no_match_origin
,
3591 no_match_origin_cmd
,
3592 "no match origin [<egp|igp|incomplete>]",
3598 "unknown heritage\n")
3600 return bgp_route_match_delete(vty
, "origin", NULL
,
3601 RMAP_EVENT_MATCH_DELETED
);
3604 DEFUN (set_ip_nexthop_peer
,
3605 set_ip_nexthop_peer_cmd
,
3606 "[no] set ip next-hop peer-address",
3610 "Next hop address\n"
3611 "Use peer address (for BGP only)\n")
3613 int (*func
)(struct vty
*, struct route_map_index
*, const char *,
3614 const char *) = strmatch(argv
[0]->text
, "no")
3615 ? generic_set_delete
3618 return func(vty
, VTY_GET_CONTEXT(route_map_index
), "ip next-hop",
3622 DEFUN (set_ip_nexthop_unchanged
,
3623 set_ip_nexthop_unchanged_cmd
,
3624 "[no] set ip next-hop unchanged",
3628 "Next hop address\n"
3629 "Don't modify existing Next hop address\n")
3631 int (*func
)(struct vty
*, struct route_map_index
*, const char *,
3632 const char *) = strmatch(argv
[0]->text
, "no")
3633 ? generic_set_delete
3636 return func(vty
, VTY_GET_CONTEXT(route_map_index
), "ip next-hop",
3641 DEFUN (set_local_pref
,
3643 "set local-preference (0-4294967295)",
3645 "BGP local preference path attribute\n"
3646 "Preference value\n")
3649 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3650 "local-preference", argv
[idx_number
]->arg
);
3654 DEFUN (no_set_local_pref
,
3655 no_set_local_pref_cmd
,
3656 "no set local-preference [(0-4294967295)]",
3659 "BGP local preference path attribute\n"
3660 "Preference value\n")
3662 int idx_localpref
= 3;
3663 if (argc
<= idx_localpref
)
3664 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3665 "local-preference", NULL
);
3666 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3667 "local-preference", argv
[idx_localpref
]->arg
);
3673 "set weight (0-4294967295)",
3675 "BGP weight for routing table\n"
3679 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
), "weight",
3680 argv
[idx_number
]->arg
);
3684 DEFUN (no_set_weight
,
3686 "no set weight [(0-4294967295)]",
3689 "BGP weight for routing table\n"
3693 if (argc
<= idx_weight
)
3694 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3696 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3697 "weight", argv
[idx_weight
]->arg
);
3700 DEFUN (set_label_index
,
3701 set_label_index_cmd
,
3702 "set label-index (0-1048560)",
3704 "Label index to associate with the prefix\n"
3705 "Label index value\n")
3708 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3709 "label-index", argv
[idx_number
]->arg
);
3712 DEFUN (no_set_label_index
,
3713 no_set_label_index_cmd
,
3714 "no set label-index [(0-1048560)]",
3717 "Label index to associate with the prefix\n"
3718 "Label index value\n")
3720 int idx_label_index
= 3;
3721 if (argc
<= idx_label_index
)
3722 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3723 "label-index", NULL
);
3724 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3725 "label-index", argv
[idx_label_index
]->arg
);
3728 DEFUN (set_aspath_prepend_asn
,
3729 set_aspath_prepend_asn_cmd
,
3730 "set as-path prepend (1-4294967295)...",
3732 "Transform BGP AS_PATH attribute\n"
3733 "Prepend to the as-path\n"
3740 str
= argv_concat(argv
, argc
, idx_asn
);
3741 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3742 "as-path prepend", str
);
3743 XFREE(MTYPE_TMP
, str
);
3748 DEFUN (set_aspath_prepend_lastas
,
3749 set_aspath_prepend_lastas_cmd
,
3750 "set as-path prepend last-as (1-10)",
3752 "Transform BGP AS_PATH attribute\n"
3753 "Prepend to the as-path\n"
3754 "Use the peer's AS-number\n"
3755 "Number of times to insert\n")
3757 return set_aspath_prepend_asn(self
, vty
, argc
, argv
);
3760 DEFUN (no_set_aspath_prepend
,
3761 no_set_aspath_prepend_cmd
,
3762 "no set as-path prepend [(1-4294967295)]",
3765 "Transform BGP AS_PATH attribute\n"
3766 "Prepend to the as-path\n"
3773 str
= argv_concat(argv
, argc
, idx_asn
);
3774 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3775 "as-path prepend", str
);
3776 XFREE(MTYPE_TMP
, str
);
3781 DEFUN (set_aspath_exclude
,
3782 set_aspath_exclude_cmd
,
3783 "set as-path exclude (1-4294967295)...",
3785 "Transform BGP AS-path attribute\n"
3786 "Exclude from the as-path\n"
3793 str
= argv_concat(argv
, argc
, idx_asn
);
3794 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3795 "as-path exclude", str
);
3796 XFREE(MTYPE_TMP
, str
);
3800 DEFUN (no_set_aspath_exclude
,
3801 no_set_aspath_exclude_cmd
,
3802 "no set as-path exclude (1-4294967295)...",
3805 "Transform BGP AS_PATH attribute\n"
3806 "Exclude from the as-path\n"
3813 str
= argv_concat(argv
, argc
, idx_asn
);
3814 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3815 "as-path exclude", str
);
3816 XFREE(MTYPE_TMP
, str
);
3821 DEFUN (set_community
,
3823 "set community AA:NN...",
3825 "BGP community attribute\n"
3833 struct community
*com
= NULL
;
3838 b
= buffer_new(1024);
3840 for (i
= idx_aa_nn
; i
< argc
; i
++) {
3841 if (strncmp(argv
[i
]->arg
, "additive", strlen(argv
[i
]->arg
))
3848 buffer_putc(b
, ' ');
3852 if (strncmp(argv
[i
]->arg
, "internet", strlen(argv
[i
]->arg
))
3854 buffer_putstr(b
, "internet");
3857 if (strncmp(argv
[i
]->arg
, "local-AS", strlen(argv
[i
]->arg
))
3859 buffer_putstr(b
, "local-AS");
3862 if (strncmp(argv
[i
]->arg
, "no-a", strlen("no-a")) == 0
3863 && strncmp(argv
[i
]->arg
, "no-advertise",
3864 strlen(argv
[i
]->arg
))
3866 buffer_putstr(b
, "no-advertise");
3869 if (strncmp(argv
[i
]->arg
, "no-e", strlen("no-e")) == 0
3870 && strncmp(argv
[i
]->arg
, "no-export", strlen(argv
[i
]->arg
))
3872 buffer_putstr(b
, "no-export");
3875 if (strncmp(argv
[i
]->arg
, "graceful-shutdown",
3876 strlen(argv
[i
]->arg
))
3878 buffer_putstr(b
, "graceful-shutdown");
3881 buffer_putstr(b
, argv
[i
]->arg
);
3883 buffer_putc(b
, '\0');
3885 /* Fetch result string then compile it to communities attribute. */
3886 str
= buffer_getstr(b
);
3890 com
= community_str2com(str
);
3891 XFREE(MTYPE_TMP
, str
);
3894 /* Can't compile user input into communities attribute. */
3896 vty_out(vty
, "%% Malformed communities attribute\n");
3897 return CMD_WARNING_CONFIG_FAILED
;
3900 /* Set communites attribute string. */
3901 str
= community_str(com
, false);
3904 argstr
= XCALLOC(MTYPE_TMP
,
3905 strlen(str
) + strlen(" additive") + 1);
3906 strcpy(argstr
, str
);
3907 strcpy(argstr
+ strlen(str
), " additive");
3908 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3909 "community", argstr
);
3910 XFREE(MTYPE_TMP
, argstr
);
3912 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3915 community_free(com
);
3920 DEFUN (set_community_none
,
3921 set_community_none_cmd
,
3922 "set community none",
3924 "BGP community attribute\n"
3925 "No community attribute\n")
3927 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3928 "community", "none");
3931 DEFUN (no_set_community
,
3932 no_set_community_cmd
,
3933 "no set community AA:NN...",
3936 "BGP community attribute\n"
3939 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3944 DEFUN (set_community_delete
,
3945 set_community_delete_cmd
,
3946 "set comm-list <(1-99)|(100-500)|WORD> delete",
3948 "set BGP community list (for deletion)\n"
3949 "Community-list number (standard)\n"
3950 "Community-list number (expanded)\n"
3951 "Community-list name\n"
3952 "Delete matching communities\n")
3954 int idx_comm_list
= 2;
3957 str
= XCALLOC(MTYPE_TMP
,
3958 strlen(argv
[idx_comm_list
]->arg
) + strlen(" delete") + 1);
3959 strcpy(str
, argv
[idx_comm_list
]->arg
);
3960 strcpy(str
+ strlen(argv
[idx_comm_list
]->arg
), " delete");
3962 generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
), "comm-list",
3965 XFREE(MTYPE_TMP
, str
);
3969 DEFUN (no_set_community_delete
,
3970 no_set_community_delete_cmd
,
3971 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
3974 "set BGP community list (for deletion)\n"
3975 "Community-list number (standard)\n"
3976 "Community-list number (expanded)\n"
3977 "Community-list name\n"
3978 "Delete matching communities\n")
3980 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3984 DEFUN (set_lcommunity
,
3986 "set large-community AA:BB:CC...",
3988 "BGP large community attribute\n"
3989 "Large Community number in aa:bb:cc format or additive\n")
3994 str
= argv_concat(argv
, argc
, 2);
3995 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3996 "large-community", str
);
3997 XFREE(MTYPE_TMP
, str
);
4002 DEFUN (set_lcommunity_none
,
4003 set_lcommunity_none_cmd
,
4004 "set large-community none",
4006 "BGP large community attribute\n"
4007 "No large community attribute\n")
4009 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4010 "large-community", "none");
4013 DEFUN (no_set_lcommunity
,
4014 no_set_lcommunity_cmd
,
4015 "no set large-community none",
4018 "BGP large community attribute\n"
4019 "No community attribute\n")
4021 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4022 "large-community", NULL
);
4025 DEFUN (no_set_lcommunity1
,
4026 no_set_lcommunity1_cmd
,
4027 "no set large-community AA:BB:CC...",
4030 "BGP large community attribute\n"
4031 "Large community in AA:BB:CC... format or additive\n")
4033 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4034 "large-community", NULL
);
4037 DEFUN (set_lcommunity_delete
,
4038 set_lcommunity_delete_cmd
,
4039 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4041 "set BGP large community list (for deletion)\n"
4042 "Large Community-list number (standard)\n"
4043 "Large Communitly-list number (expanded)\n"
4044 "Large Community-list name\n"
4045 "Delete matching large communities\n")
4049 str
= XCALLOC(MTYPE_TMP
, strlen(argv
[2]->arg
) + strlen(" delete") + 1);
4050 strcpy(str
, argv
[2]->arg
);
4051 strcpy(str
+ strlen(argv
[2]->arg
), " delete");
4053 generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4054 "large-comm-list", str
);
4056 XFREE(MTYPE_TMP
, str
);
4060 DEFUN (no_set_lcommunity_delete
,
4061 no_set_lcommunity_delete_cmd
,
4062 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
4065 "set BGP large community list (for deletion)\n"
4066 "Large Community-list number (standard)\n"
4067 "Large Communitly-list number (expanded)\n"
4068 "Large Community-list name\n"
4069 "Delete matching large communities\n")
4071 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4072 "large-comm-list", NULL
);
4075 DEFUN (set_ecommunity_rt
,
4076 set_ecommunity_rt_cmd
,
4077 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4079 "BGP extended community attribute\n"
4080 "Route Target extended community\n"
4081 "VPN extended community\n")
4087 str
= argv_concat(argv
, argc
, idx_asn_nn
);
4088 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4089 "extcommunity rt", str
);
4090 XFREE(MTYPE_TMP
, str
);
4095 DEFUN (no_set_ecommunity_rt
,
4096 no_set_ecommunity_rt_cmd
,
4097 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4100 "BGP extended community attribute\n"
4101 "Route Target extended community\n"
4102 "VPN extended community\n")
4104 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4105 "extcommunity rt", NULL
);
4109 DEFUN (set_ecommunity_soo
,
4110 set_ecommunity_soo_cmd
,
4111 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4113 "BGP extended community attribute\n"
4114 "Site-of-Origin extended community\n"
4115 "VPN extended community\n")
4121 str
= argv_concat(argv
, argc
, idx_asn_nn
);
4122 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4123 "extcommunity soo", str
);
4124 XFREE(MTYPE_TMP
, str
);
4129 DEFUN (no_set_ecommunity_soo
,
4130 no_set_ecommunity_soo_cmd
,
4131 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4134 "BGP extended community attribute\n"
4135 "Site-of-Origin extended community\n"
4136 "VPN extended community\n")
4138 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4139 "extcommunity soo", NULL
);
4145 "set origin <egp|igp|incomplete>",
4150 "unknown heritage\n")
4153 if (strncmp(argv
[idx_origin
]->arg
, "igp", 2) == 0)
4154 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4156 if (strncmp(argv
[idx_origin
]->arg
, "egp", 1) == 0)
4157 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4159 if (strncmp(argv
[idx_origin
]->arg
, "incomplete", 2) == 0)
4160 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4161 "origin", "incomplete");
4163 vty_out(vty
, "%% Invalid set origin type\n");
4164 return CMD_WARNING_CONFIG_FAILED
;
4168 DEFUN (no_set_origin
,
4170 "no set origin [<egp|igp|incomplete>]",
4176 "unknown heritage\n")
4178 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4183 DEFUN (set_atomic_aggregate
,
4184 set_atomic_aggregate_cmd
,
4185 "set atomic-aggregate",
4187 "BGP atomic aggregate attribute\n" )
4189 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4190 "atomic-aggregate", NULL
);
4193 DEFUN (no_set_atomic_aggregate
,
4194 no_set_atomic_aggregate_cmd
,
4195 "no set atomic-aggregate",
4198 "BGP atomic aggregate attribute\n" )
4200 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4201 "atomic-aggregate", NULL
);
4204 DEFUN (set_aggregator_as
,
4205 set_aggregator_as_cmd
,
4206 "set aggregator as (1-4294967295) A.B.C.D",
4208 "BGP aggregator attribute\n"
4209 "AS number of aggregator\n"
4211 "IP address of aggregator\n")
4216 struct in_addr address
;
4219 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &address
);
4221 vty_out(vty
, "Aggregator IP address is invalid\n");
4222 return CMD_WARNING_CONFIG_FAILED
;
4225 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
4226 strlen(argv
[idx_number
]->arg
)
4227 + strlen(argv
[idx_ipv4
]->arg
) + 2);
4229 sprintf(argstr
, "%s %s", argv
[idx_number
]->arg
, argv
[idx_ipv4
]->arg
);
4231 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4232 "aggregator as", argstr
);
4234 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
4240 DEFUN (no_set_aggregator_as
,
4241 no_set_aggregator_as_cmd
,
4242 "no set aggregator as [(1-4294967295) A.B.C.D]",
4245 "BGP aggregator attribute\n"
4246 "AS number of aggregator\n"
4248 "IP address of aggregator\n")
4253 struct in_addr address
;
4256 if (argc
<= idx_asn
)
4257 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4258 "aggregator as", NULL
);
4260 ret
= inet_aton(argv
[idx_ip
]->arg
, &address
);
4262 vty_out(vty
, "Aggregator IP address is invalid\n");
4263 return CMD_WARNING_CONFIG_FAILED
;
4266 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
4267 strlen(argv
[idx_asn
]->arg
) + strlen(argv
[idx_ip
]->arg
)
4270 sprintf(argstr
, "%s %s", argv
[idx_asn
]->arg
, argv
[idx_ip
]->arg
);
4272 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4273 "aggregator as", argstr
);
4275 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
4280 DEFUN (match_ipv6_next_hop
,
4281 match_ipv6_next_hop_cmd
,
4282 "match ipv6 next-hop X:X::X:X",
4285 "Match IPv6 next-hop address of route\n"
4286 "IPv6 address of next hop\n")
4289 return bgp_route_match_add(vty
, "ipv6 next-hop", argv
[idx_ipv6
]->arg
,
4290 RMAP_EVENT_MATCH_ADDED
);
4293 DEFUN (no_match_ipv6_next_hop
,
4294 no_match_ipv6_next_hop_cmd
,
4295 "no match ipv6 next-hop X:X::X:X",
4299 "Match IPv6 next-hop address of route\n"
4300 "IPv6 address of next hop\n")
4303 return bgp_route_match_delete(vty
, "ipv6 next-hop", argv
[idx_ipv6
]->arg
,
4304 RMAP_EVENT_MATCH_DELETED
);
4308 DEFUN (set_ipv6_nexthop_peer
,
4309 set_ipv6_nexthop_peer_cmd
,
4310 "set ipv6 next-hop peer-address",
4313 "Next hop address\n"
4314 "Use peer address (for BGP only)\n")
4316 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4317 "ipv6 next-hop peer-address", NULL
);
4320 DEFUN (no_set_ipv6_nexthop_peer
,
4321 no_set_ipv6_nexthop_peer_cmd
,
4322 "no set ipv6 next-hop peer-address",
4326 "IPv6 next-hop address\n"
4327 "Use peer address (for BGP only)\n")
4329 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4330 "ipv6 next-hop peer-address", NULL
);
4333 DEFUN (set_ipv6_nexthop_prefer_global
,
4334 set_ipv6_nexthop_prefer_global_cmd
,
4335 "set ipv6 next-hop prefer-global",
4338 "IPv6 next-hop address\n"
4339 "Prefer global over link-local if both exist\n")
4341 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4342 "ipv6 next-hop prefer-global", NULL
);
4346 DEFUN (no_set_ipv6_nexthop_prefer_global
,
4347 no_set_ipv6_nexthop_prefer_global_cmd
,
4348 "no set ipv6 next-hop prefer-global",
4352 "IPv6 next-hop address\n"
4353 "Prefer global over link-local if both exist\n")
4355 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4356 "ipv6 next-hop prefer-global", NULL
);
4359 DEFUN (set_ipv6_nexthop_global
,
4360 set_ipv6_nexthop_global_cmd
,
4361 "set ipv6 next-hop global X:X::X:X",
4364 "IPv6 next-hop address\n"
4365 "IPv6 global address\n"
4366 "IPv6 address of next hop\n")
4369 struct in6_addr addr
;
4372 ret
= inet_pton(AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
4374 vty_out(vty
, "%% Malformed nexthop address\n");
4375 return CMD_WARNING_CONFIG_FAILED
;
4377 if (IN6_IS_ADDR_UNSPECIFIED(&addr
) || IN6_IS_ADDR_LOOPBACK(&addr
)
4378 || IN6_IS_ADDR_MULTICAST(&addr
) || IN6_IS_ADDR_LINKLOCAL(&addr
)) {
4379 vty_out(vty
, "%% Invalid global nexthop address\n");
4380 return CMD_WARNING_CONFIG_FAILED
;
4383 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4384 "ipv6 next-hop global", argv
[idx_ipv6
]->arg
);
4388 DEFUN (no_set_ipv6_nexthop_global
,
4389 no_set_ipv6_nexthop_global_cmd
,
4390 "no set ipv6 next-hop global X:X::X:X",
4394 "IPv6 next-hop address\n"
4395 "IPv6 global address\n"
4396 "IPv6 address of next hop\n")
4399 if (argc
<= idx_ipv6
)
4400 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4401 "ipv6 next-hop global", NULL
);
4402 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4403 "ipv6 next-hop global", argv
[idx_ipv6
]->arg
);
4406 #ifdef KEEP_OLD_VPN_COMMANDS
4407 DEFUN (set_vpn_nexthop
,
4408 set_vpn_nexthop_cmd
,
4409 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4411 "VPNv4 information\n"
4412 "VPN next-hop address\n"
4413 "IP address of next hop\n"
4414 "VPNv6 information\n"
4415 "VPN next-hop address\n"
4416 "IPv6 address of next hop\n")
4422 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
4424 return generic_set_add(
4425 vty
, VTY_GET_CONTEXT(route_map_index
),
4426 "ipv4 vpn next-hop", argv
[idx_ip
]->arg
);
4428 return generic_set_add(
4429 vty
, VTY_GET_CONTEXT(route_map_index
),
4430 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4435 DEFUN (no_set_vpn_nexthop
,
4436 no_set_vpn_nexthop_cmd
,
4437 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4440 "VPNv4 information\n"
4441 "VPN next-hop address\n"
4442 "IP address of next hop\n"
4443 "VPNv6 information\n"
4444 "VPN next-hop address\n"
4445 "IPv6 address of next hop\n")
4455 arg
= argv
[idx_ip
]->arg
;
4456 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
4458 return generic_set_delete(
4459 vty
, VTY_GET_CONTEXT(route_map_index
),
4460 "ipv4 vpn next-hop", arg
);
4462 return generic_set_delete(
4463 vty
, VTY_GET_CONTEXT(route_map_index
),
4464 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4468 #endif /* KEEP_OLD_VPN_COMMANDS */
4470 DEFUN (set_ipx_vpn_nexthop
,
4471 set_ipx_vpn_nexthop_cmd
,
4472 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
4474 "IPv4 information\n"
4475 "IPv6 information\n"
4477 "VPN next-hop address\n"
4478 "IP address of next hop\n"
4479 "IPv6 address of next hop\n")
4485 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
4487 return generic_set_add(
4488 vty
, VTY_GET_CONTEXT(route_map_index
),
4489 "ipv4 vpn next-hop", argv
[idx_ip
]->arg
);
4491 return generic_set_add(
4492 vty
, VTY_GET_CONTEXT(route_map_index
),
4493 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4498 DEFUN (no_set_ipx_vpn_nexthop
,
4499 no_set_ipx_vpn_nexthop_cmd
,
4500 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
4503 "IPv4 information\n"
4504 "IPv6 information\n"
4506 "VPN next-hop address\n"
4507 "IP address of next hop\n"
4508 "IPv6 address of next hop\n")
4518 arg
= argv
[idx_ip
]->arg
;
4519 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
4521 return generic_set_delete(
4522 vty
, VTY_GET_CONTEXT(route_map_index
),
4523 "ipv4 vpn next-hop", arg
);
4525 return generic_set_delete(
4526 vty
, VTY_GET_CONTEXT(route_map_index
),
4527 "ipv6 vpn next-hop", arg
);
4532 DEFUN (set_originator_id
,
4533 set_originator_id_cmd
,
4534 "set originator-id A.B.C.D",
4536 "BGP originator ID attribute\n"
4537 "IP address of originator\n")
4540 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4541 "originator-id", argv
[idx_ipv4
]->arg
);
4545 DEFUN (no_set_originator_id
,
4546 no_set_originator_id_cmd
,
4547 "no set originator-id [A.B.C.D]",
4550 "BGP originator ID attribute\n"
4551 "IP address of originator\n")
4555 argv_find(argv
, argc
, "A.B.C.D", &idx
) ? argv
[idx
]->arg
: NULL
;
4557 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4558 "originator-id", arg
);
4562 /* Initialization of route map. */
4563 void bgp_route_map_init(void)
4567 route_map_add_hook(bgp_route_map_add
);
4568 route_map_delete_hook(bgp_route_map_delete
);
4569 route_map_event_hook(bgp_route_map_event
);
4571 route_map_match_interface_hook(generic_match_add
);
4572 route_map_no_match_interface_hook(generic_match_delete
);
4574 route_map_match_ip_address_hook(generic_match_add
);
4575 route_map_no_match_ip_address_hook(generic_match_delete
);
4577 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
4578 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
4580 route_map_match_ip_next_hop_hook(generic_match_add
);
4581 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
4583 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
4584 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
4586 route_map_match_ipv6_address_hook(generic_match_add
);
4587 route_map_no_match_ipv6_address_hook(generic_match_delete
);
4589 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
4590 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
4592 route_map_match_metric_hook(generic_match_add
);
4593 route_map_no_match_metric_hook(generic_match_delete
);
4595 route_map_match_tag_hook(generic_match_add
);
4596 route_map_no_match_tag_hook(generic_match_delete
);
4598 route_map_set_ip_nexthop_hook(generic_set_add
);
4599 route_map_no_set_ip_nexthop_hook(generic_set_delete
);
4601 route_map_set_ipv6_nexthop_local_hook(generic_set_add
);
4602 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete
);
4604 route_map_set_metric_hook(generic_set_add
);
4605 route_map_no_set_metric_hook(generic_set_delete
);
4607 route_map_set_tag_hook(generic_set_add
);
4608 route_map_no_set_tag_hook(generic_set_delete
);
4610 route_map_install_match(&route_match_peer_cmd
);
4611 route_map_install_match(&route_match_local_pref_cmd
);
4612 route_map_install_match(&route_match_ip_address_cmd
);
4613 route_map_install_match(&route_match_ip_next_hop_cmd
);
4614 route_map_install_match(&route_match_ip_route_source_cmd
);
4615 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
4616 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
4617 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd
);
4618 route_map_install_match(&route_match_aspath_cmd
);
4619 route_map_install_match(&route_match_community_cmd
);
4620 route_map_install_match(&route_match_lcommunity_cmd
);
4621 route_map_install_match(&route_match_ecommunity_cmd
);
4622 route_map_install_match(&route_match_local_pref_cmd
);
4623 route_map_install_match(&route_match_metric_cmd
);
4624 route_map_install_match(&route_match_origin_cmd
);
4625 route_map_install_match(&route_match_probability_cmd
);
4626 route_map_install_match(&route_match_interface_cmd
);
4627 route_map_install_match(&route_match_tag_cmd
);
4628 route_map_install_match(&route_match_mac_address_cmd
);
4629 route_map_install_match(&route_match_evpn_vni_cmd
);
4630 route_map_install_match(&route_match_evpn_route_type_cmd
);
4632 route_map_install_set(&route_set_ip_nexthop_cmd
);
4633 route_map_install_set(&route_set_local_pref_cmd
);
4634 route_map_install_set(&route_set_weight_cmd
);
4635 route_map_install_set(&route_set_label_index_cmd
);
4636 route_map_install_set(&route_set_metric_cmd
);
4637 route_map_install_set(&route_set_aspath_prepend_cmd
);
4638 route_map_install_set(&route_set_aspath_exclude_cmd
);
4639 route_map_install_set(&route_set_origin_cmd
);
4640 route_map_install_set(&route_set_atomic_aggregate_cmd
);
4641 route_map_install_set(&route_set_aggregator_as_cmd
);
4642 route_map_install_set(&route_set_community_cmd
);
4643 route_map_install_set(&route_set_community_delete_cmd
);
4644 route_map_install_set(&route_set_lcommunity_cmd
);
4645 route_map_install_set(&route_set_lcommunity_delete_cmd
);
4646 route_map_install_set(&route_set_vpnv4_nexthop_cmd
);
4647 route_map_install_set(&route_set_vpnv6_nexthop_cmd
);
4648 route_map_install_set(&route_set_originator_id_cmd
);
4649 route_map_install_set(&route_set_ecommunity_rt_cmd
);
4650 route_map_install_set(&route_set_ecommunity_soo_cmd
);
4651 route_map_install_set(&route_set_tag_cmd
);
4652 route_map_install_set(&route_set_label_index_cmd
);
4654 install_element(RMAP_NODE
, &match_peer_cmd
);
4655 install_element(RMAP_NODE
, &match_peer_local_cmd
);
4656 install_element(RMAP_NODE
, &no_match_peer_cmd
);
4657 install_element(RMAP_NODE
, &match_ip_route_source_cmd
);
4658 install_element(RMAP_NODE
, &no_match_ip_route_source_cmd
);
4659 install_element(RMAP_NODE
, &match_ip_route_source_prefix_list_cmd
);
4660 install_element(RMAP_NODE
, &no_match_ip_route_source_prefix_list_cmd
);
4661 install_element(RMAP_NODE
, &match_mac_address_cmd
);
4662 install_element(RMAP_NODE
, &no_match_mac_address_cmd
);
4663 install_element(RMAP_NODE
, &match_evpn_vni_cmd
);
4664 install_element(RMAP_NODE
, &no_match_evpn_vni_cmd
);
4665 install_element(RMAP_NODE
, &match_evpn_route_type_cmd
);
4666 install_element(RMAP_NODE
, &no_match_evpn_route_type_cmd
);
4668 install_element(RMAP_NODE
, &match_aspath_cmd
);
4669 install_element(RMAP_NODE
, &no_match_aspath_cmd
);
4670 install_element(RMAP_NODE
, &match_local_pref_cmd
);
4671 install_element(RMAP_NODE
, &no_match_local_pref_cmd
);
4672 install_element(RMAP_NODE
, &match_community_cmd
);
4673 install_element(RMAP_NODE
, &no_match_community_cmd
);
4674 install_element(RMAP_NODE
, &match_lcommunity_cmd
);
4675 install_element(RMAP_NODE
, &no_match_lcommunity_cmd
);
4676 install_element(RMAP_NODE
, &match_ecommunity_cmd
);
4677 install_element(RMAP_NODE
, &no_match_ecommunity_cmd
);
4678 install_element(RMAP_NODE
, &match_origin_cmd
);
4679 install_element(RMAP_NODE
, &no_match_origin_cmd
);
4680 install_element(RMAP_NODE
, &match_probability_cmd
);
4681 install_element(RMAP_NODE
, &no_match_probability_cmd
);
4683 install_element(RMAP_NODE
, &set_ip_nexthop_peer_cmd
);
4684 install_element(RMAP_NODE
, &set_ip_nexthop_unchanged_cmd
);
4685 install_element(RMAP_NODE
, &set_local_pref_cmd
);
4686 install_element(RMAP_NODE
, &no_set_local_pref_cmd
);
4687 install_element(RMAP_NODE
, &set_weight_cmd
);
4688 install_element(RMAP_NODE
, &set_label_index_cmd
);
4689 install_element(RMAP_NODE
, &no_set_weight_cmd
);
4690 install_element(RMAP_NODE
, &no_set_label_index_cmd
);
4691 install_element(RMAP_NODE
, &set_aspath_prepend_asn_cmd
);
4692 install_element(RMAP_NODE
, &set_aspath_prepend_lastas_cmd
);
4693 install_element(RMAP_NODE
, &set_aspath_exclude_cmd
);
4694 install_element(RMAP_NODE
, &no_set_aspath_prepend_cmd
);
4695 install_element(RMAP_NODE
, &no_set_aspath_exclude_cmd
);
4696 install_element(RMAP_NODE
, &set_origin_cmd
);
4697 install_element(RMAP_NODE
, &no_set_origin_cmd
);
4698 install_element(RMAP_NODE
, &set_atomic_aggregate_cmd
);
4699 install_element(RMAP_NODE
, &no_set_atomic_aggregate_cmd
);
4700 install_element(RMAP_NODE
, &set_aggregator_as_cmd
);
4701 install_element(RMAP_NODE
, &no_set_aggregator_as_cmd
);
4702 install_element(RMAP_NODE
, &set_community_cmd
);
4703 install_element(RMAP_NODE
, &set_community_none_cmd
);
4704 install_element(RMAP_NODE
, &no_set_community_cmd
);
4705 install_element(RMAP_NODE
, &set_community_delete_cmd
);
4706 install_element(RMAP_NODE
, &no_set_community_delete_cmd
);
4707 install_element(RMAP_NODE
, &set_lcommunity_cmd
);
4708 install_element(RMAP_NODE
, &set_lcommunity_none_cmd
);
4709 install_element(RMAP_NODE
, &no_set_lcommunity_cmd
);
4710 install_element(RMAP_NODE
, &no_set_lcommunity1_cmd
);
4711 install_element(RMAP_NODE
, &set_lcommunity_delete_cmd
);
4712 install_element(RMAP_NODE
, &no_set_lcommunity_delete_cmd
);
4713 install_element(RMAP_NODE
, &set_ecommunity_rt_cmd
);
4714 install_element(RMAP_NODE
, &no_set_ecommunity_rt_cmd
);
4715 install_element(RMAP_NODE
, &set_ecommunity_soo_cmd
);
4716 install_element(RMAP_NODE
, &no_set_ecommunity_soo_cmd
);
4717 #ifdef KEEP_OLD_VPN_COMMANDS
4718 install_element(RMAP_NODE
, &set_vpn_nexthop_cmd
);
4719 install_element(RMAP_NODE
, &no_set_vpn_nexthop_cmd
);
4720 #endif /* KEEP_OLD_VPN_COMMANDS */
4721 install_element(RMAP_NODE
, &set_ipx_vpn_nexthop_cmd
);
4722 install_element(RMAP_NODE
, &no_set_ipx_vpn_nexthop_cmd
);
4723 install_element(RMAP_NODE
, &set_originator_id_cmd
);
4724 install_element(RMAP_NODE
, &no_set_originator_id_cmd
);
4726 route_map_install_match(&route_match_ipv6_address_cmd
);
4727 route_map_install_match(&route_match_ipv6_next_hop_cmd
);
4728 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
4729 route_map_install_set(&route_set_ipv6_nexthop_global_cmd
);
4730 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd
);
4731 route_map_install_set(&route_set_ipv6_nexthop_local_cmd
);
4732 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd
);
4734 install_element(RMAP_NODE
, &match_ipv6_next_hop_cmd
);
4735 install_element(RMAP_NODE
, &no_match_ipv6_next_hop_cmd
);
4736 install_element(RMAP_NODE
, &set_ipv6_nexthop_global_cmd
);
4737 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_global_cmd
);
4738 install_element(RMAP_NODE
, &set_ipv6_nexthop_prefer_global_cmd
);
4739 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_prefer_global_cmd
);
4740 install_element(RMAP_NODE
, &set_ipv6_nexthop_peer_cmd
);
4741 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_peer_cmd
);
4744 void bgp_route_map_terminate(void)
4746 /* ToDo: Cleanup all the used memory */
4748 route_map_add_hook(NULL
);
4749 route_map_delete_hook(NULL
);
4750 route_map_event_hook(NULL
);