2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>

(at Technical University of Madrid as part of Euro6ix Project)

        Enhanced Route Server functionality and Route-Maps:

        * bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
        support rs-clients. A 'struct bgp_table *rib' has been added to the
        first (to mantain a separated RIB for each rs-client) and two new
        route-maps have been added to the last (for import/export policies).
        Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
        PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.

        * bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
        order to consider the new fields included in 'struct peer' for
        supporting rs-clients, i.e. the import/export route-maps and the
        'struct bgp_table'.

        * bgpd/bgp_route.{ch}: Modified several functions related with
        receiving/sending announces in order to support the new Route Server
        capabilities.
        Function 'bgp_process' has been reorganized, creating an auxiliar
        function for best path selection ('bgp_best_selection').
        Modified 'bgp_show' and 'bgp_show_route' for displaying information
        about any RIB (and not only the main bgp RIB).
        Added commands for displaying information about RS-clients RIBs:
        'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
        (A.B.C.D|X:X::X:X) X:X::X:X/M', etc

        * bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
        new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
        and 'void *owner' which points to 'struct bgp' or 'struct peer' which
        owns the table.
        When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.

        * bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
        'no neighbor ... route-server-client' now not only set/unset the flag
        PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
        bgp_table' of the peer. Special actions are taken for peer_groups.
        Command 'neighbor ... route-map WORD (in|out)' now also supports two
        new kinds of route-map: 'import' and 'export'.
        Added commands 'clear bgp * rsclient', etc. These commands allow a new
        kind of soft_reconfig which affects only the RIB of the specified
        RS-client.
        Added commands 'show bgp rsclient summary', etc which display a
        summary of the rs-clients configured for the corresponding address
        family.

        * bgpd/bgp_routemap.c: A new match statement is available,
        'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
        import/export route-maps, and it matches when the peer who announces
        (when used in an import route-map) or is going to receive (when used
        in an export route-map) the route is the same than the one specified
        in the statement.
        For peer-groups the statement matches if the specified peer is member
        of the peer-group.
        A special version of the command, 'match peer local', matches with
        routes originated by the Route Server (defined with 'network ...',
        redistributed routes and default-originate).

        * lib/routemap.{ch}: Added a new clause 'call NAME' for use in
        route-maps. It jumps into the specified route-map and when it returns
        the first route-map ends if the called RM returns DENY_MATCH, or
        continues in other case.
This commit is contained in:
paul 2004-09-13 05:12:46 +00:00
parent 0e82d0e120
commit fee0f4c629
12 changed files with 2666 additions and 184 deletions

View file

@ -1,3 +1,67 @@
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-08-31 Greg Troxel <gdt@poblano.ir.bbn.com>
* Makefile.am: make m4 as subdir, rather the EXTRA_DISTing it

View file

