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
32 #ifdef HAVE_LIBPCREPOSIX
33 #include <pcreposix.h>
36 #endif /* HAVE_LIBPCREPOSIX */
38 #include "sockunion.h"
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_aspath.h"
47 #include "bgpd/bgp_packet.h"
48 #include "bgpd/bgp_route.h"
49 #include "bgpd/bgp_zebra.h"
50 #include "bgpd/bgp_regex.h"
51 #include "bgpd/bgp_community.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_filter.h"
54 #include "bgpd/bgp_mplsvpn.h"
55 #include "bgpd/bgp_ecommunity.h"
56 #include "bgpd/bgp_lcommunity.h"
57 #include "bgpd/bgp_vty.h"
58 #include "bgpd/bgp_debug.h"
59 #include "bgpd/bgp_evpn.h"
60 #include "bgpd/bgp_evpn_private.h"
61 #include "bgpd/bgp_evpn_vty.h"
62 #include "bgpd/bgp_mplsvpn.h"
65 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
68 /* Memo of route-map commands.
77 ip route-source : Done
81 ipv6 route-source: (This will not be implemented by bgpd)
82 ipv6 prefix-list : Done
83 length : (This will not be implemented by bgpd)
85 route-type : (This will not be implemented by bgpd)
87 local-preference : Done
89 set as-path prepend : Done
91 automatic-tag : (This will not be implemented by bgpd)
93 large-community : Done
94 large-comm-list : Done
97 default : (This will not be implemented by bgpd)
98 interface : (This will not be implemented by bgpd)
99 ip default : (This will not be implemented by bgpd)
101 ip precedence : (This will not be implemented by bgpd)
102 ip tos : (This will not be implemented by bgpd)
103 level : (This will not be implemented by bgpd)
104 local-preference : Done
106 metric-type : Not yet
113 set ipv6 next-hop global: Done
114 set ipv6 next-hop prefer-global: Done
115 set ipv6 next-hop local : Done
116 set as-path exclude : Done
120 /* generic value manipulation to be shared in multiple rules */
122 #define RMAP_VALUE_SET 0
123 #define RMAP_VALUE_ADD 1
124 #define RMAP_VALUE_SUB 2
132 static int route_value_match(struct rmap_value
*rv
, uint32_t value
)
134 if (rv
->variable
== 0 && value
== rv
->value
)
140 static uint32_t route_value_adjust(struct rmap_value
*rv
, uint32_t current
,
145 switch (rv
->variable
) {
154 switch (rv
->action
) {
156 if (current
> UINT32_MAX
- value
)
158 return current
+ value
;
160 if (current
<= value
)
162 return current
- value
;
168 static void *route_value_compile(const char *arg
)
170 uint8_t action
= RMAP_VALUE_SET
, var
= 0;
171 unsigned long larg
= 0;
173 struct rmap_value
*rv
;
176 action
= RMAP_VALUE_ADD
;
178 } else if (arg
[0] == '-') {
179 action
= RMAP_VALUE_SUB
;
183 if (all_digit(arg
)) {
185 larg
= strtoul(arg
, &endptr
, 10);
186 if (*arg
== 0 || *endptr
!= 0 || errno
|| larg
> UINT32_MAX
)
189 if (strcmp(arg
, "rtt") == 0)
195 rv
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_value
));
205 static void route_value_free(void *rule
)
207 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
210 /* generic as path object to be shared in multiple rules */
212 static void *route_aspath_compile(const char *arg
)
214 struct aspath
*aspath
;
216 aspath
= aspath_str2aspath(arg
);
222 static void route_aspath_free(void *rule
)
224 struct aspath
*aspath
= rule
;
228 struct bgp_match_peer_compiled
{
233 /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
235 /* Compares the peer specified in the 'match peer' clause with the peer
236 received in bgp_info->peer. If it is the same, or if the peer structure
237 received is a peer_group containing it, returns RMAP_MATCH. */
238 static route_map_result_t
route_match_peer(void *rule
,
239 const struct prefix
*prefix
,
240 route_map_object_t type
,
243 struct bgp_match_peer_compiled
*pc
;
245 union sockunion su_def
= {
246 .sin
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= INADDR_ANY
}};
247 struct peer_group
*group
;
249 struct listnode
*node
, *nnode
;
251 if (type
== RMAP_BGP
) {
254 peer
= ((struct bgp_info
*)object
)->peer
;
260 if (strcmp(peer
->conf_if
, pc
->interface
) == 0)
266 /* If su='0.0.0.0' (command 'match peer local'), and it's a
268 REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH
270 if (sockunion_same(su
, &su_def
)) {
272 if (CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_NETWORK
)
273 || CHECK_FLAG(peer
->rmap_type
,
274 PEER_RMAP_TYPE_REDISTRIBUTE
)
275 || CHECK_FLAG(peer
->rmap_type
,
276 PEER_RMAP_TYPE_DEFAULT
))
283 if (!CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
284 if (sockunion_same(su
, &peer
->su
))
290 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
,
292 if (sockunion_same(su
, &peer
->su
))
301 static void *route_match_peer_compile(const char *arg
)
303 struct bgp_match_peer_compiled
*pc
;
306 pc
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
,
307 sizeof(struct bgp_match_peer_compiled
));
309 ret
= str2sockunion(strcmp(arg
, "local") ? arg
: "0.0.0.0", &pc
->su
);
311 pc
->interface
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
318 /* Free route map's compiled `ip address' value. */
319 static void route_match_peer_free(void *rule
)
321 struct bgp_match_peer_compiled
*pc
= rule
;
324 XFREE(MTYPE_ROUTE_MAP_COMPILED
, pc
->interface
);
326 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
329 /* Route map commands for ip address matching. */
330 struct route_map_rule_cmd route_match_peer_cmd
= {"peer", route_match_peer
,
331 route_match_peer_compile
,
332 route_match_peer_free
};
334 #if defined(HAVE_LUA)
335 static route_map_result_t
route_match_command(void *rule
,
336 const struct prefix
*prefix
,
337 route_map_object_t type
,
340 int status
= RMAP_NOMATCH
;
341 u_int32_t locpref
= 0;
342 u_int32_t newlocpref
= 0;
343 enum lua_rm_status lrm_status
;
344 struct bgp_info
*info
= (struct bgp_info
*)object
;
345 lua_State
*L
= lua_initialize("/etc/frr/lua.scr");
351 * Setup the prefix information to pass in
353 lua_setup_prefix_table(L
, prefix
);
355 zlog_debug("Set up prefix table");
357 * Setup the bgp_info information
360 lua_pushinteger(L
, info
->attr
->med
);
361 lua_setfield(L
, -2, "metric");
362 lua_pushinteger(L
, info
->attr
->nh_ifindex
);
363 lua_setfield(L
, -2, "ifindex");
364 lua_pushstring(L
, info
->attr
->aspath
->str
);
365 lua_setfield(L
, -2, "aspath");
366 lua_pushinteger(L
, info
->attr
->local_pref
);
367 lua_setfield(L
, -2, "localpref");
368 zlog_debug("%s %d", info
->attr
->aspath
->str
, info
->attr
->nh_ifindex
);
369 lua_setglobal(L
, "nexthop");
371 zlog_debug("Set up nexthop information");
375 lrm_status
= lua_run_rm_rule(L
, rule
);
376 switch (lrm_status
) {
378 zlog_debug("RM_FAILURE");
381 zlog_debug("RM_NOMATCH");
383 case LUA_RM_MATCH_AND_CHANGE
:
384 zlog_debug("MATCH AND CHANGE");
385 lua_getglobal(L
, "nexthop");
386 info
->attr
->med
= get_integer(L
, "metric");
388 * This needs to be abstraced with the set function
390 if (info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
391 locpref
= info
->attr
->local_pref
;
392 newlocpref
= get_integer(L
, "localpref");
393 if (newlocpref
!= locpref
) {
394 info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
395 info
->attr
->local_pref
= newlocpref
;
400 zlog_debug("MATCH ONLY");
408 static void *route_match_command_compile(const char *arg
)
412 command
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
417 route_match_command_free(void *rule
)
419 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
422 struct route_map_rule_cmd route_match_command_cmd
= {
425 route_match_command_compile
,
426 route_match_command_free
430 /* `match ip address IP_ACCESS_LIST' */
432 /* Match function should return 1 if match is success else return
434 static route_map_result_t
route_match_ip_address(void *rule
,
435 const struct prefix
*prefix
,
436 route_map_object_t type
,
439 struct access_list
*alist
;
441 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
442 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
446 return (access_list_apply(alist
, prefix
) == FILTER_DENY
453 /* Route map `ip address' match statement. `arg' should be
455 static void *route_match_ip_address_compile(const char *arg
)
457 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
460 /* Free route map's compiled `ip address' value. */
461 static void route_match_ip_address_free(void *rule
)
463 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
466 /* Route map commands for ip address matching. */
467 struct route_map_rule_cmd route_match_ip_address_cmd
= {
468 "ip address", route_match_ip_address
, route_match_ip_address_compile
,
469 route_match_ip_address_free
};
471 /* `match ip next-hop IP_ADDRESS' */
473 /* Match function return 1 if match is success else return zero. */
474 static route_map_result_t
route_match_ip_next_hop(void *rule
,
475 const struct prefix
*prefix
,
476 route_map_object_t type
,
479 struct access_list
*alist
;
480 struct bgp_info
*bgp_info
;
481 struct prefix_ipv4 p
;
483 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
486 p
.prefix
= bgp_info
->attr
->nexthop
;
487 p
.prefixlen
= IPV4_MAX_BITLEN
;
489 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
493 return (access_list_apply(alist
, &p
) == FILTER_DENY
500 /* Route map `ip next-hop' match statement. `arg' is
502 static void *route_match_ip_next_hop_compile(const char *arg
)
504 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
507 /* Free route map's compiled `ip address' value. */
508 static void route_match_ip_next_hop_free(void *rule
)
510 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
513 /* Route map commands for ip next-hop matching. */
514 struct route_map_rule_cmd route_match_ip_next_hop_cmd
= {
515 "ip next-hop", route_match_ip_next_hop
, route_match_ip_next_hop_compile
,
516 route_match_ip_next_hop_free
};
518 /* `match ip route-source ACCESS-LIST' */
520 /* Match function return 1 if match is success else return zero. */
521 static route_map_result_t
route_match_ip_route_source(void *rule
,
522 const struct prefix
*pfx
,
523 route_map_object_t type
,
526 struct access_list
*alist
;
527 struct bgp_info
*bgp_info
;
529 struct prefix_ipv4 p
;
531 if (type
== RMAP_BGP
&& pfx
->family
== AF_INET
) {
533 peer
= bgp_info
->peer
;
535 if (!peer
|| sockunion_family(&peer
->su
) != AF_INET
)
539 p
.prefix
= peer
->su
.sin
.sin_addr
;
540 p
.prefixlen
= IPV4_MAX_BITLEN
;
542 alist
= access_list_lookup(AFI_IP
, (char *)rule
);
546 return (access_list_apply(alist
, &p
) == FILTER_DENY
553 /* Route map `ip route-source' match statement. `arg' is
555 static void *route_match_ip_route_source_compile(const char *arg
)
557 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
560 /* Free route map's compiled `ip address' value. */
561 static void route_match_ip_route_source_free(void *rule
)
563 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
566 /* Route map commands for ip route-source matching. */
567 struct route_map_rule_cmd route_match_ip_route_source_cmd
= {
568 "ip route-source", route_match_ip_route_source
,
569 route_match_ip_route_source_compile
, route_match_ip_route_source_free
};
571 /* `match ip address prefix-list PREFIX_LIST' */
573 static route_map_result_t
574 route_match_ip_address_prefix_list(void *rule
, const struct prefix
*prefix
,
575 route_map_object_t type
, void *object
)
577 struct prefix_list
*plist
;
579 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
580 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
584 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
591 static void *route_match_ip_address_prefix_list_compile(const char *arg
)
593 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
596 static void route_match_ip_address_prefix_list_free(void *rule
)
598 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
601 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
= {
602 "ip address prefix-list", route_match_ip_address_prefix_list
,
603 route_match_ip_address_prefix_list_compile
,
604 route_match_ip_address_prefix_list_free
};
606 /* `match ip next-hop prefix-list PREFIX_LIST' */
608 static route_map_result_t
609 route_match_ip_next_hop_prefix_list(void *rule
, const struct prefix
*prefix
,
610 route_map_object_t type
, void *object
)
612 struct prefix_list
*plist
;
613 struct bgp_info
*bgp_info
;
614 struct prefix_ipv4 p
;
616 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
619 p
.prefix
= bgp_info
->attr
->nexthop
;
620 p
.prefixlen
= IPV4_MAX_BITLEN
;
622 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
626 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
633 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg
)
635 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
638 static void route_match_ip_next_hop_prefix_list_free(void *rule
)
640 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
643 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
= {
644 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list
,
645 route_match_ip_next_hop_prefix_list_compile
,
646 route_match_ip_next_hop_prefix_list_free
};
648 /* `match ip route-source prefix-list PREFIX_LIST' */
650 static route_map_result_t
651 route_match_ip_route_source_prefix_list(void *rule
,
652 const struct prefix
*prefix
,
653 route_map_object_t type
, void *object
)
655 struct prefix_list
*plist
;
656 struct bgp_info
*bgp_info
;
658 struct prefix_ipv4 p
;
660 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET
) {
662 peer
= bgp_info
->peer
;
664 if (!peer
|| sockunion_family(&peer
->su
) != AF_INET
)
668 p
.prefix
= peer
->su
.sin
.sin_addr
;
669 p
.prefixlen
= IPV4_MAX_BITLEN
;
671 plist
= prefix_list_lookup(AFI_IP
, (char *)rule
);
675 return (prefix_list_apply(plist
, &p
) == PREFIX_DENY
682 static void *route_match_ip_route_source_prefix_list_compile(const char *arg
)
684 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
687 static void route_match_ip_route_source_prefix_list_free(void *rule
)
689 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
692 struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd
= {
693 "ip route-source prefix-list", route_match_ip_route_source_prefix_list
,
694 route_match_ip_route_source_prefix_list_compile
,
695 route_match_ip_route_source_prefix_list_free
};
697 /* `match evpn default-route' */
699 /* Match function should return 1 if match is success else 0 */
700 static route_map_result_t
route_match_evpn_default_route(void *rule
,
701 const struct prefix
*p
,
705 if (type
== RMAP_BGP
&& is_evpn_prefix_default(p
))
711 /* Route map commands for default-route matching. */
712 struct route_map_rule_cmd route_match_evpn_default_route_cmd
= {
713 "evpn default-route", route_match_evpn_default_route
, NULL
, NULL
};
715 /* `match mac address MAC_ACCESS_LIST' */
717 /* Match function should return 1 if match is success else return
719 static route_map_result_t
route_match_mac_address(void *rule
,
720 const struct prefix
*prefix
,
721 route_map_object_t type
,
724 struct access_list
*alist
;
727 if (type
== RMAP_BGP
) {
728 alist
= access_list_lookup(AFI_L2VPN
, (char *)rule
);
732 if (prefix
->u
.prefix_evpn
.route_type
!= BGP_EVPN_MAC_IP_ROUTE
)
735 p
.family
= AF_ETHERNET
;
736 p
.prefixlen
= ETH_ALEN
* 8;
737 p
.u
.prefix_eth
= prefix
->u
.prefix_evpn
.macip_addr
.mac
;
739 return (access_list_apply(alist
, &p
) == FILTER_DENY
747 /* Route map `mac address' match statement. `arg' should be
749 static void *route_match_mac_address_compile(const char *arg
)
751 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
754 /* Free route map's compiled `ip address' value. */
755 static void route_match_mac_address_free(void *rule
)
757 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
760 /* Route map commands for mac address matching. */
761 struct route_map_rule_cmd route_match_mac_address_cmd
= {
762 "mac address", route_match_mac_address
, route_match_mac_address_compile
,
763 route_match_mac_address_free
};
767 /* Match function should return 1 if match is success else return
769 static route_map_result_t
route_match_vni(void *rule
,
770 const struct prefix
*prefix
,
771 route_map_object_t type
, void *object
)
774 struct bgp_info
*bgp_info
= NULL
;
776 if (type
== RMAP_BGP
) {
777 vni
= *((vni_t
*)rule
);
778 bgp_info
= (struct bgp_info
*)object
;
780 if (bgp_info
->extra
== NULL
)
783 if (vni
== label2vni(&bgp_info
->extra
->label
[0]))
790 /* Route map `vni' match statement. */
791 static void *route_match_vni_compile(const char *arg
)
796 vni
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(vni_t
));
800 *vni
= strtoul(arg
, &end
, 10);
802 XFREE(MTYPE_ROUTE_MAP_COMPILED
, vni
);
809 /* Free route map's compiled `vni' value. */
810 static void route_match_vni_free(void *rule
)
812 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
815 /* Route map commands for vni matching. */
816 struct route_map_rule_cmd route_match_evpn_vni_cmd
= {
817 "evpn vni", route_match_vni
, route_match_vni_compile
,
818 route_match_vni_free
};
820 /* `match evpn route-type' */
822 /* Match function should return 1 if match is success else return
824 static route_map_result_t
route_match_evpn_route_type(void *rule
,
825 const struct prefix
*pfx
,
826 route_map_object_t type
,
829 uint8_t route_type
= 0;
831 if (type
== RMAP_BGP
) {
832 route_type
= *((uint8_t *)rule
);
834 if (route_type
== pfx
->u
.prefix_evpn
.route_type
)
841 /* Route map `route-type' match statement. */
842 static void *route_match_evpn_route_type_compile(const char *arg
)
844 uint8_t *route_type
= NULL
;
846 route_type
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
848 if (strncmp(arg
, "ma", 2) == 0)
849 *route_type
= BGP_EVPN_MAC_IP_ROUTE
;
850 else if (strncmp(arg
, "mu", 2) == 0)
851 *route_type
= BGP_EVPN_IMET_ROUTE
;
853 *route_type
= BGP_EVPN_IP_PREFIX_ROUTE
;
858 /* Free route map's compiled `route-type' value. */
859 static void route_match_evpn_route_type_free(void *rule
)
861 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
864 /* Route map commands for evpn route-type matching. */
865 struct route_map_rule_cmd route_match_evpn_route_type_cmd
= {
866 "evpn route-type", route_match_evpn_route_type
,
867 route_match_evpn_route_type_compile
, route_match_evpn_route_type_free
};
869 /* `match local-preference LOCAL-PREF' */
871 /* Match function return 1 if match is success else return zero. */
872 static route_map_result_t
route_match_local_pref(void *rule
,
873 const struct prefix
*prefix
,
874 route_map_object_t type
,
877 uint32_t *local_pref
;
878 struct bgp_info
*bgp_info
;
880 if (type
== RMAP_BGP
) {
884 if (bgp_info
->attr
->local_pref
== *local_pref
)
892 /* Route map `match local-preference' match statement.
893 `arg' is local-pref value */
894 static void *route_match_local_pref_compile(const char *arg
)
896 uint32_t *local_pref
;
898 unsigned long tmpval
;
900 /* Locpref value shoud be integer. */
905 tmpval
= strtoul(arg
, &endptr
, 10);
906 if (*endptr
!= '\0' || errno
|| tmpval
> UINT32_MAX
)
909 local_pref
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint32_t));
914 *local_pref
= tmpval
;
918 /* Free route map's compiled `match local-preference' value. */
919 static void route_match_local_pref_free(void *rule
)
921 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
924 /* Route map commands for metric matching. */
925 struct route_map_rule_cmd route_match_local_pref_cmd
= {
926 "local-preference", route_match_local_pref
,
927 route_match_local_pref_compile
, route_match_local_pref_free
};
929 /* `match metric METRIC' */
931 /* Match function return 1 if match is success else return zero. */
932 static route_map_result_t
route_match_metric(void *rule
,
933 const struct prefix
*prefix
,
934 route_map_object_t type
,
937 struct rmap_value
*rv
;
938 struct bgp_info
*bgp_info
;
940 if (type
== RMAP_BGP
) {
943 return route_value_match(rv
, bgp_info
->attr
->med
);
948 /* Route map commands for metric matching. */
949 struct route_map_rule_cmd route_match_metric_cmd
= {
950 "metric", route_match_metric
, route_value_compile
, route_value_free
,
953 /* `match as-path ASPATH' */
955 /* Match function for as-path match. I assume given object is */
956 static route_map_result_t
route_match_aspath(void *rule
,
957 const struct prefix
*prefix
,
958 route_map_object_t type
,
962 struct as_list
*as_list
;
963 struct bgp_info
*bgp_info
;
965 if (type
== RMAP_BGP
) {
966 as_list
= as_list_lookup((char *)rule
);
973 return ((as_list_apply(as_list
, bgp_info
->attr
->aspath
)
981 /* Compile function for as-path match. */
982 static void *route_match_aspath_compile(const char *arg
)
984 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
987 /* Compile function for as-path match. */
988 static void route_match_aspath_free(void *rule
)
990 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
993 /* Route map commands for aspath matching. */
994 struct route_map_rule_cmd route_match_aspath_cmd
= {
995 "as-path", route_match_aspath
, route_match_aspath_compile
,
996 route_match_aspath_free
};
998 /* `match community COMMUNIY' */
999 struct rmap_community
{
1004 /* Match function for community match. */
1005 static route_map_result_t
route_match_community(void *rule
,
1006 const struct prefix
*prefix
,
1007 route_map_object_t type
,
1010 struct community_list
*list
;
1011 struct bgp_info
*bgp_info
;
1012 struct rmap_community
*rcom
;
1014 if (type
== RMAP_BGP
) {
1018 list
= community_list_lookup(bgp_clist
, rcom
->name
,
1019 COMMUNITY_LIST_MASTER
);
1021 return RMAP_NOMATCH
;
1024 if (community_list_exact_match(
1025 bgp_info
->attr
->community
, list
))
1028 if (community_list_match(bgp_info
->attr
->community
,
1033 return RMAP_NOMATCH
;
1036 /* Compile function for community match. */
1037 static void *route_match_community_compile(const char *arg
)
1039 struct rmap_community
*rcom
;
1043 rcom
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_community
));
1045 p
= strchr(arg
, ' ');
1048 rcom
->name
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1049 memcpy(rcom
->name
, arg
, len
);
1052 rcom
->name
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1058 /* Compile function for community match. */
1059 static void route_match_community_free(void *rule
)
1061 struct rmap_community
*rcom
= rule
;
1063 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
->name
);
1064 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
);
1067 /* Route map commands for community matching. */
1068 struct route_map_rule_cmd route_match_community_cmd
= {
1069 "community", route_match_community
, route_match_community_compile
,
1070 route_match_community_free
};
1072 /* Match function for lcommunity match. */
1073 static route_map_result_t
route_match_lcommunity(void *rule
,
1074 const struct prefix
*prefix
,
1075 route_map_object_t type
,
1078 struct community_list
*list
;
1079 struct bgp_info
*bgp_info
;
1080 struct rmap_community
*rcom
;
1082 if (type
== RMAP_BGP
) {
1086 list
= community_list_lookup(bgp_clist
, rcom
->name
,
1087 LARGE_COMMUNITY_LIST_MASTER
);
1089 return RMAP_NOMATCH
;
1091 if (lcommunity_list_match(bgp_info
->attr
->lcommunity
, list
))
1094 return RMAP_NOMATCH
;
1097 /* Compile function for community match. */
1098 static void *route_match_lcommunity_compile(const char *arg
)
1100 struct rmap_community
*rcom
;
1104 rcom
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_community
));
1106 p
= strchr(arg
, ' ');
1109 rcom
->name
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1110 memcpy(rcom
->name
, arg
, len
);
1112 rcom
->name
= XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1118 /* Compile function for community match. */
1119 static void route_match_lcommunity_free(void *rule
)
1121 struct rmap_community
*rcom
= rule
;
1123 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
->name
);
1124 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcom
);
1127 /* Route map commands for community matching. */
1128 struct route_map_rule_cmd route_match_lcommunity_cmd
= {
1129 "large-community", route_match_lcommunity
,
1130 route_match_lcommunity_compile
, route_match_lcommunity_free
};
1133 /* Match function for extcommunity match. */
1134 static route_map_result_t
route_match_ecommunity(void *rule
,
1135 const struct prefix
*prefix
,
1136 route_map_object_t type
,
1139 struct community_list
*list
;
1140 struct bgp_info
*bgp_info
;
1142 if (type
== RMAP_BGP
) {
1145 list
= community_list_lookup(bgp_clist
, (char *)rule
,
1146 EXTCOMMUNITY_LIST_MASTER
);
1148 return RMAP_NOMATCH
;
1150 if (ecommunity_list_match(bgp_info
->attr
->ecommunity
, list
))
1153 return RMAP_NOMATCH
;
1156 /* Compile function for extcommunity match. */
1157 static void *route_match_ecommunity_compile(const char *arg
)
1159 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1162 /* Compile function for extcommunity match. */
1163 static void route_match_ecommunity_free(void *rule
)
1165 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1168 /* Route map commands for community matching. */
1169 struct route_map_rule_cmd route_match_ecommunity_cmd
= {
1170 "extcommunity", route_match_ecommunity
, route_match_ecommunity_compile
,
1171 route_match_ecommunity_free
};
1173 /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1174 and `address-family vpnv4'. */
1176 /* `match origin' */
1177 static route_map_result_t
route_match_origin(void *rule
,
1178 const struct prefix
*prefix
,
1179 route_map_object_t type
,
1183 struct bgp_info
*bgp_info
;
1185 if (type
== RMAP_BGP
) {
1189 if (bgp_info
->attr
->origin
== *origin
)
1193 return RMAP_NOMATCH
;
1196 static void *route_match_origin_compile(const char *arg
)
1200 origin
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
1202 if (strcmp(arg
, "igp") == 0)
1204 else if (strcmp(arg
, "egp") == 0)
1212 /* Free route map's compiled `ip address' value. */
1213 static void route_match_origin_free(void *rule
)
1215 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1218 /* Route map commands for origin matching. */
1219 struct route_map_rule_cmd route_match_origin_cmd
= {
1220 "origin", route_match_origin
, route_match_origin_compile
,
1221 route_match_origin_free
};
1223 /* match probability { */
1225 static route_map_result_t
route_match_probability(void *rule
,
1226 const struct prefix
*prefix
,
1227 route_map_object_t type
,
1232 switch (*(long *)rule
) {
1238 if (r
< *(long *)rule
) {
1243 return RMAP_NOMATCH
;
1246 static void *route_match_probability_compile(const char *arg
)
1252 lobule
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(long));
1262 *lobule
= RAND_MAX
/ 100 * perc
;
1268 static void route_match_probability_free(void *rule
)
1270 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1273 struct route_map_rule_cmd route_match_probability_cmd
= {
1274 "probability", route_match_probability
, route_match_probability_compile
,
1275 route_match_probability_free
};
1277 /* `match interface IFNAME' */
1278 /* Match function should return 1 if match is success else return
1280 static route_map_result_t
route_match_interface(void *rule
,
1281 const struct prefix
*prefix
,
1282 route_map_object_t type
,
1285 struct interface
*ifp
;
1286 struct bgp_info
*info
;
1288 if (type
== RMAP_BGP
) {
1291 if (!info
|| !info
->attr
)
1292 return RMAP_NOMATCH
;
1294 ifp
= if_lookup_by_name_all_vrf((char *)rule
);
1296 if (ifp
== NULL
|| ifp
->ifindex
!= info
->attr
->nh_ifindex
)
1297 return RMAP_NOMATCH
;
1301 return RMAP_NOMATCH
;
1304 /* Route map `interface' match statement. `arg' should be
1306 static void *route_match_interface_compile(const char *arg
)
1308 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
1311 /* Free route map's compiled `interface' value. */
1312 static void route_match_interface_free(void *rule
)
1314 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1317 /* Route map commands for ip address matching. */
1318 struct route_map_rule_cmd route_match_interface_cmd
= {
1319 "interface", route_match_interface
, route_match_interface_compile
,
1320 route_match_interface_free
};
1324 /* `set ip next-hop IP_ADDRESS' */
1326 /* Match function return 1 if match is success else return zero. */
1327 static route_map_result_t
route_match_tag(void *rule
,
1328 const struct prefix
*prefix
,
1329 route_map_object_t type
, void *object
)
1332 struct bgp_info
*bgp_info
;
1334 if (type
== RMAP_BGP
) {
1338 return ((bgp_info
->attr
->tag
== *tag
) ? RMAP_MATCH
1342 return RMAP_NOMATCH
;
1346 /* Route map commands for tag matching. */
1347 static struct route_map_rule_cmd route_match_tag_cmd
= {
1348 "tag", route_match_tag
, route_map_rule_tag_compile
,
1349 route_map_rule_tag_free
,
1353 /* Set nexthop to object. ojbect must be pointer to struct attr. */
1354 struct rmap_ip_nexthop_set
{
1355 struct in_addr
*address
;
1360 static route_map_result_t
route_set_ip_nexthop(void *rule
,
1361 const struct prefix
*prefix
,
1362 route_map_object_t type
,
1365 struct rmap_ip_nexthop_set
*rins
= rule
;
1366 struct bgp_info
*bgp_info
;
1369 if (type
== RMAP_BGP
) {
1371 peer
= bgp_info
->peer
;
1373 if (rins
->unchanged
) {
1374 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1375 BATTR_RMAP_NEXTHOP_UNCHANGED
);
1376 } else if (rins
->peer_address
) {
1377 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
1378 || CHECK_FLAG(peer
->rmap_type
,
1379 PEER_RMAP_TYPE_IMPORT
))
1381 && sockunion_family(peer
->su_remote
) == AF_INET
) {
1382 bgp_info
->attr
->nexthop
.s_addr
=
1383 sockunion2ip(peer
->su_remote
);
1384 bgp_info
->attr
->flag
|=
1385 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1386 } else if (CHECK_FLAG(peer
->rmap_type
,
1387 PEER_RMAP_TYPE_OUT
)) {
1388 /* The next hop value will be set as part of
1390 * Set the flags here to indicate that rewrite
1392 * Also, clear the value.
1394 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1395 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
);
1396 bgp_info
->attr
->nexthop
.s_addr
= 0;
1399 /* Set next hop value. */
1400 bgp_info
->attr
->flag
|=
1401 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
1402 bgp_info
->attr
->nexthop
= *rins
->address
;
1403 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
1404 BATTR_RMAP_IPV4_NHOP_CHANGED
);
1405 /* case for MP-BGP : MPLS VPN */
1406 bgp_info
->attr
->mp_nexthop_global_in
= *rins
->address
;
1407 bgp_info
->attr
->mp_nexthop_len
= sizeof(*rins
->address
);
1414 /* Route map `ip nexthop' compile function. Given string is converted
1415 to struct in_addr structure. */
1416 static void *route_set_ip_nexthop_compile(const char *arg
)
1418 struct rmap_ip_nexthop_set
*rins
;
1419 struct in_addr
*address
= NULL
;
1420 int peer_address
= 0;
1424 if (strcmp(arg
, "peer-address") == 0)
1426 else if (strcmp(arg
, "unchanged") == 0)
1429 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
1430 sizeof(struct in_addr
));
1431 ret
= inet_aton(arg
, address
);
1434 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
1439 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
,
1440 sizeof(struct rmap_ip_nexthop_set
));
1442 rins
->address
= address
;
1443 rins
->peer_address
= peer_address
;
1444 rins
->unchanged
= unchanged
;
1449 /* Free route map's compiled `ip nexthop' value. */
1450 static void route_set_ip_nexthop_free(void *rule
)
1452 struct rmap_ip_nexthop_set
*rins
= rule
;
1455 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rins
->address
);
1457 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rins
);
1460 /* Route map commands for ip nexthop set. */
1461 struct route_map_rule_cmd route_set_ip_nexthop_cmd
= {
1462 "ip next-hop", route_set_ip_nexthop
, route_set_ip_nexthop_compile
,
1463 route_set_ip_nexthop_free
};
1465 /* `set local-preference LOCAL_PREF' */
1467 /* Set local preference. */
1468 static route_map_result_t
route_set_local_pref(void *rule
,
1469 const struct prefix
*prefix
,
1470 route_map_object_t type
,
1473 struct rmap_value
*rv
;
1474 struct bgp_info
*bgp_info
;
1475 uint32_t locpref
= 0;
1477 if (type
== RMAP_BGP
) {
1478 /* Fetch routemap's rule information. */
1482 /* Set local preference value. */
1483 if (bgp_info
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
1484 locpref
= bgp_info
->attr
->local_pref
;
1486 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1487 bgp_info
->attr
->local_pref
=
1488 route_value_adjust(rv
, locpref
, bgp_info
->peer
);
1494 /* Set local preference rule structure. */
1495 struct route_map_rule_cmd route_set_local_pref_cmd
= {
1496 "local-preference", route_set_local_pref
, route_value_compile
,
1500 /* `set weight WEIGHT' */
1503 static route_map_result_t
route_set_weight(void *rule
,
1504 const struct prefix
*prefix
,
1505 route_map_object_t type
,
1508 struct rmap_value
*rv
;
1509 struct bgp_info
*bgp_info
;
1511 if (type
== RMAP_BGP
) {
1512 /* Fetch routemap's rule information. */
1516 /* Set weight value. */
1517 bgp_info
->attr
->weight
=
1518 route_value_adjust(rv
, 0, bgp_info
->peer
);
1524 /* Set local preference rule structure. */
1525 struct route_map_rule_cmd route_set_weight_cmd
= {
1526 "weight", route_set_weight
, route_value_compile
, route_value_free
,
1529 /* `set metric METRIC' */
1531 /* Set metric to attribute. */
1532 static route_map_result_t
route_set_metric(void *rule
,
1533 const struct prefix
*prefix
,
1534 route_map_object_t type
,
1537 struct rmap_value
*rv
;
1538 struct bgp_info
*bgp_info
;
1541 if (type
== RMAP_BGP
) {
1542 /* Fetch routemap's rule information. */
1546 if (bgp_info
->attr
->flag
1547 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
1548 med
= bgp_info
->attr
->med
;
1550 bgp_info
->attr
->med
=
1551 route_value_adjust(rv
, med
, bgp_info
->peer
);
1552 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
1557 /* Set metric rule structure. */
1558 struct route_map_rule_cmd route_set_metric_cmd
= {
1559 "metric", route_set_metric
, route_value_compile
, route_value_free
,
1562 /* `set as-path prepend ASPATH' */
1564 /* For AS path prepend mechanism. */
1565 static route_map_result_t
route_set_aspath_prepend(void *rule
,
1566 const struct prefix
*prefix
,
1567 route_map_object_t type
,
1570 struct aspath
*aspath
;
1572 struct bgp_info
*binfo
;
1574 if (type
== RMAP_BGP
) {
1577 if (binfo
->attr
->aspath
->refcnt
)
1578 new = aspath_dup(binfo
->attr
->aspath
);
1580 new = binfo
->attr
->aspath
;
1582 if ((uintptr_t)rule
> 10) {
1584 aspath_prepend(aspath
, new);
1586 as_t as
= aspath_leftmost(new);
1588 as
= binfo
->peer
->as
;
1589 new = aspath_add_seq_n(new, as
, (uintptr_t)rule
);
1592 binfo
->attr
->aspath
= new;
1598 static void *route_set_aspath_prepend_compile(const char *arg
)
1602 if (sscanf(arg
, "last-as %u", &num
) == 1 && num
> 0 && num
<= 10)
1603 return (void *)(uintptr_t)num
;
1605 return route_aspath_compile(arg
);
1608 static void route_set_aspath_prepend_free(void *rule
)
1610 if ((uintptr_t)rule
> 10)
1611 route_aspath_free(rule
);
1615 /* Set as-path prepend rule structure. */
1616 struct route_map_rule_cmd route_set_aspath_prepend_cmd
= {
1617 "as-path prepend", route_set_aspath_prepend
,
1618 route_set_aspath_prepend_compile
, route_set_aspath_prepend_free
,
1621 /* `set as-path exclude ASn' */
1623 /* For ASN exclude mechanism.
1624 * Iterate over ASns requested and filter them from the given AS_PATH one by
1626 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1628 static route_map_result_t
route_set_aspath_exclude(void *rule
,
1629 const struct prefix
*dummy
,
1630 route_map_object_t type
,
1633 struct aspath
*new_path
, *exclude_path
;
1634 struct bgp_info
*binfo
;
1636 if (type
== RMAP_BGP
) {
1637 exclude_path
= rule
;
1639 if (binfo
->attr
->aspath
->refcnt
)
1640 new_path
= aspath_dup(binfo
->attr
->aspath
);
1642 new_path
= binfo
->attr
->aspath
;
1643 binfo
->attr
->aspath
=
1644 aspath_filter_exclude(new_path
, exclude_path
);
1649 /* Set ASn exlude rule structure. */
1650 struct route_map_rule_cmd route_set_aspath_exclude_cmd
= {
1651 "as-path exclude", route_set_aspath_exclude
, route_aspath_compile
,
1655 /* `set community COMMUNITY' */
1656 struct rmap_com_set
{
1657 struct community
*com
;
1662 /* For community set mechanism. */
1663 static route_map_result_t
route_set_community(void *rule
,
1664 const struct prefix
*prefix
,
1665 route_map_object_t type
,
1668 struct rmap_com_set
*rcs
;
1669 struct bgp_info
*binfo
;
1671 struct community
*new = NULL
;
1672 struct community
*old
;
1673 struct community
*merge
;
1675 if (type
== RMAP_BGP
) {
1679 old
= attr
->community
;
1683 attr
->flag
&= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
));
1684 attr
->community
= NULL
;
1685 /* See the longer comment down below. */
1686 if (old
&& old
->refcnt
== 0)
1687 community_free(old
);
1691 /* "additive" case. */
1692 if (rcs
->additive
&& old
) {
1693 merge
= community_merge(community_dup(old
), rcs
->com
);
1695 new = community_uniq_sort(merge
);
1696 community_free(merge
);
1698 new = community_dup(rcs
->com
);
1700 /* HACK: if the old community is not intern'd,
1701 * we should free it here, or all reference to it may be
1703 * Really need to cleanup attribute caching sometime.
1705 if (old
&& old
->refcnt
== 0)
1706 community_free(old
);
1708 /* will be interned by caller if required */
1709 attr
->community
= new;
1711 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1717 /* Compile function for set community. */
1718 static void *route_set_community_compile(const char *arg
)
1720 struct rmap_com_set
*rcs
;
1721 struct community
*com
= NULL
;
1726 if (strcmp(arg
, "none") == 0)
1729 sp
= strstr(arg
, "additive");
1731 if (sp
&& sp
> arg
) {
1732 /* "additive" keyword is included. */
1737 com
= community_str2com(arg
);
1746 rcs
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_com_set
));
1748 rcs
->additive
= additive
;
1754 /* Free function for set community. */
1755 static void route_set_community_free(void *rule
)
1757 struct rmap_com_set
*rcs
= rule
;
1760 community_free(rcs
->com
);
1761 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcs
);
1764 /* Set community rule structure. */
1765 struct route_map_rule_cmd route_set_community_cmd
= {
1766 "community", route_set_community
, route_set_community_compile
,
1767 route_set_community_free
,
1770 /* `set community COMMUNITY' */
1771 struct rmap_lcom_set
{
1772 struct lcommunity
*lcom
;
1778 /* For lcommunity set mechanism. */
1779 static route_map_result_t
route_set_lcommunity(void *rule
,
1780 const struct prefix
*prefix
,
1781 route_map_object_t type
,
1784 struct rmap_lcom_set
*rcs
;
1785 struct bgp_info
*binfo
;
1787 struct lcommunity
*new = NULL
;
1788 struct lcommunity
*old
;
1789 struct lcommunity
*merge
;
1791 if (type
== RMAP_BGP
) {
1795 old
= attr
->lcommunity
;
1800 ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
));
1801 attr
->lcommunity
= NULL
;
1803 /* See the longer comment down below. */
1804 if (old
&& old
->refcnt
== 0)
1805 lcommunity_free(&old
);
1809 if (rcs
->additive
&& old
) {
1810 merge
= lcommunity_merge(lcommunity_dup(old
),
1813 new = lcommunity_uniq_sort(merge
);
1814 lcommunity_free(&merge
);
1816 new = lcommunity_dup(rcs
->lcom
);
1818 /* HACK: if the old large-community is not intern'd,
1819 * we should free it here, or all reference to it may be
1821 * Really need to cleanup attribute caching sometime.
1823 if (old
&& old
->refcnt
== 0)
1824 lcommunity_free(&old
);
1826 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1827 attr
->lcommunity
= new;
1829 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
);
1835 /* Compile function for set community. */
1836 static void *route_set_lcommunity_compile(const char *arg
)
1838 struct rmap_lcom_set
*rcs
;
1839 struct lcommunity
*lcom
= NULL
;
1844 if (strcmp(arg
, "none") == 0)
1847 sp
= strstr(arg
, "additive");
1849 if (sp
&& sp
> arg
) {
1850 /* "additive" keyworkd is included. */
1855 lcom
= lcommunity_str2com(arg
);
1864 rcs
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct rmap_com_set
));
1866 rcs
->additive
= additive
;
1872 /* Free function for set lcommunity. */
1873 static void route_set_lcommunity_free(void *rule
)
1875 struct rmap_lcom_set
*rcs
= rule
;
1878 lcommunity_free(&rcs
->lcom
);
1880 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rcs
);
1883 /* Set community rule structure. */
1884 struct route_map_rule_cmd route_set_lcommunity_cmd
= {
1885 "large-community", route_set_lcommunity
, route_set_lcommunity_compile
,
1886 route_set_lcommunity_free
,
1889 /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
1891 /* For large community set mechanism. */
1892 static route_map_result_t
route_set_lcommunity_delete(void *rule
,
1893 const struct prefix
*pfx
,
1894 route_map_object_t type
,
1897 struct community_list
*list
;
1898 struct lcommunity
*merge
;
1899 struct lcommunity
*new;
1900 struct lcommunity
*old
;
1901 struct bgp_info
*binfo
;
1903 if (type
== RMAP_BGP
) {
1908 list
= community_list_lookup(bgp_clist
, rule
,
1909 LARGE_COMMUNITY_LIST_MASTER
);
1910 old
= binfo
->attr
->lcommunity
;
1913 merge
= lcommunity_list_match_delete(
1914 lcommunity_dup(old
), list
);
1915 new = lcommunity_uniq_sort(merge
);
1916 lcommunity_free(&merge
);
1918 /* HACK: if the old community is not intern'd,
1919 * we should free it here, or all reference to it may be
1921 * Really need to cleanup attribute caching sometime.
1923 if (old
->refcnt
== 0)
1924 lcommunity_free(&old
);
1926 if (new->size
== 0) {
1927 binfo
->attr
->lcommunity
= NULL
;
1928 binfo
->attr
->flag
&= ~ATTR_FLAG_BIT(
1929 BGP_ATTR_LARGE_COMMUNITIES
);
1930 lcommunity_free(&new);
1932 binfo
->attr
->lcommunity
= new;
1933 binfo
->attr
->flag
|= ATTR_FLAG_BIT(
1934 BGP_ATTR_LARGE_COMMUNITIES
);
1942 /* Compile function for set lcommunity. */
1943 static void *route_set_lcommunity_delete_compile(const char *arg
)
1949 p
= strchr(arg
, ' ');
1952 str
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
1953 memcpy(str
, arg
, len
);
1960 /* Free function for set lcommunity. */
1961 static void route_set_lcommunity_delete_free(void *rule
)
1963 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
1966 /* Set lcommunity rule structure. */
1967 struct route_map_rule_cmd route_set_lcommunity_delete_cmd
= {
1968 "large-comm-list", route_set_lcommunity_delete
,
1969 route_set_lcommunity_delete_compile
, route_set_lcommunity_delete_free
,
1973 /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
1975 /* For community set mechanism. */
1976 static route_map_result_t
route_set_community_delete(
1978 const struct prefix
*prefix
,
1979 route_map_object_t type
,
1982 struct community_list
*list
;
1983 struct community
*merge
;
1984 struct community
*new;
1985 struct community
*old
;
1986 struct bgp_info
*binfo
;
1988 if (type
== RMAP_BGP
) {
1993 list
= community_list_lookup(bgp_clist
, rule
,
1994 COMMUNITY_LIST_MASTER
);
1995 old
= binfo
->attr
->community
;
1998 merge
= community_list_match_delete(community_dup(old
),
2000 new = community_uniq_sort(merge
);
2001 community_free(merge
);
2003 /* HACK: if the old community is not intern'd,
2004 * we should free it here, or all reference to it may be
2006 * Really need to cleanup attribute caching sometime.
2008 if (old
->refcnt
== 0)
2009 community_free(old
);
2011 if (new->size
== 0) {
2012 binfo
->attr
->community
= NULL
;
2013 binfo
->attr
->flag
&=
2014 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
2015 community_free(new);
2017 binfo
->attr
->community
= new;
2018 binfo
->attr
->flag
|=
2019 ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
2027 /* Compile function for set community. */
2028 static void *route_set_community_delete_compile(const char *arg
)
2034 p
= strchr(arg
, ' ');
2037 str
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, len
+ 1);
2038 memcpy(str
, arg
, len
);
2045 /* Free function for set community. */
2046 static void route_set_community_delete_free(void *rule
)
2048 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2051 /* Set community rule structure. */
2052 struct route_map_rule_cmd route_set_community_delete_cmd
= {
2053 "comm-list", route_set_community_delete
,
2054 route_set_community_delete_compile
, route_set_community_delete_free
,
2057 /* `set extcommunity rt COMMUNITY' */
2059 /* For community set mechanism. Used by _rt and _soo. */
2060 static route_map_result_t
route_set_ecommunity(void *rule
,
2061 const struct prefix
*prefix
,
2062 route_map_object_t type
,
2065 struct ecommunity
*ecom
;
2066 struct ecommunity
*new_ecom
;
2067 struct ecommunity
*old_ecom
;
2068 struct bgp_info
*bgp_info
;
2070 if (type
== RMAP_BGP
) {
2077 /* We assume additive for Extended Community. */
2078 old_ecom
= bgp_info
->attr
->ecommunity
;
2081 new_ecom
= ecommunity_merge(ecommunity_dup(old_ecom
),
2084 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2085 * bgp_update_receive()
2086 * ->refcnt = 0 => set by a previous route-map
2088 if (!old_ecom
->refcnt
)
2089 ecommunity_free(&old_ecom
);
2091 new_ecom
= ecommunity_dup(ecom
);
2093 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2094 bgp_info
->attr
->ecommunity
= new_ecom
;
2096 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
2101 /* Compile function for set community. */
2102 static void *route_set_ecommunity_rt_compile(const char *arg
)
2104 struct ecommunity
*ecom
;
2106 ecom
= ecommunity_str2com(arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
2109 return ecommunity_intern(ecom
);
2112 /* Free function for set community. Used by _rt and _soo */
2113 static void route_set_ecommunity_free(void *rule
)
2115 struct ecommunity
*ecom
= rule
;
2116 ecommunity_unintern(&ecom
);
2119 /* Set community rule structure. */
2120 struct route_map_rule_cmd route_set_ecommunity_rt_cmd
= {
2121 "extcommunity rt", route_set_ecommunity
,
2122 route_set_ecommunity_rt_compile
, route_set_ecommunity_free
,
2125 /* `set extcommunity soo COMMUNITY' */
2127 /* Compile function for set community. */
2128 static void *route_set_ecommunity_soo_compile(const char *arg
)
2130 struct ecommunity
*ecom
;
2132 ecom
= ecommunity_str2com(arg
, ECOMMUNITY_SITE_ORIGIN
, 0);
2136 return ecommunity_intern(ecom
);
2139 /* Set community rule structure. */
2140 struct route_map_rule_cmd route_set_ecommunity_soo_cmd
= {
2141 "extcommunity soo", route_set_ecommunity
,
2142 route_set_ecommunity_soo_compile
, route_set_ecommunity_free
,
2145 /* `set origin ORIGIN' */
2147 /* For origin set. */
2148 static route_map_result_t
route_set_origin(void *rule
,
2149 const struct prefix
*prefix
,
2150 route_map_object_t type
,
2154 struct bgp_info
*bgp_info
;
2156 if (type
== RMAP_BGP
) {
2160 bgp_info
->attr
->origin
= *origin
;
2166 /* Compile function for origin set. */
2167 static void *route_set_origin_compile(const char *arg
)
2171 origin
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(uint8_t));
2173 if (strcmp(arg
, "igp") == 0)
2175 else if (strcmp(arg
, "egp") == 0)
2183 /* Compile function for origin set. */
2184 static void route_set_origin_free(void *rule
)
2186 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2189 /* Set origin rule structure. */
2190 struct route_map_rule_cmd route_set_origin_cmd
= {
2191 "origin", route_set_origin
, route_set_origin_compile
,
2192 route_set_origin_free
,
2195 /* `set atomic-aggregate' */
2197 /* For atomic aggregate set. */
2198 static route_map_result_t
route_set_atomic_aggregate(void *rule
,
2199 const struct prefix
*pfx
,
2200 route_map_object_t type
,
2203 struct bgp_info
*bgp_info
;
2205 if (type
== RMAP_BGP
) {
2207 bgp_info
->attr
->flag
|=
2208 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
2214 /* Compile function for atomic aggregate. */
2215 static void *route_set_atomic_aggregate_compile(const char *arg
)
2220 /* Compile function for atomic aggregate. */
2221 static void route_set_atomic_aggregate_free(void *rule
)
2226 /* Set atomic aggregate rule structure. */
2227 struct route_map_rule_cmd route_set_atomic_aggregate_cmd
= {
2228 "atomic-aggregate", route_set_atomic_aggregate
,
2229 route_set_atomic_aggregate_compile
, route_set_atomic_aggregate_free
,
2232 /* `set aggregator as AS A.B.C.D' */
2235 struct in_addr address
;
2238 static route_map_result_t
route_set_aggregator_as(void *rule
,
2239 const struct prefix
*prefix
,
2240 route_map_object_t type
,
2243 struct bgp_info
*bgp_info
;
2244 struct aggregator
*aggregator
;
2246 if (type
== RMAP_BGP
) {
2250 bgp_info
->attr
->aggregator_as
= aggregator
->as
;
2251 bgp_info
->attr
->aggregator_addr
= aggregator
->address
;
2252 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
);
2258 static void *route_set_aggregator_as_compile(const char *arg
)
2260 struct aggregator
*aggregator
;
2266 XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct aggregator
));
2267 if (sscanf(arg
, "%s %s", as
, address
) != 2) {
2268 XFREE(MTYPE_ROUTE_MAP_COMPILED
, aggregator
);
2272 aggregator
->as
= strtoul(as
, NULL
, 10);
2273 ret
= inet_aton(address
, &aggregator
->address
);
2275 XFREE(MTYPE_ROUTE_MAP_COMPILED
, aggregator
);
2281 static void route_set_aggregator_as_free(void *rule
)
2283 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2286 struct route_map_rule_cmd route_set_aggregator_as_cmd
= {
2287 "aggregator as", route_set_aggregator_as
,
2288 route_set_aggregator_as_compile
, route_set_aggregator_as_free
,
2291 /* Set tag to object. object must be pointer to struct bgp_info */
2292 static route_map_result_t
route_set_tag(void *rule
,
2293 const struct prefix
*prefix
,
2294 route_map_object_t type
, void *object
)
2297 struct bgp_info
*bgp_info
;
2299 if (type
== RMAP_BGP
) {
2304 bgp_info
->attr
->tag
= *tag
;
2310 /* Route map commands for tag set. */
2311 static struct route_map_rule_cmd route_set_tag_cmd
= {
2312 "tag", route_set_tag
, route_map_rule_tag_compile
,
2313 route_map_rule_tag_free
,
2316 /* Set label-index to object. object must be pointer to struct bgp_info */
2317 static route_map_result_t
route_set_label_index(void *rule
,
2318 const struct prefix
*prefix
,
2319 route_map_object_t type
,
2322 struct rmap_value
*rv
;
2323 struct bgp_info
*bgp_info
;
2324 uint32_t label_index
;
2326 if (type
== RMAP_BGP
) {
2327 /* Fetch routemap's rule information. */
2331 /* Set label-index value. */
2332 label_index
= rv
->value
;
2334 bgp_info
->attr
->label_index
= label_index
;
2335 bgp_info
->attr
->flag
|=
2336 ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
2343 /* Route map commands for label-index set. */
2344 static struct route_map_rule_cmd route_set_label_index_cmd
= {
2345 "label-index", route_set_label_index
, route_value_compile
,
2349 /* `match ipv6 address IP_ACCESS_LIST' */
2351 static route_map_result_t
route_match_ipv6_address(void *rule
,
2352 const struct prefix
*prefix
,
2353 route_map_object_t type
,
2356 struct access_list
*alist
;
2358 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET6
) {
2359 alist
= access_list_lookup(AFI_IP6
, (char *)rule
);
2361 return RMAP_NOMATCH
;
2363 return (access_list_apply(alist
, prefix
) == FILTER_DENY
2367 return RMAP_NOMATCH
;
2370 static void *route_match_ipv6_address_compile(const char *arg
)
2372 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
2375 static void route_match_ipv6_address_free(void *rule
)
2377 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2380 /* Route map commands for ip address matching. */
2381 struct route_map_rule_cmd route_match_ipv6_address_cmd
= {
2382 "ipv6 address", route_match_ipv6_address
,
2383 route_match_ipv6_address_compile
, route_match_ipv6_address_free
};
2385 /* `match ipv6 next-hop IP_ADDRESS' */
2387 static route_map_result_t
route_match_ipv6_next_hop(void *rule
,
2388 const struct prefix
*prefix
,
2389 route_map_object_t type
,
2392 struct in6_addr
*addr
= rule
;
2393 struct bgp_info
*bgp_info
;
2395 if (type
== RMAP_BGP
) {
2398 if (IPV6_ADDR_SAME(&bgp_info
->attr
->mp_nexthop_global
, addr
))
2401 if (bgp_info
->attr
->mp_nexthop_len
2402 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
2403 && IPV6_ADDR_SAME(&bgp_info
->attr
->mp_nexthop_local
, rule
))
2406 return RMAP_NOMATCH
;
2409 return RMAP_NOMATCH
;
2412 static void *route_match_ipv6_next_hop_compile(const char *arg
)
2414 struct in6_addr
*address
;
2417 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2419 ret
= inet_pton(AF_INET6
, arg
, address
);
2421 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2428 static void route_match_ipv6_next_hop_free(void *rule
)
2430 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2433 struct route_map_rule_cmd route_match_ipv6_next_hop_cmd
= {
2434 "ipv6 next-hop", route_match_ipv6_next_hop
,
2435 route_match_ipv6_next_hop_compile
, route_match_ipv6_next_hop_free
};
2437 /* `match ipv6 address prefix-list PREFIX_LIST' */
2439 static route_map_result_t
2440 route_match_ipv6_address_prefix_list(void *rule
, const struct prefix
*prefix
,
2441 route_map_object_t type
, void *object
)
2443 struct prefix_list
*plist
;
2445 if (type
== RMAP_BGP
&& prefix
->family
== AF_INET6
) {
2446 plist
= prefix_list_lookup(AFI_IP6
, (char *)rule
);
2448 return RMAP_NOMATCH
;
2450 return (prefix_list_apply(plist
, prefix
) == PREFIX_DENY
2454 return RMAP_NOMATCH
;
2457 static void *route_match_ipv6_address_prefix_list_compile(const char *arg
)
2459 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED
, arg
);
2462 static void route_match_ipv6_address_prefix_list_free(void *rule
)
2464 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2467 struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd
= {
2468 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list
,
2469 route_match_ipv6_address_prefix_list_compile
,
2470 route_match_ipv6_address_prefix_list_free
};
2472 /* `set ipv6 nexthop global IP_ADDRESS' */
2474 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2475 static route_map_result_t
route_set_ipv6_nexthop_global(void *rule
,
2476 const struct prefix
*p
,
2477 route_map_object_t type
,
2480 struct in6_addr
*address
;
2481 struct bgp_info
*bgp_info
;
2483 if (type
== RMAP_BGP
) {
2484 /* Fetch routemap's rule information. */
2488 /* Set next hop value. */
2489 bgp_info
->attr
->mp_nexthop_global
= *address
;
2491 /* Set nexthop length. */
2492 if (bgp_info
->attr
->mp_nexthop_len
== 0)
2493 bgp_info
->attr
->mp_nexthop_len
=
2494 BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2496 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2497 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
);
2503 /* Route map `ip next-hop' compile function. Given string is converted
2504 to struct in_addr structure. */
2505 static void *route_set_ipv6_nexthop_global_compile(const char *arg
)
2508 struct in6_addr
*address
;
2510 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2512 ret
= inet_pton(AF_INET6
, arg
, address
);
2515 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2522 /* Free route map's compiled `ip next-hop' value. */
2523 static void route_set_ipv6_nexthop_global_free(void *rule
)
2525 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2528 /* Route map commands for ip nexthop set. */
2529 struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd
= {
2530 "ipv6 next-hop global", route_set_ipv6_nexthop_global
,
2531 route_set_ipv6_nexthop_global_compile
,
2532 route_set_ipv6_nexthop_global_free
};
2534 /* Set next-hop preference value. */
2535 static route_map_result_t
2536 route_set_ipv6_nexthop_prefer_global(void *rule
, const struct prefix
*prefix
,
2537 route_map_object_t type
, void *object
)
2539 struct bgp_info
*bgp_info
;
2542 if (type
== RMAP_BGP
) {
2543 /* Fetch routemap's rule information. */
2545 peer
= bgp_info
->peer
;
2547 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
2548 || CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IMPORT
))
2550 && sockunion_family(peer
->su_remote
) == AF_INET6
) {
2551 /* Set next hop preference to global */
2552 bgp_info
->attr
->mp_nexthop_prefer_global
= TRUE
;
2553 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2554 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED
);
2556 bgp_info
->attr
->mp_nexthop_prefer_global
= FALSE
;
2557 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2558 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED
);
2564 static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg
)
2568 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
2574 /* Free route map's compiled `ip next-hop' value. */
2575 static void route_set_ipv6_nexthop_prefer_global_free(void *rule
)
2577 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2580 /* Route map commands for ip nexthop set preferred. */
2581 struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd
= {
2582 "ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global
,
2583 route_set_ipv6_nexthop_prefer_global_compile
,
2584 route_set_ipv6_nexthop_prefer_global_free
};
2586 /* `set ipv6 nexthop local IP_ADDRESS' */
2588 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2589 static route_map_result_t
route_set_ipv6_nexthop_local(void *rule
,
2590 const struct prefix
*p
,
2591 route_map_object_t type
,
2594 struct in6_addr
*address
;
2595 struct bgp_info
*bgp_info
;
2597 if (type
== RMAP_BGP
) {
2598 /* Fetch routemap's rule information. */
2602 /* Set next hop value. */
2603 bgp_info
->attr
->mp_nexthop_local
= *address
;
2605 /* Set nexthop length. */
2606 if (bgp_info
->attr
->mp_nexthop_len
2607 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
2608 bgp_info
->attr
->mp_nexthop_len
=
2609 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2611 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2612 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
);
2618 /* Route map `ip nexthop' compile function. Given string is converted
2619 to struct in_addr structure. */
2620 static void *route_set_ipv6_nexthop_local_compile(const char *arg
)
2623 struct in6_addr
*address
;
2625 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2627 ret
= inet_pton(AF_INET6
, arg
, address
);
2630 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2637 /* Free route map's compiled `ip nexthop' value. */
2638 static void route_set_ipv6_nexthop_local_free(void *rule
)
2640 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2643 /* Route map commands for ip nexthop set. */
2644 struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd
= {
2645 "ipv6 next-hop local", route_set_ipv6_nexthop_local
,
2646 route_set_ipv6_nexthop_local_compile
,
2647 route_set_ipv6_nexthop_local_free
};
2649 /* `set ipv6 nexthop peer-address' */
2651 /* Set nexthop to object. ojbect must be pointer to struct attr. */
2652 static route_map_result_t
route_set_ipv6_nexthop_peer(void *rule
,
2653 const struct prefix
*pfx
,
2654 route_map_object_t type
,
2657 struct in6_addr peer_address
;
2658 struct bgp_info
*bgp_info
;
2661 if (type
== RMAP_BGP
) {
2662 /* Fetch routemap's rule information. */
2664 peer
= bgp_info
->peer
;
2666 if ((CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
)
2667 || CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IMPORT
))
2669 && sockunion_family(peer
->su_remote
) == AF_INET6
) {
2670 peer_address
= peer
->su_remote
->sin6
.sin6_addr
;
2671 /* Set next hop value and length in attribute. */
2672 if (IN6_IS_ADDR_LINKLOCAL(&peer_address
)) {
2673 bgp_info
->attr
->mp_nexthop_local
= peer_address
;
2674 if (bgp_info
->attr
->mp_nexthop_len
!= 32)
2675 bgp_info
->attr
->mp_nexthop_len
= 32;
2677 bgp_info
->attr
->mp_nexthop_global
=
2679 if (bgp_info
->attr
->mp_nexthop_len
== 0)
2680 bgp_info
->attr
->mp_nexthop_len
= 16;
2683 } else if (CHECK_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
)) {
2684 /* The next hop value will be set as part of packet
2686 * Set the flags here to indicate that rewrite needs to
2688 * Also, clear the value - we clear both global and
2690 * nexthops, whether we send one or both is determined
2693 SET_FLAG(bgp_info
->attr
->rmap_change_flags
,
2694 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
);
2695 /* clear next hop value. */
2696 memset(&(bgp_info
->attr
->mp_nexthop_global
), 0,
2697 sizeof(struct in6_addr
));
2698 memset(&(bgp_info
->attr
->mp_nexthop_local
), 0,
2699 sizeof(struct in6_addr
));
2706 /* Route map `ip next-hop' compile function. Given string is converted
2707 to struct in_addr structure. */
2708 static void *route_set_ipv6_nexthop_peer_compile(const char *arg
)
2712 rins
= XCALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
2718 /* Free route map's compiled `ip next-hop' value. */
2719 static void route_set_ipv6_nexthop_peer_free(void *rule
)
2721 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2724 /* Route map commands for ip nexthop set. */
2725 struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd
= {
2726 "ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer
,
2727 route_set_ipv6_nexthop_peer_compile
, route_set_ipv6_nexthop_peer_free
};
2729 /* `set ipv4 vpn next-hop A.B.C.D' */
2731 static route_map_result_t
route_set_vpnv4_nexthop(void *rule
,
2732 const struct prefix
*prefix
,
2733 route_map_object_t type
,
2736 struct in_addr
*address
;
2737 struct bgp_info
*bgp_info
;
2739 if (type
== RMAP_BGP
) {
2740 /* Fetch routemap's rule information. */
2744 /* Set next hop value. */
2745 bgp_info
->attr
->mp_nexthop_global_in
= *address
;
2746 bgp_info
->attr
->mp_nexthop_len
= 4;
2752 static void *route_set_vpnv4_nexthop_compile(const char *arg
)
2755 struct in_addr
*address
;
2757 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in_addr
));
2759 ret
= inet_aton(arg
, address
);
2762 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2769 /* `set ipv6 vpn next-hop A.B.C.D' */
2771 static route_map_result_t
route_set_vpnv6_nexthop(void *rule
,
2772 const struct prefix
*prefix
,
2773 route_map_object_t type
,
2776 struct in6_addr
*address
;
2777 struct bgp_info
*bgp_info
;
2779 if (type
== RMAP_BGP
) {
2780 /* Fetch routemap's rule information. */
2784 /* Set next hop value. */
2785 memcpy(&bgp_info
->attr
->mp_nexthop_global
, address
,
2786 sizeof(struct in6_addr
));
2787 bgp_info
->attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_VPNV6_GLOBAL
;
2793 static void *route_set_vpnv6_nexthop_compile(const char *arg
)
2796 struct in6_addr
*address
;
2798 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in6_addr
));
2799 ret
= inet_pton(AF_INET6
, arg
, address
);
2802 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2809 static void route_set_vpn_nexthop_free(void *rule
)
2811 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2814 /* Route map commands for ipv4 next-hop set. */
2815 struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd
= {
2816 "ipv4 vpn next-hop", route_set_vpnv4_nexthop
,
2817 route_set_vpnv4_nexthop_compile
, route_set_vpn_nexthop_free
};
2819 /* Route map commands for ipv6 next-hop set. */
2820 struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd
= {
2821 "ipv6 vpn next-hop", route_set_vpnv6_nexthop
,
2822 route_set_vpnv6_nexthop_compile
, route_set_vpn_nexthop_free
};
2824 /* `set originator-id' */
2826 /* For origin set. */
2827 static route_map_result_t
route_set_originator_id(void *rule
,
2828 const struct prefix
*prefix
,
2829 route_map_object_t type
,
2832 struct in_addr
*address
;
2833 struct bgp_info
*bgp_info
;
2835 if (type
== RMAP_BGP
) {
2839 bgp_info
->attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
);
2840 bgp_info
->attr
->originator_id
= *address
;
2846 /* Compile function for originator-id set. */
2847 static void *route_set_originator_id_compile(const char *arg
)
2850 struct in_addr
*address
;
2852 address
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(struct in_addr
));
2854 ret
= inet_aton(arg
, address
);
2857 XFREE(MTYPE_ROUTE_MAP_COMPILED
, address
);
2864 /* Compile function for originator_id set. */
2865 static void route_set_originator_id_free(void *rule
)
2867 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
2870 /* Set originator-id rule structure. */
2871 struct route_map_rule_cmd route_set_originator_id_cmd
= {
2872 "originator-id", route_set_originator_id
,
2873 route_set_originator_id_compile
, route_set_originator_id_free
,
2876 /* Add bgp route map rule. */
2877 static int bgp_route_match_add(struct vty
*vty
, const char *command
,
2878 const char *arg
, route_map_event_t type
)
2880 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
2881 int retval
= CMD_SUCCESS
;
2884 ret
= route_map_add_match(index
, command
, arg
);
2886 case RMAP_RULE_MISSING
:
2887 vty_out(vty
, "%% BGP Can't find rule.\n");
2888 retval
= CMD_WARNING_CONFIG_FAILED
;
2890 case RMAP_COMPILE_ERROR
:
2891 vty_out(vty
, "%% BGP Argument is malformed.\n");
2892 retval
= CMD_WARNING_CONFIG_FAILED
;
2894 case RMAP_COMPILE_SUCCESS
:
2895 if (type
!= RMAP_EVENT_MATCH_ADDED
) {
2896 route_map_upd8_dependency(type
, arg
, index
->map
->name
);
2904 /* Delete bgp route map rule. */
2905 static int bgp_route_match_delete(struct vty
*vty
, const char *command
,
2906 const char *arg
, route_map_event_t type
)
2908 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
2910 int retval
= CMD_SUCCESS
;
2911 char *dep_name
= NULL
;
2913 char *rmap_name
= NULL
;
2915 if (type
!= RMAP_EVENT_MATCH_DELETED
) {
2916 /* ignore the mundane, the types without any dependency */
2918 if ((tmpstr
= route_map_get_match_arg(index
, command
))
2921 XSTRDUP(MTYPE_ROUTE_MAP_RULE
, tmpstr
);
2923 dep_name
= XSTRDUP(MTYPE_ROUTE_MAP_RULE
, arg
);
2925 rmap_name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, index
->map
->name
);
2928 ret
= route_map_delete_match(index
, command
, dep_name
);
2930 case RMAP_RULE_MISSING
:
2931 vty_out(vty
, "%% BGP Can't find rule.\n");
2932 retval
= CMD_WARNING_CONFIG_FAILED
;
2934 case RMAP_COMPILE_ERROR
:
2935 vty_out(vty
, "%% BGP Argument is malformed.\n");
2936 retval
= CMD_WARNING_CONFIG_FAILED
;
2938 case RMAP_COMPILE_SUCCESS
:
2939 if (type
!= RMAP_EVENT_MATCH_DELETED
&& dep_name
)
2940 route_map_upd8_dependency(type
, dep_name
, rmap_name
);
2945 XFREE(MTYPE_ROUTE_MAP_RULE
, dep_name
);
2947 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
2953 * This is the workhorse routine for processing in/out routemap
2956 static void bgp_route_map_process_peer(const char *rmap_name
,
2957 struct route_map
*map
, struct peer
*peer
,
2958 int afi
, int safi
, int route_update
)
2962 struct bgp_filter
*filter
;
2964 if (!peer
|| !rmap_name
)
2967 filter
= &peer
->filter
[afi
][safi
];
2969 * in is for non-route-server clients,
2970 * out is for all peers
2972 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_RSERVER_CLIENT
)) {
2973 if (filter
->map
[RMAP_IN
].name
2974 && (strcmp(rmap_name
, filter
->map
[RMAP_IN
].name
) == 0)) {
2975 filter
->map
[RMAP_IN
].map
= map
;
2977 if (route_update
&& peer
->status
== Established
) {
2978 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2979 PEER_FLAG_SOFT_RECONFIG
)) {
2980 if (bgp_debug_update(peer
, NULL
, NULL
,
2983 "Processing route_map %s update on "
2984 "peer %s (inbound, soft-reconfig)",
2985 rmap_name
, peer
->host
);
2987 bgp_soft_reconfig_in(peer
, afi
, safi
);
2989 CHECK_FLAG(peer
->cap
,
2990 PEER_CAP_REFRESH_OLD_RCV
)
2993 PEER_CAP_REFRESH_NEW_RCV
)) {
2995 if (bgp_debug_update(peer
, NULL
, NULL
,
2998 "Processing route_map %s update on "
2999 "peer %s (inbound, route-refresh)",
3000 rmap_name
, peer
->host
);
3001 bgp_route_refresh_send(peer
, afi
, safi
,
3008 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_RSERVER_CLIENT
)) {
3011 if (update
&& route_update
&& peer
->status
== Established
) {
3012 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3013 PEER_FLAG_SOFT_RECONFIG
)) {
3014 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3016 "Processing route_map %s update on "
3017 "peer %s (import, soft-reconfig)",
3018 rmap_name
, peer
->host
);
3020 bgp_soft_reconfig_in(peer
, afi
, safi
);
3021 } else if (CHECK_FLAG(peer
->cap
,
3022 PEER_CAP_REFRESH_OLD_RCV
)
3023 || CHECK_FLAG(peer
->cap
,
3024 PEER_CAP_REFRESH_NEW_RCV
)) {
3025 if (bgp_debug_update(peer
, NULL
, NULL
, 1))
3027 "Processing route_map %s update on "
3028 "peer %s (import, route-refresh)",
3029 rmap_name
, peer
->host
);
3030 bgp_route_refresh_send(peer
, afi
, safi
, 0, 0,
3033 /* DD: Else, what else do we do ? Reset peer ? */
3038 * For outbound, unsuppress and default-originate map change (content or
3039 * map created), merely update the "config" here, the actual route
3040 * announcement happens at the group level.
3042 if (filter
->map
[RMAP_OUT
].name
3043 && (strcmp(rmap_name
, filter
->map
[RMAP_OUT
].name
) == 0))
3044 filter
->map
[RMAP_OUT
].map
= map
;
3046 if (filter
->usmap
.name
&& (strcmp(rmap_name
, filter
->usmap
.name
) == 0))
3047 filter
->usmap
.map
= map
;
3049 if (peer
->default_rmap
[afi
][safi
].name
3050 && (strcmp(rmap_name
, peer
->default_rmap
[afi
][safi
].name
) == 0))
3051 peer
->default_rmap
[afi
][safi
].map
= map
;
3054 static void bgp_route_map_update_peer_group(const char *rmap_name
,
3055 struct route_map
*map
,
3058 struct peer_group
*group
;
3059 struct listnode
*node
, *nnode
;
3060 struct bgp_filter
*filter
;
3067 /* All the peers have been updated correctly already. This is
3068 * just updating the placeholder data. No real update required.
3070 for (ALL_LIST_ELEMENTS(bgp
->group
, node
, nnode
, group
)) {
3071 FOREACH_AFI_SAFI (afi
, safi
) {
3072 filter
= &group
->conf
->filter
[afi
][safi
];
3074 for (direct
= RMAP_IN
; direct
< RMAP_MAX
; direct
++) {
3075 if ((filter
->map
[direct
].name
)
3076 && (strcmp(rmap_name
,
3077 filter
->map
[direct
].name
)
3079 filter
->map
[direct
].map
= map
;
3082 if (filter
->usmap
.name
3083 && (strcmp(rmap_name
, filter
->usmap
.name
) == 0))
3084 filter
->usmap
.map
= map
;
3090 * Note that if an extreme number (tens of thousands) of route-maps are in use
3091 * and if bgp has an extreme number of peers, network statements, etc then this
3092 * function can consume a lot of cycles. This is due to this function being
3093 * called for each route-map and within this function we walk the list of peers,
3094 * network statements, etc looking to see if they use this route-map.
3096 static void bgp_route_map_process_update(struct bgp
*bgp
, const char *rmap_name
,
3103 struct bgp_node
*bn
;
3104 struct bgp_static
*bgp_static
;
3105 struct listnode
*node
, *nnode
;
3106 struct route_map
*map
;
3107 char buf
[INET6_ADDRSTRLEN
];
3109 map
= route_map_lookup_by_name(rmap_name
);
3111 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
3113 /* Ignore dummy peer-group structure */
3114 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
))
3117 FOREACH_AFI_SAFI (afi
, safi
) {
3118 /* process in/out/import/export/default-orig
3120 bgp_route_map_process_peer(rmap_name
, map
, peer
, afi
,
3121 safi
, route_update
);
3125 /* for outbound/default-orig route-maps, process for groups */
3126 update_group_policy_update(bgp
, BGP_POLICY_ROUTE_MAP
, rmap_name
,
3129 /* update peer-group config (template) */
3130 bgp_route_map_update_peer_group(rmap_name
, map
, bgp
);
3132 FOREACH_AFI_SAFI (afi
, safi
) {
3133 /* For table route-map updates. */
3134 if (!bgp_fibupd_safi(safi
))
3137 if (bgp
->table_map
[afi
][safi
].name
3138 && (strcmp(rmap_name
, bgp
->table_map
[afi
][safi
].name
)
3140 bgp
->table_map
[afi
][safi
].map
= map
;
3142 if (BGP_DEBUG(zebra
, ZEBRA
))
3144 "Processing route_map %s update on "
3148 bgp_zebra_announce_table(bgp
, afi
, safi
);
3151 /* For network route-map updates. */
3152 for (bn
= bgp_table_top(bgp
->route
[afi
][safi
]); bn
;
3153 bn
= bgp_route_next(bn
))
3154 if ((bgp_static
= bn
->info
) != NULL
) {
3155 if (bgp_static
->rmap
.name
3156 && (strcmp(rmap_name
, bgp_static
->rmap
.name
)
3158 bgp_static
->rmap
.map
= map
;
3161 if (!bgp_static
->backdoor
) {
3162 if (bgp_debug_zebra(
3165 "Processing route_map %s update on "
3182 /* For redistribute route-map updates. */
3183 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3184 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
3185 struct list
*red_list
;
3186 struct bgp_redist
*red
;
3188 red_list
= bgp
->redist
[afi
][i
];
3192 for (ALL_LIST_ELEMENTS_RO(red_list
, node
, red
)) {
3194 && (strcmp(rmap_name
, red
->rmap
.name
)
3196 red
->rmap
.map
= map
;
3199 if (BGP_DEBUG(zebra
, ZEBRA
))
3201 "Processing route_map %s update on "
3202 "redistributed routes",
3205 bgp_redistribute_resend(
3213 /* for type5 command route-maps */
3214 FOREACH_AFI_SAFI (afi
, safi
) {
3215 if (bgp
->adv_cmd_rmap
[afi
][safi
].name
3216 && strcmp(rmap_name
, bgp
->adv_cmd_rmap
[afi
][safi
].name
)
3218 if (BGP_DEBUG(zebra
, ZEBRA
))
3220 "Processing route_map %s update on advertise type5 route command",
3222 bgp_evpn_withdraw_type5_routes(bgp
, afi
, safi
);
3223 bgp_evpn_advertise_type5_routes(bgp
, afi
, safi
);
3228 static void bgp_route_map_process_update_cb(char *rmap_name
)
3230 struct listnode
*node
, *nnode
;
3233 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
3234 bgp_route_map_process_update(bgp
, rmap_name
, 1);
3237 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3238 vnc_routemap_update(bgp
, __func__
);
3242 vpn_policy_routemap_event(rmap_name
);
3245 int bgp_route_map_update_timer(struct thread
*thread
)
3247 bm
->t_rmap_update
= NULL
;
3249 route_map_walk_update_list(bgp_route_map_process_update_cb
);
3254 static void bgp_route_map_mark_update(const char *rmap_name
)
3256 if (bm
->t_rmap_update
== NULL
) {
3257 struct listnode
*node
, *nnode
;
3260 /* rmap_update_timer of 0 means don't do route updates */
3261 if (bm
->rmap_update_timer
) {
3262 bm
->t_rmap_update
= NULL
;
3263 thread_add_timer(bm
->master
, bgp_route_map_update_timer
,
3264 NULL
, bm
->rmap_update_timer
,
3265 &bm
->t_rmap_update
);
3267 /* Signal the groups that a route-map update event has
3269 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3270 update_group_policy_update(bgp
,
3271 BGP_POLICY_ROUTE_MAP
,
3274 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
3275 bgp_route_map_process_update(bgp
, rmap_name
, 0);
3277 zlog_debug("%s: calling vnc_routemap_update", __func__
);
3278 vnc_routemap_update(bgp
, __func__
);
3284 static void bgp_route_map_add(const char *rmap_name
)
3286 if (route_map_mark_updated(rmap_name
) == 0)
3287 bgp_route_map_mark_update(rmap_name
);
3289 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
3292 static void bgp_route_map_delete(const char *rmap_name
)
3294 if (route_map_mark_updated(rmap_name
) == 0)
3295 bgp_route_map_mark_update(rmap_name
);
3297 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_DELETED
);
3300 static void bgp_route_map_event(route_map_event_t event
, const char *rmap_name
)
3302 if (route_map_mark_updated(rmap_name
) == 0)
3303 bgp_route_map_mark_update(rmap_name
);
3305 route_map_notify_dependencies(rmap_name
, RMAP_EVENT_MATCH_ADDED
);
3308 DEFUN (match_mac_address
,
3309 match_mac_address_cmd
,
3310 "match mac address WORD",
3313 "Match address of route\n"
3314 "MAC Access-list name\n")
3316 return bgp_route_match_add(vty
, "mac address", argv
[3]->arg
,
3317 RMAP_EVENT_FILTER_ADDED
);
3320 DEFUN (no_match_mac_address
,
3321 no_match_mac_address_cmd
,
3322 "no match mac address WORD",
3326 "Match address of route\n"
3327 "MAC acess-list name\n")
3329 return bgp_route_match_delete(vty
, "mac address", argv
[4]->arg
,
3330 RMAP_EVENT_FILTER_DELETED
);
3333 DEFUN (match_evpn_route_type
,
3334 match_evpn_route_type_cmd
,
3335 "match evpn route-type <macip | multicast | prefix>",
3338 "Match route-type\n"
3343 return bgp_route_match_add(vty
, "evpn route-type", argv
[3]->arg
,
3344 RMAP_EVENT_MATCH_ADDED
);
3347 DEFUN (no_match_evpn_route_type
,
3348 no_match_evpn_route_type_cmd
,
3349 "no match evpn route-type <macip | multicast | prefix>",
3353 "Match route-type\n"
3358 return bgp_route_match_delete(vty
, "evpn route-type", argv
[4]->arg
,
3359 RMAP_EVENT_MATCH_DELETED
);
3363 DEFUN (match_evpn_vni
,
3365 "match evpn vni (1-16777215)",
3371 return bgp_route_match_add(vty
, "evpn vni", argv
[3]->arg
,
3372 RMAP_EVENT_MATCH_ADDED
);
3375 DEFUN (no_match_evpn_vni
,
3376 no_match_evpn_vni_cmd
,
3377 "no match evpn vni (1-16777215)",
3384 return bgp_route_match_delete(vty
, "evpn vni", argv
[4]->arg
,
3385 RMAP_EVENT_MATCH_DELETED
);
3388 DEFUN (match_evpn_default_route
,
3389 match_evpn_default_route_cmd
,
3390 "match evpn default-route",
3393 "default EVPN type-5 route\n")
3395 return bgp_route_match_add(vty
, "evpn default-route", NULL
,
3396 RMAP_EVENT_MATCH_ADDED
);
3399 DEFUN (no_match_evpn_default_route
,
3400 no_match_evpn_default_route_cmd
,
3401 "no match evpn default-route",
3405 "default EVPN type-5 route\n")
3407 return bgp_route_match_delete(vty
, "evpn default-route", NULL
,
3408 RMAP_EVENT_MATCH_DELETED
);
3413 "match peer <A.B.C.D|X:X::X:X|WORD>",
3415 "Match peer address\n"
3416 "IP address of peer\n"
3417 "IPv6 address of peer\n"
3418 "Interface name of peer\n")
3421 return bgp_route_match_add(vty
, "peer", argv
[idx_ip
]->arg
,
3422 RMAP_EVENT_MATCH_ADDED
);
3425 DEFUN (match_peer_local
,
3426 match_peer_local_cmd
,
3429 "Match peer address\n"
3430 "Static or Redistributed routes\n")
3432 return bgp_route_match_add(vty
, "peer", "local",
3433 RMAP_EVENT_MATCH_DELETED
);
3436 DEFUN (no_match_peer
,
3438 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
3441 "Match peer address\n"
3442 "Static or Redistributed routes\n"
3443 "IP address of peer\n"
3444 "IPv6 address of peer\n"
3445 "Interface name of peer\n")
3449 if (argc
<= idx_peer
)
3450 return bgp_route_match_delete(vty
, "peer", NULL
,
3451 RMAP_EVENT_MATCH_DELETED
);
3452 return bgp_route_match_delete(vty
, "peer", argv
[idx_peer
]->arg
,
3453 RMAP_EVENT_MATCH_DELETED
);
3456 #if defined(HAVE_LUA)
3457 DEFUN (match_command
,
3459 "match command WORD",
3461 "Run a command to match\n"
3462 "The command to run\n")
3464 return bgp_route_match_add(vty
, "command", argv
[2]->arg
,
3465 RMAP_EVENT_FILTER_ADDED
);
3468 DEFUN (no_match_command
,
3469 no_match_command_cmd
,
3470 "no match command WORD",
3473 "Run a command to match\n"
3474 "The command to run\n")
3476 return bgp_route_match_delete(vty
, "command", argv
[3]->arg
,
3477 RMAP_EVENT_FILTER_DELETED
);
3481 /* match probability */
3482 DEFUN (match_probability
,
3483 match_probability_cmd
,
3484 "match probability (0-100)",
3486 "Match portion of routes defined by percentage value\n"
3487 "Percentage of routes\n")
3490 return bgp_route_match_add(vty
, "probability", argv
[idx_number
]->arg
,
3491 RMAP_EVENT_MATCH_ADDED
);
3495 DEFUN (no_match_probability
,
3496 no_match_probability_cmd
,
3497 "no match probability [(1-99)]",
3500 "Match portion of routes defined by percentage value\n"
3501 "Percentage of routes\n")
3504 if (argc
<= idx_number
)
3505 return bgp_route_match_delete(vty
, "probability", NULL
,
3506 RMAP_EVENT_MATCH_DELETED
);
3507 return bgp_route_match_delete(vty
, "probability", argv
[idx_number
]->arg
,
3508 RMAP_EVENT_MATCH_DELETED
);
3512 DEFUN (match_ip_route_source
,
3513 match_ip_route_source_cmd
,
3514 "match ip route-source <(1-199)|(1300-2699)|WORD>",
3517 "Match advertising source address of route\n"
3518 "IP access-list number\n"
3519 "IP access-list number (expanded range)\n"
3520 "IP standard access-list name\n")
3523 return bgp_route_match_add(vty
, "ip route-source", argv
[idx_acl
]->arg
,
3524 RMAP_EVENT_FILTER_ADDED
);
3528 DEFUN (no_match_ip_route_source
,
3529 no_match_ip_route_source_cmd
,
3530 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
3534 "Match advertising source address of route\n"
3535 "IP access-list number\n"
3536 "IP access-list number (expanded range)\n"
3537 "IP standard access-list name\n")
3540 if (argc
<= idx_number
)
3541 return bgp_route_match_delete(vty
, "ip route-source", NULL
,
3542 RMAP_EVENT_FILTER_DELETED
);
3543 return bgp_route_match_delete(vty
, "ip route-source",
3544 argv
[idx_number
]->arg
,
3545 RMAP_EVENT_FILTER_DELETED
);
3549 DEFUN (match_ip_route_source_prefix_list
,
3550 match_ip_route_source_prefix_list_cmd
,
3551 "match ip route-source prefix-list WORD",
3554 "Match advertising source address of route\n"
3555 "Match entries of prefix-lists\n"
3556 "IP prefix-list name\n")
3559 return bgp_route_match_add(vty
, "ip route-source prefix-list",
3560 argv
[idx_word
]->arg
, RMAP_EVENT_PLIST_ADDED
);
3564 DEFUN (no_match_ip_route_source_prefix_list
,
3565 no_match_ip_route_source_prefix_list_cmd
,
3566 "no match ip route-source prefix-list [WORD]",
3570 "Match advertising source address of route\n"
3571 "Match entries of prefix-lists\n"
3572 "IP prefix-list name\n")
3575 if (argc
<= idx_word
)
3576 return bgp_route_match_delete(vty
,
3577 "ip route-source prefix-list",
3578 NULL
, RMAP_EVENT_PLIST_DELETED
);
3579 return bgp_route_match_delete(vty
, "ip route-source prefix-list",
3580 argv
[idx_word
]->arg
,
3581 RMAP_EVENT_PLIST_DELETED
);
3585 DEFUN (match_local_pref
,
3586 match_local_pref_cmd
,
3587 "match local-preference (0-4294967295)",
3589 "Match local-preference of route\n"
3593 return bgp_route_match_add(vty
, "local-preference",
3594 argv
[idx_number
]->arg
,
3595 RMAP_EVENT_MATCH_ADDED
);
3599 DEFUN (no_match_local_pref
,
3600 no_match_local_pref_cmd
,
3601 "no match local-preference [(0-4294967295)]",
3604 "Match local preference of route\n"
3605 "Local preference value\n")
3607 int idx_localpref
= 3;
3608 if (argc
<= idx_localpref
)
3609 return bgp_route_match_delete(vty
, "local-preference", NULL
,
3610 RMAP_EVENT_MATCH_DELETED
);
3611 return bgp_route_match_delete(vty
, "local-preference",
3612 argv
[idx_localpref
]->arg
,
3613 RMAP_EVENT_MATCH_DELETED
);
3617 DEFUN (match_community
,
3618 match_community_cmd
,
3619 "match community <(1-99)|(100-500)|WORD> [exact-match]",
3621 "Match BGP community list\n"
3622 "Community-list number (standard)\n"
3623 "Community-list number (expanded)\n"
3624 "Community-list name\n"
3625 "Do exact matching of communities\n")
3627 int idx_comm_list
= 2;
3632 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
3633 strlen(argv
[idx_comm_list
]->arg
)
3634 + strlen("exact-match") + 2);
3636 sprintf(argstr
, "%s exact-match", argv
[idx_comm_list
]->arg
);
3638 argstr
= argv
[idx_comm_list
]->arg
;
3640 ret
= bgp_route_match_add(vty
, "community", argstr
,
3641 RMAP_EVENT_CLIST_ADDED
);
3643 if (argstr
!= argv
[idx_comm_list
]->arg
)
3644 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
3649 DEFUN (no_match_community
,
3650 no_match_community_cmd
,
3651 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
3654 "Match BGP community list\n"
3655 "Community-list number (standard)\n"
3656 "Community-list number (expanded)\n"
3657 "Community-list name\n"
3658 "Do exact matching of communities\n")
3660 return bgp_route_match_delete(vty
, "community", NULL
,
3661 RMAP_EVENT_CLIST_DELETED
);
3664 DEFUN (match_lcommunity
,
3665 match_lcommunity_cmd
,
3666 "match large-community <(1-99)|(100-500)|WORD>",
3668 "Match BGP large community list\n"
3669 "Large Community-list number (standard)\n"
3670 "Large Community-list number (expanded)\n"
3671 "Large Community-list name\n")
3673 return bgp_route_match_add(vty
, "large-community", argv
[2]->arg
,
3674 RMAP_EVENT_LLIST_ADDED
);
3677 DEFUN (no_match_lcommunity
,
3678 no_match_lcommunity_cmd
,
3679 "no match large-community [<(1-99)|(100-500)|WORD>]",
3682 "Match BGP large community list\n"
3683 "Large Community-list number (standard)\n"
3684 "Large Community-list number (expanded)\n"
3685 "Large Community-list name\n")
3687 return bgp_route_match_delete(vty
, "large-community", NULL
,
3688 RMAP_EVENT_LLIST_DELETED
);
3691 DEFUN (match_ecommunity
,
3692 match_ecommunity_cmd
,
3693 "match extcommunity <(1-99)|(100-500)|WORD>",
3695 "Match BGP/VPN extended community list\n"
3696 "Extended community-list number (standard)\n"
3697 "Extended community-list number (expanded)\n"
3698 "Extended community-list name\n")
3700 int idx_comm_list
= 2;
3701 return bgp_route_match_add(vty
, "extcommunity",
3702 argv
[idx_comm_list
]->arg
,
3703 RMAP_EVENT_ECLIST_ADDED
);
3707 DEFUN (no_match_ecommunity
,
3708 no_match_ecommunity_cmd
,
3709 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
3712 "Match BGP/VPN extended community list\n"
3713 "Extended community-list number (standard)\n"
3714 "Extended community-list number (expanded)\n"
3715 "Extended community-list name\n")
3717 return bgp_route_match_delete(vty
, "extcommunity", NULL
,
3718 RMAP_EVENT_ECLIST_DELETED
);
3722 DEFUN (match_aspath
,
3724 "match as-path WORD",
3726 "Match BGP AS path list\n"
3727 "AS path access-list name\n")
3730 return bgp_route_match_add(vty
, "as-path", argv
[idx_word
]->arg
,
3731 RMAP_EVENT_ASLIST_ADDED
);
3735 DEFUN (no_match_aspath
,
3736 no_match_aspath_cmd
,
3737 "no match as-path [WORD]",
3740 "Match BGP AS path list\n"
3741 "AS path access-list name\n")
3743 return bgp_route_match_delete(vty
, "as-path", NULL
,
3744 RMAP_EVENT_ASLIST_DELETED
);
3748 DEFUN (match_origin
,
3750 "match origin <egp|igp|incomplete>",
3755 "unknown heritage\n")
3758 if (strncmp(argv
[idx_origin
]->arg
, "igp", 2) == 0)
3759 return bgp_route_match_add(vty
, "origin", "igp",
3760 RMAP_EVENT_MATCH_ADDED
);
3761 if (strncmp(argv
[idx_origin
]->arg
, "egp", 1) == 0)
3762 return bgp_route_match_add(vty
, "origin", "egp",
3763 RMAP_EVENT_MATCH_ADDED
);
3764 if (strncmp(argv
[idx_origin
]->arg
, "incomplete", 2) == 0)
3765 return bgp_route_match_add(vty
, "origin", "incomplete",
3766 RMAP_EVENT_MATCH_ADDED
);
3768 vty_out(vty
, "%% Invalid match origin type\n");
3769 return CMD_WARNING_CONFIG_FAILED
;
3773 DEFUN (no_match_origin
,
3774 no_match_origin_cmd
,
3775 "no match origin [<egp|igp|incomplete>]",
3781 "unknown heritage\n")
3783 return bgp_route_match_delete(vty
, "origin", NULL
,
3784 RMAP_EVENT_MATCH_DELETED
);
3787 DEFUN (set_ip_nexthop_peer
,
3788 set_ip_nexthop_peer_cmd
,
3789 "[no] set ip next-hop peer-address",
3793 "Next hop address\n"
3794 "Use peer address (for BGP only)\n")
3796 int (*func
)(struct vty
*, struct route_map_index
*, const char *,
3797 const char *) = strmatch(argv
[0]->text
, "no")
3798 ? generic_set_delete
3801 return func(vty
, VTY_GET_CONTEXT(route_map_index
), "ip next-hop",
3805 DEFUN (set_ip_nexthop_unchanged
,
3806 set_ip_nexthop_unchanged_cmd
,
3807 "[no] set ip next-hop unchanged",
3811 "Next hop address\n"
3812 "Don't modify existing Next hop address\n")
3814 int (*func
)(struct vty
*, struct route_map_index
*, const char *,
3815 const char *) = strmatch(argv
[0]->text
, "no")
3816 ? generic_set_delete
3819 return func(vty
, VTY_GET_CONTEXT(route_map_index
), "ip next-hop",
3824 DEFUN (set_local_pref
,
3826 "set local-preference (0-4294967295)",
3828 "BGP local preference path attribute\n"
3829 "Preference value\n")
3832 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3833 "local-preference", argv
[idx_number
]->arg
);
3837 DEFUN (no_set_local_pref
,
3838 no_set_local_pref_cmd
,
3839 "no set local-preference [(0-4294967295)]",
3842 "BGP local preference path attribute\n"
3843 "Preference value\n")
3845 int idx_localpref
= 3;
3846 if (argc
<= idx_localpref
)
3847 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3848 "local-preference", NULL
);
3849 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3850 "local-preference", argv
[idx_localpref
]->arg
);
3856 "set weight (0-4294967295)",
3858 "BGP weight for routing table\n"
3862 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
), "weight",
3863 argv
[idx_number
]->arg
);
3867 DEFUN (no_set_weight
,
3869 "no set weight [(0-4294967295)]",
3872 "BGP weight for routing table\n"
3876 if (argc
<= idx_weight
)
3877 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3879 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3880 "weight", argv
[idx_weight
]->arg
);
3883 DEFUN (set_label_index
,
3884 set_label_index_cmd
,
3885 "set label-index (0-1048560)",
3887 "Label index to associate with the prefix\n"
3888 "Label index value\n")
3891 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3892 "label-index", argv
[idx_number
]->arg
);
3895 DEFUN (no_set_label_index
,
3896 no_set_label_index_cmd
,
3897 "no set label-index [(0-1048560)]",
3900 "Label index to associate with the prefix\n"
3901 "Label index value\n")
3903 int idx_label_index
= 3;
3904 if (argc
<= idx_label_index
)
3905 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3906 "label-index", NULL
);
3907 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3908 "label-index", argv
[idx_label_index
]->arg
);
3911 DEFUN (set_aspath_prepend_asn
,
3912 set_aspath_prepend_asn_cmd
,
3913 "set as-path prepend (1-4294967295)...",
3915 "Transform BGP AS_PATH attribute\n"
3916 "Prepend to the as-path\n"
3923 str
= argv_concat(argv
, argc
, idx_asn
);
3924 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3925 "as-path prepend", str
);
3926 XFREE(MTYPE_TMP
, str
);
3931 DEFUN (set_aspath_prepend_lastas
,
3932 set_aspath_prepend_lastas_cmd
,
3933 "set as-path prepend last-as (1-10)",
3935 "Transform BGP AS_PATH attribute\n"
3936 "Prepend to the as-path\n"
3937 "Use the peer's AS-number\n"
3938 "Number of times to insert\n")
3940 return set_aspath_prepend_asn(self
, vty
, argc
, argv
);
3943 DEFUN (no_set_aspath_prepend
,
3944 no_set_aspath_prepend_cmd
,
3945 "no set as-path prepend [(1-4294967295)]",
3948 "Transform BGP AS_PATH attribute\n"
3949 "Prepend to the as-path\n"
3956 str
= argv_concat(argv
, argc
, idx_asn
);
3957 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3958 "as-path prepend", str
);
3959 XFREE(MTYPE_TMP
, str
);
3964 DEFUN (set_aspath_exclude
,
3965 set_aspath_exclude_cmd
,
3966 "set as-path exclude (1-4294967295)...",
3968 "Transform BGP AS-path attribute\n"
3969 "Exclude from the as-path\n"
3976 str
= argv_concat(argv
, argc
, idx_asn
);
3977 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
3978 "as-path exclude", str
);
3979 XFREE(MTYPE_TMP
, str
);
3983 DEFUN (no_set_aspath_exclude
,
3984 no_set_aspath_exclude_cmd
,
3985 "no set as-path exclude (1-4294967295)...",
3988 "Transform BGP AS_PATH attribute\n"
3989 "Exclude from the as-path\n"
3996 str
= argv_concat(argv
, argc
, idx_asn
);
3997 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
3998 "as-path exclude", str
);
3999 XFREE(MTYPE_TMP
, str
);
4004 DEFUN (set_community
,
4006 "set community AA:NN...",
4008 "BGP community attribute\n"
4016 struct community
*com
= NULL
;
4021 b
= buffer_new(1024);
4023 for (i
= idx_aa_nn
; i
< argc
; i
++) {
4024 if (strncmp(argv
[i
]->arg
, "additive", strlen(argv
[i
]->arg
))
4031 buffer_putc(b
, ' ');
4035 if (strncmp(argv
[i
]->arg
, "internet", strlen(argv
[i
]->arg
))
4037 buffer_putstr(b
, "internet");
4040 if (strncmp(argv
[i
]->arg
, "local-AS", strlen(argv
[i
]->arg
))
4042 buffer_putstr(b
, "local-AS");
4045 if (strncmp(argv
[i
]->arg
, "no-a", strlen("no-a")) == 0
4046 && strncmp(argv
[i
]->arg
, "no-advertise",
4047 strlen(argv
[i
]->arg
))
4049 buffer_putstr(b
, "no-advertise");
4052 if (strncmp(argv
[i
]->arg
, "no-e", strlen("no-e")) == 0
4053 && strncmp(argv
[i
]->arg
, "no-export", strlen(argv
[i
]->arg
))
4055 buffer_putstr(b
, "no-export");
4058 if (strncmp(argv
[i
]->arg
, "graceful-shutdown",
4059 strlen(argv
[i
]->arg
))
4061 buffer_putstr(b
, "graceful-shutdown");
4064 buffer_putstr(b
, argv
[i
]->arg
);
4066 buffer_putc(b
, '\0');
4068 /* Fetch result string then compile it to communities attribute. */
4069 str
= buffer_getstr(b
);
4073 com
= community_str2com(str
);
4074 XFREE(MTYPE_TMP
, str
);
4077 /* Can't compile user input into communities attribute. */
4079 vty_out(vty
, "%% Malformed communities attribute\n");
4080 return CMD_WARNING_CONFIG_FAILED
;
4083 /* Set communites attribute string. */
4084 str
= community_str(com
, false);
4087 argstr
= XCALLOC(MTYPE_TMP
,
4088 strlen(str
) + strlen(" additive") + 1);
4089 strcpy(argstr
, str
);
4090 strcpy(argstr
+ strlen(str
), " additive");
4091 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4092 "community", argstr
);
4093 XFREE(MTYPE_TMP
, argstr
);
4095 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4098 community_free(com
);
4103 DEFUN (set_community_none
,
4104 set_community_none_cmd
,
4105 "set community none",
4107 "BGP community attribute\n"
4108 "No community attribute\n")
4110 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4111 "community", "none");
4114 DEFUN (no_set_community
,
4115 no_set_community_cmd
,
4116 "no set community AA:NN...",
4119 "BGP community attribute\n"
4122 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4127 DEFUN (set_community_delete
,
4128 set_community_delete_cmd
,
4129 "set comm-list <(1-99)|(100-500)|WORD> delete",
4131 "set BGP community list (for deletion)\n"
4132 "Community-list number (standard)\n"
4133 "Community-list number (expanded)\n"
4134 "Community-list name\n"
4135 "Delete matching communities\n")
4137 int idx_comm_list
= 2;
4140 str
= XCALLOC(MTYPE_TMP
,
4141 strlen(argv
[idx_comm_list
]->arg
) + strlen(" delete") + 1);
4142 strcpy(str
, argv
[idx_comm_list
]->arg
);
4143 strcpy(str
+ strlen(argv
[idx_comm_list
]->arg
), " delete");
4145 generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
), "comm-list",
4148 XFREE(MTYPE_TMP
, str
);
4152 DEFUN (no_set_community_delete
,
4153 no_set_community_delete_cmd
,
4154 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
4157 "set BGP community list (for deletion)\n"
4158 "Community-list number (standard)\n"
4159 "Community-list number (expanded)\n"
4160 "Community-list name\n"
4161 "Delete matching communities\n")
4163 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4167 DEFUN (set_lcommunity
,
4169 "set large-community AA:BB:CC...",
4171 "BGP large community attribute\n"
4172 "Large Community number in aa:bb:cc format or additive\n")
4177 str
= argv_concat(argv
, argc
, 2);
4178 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4179 "large-community", str
);
4180 XFREE(MTYPE_TMP
, str
);
4185 DEFUN (set_lcommunity_none
,
4186 set_lcommunity_none_cmd
,
4187 "set large-community none",
4189 "BGP large community attribute\n"
4190 "No large community attribute\n")
4192 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4193 "large-community", "none");
4196 DEFUN (no_set_lcommunity
,
4197 no_set_lcommunity_cmd
,
4198 "no set large-community none",
4201 "BGP large community attribute\n"
4202 "No community attribute\n")
4204 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4205 "large-community", NULL
);
4208 DEFUN (no_set_lcommunity1
,
4209 no_set_lcommunity1_cmd
,
4210 "no set large-community AA:BB:CC...",
4213 "BGP large community attribute\n"
4214 "Large community in AA:BB:CC... format or additive\n")
4216 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4217 "large-community", NULL
);
4220 DEFUN (set_lcommunity_delete
,
4221 set_lcommunity_delete_cmd
,
4222 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4224 "set BGP large community list (for deletion)\n"
4225 "Large Community-list number (standard)\n"
4226 "Large Communitly-list number (expanded)\n"
4227 "Large Community-list name\n"
4228 "Delete matching large communities\n")
4232 str
= XCALLOC(MTYPE_TMP
, strlen(argv
[2]->arg
) + strlen(" delete") + 1);
4233 strcpy(str
, argv
[2]->arg
);
4234 strcpy(str
+ strlen(argv
[2]->arg
), " delete");
4236 generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4237 "large-comm-list", str
);
4239 XFREE(MTYPE_TMP
, str
);
4243 DEFUN (no_set_lcommunity_delete
,
4244 no_set_lcommunity_delete_cmd
,
4245 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
4248 "set BGP large community list (for deletion)\n"
4249 "Large Community-list number (standard)\n"
4250 "Large Communitly-list number (expanded)\n"
4251 "Large Community-list name\n"
4252 "Delete matching large communities\n")
4254 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4255 "large-comm-list", NULL
);
4258 DEFUN (set_ecommunity_rt
,
4259 set_ecommunity_rt_cmd
,
4260 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4262 "BGP extended community attribute\n"
4263 "Route Target extended community\n"
4264 "VPN extended community\n")
4270 str
= argv_concat(argv
, argc
, idx_asn_nn
);
4271 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4272 "extcommunity rt", str
);
4273 XFREE(MTYPE_TMP
, str
);
4278 DEFUN (no_set_ecommunity_rt
,
4279 no_set_ecommunity_rt_cmd
,
4280 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4283 "BGP extended community attribute\n"
4284 "Route Target extended community\n"
4285 "VPN extended community\n")
4287 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4288 "extcommunity rt", NULL
);
4292 DEFUN (set_ecommunity_soo
,
4293 set_ecommunity_soo_cmd
,
4294 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4296 "BGP extended community attribute\n"
4297 "Site-of-Origin extended community\n"
4298 "VPN extended community\n")
4304 str
= argv_concat(argv
, argc
, idx_asn_nn
);
4305 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4306 "extcommunity soo", str
);
4307 XFREE(MTYPE_TMP
, str
);
4312 DEFUN (no_set_ecommunity_soo
,
4313 no_set_ecommunity_soo_cmd
,
4314 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4317 "BGP extended community attribute\n"
4318 "Site-of-Origin extended community\n"
4319 "VPN extended community\n")
4321 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4322 "extcommunity soo", NULL
);
4328 "set origin <egp|igp|incomplete>",
4333 "unknown heritage\n")
4336 if (strncmp(argv
[idx_origin
]->arg
, "igp", 2) == 0)
4337 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4339 if (strncmp(argv
[idx_origin
]->arg
, "egp", 1) == 0)
4340 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4342 if (strncmp(argv
[idx_origin
]->arg
, "incomplete", 2) == 0)
4343 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4344 "origin", "incomplete");
4346 vty_out(vty
, "%% Invalid set origin type\n");
4347 return CMD_WARNING_CONFIG_FAILED
;
4351 DEFUN (no_set_origin
,
4353 "no set origin [<egp|igp|incomplete>]",
4359 "unknown heritage\n")
4361 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4366 DEFUN (set_atomic_aggregate
,
4367 set_atomic_aggregate_cmd
,
4368 "set atomic-aggregate",
4370 "BGP atomic aggregate attribute\n" )
4372 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4373 "atomic-aggregate", NULL
);
4376 DEFUN (no_set_atomic_aggregate
,
4377 no_set_atomic_aggregate_cmd
,
4378 "no set atomic-aggregate",
4381 "BGP atomic aggregate attribute\n" )
4383 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4384 "atomic-aggregate", NULL
);
4387 DEFUN (set_aggregator_as
,
4388 set_aggregator_as_cmd
,
4389 "set aggregator as (1-4294967295) A.B.C.D",
4391 "BGP aggregator attribute\n"
4392 "AS number of aggregator\n"
4394 "IP address of aggregator\n")
4399 struct in_addr address
;
4402 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &address
);
4404 vty_out(vty
, "Aggregator IP address is invalid\n");
4405 return CMD_WARNING_CONFIG_FAILED
;
4408 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
4409 strlen(argv
[idx_number
]->arg
)
4410 + strlen(argv
[idx_ipv4
]->arg
) + 2);
4412 sprintf(argstr
, "%s %s", argv
[idx_number
]->arg
, argv
[idx_ipv4
]->arg
);
4414 ret
= generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4415 "aggregator as", argstr
);
4417 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
4423 DEFUN (no_set_aggregator_as
,
4424 no_set_aggregator_as_cmd
,
4425 "no set aggregator as [(1-4294967295) A.B.C.D]",
4428 "BGP aggregator attribute\n"
4429 "AS number of aggregator\n"
4431 "IP address of aggregator\n")
4436 struct in_addr address
;
4439 if (argc
<= idx_asn
)
4440 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4441 "aggregator as", NULL
);
4443 ret
= inet_aton(argv
[idx_ip
]->arg
, &address
);
4445 vty_out(vty
, "Aggregator IP address is invalid\n");
4446 return CMD_WARNING_CONFIG_FAILED
;
4449 argstr
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
,
4450 strlen(argv
[idx_asn
]->arg
) + strlen(argv
[idx_ip
]->arg
)
4453 sprintf(argstr
, "%s %s", argv
[idx_asn
]->arg
, argv
[idx_ip
]->arg
);
4455 ret
= generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4456 "aggregator as", argstr
);
4458 XFREE(MTYPE_ROUTE_MAP_COMPILED
, argstr
);
4463 DEFUN (match_ipv6_next_hop
,
4464 match_ipv6_next_hop_cmd
,
4465 "match ipv6 next-hop X:X::X:X",
4468 "Match IPv6 next-hop address of route\n"
4469 "IPv6 address of next hop\n")
4472 return bgp_route_match_add(vty
, "ipv6 next-hop", argv
[idx_ipv6
]->arg
,
4473 RMAP_EVENT_MATCH_ADDED
);
4476 DEFUN (no_match_ipv6_next_hop
,
4477 no_match_ipv6_next_hop_cmd
,
4478 "no match ipv6 next-hop X:X::X:X",
4482 "Match IPv6 next-hop address of route\n"
4483 "IPv6 address of next hop\n")
4486 return bgp_route_match_delete(vty
, "ipv6 next-hop", argv
[idx_ipv6
]->arg
,
4487 RMAP_EVENT_MATCH_DELETED
);
4491 DEFUN (set_ipv6_nexthop_peer
,
4492 set_ipv6_nexthop_peer_cmd
,
4493 "set ipv6 next-hop peer-address",
4496 "Next hop address\n"
4497 "Use peer address (for BGP only)\n")
4499 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4500 "ipv6 next-hop peer-address", NULL
);
4503 DEFUN (no_set_ipv6_nexthop_peer
,
4504 no_set_ipv6_nexthop_peer_cmd
,
4505 "no set ipv6 next-hop peer-address",
4509 "IPv6 next-hop address\n"
4510 "Use peer address (for BGP only)\n")
4512 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4513 "ipv6 next-hop peer-address", NULL
);
4516 DEFUN (set_ipv6_nexthop_prefer_global
,
4517 set_ipv6_nexthop_prefer_global_cmd
,
4518 "set ipv6 next-hop prefer-global",
4521 "IPv6 next-hop address\n"
4522 "Prefer global over link-local if both exist\n")
4524 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4525 "ipv6 next-hop prefer-global", NULL
);
4529 DEFUN (no_set_ipv6_nexthop_prefer_global
,
4530 no_set_ipv6_nexthop_prefer_global_cmd
,
4531 "no set ipv6 next-hop prefer-global",
4535 "IPv6 next-hop address\n"
4536 "Prefer global over link-local if both exist\n")
4538 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4539 "ipv6 next-hop prefer-global", NULL
);
4542 DEFUN (set_ipv6_nexthop_global
,
4543 set_ipv6_nexthop_global_cmd
,
4544 "set ipv6 next-hop global X:X::X:X",
4547 "IPv6 next-hop address\n"
4548 "IPv6 global address\n"
4549 "IPv6 address of next hop\n")
4552 struct in6_addr addr
;
4555 ret
= inet_pton(AF_INET6
, argv
[idx_ipv6
]->arg
, &addr
);
4557 vty_out(vty
, "%% Malformed nexthop address\n");
4558 return CMD_WARNING_CONFIG_FAILED
;
4560 if (IN6_IS_ADDR_UNSPECIFIED(&addr
) || IN6_IS_ADDR_LOOPBACK(&addr
)
4561 || IN6_IS_ADDR_MULTICAST(&addr
) || IN6_IS_ADDR_LINKLOCAL(&addr
)) {
4562 vty_out(vty
, "%% Invalid global nexthop address\n");
4563 return CMD_WARNING_CONFIG_FAILED
;
4566 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4567 "ipv6 next-hop global", argv
[idx_ipv6
]->arg
);
4571 DEFUN (no_set_ipv6_nexthop_global
,
4572 no_set_ipv6_nexthop_global_cmd
,
4573 "no set ipv6 next-hop global X:X::X:X",
4577 "IPv6 next-hop address\n"
4578 "IPv6 global address\n"
4579 "IPv6 address of next hop\n")
4582 if (argc
<= idx_ipv6
)
4583 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4584 "ipv6 next-hop global", NULL
);
4585 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4586 "ipv6 next-hop global", argv
[idx_ipv6
]->arg
);
4589 #ifdef KEEP_OLD_VPN_COMMANDS
4590 DEFUN (set_vpn_nexthop
,
4591 set_vpn_nexthop_cmd
,
4592 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4594 "VPNv4 information\n"
4595 "VPN next-hop address\n"
4596 "IP address of next hop\n"
4597 "VPNv6 information\n"
4598 "VPN next-hop address\n"
4599 "IPv6 address of next hop\n")
4605 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
4607 return generic_set_add(
4608 vty
, VTY_GET_CONTEXT(route_map_index
),
4609 "ipv4 vpn next-hop", argv
[idx_ip
]->arg
);
4611 return generic_set_add(
4612 vty
, VTY_GET_CONTEXT(route_map_index
),
4613 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4618 DEFUN (no_set_vpn_nexthop
,
4619 no_set_vpn_nexthop_cmd
,
4620 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4623 "VPNv4 information\n"
4624 "VPN next-hop address\n"
4625 "IP address of next hop\n"
4626 "VPNv6 information\n"
4627 "VPN next-hop address\n"
4628 "IPv6 address of next hop\n")
4638 arg
= argv
[idx_ip
]->arg
;
4639 if (argv_find_and_parse_vpnvx(argv
, argc
, &idx
, &afi
)) {
4641 return generic_set_delete(
4642 vty
, VTY_GET_CONTEXT(route_map_index
),
4643 "ipv4 vpn next-hop", arg
);
4645 return generic_set_delete(
4646 vty
, VTY_GET_CONTEXT(route_map_index
),
4647 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4651 #endif /* KEEP_OLD_VPN_COMMANDS */
4653 DEFUN (set_ipx_vpn_nexthop
,
4654 set_ipx_vpn_nexthop_cmd
,
4655 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
4657 "IPv4 information\n"
4658 "IPv6 information\n"
4660 "VPN next-hop address\n"
4661 "IP address of next hop\n"
4662 "IPv6 address of next hop\n")
4668 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
4670 return generic_set_add(
4671 vty
, VTY_GET_CONTEXT(route_map_index
),
4672 "ipv4 vpn next-hop", argv
[idx_ip
]->arg
);
4674 return generic_set_add(
4675 vty
, VTY_GET_CONTEXT(route_map_index
),
4676 "ipv6 vpn next-hop", argv
[idx_ip
]->arg
);
4681 DEFUN (no_set_ipx_vpn_nexthop
,
4682 no_set_ipx_vpn_nexthop_cmd
,
4683 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
4686 "IPv4 information\n"
4687 "IPv6 information\n"
4689 "VPN next-hop address\n"
4690 "IP address of next hop\n"
4691 "IPv6 address of next hop\n")
4701 arg
= argv
[idx_ip
]->arg
;
4702 if (argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
4704 return generic_set_delete(
4705 vty
, VTY_GET_CONTEXT(route_map_index
),
4706 "ipv4 vpn next-hop", arg
);
4708 return generic_set_delete(
4709 vty
, VTY_GET_CONTEXT(route_map_index
),
4710 "ipv6 vpn next-hop", arg
);
4715 DEFUN (set_originator_id
,
4716 set_originator_id_cmd
,
4717 "set originator-id A.B.C.D",
4719 "BGP originator ID attribute\n"
4720 "IP address of originator\n")
4723 return generic_set_add(vty
, VTY_GET_CONTEXT(route_map_index
),
4724 "originator-id", argv
[idx_ipv4
]->arg
);
4728 DEFUN (no_set_originator_id
,
4729 no_set_originator_id_cmd
,
4730 "no set originator-id [A.B.C.D]",
4733 "BGP originator ID attribute\n"
4734 "IP address of originator\n")
4738 argv_find(argv
, argc
, "A.B.C.D", &idx
) ? argv
[idx
]->arg
: NULL
;
4740 return generic_set_delete(vty
, VTY_GET_CONTEXT(route_map_index
),
4741 "originator-id", arg
);
4745 /* Initialization of route map. */
4746 void bgp_route_map_init(void)
4750 route_map_add_hook(bgp_route_map_add
);
4751 route_map_delete_hook(bgp_route_map_delete
);
4752 route_map_event_hook(bgp_route_map_event
);
4754 route_map_match_interface_hook(generic_match_add
);
4755 route_map_no_match_interface_hook(generic_match_delete
);
4757 route_map_match_ip_address_hook(generic_match_add
);
4758 route_map_no_match_ip_address_hook(generic_match_delete
);
4760 route_map_match_ip_address_prefix_list_hook(generic_match_add
);
4761 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete
);
4763 route_map_match_ip_next_hop_hook(generic_match_add
);
4764 route_map_no_match_ip_next_hop_hook(generic_match_delete
);
4766 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add
);
4767 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete
);
4769 route_map_match_ipv6_address_hook(generic_match_add
);
4770 route_map_no_match_ipv6_address_hook(generic_match_delete
);
4772 route_map_match_ipv6_address_prefix_list_hook(generic_match_add
);
4773 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete
);
4775 route_map_match_metric_hook(generic_match_add
);
4776 route_map_no_match_metric_hook(generic_match_delete
);
4778 route_map_match_tag_hook(generic_match_add
);
4779 route_map_no_match_tag_hook(generic_match_delete
);
4781 route_map_set_ip_nexthop_hook(generic_set_add
);
4782 route_map_no_set_ip_nexthop_hook(generic_set_delete
);
4784 route_map_set_ipv6_nexthop_local_hook(generic_set_add
);
4785 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete
);
4787 route_map_set_metric_hook(generic_set_add
);
4788 route_map_no_set_metric_hook(generic_set_delete
);
4790 route_map_set_tag_hook(generic_set_add
);
4791 route_map_no_set_tag_hook(generic_set_delete
);
4793 route_map_install_match(&route_match_peer_cmd
);
4794 route_map_install_match(&route_match_local_pref_cmd
);
4795 #if defined(HAVE_LUA)
4796 route_map_install_match(&route_match_command_cmd
);
4798 route_map_install_match(&route_match_ip_address_cmd
);
4799 route_map_install_match(&route_match_ip_next_hop_cmd
);
4800 route_map_install_match(&route_match_ip_route_source_cmd
);
4801 route_map_install_match(&route_match_ip_address_prefix_list_cmd
);
4802 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd
);
4803 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd
);
4804 route_map_install_match(&route_match_aspath_cmd
);
4805 route_map_install_match(&route_match_community_cmd
);
4806 route_map_install_match(&route_match_lcommunity_cmd
);
4807 route_map_install_match(&route_match_ecommunity_cmd
);
4808 route_map_install_match(&route_match_local_pref_cmd
);
4809 route_map_install_match(&route_match_metric_cmd
);
4810 route_map_install_match(&route_match_origin_cmd
);
4811 route_map_install_match(&route_match_probability_cmd
);
4812 route_map_install_match(&route_match_interface_cmd
);
4813 route_map_install_match(&route_match_tag_cmd
);
4814 route_map_install_match(&route_match_mac_address_cmd
);
4815 route_map_install_match(&route_match_evpn_vni_cmd
);
4816 route_map_install_match(&route_match_evpn_route_type_cmd
);
4817 route_map_install_match(&route_match_evpn_default_route_cmd
);
4819 route_map_install_set(&route_set_ip_nexthop_cmd
);
4820 route_map_install_set(&route_set_local_pref_cmd
);
4821 route_map_install_set(&route_set_weight_cmd
);
4822 route_map_install_set(&route_set_label_index_cmd
);
4823 route_map_install_set(&route_set_metric_cmd
);
4824 route_map_install_set(&route_set_aspath_prepend_cmd
);
4825 route_map_install_set(&route_set_aspath_exclude_cmd
);
4826 route_map_install_set(&route_set_origin_cmd
);
4827 route_map_install_set(&route_set_atomic_aggregate_cmd
);
4828 route_map_install_set(&route_set_aggregator_as_cmd
);
4829 route_map_install_set(&route_set_community_cmd
);
4830 route_map_install_set(&route_set_community_delete_cmd
);
4831 route_map_install_set(&route_set_lcommunity_cmd
);
4832 route_map_install_set(&route_set_lcommunity_delete_cmd
);
4833 route_map_install_set(&route_set_vpnv4_nexthop_cmd
);
4834 route_map_install_set(&route_set_vpnv6_nexthop_cmd
);
4835 route_map_install_set(&route_set_originator_id_cmd
);
4836 route_map_install_set(&route_set_ecommunity_rt_cmd
);
4837 route_map_install_set(&route_set_ecommunity_soo_cmd
);
4838 route_map_install_set(&route_set_tag_cmd
);
4839 route_map_install_set(&route_set_label_index_cmd
);
4841 install_element(RMAP_NODE
, &match_peer_cmd
);
4842 install_element(RMAP_NODE
, &match_peer_local_cmd
);
4843 install_element(RMAP_NODE
, &no_match_peer_cmd
);
4844 install_element(RMAP_NODE
, &match_ip_route_source_cmd
);
4845 install_element(RMAP_NODE
, &no_match_ip_route_source_cmd
);
4846 install_element(RMAP_NODE
, &match_ip_route_source_prefix_list_cmd
);
4847 install_element(RMAP_NODE
, &no_match_ip_route_source_prefix_list_cmd
);
4848 install_element(RMAP_NODE
, &match_mac_address_cmd
);
4849 install_element(RMAP_NODE
, &no_match_mac_address_cmd
);
4850 install_element(RMAP_NODE
, &match_evpn_vni_cmd
);
4851 install_element(RMAP_NODE
, &no_match_evpn_vni_cmd
);
4852 install_element(RMAP_NODE
, &match_evpn_route_type_cmd
);
4853 install_element(RMAP_NODE
, &no_match_evpn_route_type_cmd
);
4854 install_element(RMAP_NODE
, &match_evpn_default_route_cmd
);
4855 install_element(RMAP_NODE
, &no_match_evpn_default_route_cmd
);
4857 install_element(RMAP_NODE
, &match_aspath_cmd
);
4858 install_element(RMAP_NODE
, &no_match_aspath_cmd
);
4859 install_element(RMAP_NODE
, &match_local_pref_cmd
);
4860 install_element(RMAP_NODE
, &no_match_local_pref_cmd
);
4861 install_element(RMAP_NODE
, &match_community_cmd
);
4862 install_element(RMAP_NODE
, &no_match_community_cmd
);
4863 install_element(RMAP_NODE
, &match_lcommunity_cmd
);
4864 install_element(RMAP_NODE
, &no_match_lcommunity_cmd
);
4865 install_element(RMAP_NODE
, &match_ecommunity_cmd
);
4866 install_element(RMAP_NODE
, &no_match_ecommunity_cmd
);
4867 install_element(RMAP_NODE
, &match_origin_cmd
);
4868 install_element(RMAP_NODE
, &no_match_origin_cmd
);
4869 install_element(RMAP_NODE
, &match_probability_cmd
);
4870 install_element(RMAP_NODE
, &no_match_probability_cmd
);
4872 install_element(RMAP_NODE
, &set_ip_nexthop_peer_cmd
);
4873 install_element(RMAP_NODE
, &set_ip_nexthop_unchanged_cmd
);
4874 install_element(RMAP_NODE
, &set_local_pref_cmd
);
4875 install_element(RMAP_NODE
, &no_set_local_pref_cmd
);
4876 install_element(RMAP_NODE
, &set_weight_cmd
);
4877 install_element(RMAP_NODE
, &set_label_index_cmd
);
4878 install_element(RMAP_NODE
, &no_set_weight_cmd
);
4879 install_element(RMAP_NODE
, &no_set_label_index_cmd
);
4880 install_element(RMAP_NODE
, &set_aspath_prepend_asn_cmd
);
4881 install_element(RMAP_NODE
, &set_aspath_prepend_lastas_cmd
);
4882 install_element(RMAP_NODE
, &set_aspath_exclude_cmd
);
4883 install_element(RMAP_NODE
, &no_set_aspath_prepend_cmd
);
4884 install_element(RMAP_NODE
, &no_set_aspath_exclude_cmd
);
4885 install_element(RMAP_NODE
, &set_origin_cmd
);
4886 install_element(RMAP_NODE
, &no_set_origin_cmd
);
4887 install_element(RMAP_NODE
, &set_atomic_aggregate_cmd
);
4888 install_element(RMAP_NODE
, &no_set_atomic_aggregate_cmd
);
4889 install_element(RMAP_NODE
, &set_aggregator_as_cmd
);
4890 install_element(RMAP_NODE
, &no_set_aggregator_as_cmd
);
4891 install_element(RMAP_NODE
, &set_community_cmd
);
4892 install_element(RMAP_NODE
, &set_community_none_cmd
);
4893 install_element(RMAP_NODE
, &no_set_community_cmd
);
4894 install_element(RMAP_NODE
, &set_community_delete_cmd
);
4895 install_element(RMAP_NODE
, &no_set_community_delete_cmd
);
4896 install_element(RMAP_NODE
, &set_lcommunity_cmd
);
4897 install_element(RMAP_NODE
, &set_lcommunity_none_cmd
);
4898 install_element(RMAP_NODE
, &no_set_lcommunity_cmd
);
4899 install_element(RMAP_NODE
, &no_set_lcommunity1_cmd
);
4900 install_element(RMAP_NODE
, &set_lcommunity_delete_cmd
);
4901 install_element(RMAP_NODE
, &no_set_lcommunity_delete_cmd
);
4902 install_element(RMAP_NODE
, &set_ecommunity_rt_cmd
);
4903 install_element(RMAP_NODE
, &no_set_ecommunity_rt_cmd
);
4904 install_element(RMAP_NODE
, &set_ecommunity_soo_cmd
);
4905 install_element(RMAP_NODE
, &no_set_ecommunity_soo_cmd
);
4906 #ifdef KEEP_OLD_VPN_COMMANDS
4907 install_element(RMAP_NODE
, &set_vpn_nexthop_cmd
);
4908 install_element(RMAP_NODE
, &no_set_vpn_nexthop_cmd
);
4909 #endif /* KEEP_OLD_VPN_COMMANDS */
4910 install_element(RMAP_NODE
, &set_ipx_vpn_nexthop_cmd
);
4911 install_element(RMAP_NODE
, &no_set_ipx_vpn_nexthop_cmd
);
4912 install_element(RMAP_NODE
, &set_originator_id_cmd
);
4913 install_element(RMAP_NODE
, &no_set_originator_id_cmd
);
4915 route_map_install_match(&route_match_ipv6_address_cmd
);
4916 route_map_install_match(&route_match_ipv6_next_hop_cmd
);
4917 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd
);
4918 route_map_install_set(&route_set_ipv6_nexthop_global_cmd
);
4919 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd
);
4920 route_map_install_set(&route_set_ipv6_nexthop_local_cmd
);
4921 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd
);
4923 install_element(RMAP_NODE
, &match_ipv6_next_hop_cmd
);
4924 install_element(RMAP_NODE
, &no_match_ipv6_next_hop_cmd
);
4925 install_element(RMAP_NODE
, &set_ipv6_nexthop_global_cmd
);
4926 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_global_cmd
);
4927 install_element(RMAP_NODE
, &set_ipv6_nexthop_prefer_global_cmd
);
4928 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_prefer_global_cmd
);
4929 install_element(RMAP_NODE
, &set_ipv6_nexthop_peer_cmd
);
4930 install_element(RMAP_NODE
, &no_set_ipv6_nexthop_peer_cmd
);
4931 #if defined(HAVE_LUA)
4932 install_element(RMAP_NODE
, &match_command_cmd
);
4933 install_element(RMAP_NODE
, &no_match_command_cmd
);
4937 void bgp_route_map_terminate(void)
4939 /* ToDo: Cleanup all the used memory */