@ -1365,8 +1365,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
if (peer_sort (peer) == BGP_PEER_EBGP
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
|| attr->aspath->length == 0)
&& ! (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
{
aspath = aspath_dup (attr->aspath);

File diff suppressed because it is too large Load diff

View file

@ -109,10 +109,15 @@ struct bgp_static
#define FILTER_LIST_OUT_NAME(F) ((F)->aslist[FILTER_OUT].name)
#define FILTER_LIST_OUT(F) ((F)->aslist[FILTER_OUT].aslist)
#define ROUTE_MAP_IN_NAME(F) ((F)->map[FILTER_IN].name)
#define ROUTE_MAP_IN(F) ((F)->map[FILTER_IN].map)
#define ROUTE_MAP_OUT_NAME(F) ((F)->map[FILTER_OUT].name)
#define ROUTE_MAP_OUT(F) ((F)->map[FILTER_OUT].map)
#define ROUTE_MAP_IN_NAME(F) ((F)->map[RMAP_IN].name)
#define ROUTE_MAP_IN(F) ((F)->map[RMAP_IN].map)
#define ROUTE_MAP_OUT_NAME(F) ((F)->map[RMAP_OUT].name)
#define ROUTE_MAP_OUT(F) ((F)->map[RMAP_OUT].map)
#define ROUTE_MAP_IMPORT_NAME(F) ((F)->map[RMAP_IMPORT].name)
#define ROUTE_MAP_IMPORT(F) ((F)->map[RMAP_IMPORT].map)
#define ROUTE_MAP_EXPORT_NAME(F) ((F)->map[RMAP_EXPORT].name)
#define ROUTE_MAP_EXPORT(F) ((F)->map[RMAP_EXPORT].map)
#define UNSUPPRESS_MAP_NAME(F) ((F)->usmap.name)
#define UNSUPPRESS_MAP(F) ((F)->usmap.map)
@ -124,6 +129,8 @@ void bgp_announce_route (struct peer *, afi_t, safi_t);
void bgp_announce_route_all (struct peer *);
void bgp_default_originate (struct peer *, afi_t, safi_t, int);
void bgp_soft_reconfig_in (struct peer *, afi_t, safi_t);
void bgp_soft_reconfig_rsclient (struct peer *, afi_t, safi_t);
void bgp_check_local_routes_rsclient (struct peer *rsclient, afi_t afi, safi_t safi);
void bgp_clear_route (struct peer *, afi_t, safi_t);
void bgp_clear_route_all (struct peer *);
void bgp_clear_adj_in (struct peer *, afi_t, safi_t);

View file

@ -95,6 +95,103 @@ o Local extention
*/
/* 'match peer (A.B.C.D|X:X::X:X)' */
/* Compares the peer specified in the 'match peer' clause with the peer
received in bgp_info->peer. If it is the same, or if the peer structure
received is a peer_group containing it, returns RMAP_MATCH. */
route_map_result_t
route_match_peer (void *rule, struct prefix *prefix, route_map_object_t type,
void *object)
{
union sockunion *su;
union sockunion *su2;
struct peer_group *group;
struct peer *peer;
struct listnode *nn;
if (type == RMAP_BGP)
{
su = rule;
peer = ((struct bgp_info *) object)->peer;
if ( ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT) &&
! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_EXPORT) )
return RMAP_NOMATCH;
/* If su='0.0.0.0' (command 'match peer local'), and it's a NETWORK,
REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH */
su2 = sockunion_str2su ("0.0.0.0");
if ( sockunion_same (su, su2) )
{
if ( CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_NETWORK) ||
CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE) ||
CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
{
XFREE (MTYPE_SOCKUNION, su2);
return RMAP_MATCH;
}
else
return RMAP_NOMATCH;
}
XFREE (MTYPE_SOCKUNION, su2);
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
if (sockunion_same (su, &peer->su))
return RMAP_MATCH;
return RMAP_NOMATCH;
}
else
{
group = peer->group;
LIST_LOOP (group->peer, peer, nn)
{
if (sockunion_same (su, &peer->su))
return RMAP_MATCH;
return RMAP_NOMATCH;
}
}
}
return RMAP_NOMATCH;
}
void *
route_match_peer_compile (char *arg)
{
union sockunion *su;
int ret;
su = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union sockunion));
ret = str2sockunion ( (arg)? arg : "0.0.0.0", su);
if (ret < 0) {
XFREE (MTYPE_ROUTE_MAP_COMPILED, su);
return NULL;
}
return su;
}
/* Free route map's compiled `ip address' value. */
void
route_match_peer_free (void *rule)
{
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
}
/* Route map commands for ip address matching. */
struct route_map_rule_cmd route_match_peer_cmd =
{
"peer",
route_match_peer,
route_match_peer_compile,
route_match_peer_free
};
/* `match ip address IP_ACCESS_LIST' */
/* Match function should return 1 if match is success else return
@ -643,7 +740,8 @@ route_set_ip_nexthop (void *rule, struct prefix *prefix,
if (rins->peer_address)
{
if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN)
if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
&& peer->su_remote
&& sockunion_family (peer->su_remote) == AF_INET)
{
@ -1974,7 +2072,7 @@ bgp_route_map_update (char *unused)
{
filter = &peer->filter[afi][safi];
for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
{
if (filter->map[direct].name)
filter->map[direct].map =
@ -1996,7 +2094,7 @@ bgp_route_map_update (char *unused)
{
filter = &group->conf->filter[afi][safi];
for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
{
if (filter->map[direct].name)
filter->map[direct].map =
@ -2064,6 +2162,57 @@ bgp_route_map_update (char *unused)
}
}
DEFUN (match_peer,
match_peer_cmd,
"match peer (A.B.C.D|X:X::X:X)",
MATCH_STR
"Match peer address\n"
"IPv6 address of peer\n"
"IP address of peer\n")
{
return bgp_route_match_add (vty, vty->index, "peer", argv[0]);
}
DEFUN (match_peer_local,
match_peer_local_cmd,
"match peer local",
MATCH_STR
"Match peer address\n"
"Static or Redistributed routes\n")
{
return bgp_route_match_add (vty, vty->index, "peer", NULL);
}
DEFUN (no_match_peer,
no_match_peer_cmd,
"no match peer",
NO_STR
MATCH_STR
"Match peer address\n")
{
if (argc == 0)
return bgp_route_match_delete (vty, vty->index, "peer", NULL);
return bgp_route_match_delete (vty, vty->index, "peer", argv[0]);
}
ALIAS (no_match_peer,
no_match_peer_val_cmd,
"no match peer (A.B.C.D|X:X::X:X)",
NO_STR
MATCH_STR
"Match peer address\n"
"IPv6 address of peer\n"
"IP address of peer\n")
ALIAS (no_match_peer,
no_match_peer_local_cmd,
"no match peer local",
NO_STR
MATCH_STR
"Match peer address\n"
"Static or Redistributed routes\n")
DEFUN (match_ip_address,
match_ip_address_cmd,
"match ip address (<1-199>|<1300-2699>|WORD)",
@ -3239,6 +3388,7 @@ bgp_route_map_init ()
route_map_add_hook (bgp_route_map_update);
route_map_delete_hook (bgp_route_map_update);
route_map_install_match (&route_match_peer_cmd);
route_map_install_match (&route_match_ip_address_cmd);
route_map_install_match (&route_match_ip_next_hop_cmd);
route_map_install_match (&route_match_ip_address_prefix_list_cmd);
@ -3264,6 +3414,11 @@ bgp_route_map_init ()
route_map_install_set (&route_set_ecommunity_rt_cmd);
route_map_install_set (&route_set_ecommunity_soo_cmd);
install_element (RMAP_NODE, &match_peer_cmd);
install_element (RMAP_NODE, &match_peer_local_cmd);
install_element (RMAP_NODE, &no_match_peer_cmd);
install_element (RMAP_NODE, &no_match_peer_val_cmd);
install_element (RMAP_NODE, &no_match_peer_local_cmd);
install_element (RMAP_NODE, &match_ip_address_cmd);
install_element (RMAP_NODE, &no_match_ip_address_cmd);
install_element (RMAP_NODE, &no_match_ip_address_val_cmd);

View file

@ -38,6 +38,9 @@ bgp_table_init (void)
rt = XMALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
memset (rt, 0, sizeof (struct bgp_table));
rt->type = BGP_TABLE_MAIN;
return rt;
}

View file

@ -18,8 +18,19 @@ along with GNU Zebra; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
typedef enum
{
BGP_TABLE_MAIN,
BGP_TABLE_RSCLIENT,
} bgp_table_t;
struct bgp_table
{
bgp_table_t type;
/* The owner of this 'bgp_table' structure. */
void *owner;
struct bgp_node *top;
};

View file

@ -39,6 +39,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_open.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_table.h"
/* Utility function to get address family from current node. */
afi_t
@ -1648,7 +1649,7 @@ DEFUN (no_neighbor_dont_capability_negotiate,
int
peer_af_flag_modify_vty (struct vty *vty, char *peer_str, afi_t afi,
safi_t safi, u_int16_t flag, int set)
safi_t safi, u_int32_t flag, int set)
{
int ret;
struct peer *peer;
@ -1667,14 +1668,14 @@ peer_af_flag_modify_vty (struct vty *vty, char *peer_str, afi_t afi,
int
peer_af_flag_set_vty (struct vty *vty, char *peer_str, afi_t afi,
safi_t safi, u_int16_t flag)
safi_t safi, u_int32_t flag)
{
return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 1);
}
int
peer_af_flag_unset_vty (struct vty *vty, char *peer_str, afi_t afi,
safi_t safi, u_int16_t flag)
safi_t safi, u_int32_t flag)
{
return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 0);
}
@ -1923,6 +1924,134 @@ DEFUN (no_neighbor_route_reflector_client,
PEER_FLAG_REFLECTOR_CLIENT);
}
int
peer_rsclient_set_vty (struct vty *vty, char *peer_str, int afi, int safi)
{
int ret;
struct bgp *bgp;
struct peer *peer;
struct peer_group *group;
struct listnode *nn;
struct bgp_filter *pfilter;
struct bgp_filter *gfilter;
bgp = vty->index;
peer = peer_and_group_lookup_vty (vty, peer_str);
if ( ! peer )
return CMD_WARNING;
/* If it is already a RS-Client, don't do anything. */
if ( CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) )
return CMD_SUCCESS;
if ( ! peer_rsclient_active (peer) )
listnode_add_sort (bgp->rsclient, peer);
ret = peer_af_flag_set (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT);
if (ret < 0)
return bgp_vty_return (vty, ret);
peer->rib[afi][safi] = bgp_table_init ();
peer->rib[afi][safi]->type = BGP_TABLE_RSCLIENT;
peer->rib[afi][safi]->owner = peer;
/* Check for existing 'network' and 'redistribute' routes. */
bgp_check_local_routes_rsclient (peer, afi, safi);
/* Check for routes for peers configured with 'soft-reconfiguration'. */
bgp_soft_reconfig_rsclient (peer, afi, safi);
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
{
group = peer->group;
gfilter = &peer->filter[afi][safi];
LIST_LOOP(group->peer, peer, nn)
{
pfilter = &peer->filter[afi][safi];
/* Members of a non-RS-Client group should not be RS-Clients, as that
is checked when the become part of the peer-group */
ret = peer_af_flag_set (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT);
if (ret < 0)
return bgp_vty_return (vty, ret);
/* Make peer's RIB point to group's RIB. */
peer->rib[afi][safi] = group->conf->rib[afi][safi];
/* Import policy. */
if (pfilter->map[RMAP_IMPORT].name)
free (pfilter->map[RMAP_IMPORT].name);
if (gfilter->map[RMAP_IMPORT].name)
{
pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
}
else
{
pfilter->map[RMAP_IMPORT].name = NULL;
pfilter->map[RMAP_IMPORT].map =NULL;
}
/* Export policy. */
if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
{
pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
}
}
}
return CMD_SUCCESS;
}
int
peer_rsclient_unset_vty (struct vty *vty, char *peer_str, int afi, int safi)
{
int ret;
struct bgp *bgp;
struct peer *peer;
struct peer_group *group;
struct listnode *nn;
bgp = vty->index;
peer = peer_and_group_lookup_vty (vty, peer_str);
if ( ! peer )
return CMD_WARNING;
/* If it is not a RS-Client, don't do anything. */
if ( ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) )
return CMD_SUCCESS;
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
{
group = peer->group;
LIST_LOOP (group->peer, peer, nn)
{
ret = peer_af_flag_unset (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT);
if (ret < 0)
return bgp_vty_return (vty, ret);
peer->rib[afi][safi] = NULL;
}
peer = group->conf;
}
ret = peer_af_flag_unset (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT);
if (ret < 0)
return bgp_vty_return (vty, ret);
if ( ! peer_rsclient_active (peer) )
listnode_delete (bgp->rsclient, peer);
bgp_table_finish (peer->rib[bgp_node_afi(vty)][bgp_node_safi(vty)]);
return CMD_SUCCESS;
}
/* neighbor route-server-client. */
DEFUN (neighbor_route_server_client,
neighbor_route_server_client_cmd,
@ -1931,9 +2060,8 @@ DEFUN (neighbor_route_server_client,
NEIGHBOR_ADDR_STR2
"Configure a neighbor as Route Server client\n")
{
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_RSERVER_CLIENT);
return peer_rsclient_set_vty (vty, argv[0], bgp_node_afi(vty),
bgp_node_safi(vty));
}
DEFUN (no_neighbor_route_server_client,
@ -1943,10 +2071,36 @@ DEFUN (no_neighbor_route_server_client,
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Configure a neighbor as Route Server client\n")
{
return peer_rsclient_unset_vty (vty, argv[0], bgp_node_afi(vty),
bgp_node_safi(vty));
}
DEFUN (neighbor_nexthop_local_unchanged,
neighbor_nexthop_local_unchanged_cmd,
NEIGHBOR_CMD2 "nexthop-local unchanged",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Configure treatment of outgoing link-local nexthop attribute\n"
"Leave link-local nexthop unchanged for this peer\n")
{
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED );
}
DEFUN (no_neighbor_nexthop_local_unchanged,
no_neighbor_nexthop_local_unchanged_cmd,
NO_NEIGHBOR_CMD2 "nexthop-local unchanged",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Configure treatment of outgoing link-local-nexthop attribute\n"
"Leave link-local nexthop unchanged for this peer\n")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_RSERVER_CLIENT);
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED );
}
DEFUN (neighbor_attr_unchanged,
@ -3265,17 +3419,21 @@ peer_route_map_set_vty (struct vty *vty, char *ip_str, afi_t afi, safi_t safi,
{
int ret;
struct peer *peer;
int direct = FILTER_IN;
int direct = RMAP_IN;
peer = peer_and_group_lookup_vty (vty, ip_str);
if (! peer)
return CMD_WARNING;
/* Check filter direction. */
if (strncmp (direct_str, "i", 1) == 0)
direct = FILTER_IN;
if (strncmp (direct_str, "in", 2) == 0)
direct = RMAP_IN;
else if (strncmp (direct_str, "o", 1) == 0)
direct = FILTER_OUT;
direct = RMAP_OUT;
else if (strncmp (direct_str, "im", 2) == 0)
direct = RMAP_IMPORT;
else if (strncmp (direct_str, "e", 1) == 0)
direct = RMAP_EXPORT;
ret = peer_route_map_set (peer, afi, safi, direct, name_str);
@ -3288,18 +3446,21 @@ peer_route_map_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
{
int ret;
struct peer *peer;
int direct = FILTER_IN;
int direct = RMAP_IN;
peer = peer_and_group_lookup_vty (vty, ip_str);
if (! peer)
return CMD_WARNING;
/* Check filter direction. */
if (strncmp (direct_str, "i", 1) == 0)
direct = FILTER_IN;
if (strncmp (direct_str, "in", 2) == 0)
direct = RMAP_IN;
else if (strncmp (direct_str, "o", 1) == 0)
direct = FILTER_OUT;
direct = RMAP_OUT;
else if (strncmp (direct_str, "im", 2) == 0)
direct = RMAP_IMPORT;
else if (strncmp (direct_str, "e", 1) == 0)
direct = RMAP_EXPORT;
ret = peer_route_map_unset (peer, afi, safi, direct);
@ -3308,13 +3469,15 @@ peer_route_map_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
DEFUN (neighbor_route_map,
neighbor_route_map_cmd,
NEIGHBOR_CMD2 "route-map WORD (in|out)",
NEIGHBOR_CMD2 "route-map WORD (in|out|import|export)",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Apply route map to neighbor\n"
"Name of route map\n"
"Apply map to incoming routes\n"
"Apply map to outbound routes\n")
"Apply map to outbound routes\n"
"Apply map to routes going into a Route-Server client's table\n"
"Apply map to routes coming from a Route-Server client")
{
return peer_route_map_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), argv[1], argv[2]);
@ -3322,14 +3485,16 @@ DEFUN (neighbor_route_map,
DEFUN (no_neighbor_route_map,
no_neighbor_route_map_cmd,
NO_NEIGHBOR_CMD2 "route-map WORD (in|out)",
NO_NEIGHBOR_CMD2 "route-map WORD (in|out|import|export)",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Apply route map to neighbor\n"
"Name of route map\n"
"Apply map to incoming routes\n"
"Apply map to outbound routes\n")
"Apply map to outbound routes\n"
"Apply map to routes going into a Route-Server client's table\n"
"Apply map to routes coming from a Route-Server client")
{
return peer_route_map_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), argv[2]);
@ -5990,6 +6155,166 @@ ALIAS (clear_bgp_as_soft,
"Clear peers with the AS number\n"
"Soft reconfig\n")
/* RS-client soft reconfiguration. */
#ifdef HAVE_IPV6
DEFUN (clear_bgp_all_rsclient,
clear_bgp_all_rsclient_cmd,
"clear bgp * rsclient",
CLEAR_STR
BGP_STR
"Clear all peers\n"
"Soft reconfig for rsclient RIB\n")
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_RSCLIENT, NULL);
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_RSCLIENT, NULL);
}
ALIAS (clear_bgp_all_rsclient,
clear_bgp_ipv6_all_rsclient_cmd,
"clear bgp ipv6 * rsclient",
CLEAR_STR
BGP_STR
"Address family\n"
"Clear all peers\n"
"Soft reconfig for rsclient RIB\n")
ALIAS (clear_bgp_all_rsclient,
clear_bgp_instance_all_rsclient_cmd,
"clear bgp view WORD * rsclient",
CLEAR_STR
BGP_STR
"BGP view\n"
"view name\n"
"Clear all peers\n"
"Soft reconfig for rsclient RIB\n")
ALIAS (clear_bgp_all_rsclient,
clear_bgp_ipv6_instance_all_rsclient_cmd,
"clear bgp ipv6 view WORD * rsclient",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP view\n"
"view name\n"
"Clear all peers\n"
"Soft reconfig for rsclient RIB\n")
#endif /* HAVE_IPV6 */
DEFUN (clear_ip_bgp_all_rsclient,
clear_ip_bgp_all_rsclient_cmd,
"clear ip bgp * rsclient",
CLEAR_STR
IP_STR
BGP_STR
"Clear all peers\n"
"Soft reconfig for rsclient RIB\n")
{
if (argc == 1)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_RSCLIENT, NULL);
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
BGP_CLEAR_SOFT_RSCLIENT, NULL);
}
ALIAS (clear_ip_bgp_all_rsclient,
clear_ip_bgp_instance_all_rsclient_cmd,
"clear ip bgp view WORD * rsclient",
CLEAR_STR
IP_STR
BGP_STR
"BGP view\n"
"view name\n"
"Clear all peers\n"
"Soft reconfig for rsclient RIB\n")
#ifdef HAVE_IPV6
DEFUN (clear_bgp_peer_rsclient,
clear_bgp_peer_rsclient_cmd,
"clear bgp (A.B.C.D|X:X::X:X) rsclient",
CLEAR_STR
BGP_STR
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
"Soft reconfig for rsclient RIB\n")
{
if (argc == 2)
return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_RSCLIENT, argv[1]);
return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_RSCLIENT, argv[0]);
}
ALIAS (clear_bgp_peer_rsclient,
clear_bgp_ipv6_peer_rsclient_cmd,
"clear bgp ipv6 (A.B.C.D|X:X::X:X) rsclient",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
"Soft reconfig for rsclient RIB\n")
ALIAS (clear_bgp_peer_rsclient,
clear_bgp_instance_peer_rsclient_cmd,
"clear bgp view WORD (A.B.C.D|X:X::X:X) rsclient",
CLEAR_STR
BGP_STR
"BGP view\n"
"view name\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
"Soft reconfig for rsclient RIB\n")
ALIAS (clear_bgp_peer_rsclient,
clear_bgp_ipv6_instance_peer_rsclient_cmd,
"clear bgp ipv6 view WORD (A.B.C.D|X:X::X:X) rsclient",
CLEAR_STR
BGP_STR
"Address family\n"
"BGP view\n"
"view name\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
"Soft reconfig for rsclient RIB\n")
#endif /* HAVE_IPV6 */
DEFUN (clear_ip_bgp_peer_rsclient,
clear_ip_bgp_peer_rsclient_cmd,
"clear ip bgp (A.B.C.D|X:X::X:X) rsclient",
CLEAR_STR
IP_STR
BGP_STR
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
"Soft reconfig for rsclient RIB\n")
{
if (argc == 2)
return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_RSCLIENT, argv[1]);
return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
BGP_CLEAR_SOFT_RSCLIENT, argv[0]);
}
ALIAS (clear_ip_bgp_peer_rsclient,
clear_ip_bgp_instance_peer_rsclient_cmd,
"clear ip bgp view WORD (A.B.C.D|X:X::X:X) rsclient",
CLEAR_STR
IP_STR
BGP_STR
"BGP view\n"
"view name\n"
"BGP neighbor IP address to clear\n"
"BGP IPv6 neighbor to clear\n"
"Soft reconfig for rsclient RIB\n")
/* Show BGP peer's summary information. */
int
bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
@ -6443,14 +6768,18 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi)
if (filter->plist[FILTER_IN].name
|| filter->dlist[FILTER_IN].name
|| filter->aslist[FILTER_IN].name
|| filter->map[FILTER_IN].name)
|| filter->map[RMAP_IN].name)
vty_out (vty, " Inbound path policy configured%s", VTY_NEWLINE);
if (filter->plist[FILTER_OUT].name
|| filter->dlist[FILTER_OUT].name
|| filter->aslist[FILTER_OUT].name
|| filter->map[FILTER_OUT].name
|| filter->map[RMAP_OUT].name
|| filter->usmap.name)
vty_out (vty, " Outbound path policy configured%s", VTY_NEWLINE);
if (filter->map[RMAP_IMPORT].name)
vty_out (vty, " Import policy for this RS-client configured%s", VTY_NEWLINE);
if (filter->map[RMAP_EXPORT].name)
vty_out (vty, " Export policy for this RS-client configured%s", VTY_NEWLINE);
/* prefix-list */
if (filter->plist[FILTER_IN].name)
@ -6489,15 +6818,25 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi)
VTY_NEWLINE);
/* route-map. */
if (filter->map[FILTER_IN].name)
if (filter->map[RMAP_IN].name)
vty_out (vty, " Route map for incoming advertisements is %s%s%s",
filter->map[FILTER_IN].map ? "*" : "",
filter->map[FILTER_IN].name,
filter->map[RMAP_IN].map ? "*" : "",
filter->map[RMAP_IN].name,
VTY_NEWLINE);
if (filter->map[FILTER_OUT].name)
if (filter->map[RMAP_OUT].name)
vty_out (vty, " Route map for outgoing advertisements is %s%s%s",
filter->map[FILTER_OUT].map ? "*" : "",
filter->map[FILTER_OUT].name,
filter->map[RMAP_OUT].map ? "*" : "",
filter->map[RMAP_OUT].name,
VTY_NEWLINE);
if (filter->map[RMAP_IMPORT].name)
vty_out (vty, " Route map for advertisements going into this RS-client's table is %s%s%s",
filter->map[RMAP_IMPORT].map ? "*" : "",
filter->map[RMAP_IMPORT].name,
VTY_NEWLINE);
if (filter->map[RMAP_EXPORT].name)
vty_out (vty, " Route map for advertisements coming from this RS-client is %s%s%s",
filter->map[RMAP_EXPORT].map ? "*" : "",
filter->map[RMAP_EXPORT].name,
VTY_NEWLINE);
/* unsuppress-map */
@ -7156,6 +7495,262 @@ DEFUN (show_ip_bgp_attr_info,
return CMD_SUCCESS;
}
int
bgp_write_rsclient_summary (struct vty *vty, struct peer *rsclient,
afi_t afi, safi_t safi)
{
char timebuf[BGP_UPTIME_LEN];
char rmbuf[14];
char *rmname;
struct peer *peer;
struct listnode *nn;
int len;
int count = 0;
if (CHECK_FLAG (rsclient->sflags, PEER_STATUS_GROUP))
{
LIST_LOOP (rsclient->group->peer, peer, nn)
{
count++;
bgp_write_rsclient_summary (vty, peer, afi, safi);
}
return count;
}
len = vty_out (vty, "%s", rsclient->host);
len = 16 - len;
if (len < 1)
vty_out (vty, "%s%*s", VTY_NEWLINE, 16, " ");
else
vty_out (vty, "%*s", len, " ");
switch (rsclient->version)
{
case BGP_VERSION_4:
vty_out (vty, "4 ");
break;
case BGP_VERSION_MP_4_DRAFT_00:
vty_out (vty, "4-");
break;
}
vty_out (vty, "%5d ", rsclient->as);
rmname = ROUTE_MAP_EXPORT_NAME(&rsclient->filter[afi][safi]);
if ( rmname && strlen (rmname) > 13 )
{
sprintf (rmbuf, "%13s", "...");
rmname = strncpy (rmbuf, rmname, 10);
}
else if (! rmname)
rmname = "<none>";
vty_out (vty, " %13s ", rmname);
rmname = ROUTE_MAP_IMPORT_NAME(&rsclient->filter[afi][safi]);
if ( rmname && strlen (rmname) > 13 )
{
sprintf (rmbuf, "%13s", "...");
rmname = strncpy (rmbuf, rmname, 10);
}
else if (! rmname)
rmname = "<none>";
vty_out (vty, " %13s ", rmname);
vty_out (vty, "%8s", peer_uptime (rsclient->uptime, timebuf, BGP_UPTIME_LEN));
if (CHECK_FLAG (rsclient->flags, PEER_FLAG_SHUTDOWN))
vty_out (vty, " Idle (Admin)");
else if (CHECK_FLAG (rsclient->sflags, PEER_STATUS_PREFIX_OVERFLOW))
vty_out (vty, " Idle (PfxCt)");
else
vty_out (vty, " %-11s", LOOKUP(bgp_status_msg, rsclient->status));
vty_out (vty, "%s", VTY_NEWLINE);
return 1;
}
int
bgp_show_rsclient_summary (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
{
struct peer *peer;
struct listnode *nn;
int count = 0;
/* Header string for each address family. */
static char header[] = "Neighbor V AS Export-Policy Import-Policy Up/Down State";
LIST_LOOP (bgp->rsclient, peer, nn)
{
if (peer->afc[afi][safi] &&
CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
{
if (! count)
{
vty_out (vty,
"Route Server's BGP router identifier %s%s",
inet_ntoa (bgp->router_id), VTY_NEWLINE);
vty_out (vty,
"Route Server's local AS number %d%s", bgp->as,
VTY_NEWLINE);
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, "%s%s", header, VTY_NEWLINE);
}
count += bgp_write_rsclient_summary (vty, peer, afi, safi);
}
}
if (count)
vty_out (vty, "%sTotal number of Route Server Clients %d%s", VTY_NEWLINE,
count, VTY_NEWLINE);
else
vty_out (vty, "No %s Route Server Client is configured%s",
afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE);
return CMD_SUCCESS;
}
int
bgp_show_rsclient_summary_vty (struct vty *vty, char *name, afi_t afi, safi_t safi)
{
struct bgp *bgp;
if (name)
{
bgp = bgp_lookup_by_name (name);
if (! bgp)
{
vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
return CMD_WARNING;
}
bgp_show_rsclient_summary (vty, bgp, afi, safi);
return CMD_SUCCESS;
}
bgp = bgp_get_default ();
if (bgp)
bgp_show_rsclient_summary (vty, bgp, afi, safi);
return CMD_SUCCESS;
}
/* 'show bgp rsclient' commands. */
DEFUN (show_ip_bgp_rsclient_summary,
show_ip_bgp_rsclient_summary_cmd,
"show ip bgp rsclient summary",
SHOW_STR
IP_STR
BGP_STR
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
{
return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST);
}
DEFUN (show_ip_bgp_instance_rsclient_summary,
show_ip_bgp_instance_rsclient_summary_cmd,
"show ip bgp view WORD rsclient summary",
SHOW_STR
IP_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
{
return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
}
DEFUN (show_ip_bgp_ipv4_rsclient_summary,
show_ip_bgp_ipv4_rsclient_summary_cmd,
"show ip bgp ipv4 (unicast|multicast) rsclient summary",
SHOW_STR
IP_STR
BGP_STR
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
{
if (strncmp (argv[0], "m", 1) == 0)
return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP, SAFI_MULTICAST);
return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST);
}
DEFUN (show_ip_bgp_instance_ipv4_rsclient_summary,
show_ip_bgp_instance_ipv4_rsclient_summary_cmd,
"show ip bgp view WORD ipv4 (unicast|multicast) rsclient summary",
SHOW_STR
IP_STR
BGP_STR
"BGP view\n"
"View name\n"
"Address family\n"
"Address Family modifier\n"
"Address Family modifier\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
{
if (strncmp (argv[1], "m", 1) == 0)
return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST);
return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
}
#ifdef HAVE_IPV6
DEFUN (show_bgp_rsclient_summary,
show_bgp_rsclient_summary_cmd,
"show bgp rsclient summary",
SHOW_STR
BGP_STR
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
{
return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP6, SAFI_UNICAST);
}
DEFUN (show_bgp_instance_rsclient_summary,
show_bgp_instance_rsclient_summary_cmd,
"show bgp view WORD rsclient summary",
SHOW_STR
BGP_STR
"BGP view\n"
"View name\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
{
return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST);
}
ALIAS (show_bgp_rsclient_summary,
show_bgp_ipv6_rsclient_summary_cmd,
"show bgp ipv6 rsclient summary",
SHOW_STR
BGP_STR
"Address family\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
ALIAS (show_bgp_instance_rsclient_summary,
show_bgp_instance_ipv6_rsclient_summary_cmd,
"show bgp view WORD ipv6 rsclient summary",
SHOW_STR
BGP_STR
"BGP view\n"
"View name\n"
"Address family\n"
"Information about Route Server Clients\n"
"Summary of all Route Server Clients\n")
#endif /* HAVE IPV6 */
/* Redistribute VTY commands. */
/* Utility function to convert user input route type string to route
@ -8066,6 +8661,10 @@ bgp_vty_init ()
install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged9_cmd);
install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged10_cmd);
/* "nexthop-local unchanged" commands */
install_element (BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_local_unchanged_cmd);
/* "transparent-as" and "transparent-nexthop" for old version
compatibility. */
install_element (BGP_NODE, &neighbor_transparent_as_cmd);
@ -8562,6 +9161,22 @@ bgp_vty_init ()
install_element (ENABLE_NODE, &clear_bgp_ipv6_as_soft_cmd);
#endif /* HAVE_IPV6 */
/* "clear ip bgp neighbor rsclient" */
install_element (ENABLE_NODE, &clear_ip_bgp_all_rsclient_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_rsclient_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_peer_rsclient_cmd);
install_element (ENABLE_NODE, &clear_ip_bgp_instance_peer_rsclient_cmd);
#ifdef HAVE_IPV6
install_element (ENABLE_NODE, &clear_bgp_all_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_instance_all_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_ipv6_all_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_ipv6_instance_all_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_peer_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_instance_peer_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_rsclient_cmd);
install_element (ENABLE_NODE, &clear_bgp_ipv6_instance_peer_rsclient_cmd);
#endif /* HAVE_IPV6 */
/* "show ip bgp summary" commands. */
install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_summary_cmd);
@ -8635,6 +9250,27 @@ bgp_vty_init ()
install_element (ENABLE_NODE, &show_ipv6_mbgp_summary_cmd);
#endif /* HAVE_IPV6 */
/* "show ip bgp rsclient" commands. */
install_element (VIEW_NODE, &show_ip_bgp_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
#ifdef HAVE_IPV6
install_element (VIEW_NODE, &show_bgp_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_bgp_instance_rsclient_summary_cmd);
install_element (VIEW_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_instance_rsclient_summary_cmd);
install_element (ENABLE_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
#endif /* HAVE_IPV6 */
/* "show ip bgp paths" commands. */
install_element (VIEW_NODE, &show_ip_bgp_paths_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_paths_cmd);

View file

@ -531,6 +531,23 @@ bgp_default_local_preference_unset (struct bgp *bgp)
return 0;
}
/* If peer is RSERVER_CLIENT in at least one address family and is not member
of a peer_group for that family, return 1.
Used to check wether the peer is included in list bgp->rsclient. */
int
peer_rsclient_active (struct peer *peer)
{
int i;
int j;
for (i=AFI_IP; i < AFI_MAX; i++)
for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
&& ! peer->af_group[i][j])
return 1;
return 0;
}
/* Peer comparison function for sorting. */
static int
peer_cmp (struct peer *p1, struct peer *p2)
@ -572,6 +589,9 @@ peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
free (filter->aslist[i].name);
filter->aslist[i].name = NULL;
}
}
for (i = RMAP_IN; i < RMAP_MAX; i++)
{
if (filter->map[i].name)
{
free (filter->map[i].name);
@ -1092,7 +1112,18 @@ peer_delete (struct peer *peer)
/* Delete from all peer list. */
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
listnode_delete (bgp->peer, peer);
if (peer_rsclient_active (peer))
listnode_delete (bgp->rsclient, peer);
}
/* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
member of a peer_group. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
bgp_table_finish (peer->rib[afi][safi]);
/* Buffer. */
if (peer->ibuf)
@ -1134,6 +1165,9 @@ peer_delete (struct peer *peer)
free (filter->plist[i].name);
if (filter->aslist[i].name)
free (filter->aslist[i].name);
}
for (i = RMAP_IN; i < RMAP_MAX; i++)
{
if (filter->map[i].name)
free (filter->map[i].name);
}
@ -1300,6 +1334,34 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
/* allowas-in */
peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
/* route-server-client */
if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
{
/* Make peer's RIB point to group's RIB. */
peer->rib[afi][safi] = group->conf->rib[afi][safi];
/* Import policy. */
if (pfilter->map[RMAP_IMPORT].name)
free (pfilter->map[RMAP_IMPORT].name);
if (gfilter->map[RMAP_IMPORT].name)
{
pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
}
else
{
pfilter->map[RMAP_IMPORT].name = NULL;
pfilter->map[RMAP_IMPORT].map = NULL;
}
/* Export policy. */
if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
{
pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
}
}
/* default-originate route-map */
if (conf->default_rmap[afi][safi].name)
{
@ -1355,12 +1417,12 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
}
if (gfilter->map[in].name && ! pfilter->map[in].name)
if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
{
if (pfilter->map[in].name)
free (pfilter->map[in].name);
pfilter->map[in].name = strdup (gfilter->map[in].name);
pfilter->map[in].map = gfilter->map[in].map;
if (pfilter->map[RMAP_IN].name)
free (pfilter->map[RMAP_IN].name);
pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
}
/* outbound filter apply */
@ -1406,19 +1468,42 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
pfilter->aslist[out].name = NULL;
pfilter->aslist[out].aslist = NULL;
}
if (gfilter->map[out].name)
if (gfilter->map[RMAP_OUT].name)
{
if (pfilter->map[out].name)
free (pfilter->map[out].name);
pfilter->map[out].name = strdup (gfilter->map[out].name);
pfilter->map[out].map = gfilter->map[out].map;
if (pfilter->map[RMAP_OUT].name)
free (pfilter->map[RMAP_OUT].name);
pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
}
else
{
if (pfilter->map[out].name)
free (pfilter->map[out].name);
pfilter->map[out].name = NULL;
pfilter->map[out].map = NULL;
if (pfilter->map[RMAP_OUT].name)
free (pfilter->map[RMAP_OUT].name);
pfilter->map[RMAP_OUT].name = NULL;
pfilter->map[RMAP_OUT].map = NULL;
}
/* RS-client's import/export route-maps. */
if (gfilter->map[RMAP_IMPORT].name)
{
if (pfilter->map[RMAP_IMPORT].name)
free (pfilter->map[RMAP_IMPORT].name);
pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
}
else
{
if (pfilter->map[RMAP_IMPORT].name)
free (pfilter->map[RMAP_IMPORT].name);
pfilter->map[RMAP_IMPORT].name = NULL;
pfilter->map[RMAP_IMPORT].map = NULL;
}
if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
{
if (pfilter->map[RMAP_EXPORT].name)
free (pfilter->map[RMAP_EXPORT].name);
pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
}
if (gfilter->usmap.name)
@ -1601,6 +1686,35 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
}
}
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
{
/* If it's not configured as RSERVER_CLIENT in any other address
family, without being member of a peer_group, remove it from
list bgp->rsclient.*/
if (! peer_rsclient_active (peer))
listnode_delete (bgp->rsclient, peer);
bgp_table_finish (peer->rib[afi][safi]);
/* Import policy. */
if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
{
free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
}
/* Export policy. */
if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
&& peer->filter[afi][safi].map[RMAP_EXPORT].name)
{
free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
}
}
peer_group2peer_config_copy (group, peer, afi, safi);
if (peer->status == Established)
@ -1629,6 +1743,9 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
peer->afc[afi][safi] = 0;
peer_af_flag_reset (peer, afi, safi);
if (peer->rib[afi][safi])
peer->rib[afi][safi] = NULL;
if (! peer_group_active (peer))
{
listnode_delete (group->peer, peer);
@ -1672,6 +1789,9 @@ bgp_create (as_t *as, char *name)
bgp->group = list_new ();
bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
bgp->rsclient = list_new ();
bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
@ -1826,6 +1946,9 @@ bgp_delete (struct bgp *bgp)
peer_delete (peer);
}
bgp->rsclient->del = (void (*)(void *)) peer_delete;
list_delete (bgp->rsclient);
listnode_delete (bm->bgp, bgp);
if (bgp->name)
@ -2007,6 +2130,7 @@ struct peer_flag_action peer_af_flag_action_list[] =
{ PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
{ PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
{ PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
{ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
{ 0, 0, 0 }
};
@ -3551,10 +3675,12 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT)
if (direct != RMAP_IN && direct != RMAP_OUT &&
direct != RMAP_IMPORT && direct != RMAP_EXPORT)
return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
&& peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi];
@ -3662,10 +3788,12 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT)
if (direct != RMAP_IN && direct != RMAP_OUT &&
direct != RMAP_IMPORT && direct != RMAP_EXPORT)
return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
&& peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi];
@ -3950,6 +4078,14 @@ peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
if (! peer->afc[afi][safi])
return BGP_ERR_AF_UNCONFIGURED;
if (stype == BGP_CLEAR_SOFT_RSCLIENT)
{
if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
return 0;
bgp_check_local_routes_rsclient (peer, afi, safi);
bgp_soft_reconfig_rsclient (peer, afi, safi);
}
if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
bgp_announce_route (peer, afi, safi);
@ -4086,14 +4222,23 @@ bgp_config_write_filter (struct vty *vty, struct peer *peer,
filter->plist[out].name, VTY_NEWLINE);
/* route-map. */
if (filter->map[in].name)
if (! gfilter || ! gfilter->map[in].name
|| strcmp (filter->map[in].name, gfilter->map[in].name) != 0)
if (filter->map[RMAP_IN].name)
if (! gfilter || ! gfilter->map[RMAP_IN].name
|| strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
vty_out (vty, " neighbor %s route-map %s in%s", addr,
filter->map[in].name, VTY_NEWLINE);
if (filter->map[out].name && ! gfilter)
filter->map[RMAP_IN].name, VTY_NEWLINE);
if (filter->map[RMAP_OUT].name && ! gfilter)
vty_out (vty, " neighbor %s route-map %s out%s", addr,
filter->map[out].name, VTY_NEWLINE);
filter->map[RMAP_OUT].name, VTY_NEWLINE);
if (filter->map[RMAP_IMPORT].name && ! gfilter)
vty_out (vty, " neighbor %s route-map %s import%s", addr,
filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
if (filter->map[RMAP_EXPORT].name)
if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
|| strcmp (filter->map[RMAP_EXPORT].name,
gfilter->map[RMAP_EXPORT].name) != 0)
vty_out (vty, " neighbor %s route-map %s export%s", addr,
filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
/* unsuppress-map */
if (filter->usmap.name && ! gfilter)

View file

@ -65,6 +65,9 @@ struct bgp
/* BGP peer group. */
struct list *group;
/* BGP route-server-clients. */
struct list *rsclient;
/* BGP configuration. */
u_int16_t config;
#define BGP_CONFIG_ROUTER_ID (1 << 0)
@ -186,6 +189,12 @@ struct bgp_rd
u_char val[BGP_RD_SIZE];
};
#define RMAP_IN 0
#define RMAP_OUT 1
#define RMAP_IMPORT 2
#define RMAP_EXPORT 3
#define RMAP_MAX 4
/* BGP filter structure. */
struct bgp_filter
{
@ -215,7 +224,7 @@ struct bgp_filter
{
char *name;
struct route_map *map;
} map[FILTER_MAX];
} map[RMAP_MAX];
/* Unsuppress-map. */
struct
@ -250,6 +259,9 @@ struct peer
/* Local router ID. */
struct in_addr local_id;
/* Peer specific RIB when configured as route-server-client. */
struct bgp_table *rib[AFI_MAX][SAFI_MAX];
/* Packet receive and send buffer. */
struct stream *ibuf;
struct stream_fifo *obuf;
@ -341,6 +353,7 @@ struct peer
#define PEER_FLAG_ORF_PREFIX_RM (1 << 13) /* orf capability receive-mode */
#define PEER_FLAG_MAX_PREFIX (1 << 14) /* maximum prefix */
#define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */
#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */
/* default-originate route-map. */
struct
@ -480,6 +493,8 @@ struct peer
#define PEER_RMAP_TYPE_REDISTRIBUTE (1 << 3) /* redistribute route-map */
#define PEER_RMAP_TYPE_DEFAULT (1 << 4) /* default-originate route-map */
#define PEER_RMAP_TYPE_NOSET (1 << 5) /* not allow to set commands */
#define PEER_RMAP_TYPE_IMPORT (1 << 6) /* neighbor route-map import */
#define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */
};
/* This structure's member directly points incoming packet data
@ -689,7 +704,8 @@ enum bgp_clear_type
BGP_CLEAR_SOFT_OUT,
BGP_CLEAR_SOFT_IN,
BGP_CLEAR_SOFT_BOTH,
BGP_CLEAR_SOFT_IN_ORF_PREFIX
BGP_CLEAR_SOFT_IN_ORF_PREFIX,
BGP_CLEAR_SOFT_RSCLIENT
};
/* Macros. */
@ -797,6 +813,8 @@ int bgp_timers_unset (struct bgp *);
int bgp_default_local_preference_set (struct bgp *, u_int32_t);
int bgp_default_local_preference_unset (struct bgp *);
int peer_rsclient_active (struct peer *);
int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
int peer_group_remote_as (struct bgp *, char *, as_t *);
int peer_delete (struct peer *peer);

View file

@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "prefix.h"
#include "routemap.h"
#include "command.h"
#include "log.h"
/* Vector for route match rules. */
static vector route_match_vec;
@ -221,9 +222,11 @@ vty_show_route_map_entry (struct vty *vty, struct route_map *map)
rule->cmd->str, rule->rule_str, VTY_NEWLINE);
vty_out (vty, " Action:%s", VTY_NEWLINE);
if (index->exitpolicy == RMAP_GOTO)
vty_out (vty, " Goto %d%s", index->nextpref, VTY_NEWLINE);
if (index->nextrm)
vty_out (vty, " Call %s%s", index->nextrm, VTY_NEWLINE);
else if (index->exitpolicy == RMAP_GOTO)
vty_out (vty, " Goto %d%s", index->nextpref, VTY_NEWLINE);
else if (index->exitpolicy == RMAP_NEXT)
{
vty_out (vty, " Goto next, (entry ");
@ -298,6 +301,10 @@ route_map_index_delete (struct route_map_index *index, int notify)
else
index->map->head = index->next;
/* Free 'char *nextrm' if not NULL */
if (index->nextrm)
free (index->nextrm);
/* Execute event hook. */
if (route_map_master.event_hook && notify)
(*route_map_master.event_hook) (RMAP_EVENT_INDEX_DELETED,
@ -688,18 +695,26 @@ route_map_delete_set (struct route_map_index *index, char *set_name,
deny deny | cont
|
action) Apply Set statements, accept route
If NEXT is specified, goto NEXT statement
If GOTO is specified, goto the first clause where pref > nextpref
If nothing is specified, do as Cisco and finish
deny) If NEXT is specified, goto NEXT statement
If nothing is specified, finally will be denied by route-map.
cont) Goto Next index
action)
-Apply Set statements, accept route
-If Call statement is present jump to the specified route-map, if it
denies the route we finish.
-If NEXT is specified, goto NEXT statement
-If GOTO is specified, goto the first clause where pref > nextpref
-If nothing is specified, do as Cisco and finish
deny)
-Route is denied by route-map.
cont)
-Goto Next index
If we get no matches after we've processed all updates, then the route
is dropped too.
Some notes on the new "NEXT" and "GOTO"
Some notes on the new "CALL", "NEXT" and "GOTO"
call WORD - If this clause is matched, then the set statements
are executed and then we jump to route-map 'WORD'. If
this route-map denies the route, we finish, in other case we
do whatever the exit policy (EXIT, NEXT or GOTO) tells.
on-match next - If this clause is matched, then the set statements
are executed and then we drop through to the next clause
on-match goto n - If this clause is matched, then the set statments
@ -746,10 +761,20 @@ route_map_result_t
route_map_apply (struct route_map *map, struct prefix *prefix,
route_map_object_t type, void *object)
{
static int recursion = 0;
int ret = 0;
struct route_map_index *index;
struct route_map_rule *set;
if (recursion > RMAP_RECURSION_LIMIT)
{
zlog (NULL, LOG_WARNING,
"route-map recursion limit (%d) reached, discarding route",
RMAP_RECURSION_LIMIT);
recursion = 0;
return RMAP_DENYMATCH;
}
if (map == NULL)
return RMAP_DENYMATCH;
@ -771,6 +796,25 @@ route_map_apply (struct route_map *map, struct prefix *prefix,
for (set = index->set_list.head; set; set = set->next)
ret = (*set->cmd->func_apply) (set->value, prefix,
type, object);
/* Call another route-map if available */
if (index->nextrm)
{
struct route_map *nextrm =
route_map_lookup_by_name (index->nextrm);
if (nextrm) /* Target route-map found, jump to it */
{
recursion++;
ret = route_map_apply (nextrm, prefix, type, object);
recursion--;
}
/* If nextrm returned 'deny', finish. */
if (ret == RMAP_DENYMATCH)
return ret;
}
switch (index->exitpolicy)
{
case RMAP_EXIT:
@ -781,8 +825,9 @@ route_map_apply (struct route_map *map, struct prefix *prefix,
{
/* Find the next clause to jump to */
struct route_map_index *next = index->next;
int nextpref = index->nextpref;
while (next && next->pref < index->nextpref)
while (next && next->pref < nextpref)
{
index = next;
next = next->next;
@ -798,9 +843,6 @@ route_map_apply (struct route_map *map, struct prefix *prefix,
else if (index->type == RMAP_DENY)
/* 'deny' */
{
if (index->exitpolicy == RMAP_NEXT)
continue;
else
return RMAP_DENYMATCH;
}
}
@ -1046,7 +1088,7 @@ DEFUN (no_rmap_onmatch_goto,
"no on-match goto",
NO_STR
"Exit policy on matches\n"
"Next clause\n")
"Goto Clause number\n")
{
struct route_map_index *index;
@ -1103,6 +1145,49 @@ DEFUN (rmap_show_name,
return vty_show_route_map (vty, argv[0]);
}
ALIAS (rmap_onmatch_goto,
rmap_continue_index_cmd,
"continue <1-65536>",
"Exit policy on matches\n"
"Goto Clause number\n")
DEFUN (rmap_call,
rmap_call_cmd,
"call WORD",
"Jump to another Route-Map after match+set\n"
"Target route-map name\n")
{
struct route_map_index *index;
index = vty->index;
if (index)
{
if (index->nextrm)
free (index->nextrm);
index->nextrm = strdup (argv[0]);
}
return CMD_SUCCESS;
}
DEFUN (no_rmap_call,
no_rmap_call_cmd,
"no call",
NO_STR
"Jump to another Route-Map after match+set\n")
{
struct route_map_index *index;
index = vty->index;
if (index->nextrm)
{
free (index->nextrm);
index->nextrm = NULL;
}
return CMD_SUCCESS;
}
/* Configuration write function. */
int
route_map_config_write (struct vty *vty)
@ -1135,9 +1220,10 @@ route_map_config_write (struct vty *vty)
vty_out (vty, " set %s %s%s", rule->cmd->str,
rule->rule_str ? rule->rule_str : "",
VTY_NEWLINE);
if (index->nextrm)
vty_out (vty, " call %s%s", index->nextrm, VTY_NEWLINE);
if (index->exitpolicy == RMAP_GOTO)
vty_out (vty, " on-match goto %d%s", index->nextpref,
VTY_NEWLINE);
vty_out (vty, " on-match goto %d%s", index->nextpref, VTY_NEWLINE);
if (index->exitpolicy == RMAP_NEXT)
vty_out (vty," on-match next%s", VTY_NEWLINE);
@ -1174,6 +1260,15 @@ route_map_init_vty ()
install_element (RMAP_NODE, &rmap_onmatch_goto_cmd);
install_element (RMAP_NODE, &no_rmap_onmatch_goto_cmd);
/* Install the continue stuff (ALIAS of on-match). */
install_element (RMAP_NODE, &rmap_continue_cmd);
install_element (RMAP_NODE, &no_rmap_continue_cmd);
install_element (RMAP_NODE, &rmap_continue_index_cmd);
/* Install the call stuff. */
install_element (RMAP_NODE, &rmap_call_cmd);
install_element (RMAP_NODE, &no_rmap_call_cmd);
/* Install show command */
install_element (ENABLE_NODE, &rmap_show_cmd);
install_element (ENABLE_NODE, &rmap_show_name_cmd);

View file

@ -67,6 +67,9 @@ typedef enum
RMAP_EVENT_INDEX_DELETED
} route_map_event_t;
/* Depth limit in RMAP recursion using RMAP_CALL. */
#define RMAP_RECURSION_LIMIT 10
/* Route map rule structure for matching and setting. */
struct route_map_rule_cmd
{
@ -118,6 +121,9 @@ struct route_map_index
/* If we're using "GOTO", to where do we go? */
int nextpref;
/* If we're using "CALL", to which route-map do ew go? */
char *nextrm;
/* Matching rule list. */
struct route_map_rule_list match_list;
struct route_map_rule_list set_list;