forked from Mirror/frr
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:
parent
0e82d0e120
commit
fee0f4c629
64
ChangeLog
64
ChangeLog
|
@ -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>
|
2004-08-31 Greg Troxel <gdt@poblano.ir.bbn.com>
|
||||||
|
|
||||||
* Makefile.am: make m4 as subdir, rather the EXTRA_DISTing it
|
* Makefile.am: make m4 as subdir, rather the EXTRA_DISTing it
|
||||||
|
|
|
@ -1365,8 +1365,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
|
||||||
if (peer_sort (peer) == BGP_PEER_EBGP
|
if (peer_sort (peer) == BGP_PEER_EBGP
|
||||||
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
|
&& (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
|
||||||
|| attr->aspath->length == 0)
|
|| 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);
|
aspath = aspath_dup (attr->aspath);
|
||||||
|
|
||||||
|
|
1549
bgpd/bgp_route.c
1549
bgpd/bgp_route.c
File diff suppressed because it is too large
Load diff
|
@ -109,10 +109,15 @@ struct bgp_static
|
||||||
#define FILTER_LIST_OUT_NAME(F) ((F)->aslist[FILTER_OUT].name)
|
#define FILTER_LIST_OUT_NAME(F) ((F)->aslist[FILTER_OUT].name)
|
||||||
#define FILTER_LIST_OUT(F) ((F)->aslist[FILTER_OUT].aslist)
|
#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_NAME(F) ((F)->map[RMAP_IN].name)
|
||||||
#define ROUTE_MAP_IN(F) ((F)->map[FILTER_IN].map)
|
#define ROUTE_MAP_IN(F) ((F)->map[RMAP_IN].map)
|
||||||
#define ROUTE_MAP_OUT_NAME(F) ((F)->map[FILTER_OUT].name)
|
#define ROUTE_MAP_OUT_NAME(F) ((F)->map[RMAP_OUT].name)
|
||||||
#define ROUTE_MAP_OUT(F) ((F)->map[FILTER_OUT].map)
|
#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_NAME(F) ((F)->usmap.name)
|
||||||
#define UNSUPPRESS_MAP(F) ((F)->usmap.map)
|
#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_announce_route_all (struct peer *);
|
||||||
void bgp_default_originate (struct peer *, afi_t, safi_t, int);
|
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_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 (struct peer *, afi_t, safi_t);
|
||||||
void bgp_clear_route_all (struct peer *);
|
void bgp_clear_route_all (struct peer *);
|
||||||
void bgp_clear_adj_in (struct peer *, afi_t, safi_t);
|
void bgp_clear_adj_in (struct peer *, afi_t, safi_t);
|
||||||
|
|
|
@ -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 ip address IP_ACCESS_LIST' */
|
||||||
|
|
||||||
/* Match function should return 1 if match is success else return
|
/* 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 (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
|
&& peer->su_remote
|
||||||
&& sockunion_family (peer->su_remote) == AF_INET)
|
&& sockunion_family (peer->su_remote) == AF_INET)
|
||||||
{
|
{
|
||||||
|
@ -1974,7 +2072,7 @@ bgp_route_map_update (char *unused)
|
||||||
{
|
{
|
||||||
filter = &peer->filter[afi][safi];
|
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)
|
if (filter->map[direct].name)
|
||||||
filter->map[direct].map =
|
filter->map[direct].map =
|
||||||
|
@ -1996,7 +2094,7 @@ bgp_route_map_update (char *unused)
|
||||||
{
|
{
|
||||||
filter = &group->conf->filter[afi][safi];
|
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)
|
if (filter->map[direct].name)
|
||||||
filter->map[direct].map =
|
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,
|
DEFUN (match_ip_address,
|
||||||
match_ip_address_cmd,
|
match_ip_address_cmd,
|
||||||
"match ip address (<1-199>|<1300-2699>|WORD)",
|
"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_add_hook (bgp_route_map_update);
|
||||||
route_map_delete_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_address_cmd);
|
||||||
route_map_install_match (&route_match_ip_next_hop_cmd);
|
route_map_install_match (&route_match_ip_next_hop_cmd);
|
||||||
route_map_install_match (&route_match_ip_address_prefix_list_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_rt_cmd);
|
||||||
route_map_install_set (&route_set_ecommunity_soo_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, &match_ip_address_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_ip_address_cmd);
|
install_element (RMAP_NODE, &no_match_ip_address_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
|
install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
|
||||||
|
|
|
@ -38,6 +38,9 @@ bgp_table_init (void)
|
||||||
|
|
||||||
rt = XMALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
|
rt = XMALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
|
||||||
memset (rt, 0, sizeof (struct bgp_table));
|
memset (rt, 0, sizeof (struct bgp_table));
|
||||||
|
|
||||||
|
rt->type = BGP_TABLE_MAIN;
|
||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
02111-1307, USA. */
|
02111-1307, USA. */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BGP_TABLE_MAIN,
|
||||||
|
BGP_TABLE_RSCLIENT,
|
||||||
|
} bgp_table_t;
|
||||||
|
|
||||||
struct bgp_table
|
struct bgp_table
|
||||||
{
|
{
|
||||||
|
bgp_table_t type;
|
||||||
|
|
||||||
|
/* The owner of this 'bgp_table' structure. */
|
||||||
|
void *owner;
|
||||||
|
|
||||||
struct bgp_node *top;
|
struct bgp_node *top;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
692
bgpd/bgp_vty.c
692
bgpd/bgp_vty.c
|
@ -39,6 +39,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
#include "bgpd/bgp_open.h"
|
#include "bgpd/bgp_open.h"
|
||||||
#include "bgpd/bgp_route.h"
|
#include "bgpd/bgp_route.h"
|
||||||
#include "bgpd/bgp_zebra.h"
|
#include "bgpd/bgp_zebra.h"
|
||||||
|
#include "bgpd/bgp_table.h"
|
||||||
|
|
||||||
/* Utility function to get address family from current node. */
|
/* Utility function to get address family from current node. */
|
||||||
afi_t
|
afi_t
|
||||||
|
@ -1648,7 +1649,7 @@ DEFUN (no_neighbor_dont_capability_negotiate,
|
||||||
|
|
||||||
int
|
int
|
||||||
peer_af_flag_modify_vty (struct vty *vty, char *peer_str, afi_t afi,
|
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;
|
int ret;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
|
@ -1667,14 +1668,14 @@ peer_af_flag_modify_vty (struct vty *vty, char *peer_str, afi_t afi,
|
||||||
|
|
||||||
int
|
int
|
||||||
peer_af_flag_set_vty (struct vty *vty, char *peer_str, afi_t afi,
|
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);
|
return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
peer_af_flag_unset_vty (struct vty *vty, char *peer_str, afi_t afi,
|
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);
|
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);
|
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. */
|
/* neighbor route-server-client. */
|
||||||
DEFUN (neighbor_route_server_client,
|
DEFUN (neighbor_route_server_client,
|
||||||
neighbor_route_server_client_cmd,
|
neighbor_route_server_client_cmd,
|
||||||
|
@ -1931,9 +2060,8 @@ DEFUN (neighbor_route_server_client,
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Configure a neighbor as Route Server client\n")
|
"Configure a neighbor as Route Server client\n")
|
||||||
{
|
{
|
||||||
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
|
return peer_rsclient_set_vty (vty, argv[0], bgp_node_afi(vty),
|
||||||
bgp_node_safi (vty),
|
bgp_node_safi(vty));
|
||||||
PEER_FLAG_RSERVER_CLIENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (no_neighbor_route_server_client,
|
DEFUN (no_neighbor_route_server_client,
|
||||||
|
@ -1943,10 +2071,36 @@ DEFUN (no_neighbor_route_server_client,
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Configure a neighbor as Route Server client\n")
|
"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),
|
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
|
||||||
bgp_node_safi (vty),
|
bgp_node_safi (vty),
|
||||||
PEER_FLAG_RSERVER_CLIENT);
|
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED );
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (neighbor_attr_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;
|
int ret;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
int direct = FILTER_IN;
|
int direct = RMAP_IN;
|
||||||
|
|
||||||
peer = peer_and_group_lookup_vty (vty, ip_str);
|
peer = peer_and_group_lookup_vty (vty, ip_str);
|
||||||
if (! peer)
|
if (! peer)
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
|
|
||||||
/* Check filter direction. */
|
/* Check filter direction. */
|
||||||
if (strncmp (direct_str, "i", 1) == 0)
|
if (strncmp (direct_str, "in", 2) == 0)
|
||||||
direct = FILTER_IN;
|
direct = RMAP_IN;
|
||||||
else if (strncmp (direct_str, "o", 1) == 0)
|
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);
|
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;
|
int ret;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
int direct = FILTER_IN;
|
int direct = RMAP_IN;
|
||||||
|
|
||||||
peer = peer_and_group_lookup_vty (vty, ip_str);
|
peer = peer_and_group_lookup_vty (vty, ip_str);
|
||||||
if (! peer)
|
if (! peer)
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
|
|
||||||
/* Check filter direction. */
|
/* Check filter direction. */
|
||||||
if (strncmp (direct_str, "i", 1) == 0)
|
if (strncmp (direct_str, "in", 2) == 0)
|
||||||
direct = FILTER_IN;
|
direct = RMAP_IN;
|
||||||
else if (strncmp (direct_str, "o", 1) == 0)
|
else if (strncmp (direct_str, "o", 1) == 0)
|
||||||
|
direct = RMAP_OUT;
|
||||||
direct = FILTER_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);
|
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,
|
DEFUN (neighbor_route_map,
|
||||||
neighbor_route_map_cmd,
|
neighbor_route_map_cmd,
|
||||||
NEIGHBOR_CMD2 "route-map WORD (in|out)",
|
NEIGHBOR_CMD2 "route-map WORD (in|out|import|export)",
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Apply route map to neighbor\n"
|
"Apply route map to neighbor\n"
|
||||||
"Name of route map\n"
|
"Name of route map\n"
|
||||||
"Apply map to incoming routes\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),
|
return peer_route_map_set_vty (vty, argv[0], bgp_node_afi (vty),
|
||||||
bgp_node_safi (vty), argv[1], argv[2]);
|
bgp_node_safi (vty), argv[1], argv[2]);
|
||||||
|
@ -3322,14 +3485,16 @@ DEFUN (neighbor_route_map,
|
||||||
|
|
||||||
DEFUN (no_neighbor_route_map,
|
DEFUN (no_neighbor_route_map,
|
||||||
no_neighbor_route_map_cmd,
|
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
|
NO_STR
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Apply route map to neighbor\n"
|
"Apply route map to neighbor\n"
|
||||||
"Name of route map\n"
|
"Name of route map\n"
|
||||||
"Apply map to incoming routes\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),
|
return peer_route_map_unset_vty (vty, argv[0], bgp_node_afi (vty),
|
||||||
bgp_node_safi (vty), argv[2]);
|
bgp_node_safi (vty), argv[2]);
|
||||||
|
@ -5990,6 +6155,166 @@ ALIAS (clear_bgp_as_soft,
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
"Soft reconfig\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. */
|
/* Show BGP peer's summary information. */
|
||||||
int
|
int
|
||||||
bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
|
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
|
if (filter->plist[FILTER_IN].name
|
||||||
|| filter->dlist[FILTER_IN].name
|
|| filter->dlist[FILTER_IN].name
|
||||||
|| filter->aslist[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);
|
vty_out (vty, " Inbound path policy configured%s", VTY_NEWLINE);
|
||||||
if (filter->plist[FILTER_OUT].name
|
if (filter->plist[FILTER_OUT].name
|
||||||
|| filter->dlist[FILTER_OUT].name
|
|| filter->dlist[FILTER_OUT].name
|
||||||
|| filter->aslist[FILTER_OUT].name
|
|| filter->aslist[FILTER_OUT].name
|
||||||
|| filter->map[FILTER_OUT].name
|
|| filter->map[RMAP_OUT].name
|
||||||
|| filter->usmap.name)
|
|| filter->usmap.name)
|
||||||
vty_out (vty, " Outbound path policy configured%s", VTY_NEWLINE);
|
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 */
|
/* prefix-list */
|
||||||
if (filter->plist[FILTER_IN].name)
|
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);
|
VTY_NEWLINE);
|
||||||
|
|
||||||
/* route-map. */
|
/* 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",
|
vty_out (vty, " Route map for incoming advertisements is %s%s%s",
|
||||||
filter->map[FILTER_IN].map ? "*" : "",
|
filter->map[RMAP_IN].map ? "*" : "",
|
||||||
filter->map[FILTER_IN].name,
|
filter->map[RMAP_IN].name,
|
||||||
VTY_NEWLINE);
|
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",
|
vty_out (vty, " Route map for outgoing advertisements is %s%s%s",
|
||||||
filter->map[FILTER_OUT].map ? "*" : "",
|
filter->map[RMAP_OUT].map ? "*" : "",
|
||||||
filter->map[FILTER_OUT].name,
|
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);
|
VTY_NEWLINE);
|
||||||
|
|
||||||
/* unsuppress-map */
|
/* unsuppress-map */
|
||||||
|
@ -7156,6 +7495,262 @@ DEFUN (show_ip_bgp_attr_info,
|
||||||
return CMD_SUCCESS;
|
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. */
|
/* Redistribute VTY commands. */
|
||||||
|
|
||||||
/* Utility function to convert user input route type string to route
|
/* 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_unchanged9_cmd);
|
||||||
install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged10_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
|
/* "transparent-as" and "transparent-nexthop" for old version
|
||||||
compatibility. */
|
compatibility. */
|
||||||
install_element (BGP_NODE, &neighbor_transparent_as_cmd);
|
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);
|
install_element (ENABLE_NODE, &clear_bgp_ipv6_as_soft_cmd);
|
||||||
#endif /* HAVE_IPV6 */
|
#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. */
|
/* "show ip bgp summary" commands. */
|
||||||
install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
|
install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
|
||||||
install_element (VIEW_NODE, &show_ip_bgp_instance_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);
|
install_element (ENABLE_NODE, &show_ipv6_mbgp_summary_cmd);
|
||||||
#endif /* HAVE_IPV6 */
|
#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. */
|
/* "show ip bgp paths" commands. */
|
||||||
install_element (VIEW_NODE, &show_ip_bgp_paths_cmd);
|
install_element (VIEW_NODE, &show_ip_bgp_paths_cmd);
|
||||||
install_element (VIEW_NODE, &show_ip_bgp_ipv4_paths_cmd);
|
install_element (VIEW_NODE, &show_ip_bgp_ipv4_paths_cmd);
|
||||||
|
|
193
bgpd/bgpd.c
193
bgpd/bgpd.c
|
@ -531,6 +531,23 @@ bgp_default_local_preference_unset (struct bgp *bgp)
|
||||||
return 0;
|
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. */
|
/* Peer comparison function for sorting. */
|
||||||
static int
|
static int
|
||||||
peer_cmp (struct peer *p1, struct peer *p2)
|
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);
|
free (filter->aslist[i].name);
|
||||||
filter->aslist[i].name = NULL;
|
filter->aslist[i].name = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for (i = RMAP_IN; i < RMAP_MAX; i++)
|
||||||
|
{
|
||||||
if (filter->map[i].name)
|
if (filter->map[i].name)
|
||||||
{
|
{
|
||||||
free (filter->map[i].name);
|
free (filter->map[i].name);
|
||||||
|
@ -1092,7 +1112,18 @@ peer_delete (struct peer *peer)
|
||||||
|
|
||||||
/* Delete from all peer list. */
|
/* Delete from all peer list. */
|
||||||
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
||||||
|
{
|
||||||
listnode_delete (bgp->peer, peer);
|
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. */
|
/* Buffer. */
|
||||||
if (peer->ibuf)
|
if (peer->ibuf)
|
||||||
|
@ -1134,6 +1165,9 @@ peer_delete (struct peer *peer)
|
||||||
free (filter->plist[i].name);
|
free (filter->plist[i].name);
|
||||||
if (filter->aslist[i].name)
|
if (filter->aslist[i].name)
|
||||||
free (filter->aslist[i].name);
|
free (filter->aslist[i].name);
|
||||||
|
}
|
||||||
|
for (i = RMAP_IN; i < RMAP_MAX; i++)
|
||||||
|
{
|
||||||
if (filter->map[i].name)
|
if (filter->map[i].name)
|
||||||
free (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 */
|
/* allowas-in */
|
||||||
peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
|
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 */
|
/* default-originate route-map */
|
||||||
if (conf->default_rmap[afi][safi].name)
|
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].name = strdup (gfilter->aslist[in].name);
|
||||||
pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
|
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)
|
if (pfilter->map[RMAP_IN].name)
|
||||||
free (pfilter->map[in].name);
|
free (pfilter->map[RMAP_IN].name);
|
||||||
pfilter->map[in].name = strdup (gfilter->map[in].name);
|
pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
|
||||||
pfilter->map[in].map = gfilter->map[in].map;
|
pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* outbound filter apply */
|
/* 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].name = NULL;
|
||||||
pfilter->aslist[out].aslist = NULL;
|
pfilter->aslist[out].aslist = NULL;
|
||||||
}
|
}
|
||||||
if (gfilter->map[out].name)
|
if (gfilter->map[RMAP_OUT].name)
|
||||||
{
|
{
|
||||||
if (pfilter->map[out].name)
|
if (pfilter->map[RMAP_OUT].name)
|
||||||
free (pfilter->map[out].name);
|
free (pfilter->map[RMAP_OUT].name);
|
||||||
pfilter->map[out].name = strdup (gfilter->map[out].name);
|
pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
|
||||||
pfilter->map[out].map = gfilter->map[out].map;
|
pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pfilter->map[out].name)
|
if (pfilter->map[RMAP_OUT].name)
|
||||||
free (pfilter->map[out].name);
|
free (pfilter->map[RMAP_OUT].name);
|
||||||
pfilter->map[out].name = NULL;
|
pfilter->map[RMAP_OUT].name = NULL;
|
||||||
pfilter->map[out].map = 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)
|
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);
|
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);
|
peer_group2peer_config_copy (group, peer, afi, safi);
|
||||||
|
|
||||||
if (peer->status == Established)
|
if (peer->status == Established)
|
||||||
|
@ -1629,6 +1743,9 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
|
||||||
peer->afc[afi][safi] = 0;
|
peer->afc[afi][safi] = 0;
|
||||||
peer_af_flag_reset (peer, afi, safi);
|
peer_af_flag_reset (peer, afi, safi);
|
||||||
|
|
||||||
|
if (peer->rib[afi][safi])
|
||||||
|
peer->rib[afi][safi] = NULL;
|
||||||
|
|
||||||
if (! peer_group_active (peer))
|
if (! peer_group_active (peer))
|
||||||
{
|
{
|
||||||
listnode_delete (group->peer, peer);
|
listnode_delete (group->peer, peer);
|
||||||
|
@ -1672,6 +1789,9 @@ bgp_create (as_t *as, char *name)
|
||||||
bgp->group = list_new ();
|
bgp->group = list_new ();
|
||||||
bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
|
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 (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
||||||
{
|
{
|
||||||
|
@ -1826,6 +1946,9 @@ bgp_delete (struct bgp *bgp)
|
||||||
peer_delete (peer);
|
peer_delete (peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bgp->rsclient->del = (void (*)(void *)) peer_delete;
|
||||||
|
list_delete (bgp->rsclient);
|
||||||
|
|
||||||
listnode_delete (bm->bgp, bgp);
|
listnode_delete (bm->bgp, bgp);
|
||||||
|
|
||||||
if (bgp->name)
|
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_ALLOWAS_IN, 0, peer_change_reset_in },
|
||||||
{ PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
|
{ PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
|
||||||
{ PEER_FLAG_ORF_PREFIX_RM, 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 }
|
{ 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])
|
if (! peer->afc[afi][safi])
|
||||||
return BGP_ERR_PEER_INACTIVE;
|
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;
|
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;
|
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
|
||||||
|
|
||||||
filter = &peer->filter[afi][safi];
|
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])
|
if (! peer->afc[afi][safi])
|
||||||
return BGP_ERR_PEER_INACTIVE;
|
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;
|
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;
|
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
|
||||||
|
|
||||||
filter = &peer->filter[afi][safi];
|
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])
|
if (! peer->afc[afi][safi])
|
||||||
return BGP_ERR_AF_UNCONFIGURED;
|
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)
|
if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
|
||||||
bgp_announce_route (peer, afi, safi);
|
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);
|
filter->plist[out].name, VTY_NEWLINE);
|
||||||
|
|
||||||
/* route-map. */
|
/* route-map. */
|
||||||
if (filter->map[in].name)
|
if (filter->map[RMAP_IN].name)
|
||||||
if (! gfilter || ! gfilter->map[in].name
|
if (! gfilter || ! gfilter->map[RMAP_IN].name
|
||||||
|| strcmp (filter->map[in].name, gfilter->map[in].name) != 0)
|
|| strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
|
||||||
vty_out (vty, " neighbor %s route-map %s in%s", addr,
|
vty_out (vty, " neighbor %s route-map %s in%s", addr,
|
||||||
filter->map[in].name, VTY_NEWLINE);
|
filter->map[RMAP_IN].name, VTY_NEWLINE);
|
||||||
if (filter->map[out].name && ! gfilter)
|
if (filter->map[RMAP_OUT].name && ! gfilter)
|
||||||
vty_out (vty, " neighbor %s route-map %s out%s", addr,
|
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 */
|
/* unsuppress-map */
|
||||||
if (filter->usmap.name && ! gfilter)
|
if (filter->usmap.name && ! gfilter)
|
||||||
|
|
22
bgpd/bgpd.h
22
bgpd/bgpd.h
|
@ -65,6 +65,9 @@ struct bgp
|
||||||
/* BGP peer group. */
|
/* BGP peer group. */
|
||||||
struct list *group;
|
struct list *group;
|
||||||
|
|
||||||
|
/* BGP route-server-clients. */
|
||||||
|
struct list *rsclient;
|
||||||
|
|
||||||
/* BGP configuration. */
|
/* BGP configuration. */
|
||||||
u_int16_t config;
|
u_int16_t config;
|
||||||
#define BGP_CONFIG_ROUTER_ID (1 << 0)
|
#define BGP_CONFIG_ROUTER_ID (1 << 0)
|
||||||
|
@ -186,6 +189,12 @@ struct bgp_rd
|
||||||
u_char val[BGP_RD_SIZE];
|
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. */
|
/* BGP filter structure. */
|
||||||
struct bgp_filter
|
struct bgp_filter
|
||||||
{
|
{
|
||||||
|
@ -215,7 +224,7 @@ struct bgp_filter
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
struct route_map *map;
|
struct route_map *map;
|
||||||
} map[FILTER_MAX];
|
} map[RMAP_MAX];
|
||||||
|
|
||||||
/* Unsuppress-map. */
|
/* Unsuppress-map. */
|
||||||
struct
|
struct
|
||||||
|
@ -250,6 +259,9 @@ struct peer
|
||||||
/* Local router ID. */
|
/* Local router ID. */
|
||||||
struct in_addr local_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. */
|
/* Packet receive and send buffer. */
|
||||||
struct stream *ibuf;
|
struct stream *ibuf;
|
||||||
struct stream_fifo *obuf;
|
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_ORF_PREFIX_RM (1 << 13) /* orf capability receive-mode */
|
||||||
#define PEER_FLAG_MAX_PREFIX (1 << 14) /* maximum prefix */
|
#define PEER_FLAG_MAX_PREFIX (1 << 14) /* maximum prefix */
|
||||||
#define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */
|
#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. */
|
/* default-originate route-map. */
|
||||||
struct
|
struct
|
||||||
|
@ -480,6 +493,8 @@ struct peer
|
||||||
#define PEER_RMAP_TYPE_REDISTRIBUTE (1 << 3) /* redistribute route-map */
|
#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_DEFAULT (1 << 4) /* default-originate route-map */
|
||||||
#define PEER_RMAP_TYPE_NOSET (1 << 5) /* not allow to set commands */
|
#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
|
/* This structure's member directly points incoming packet data
|
||||||
|
@ -689,7 +704,8 @@ enum bgp_clear_type
|
||||||
BGP_CLEAR_SOFT_OUT,
|
BGP_CLEAR_SOFT_OUT,
|
||||||
BGP_CLEAR_SOFT_IN,
|
BGP_CLEAR_SOFT_IN,
|
||||||
BGP_CLEAR_SOFT_BOTH,
|
BGP_CLEAR_SOFT_BOTH,
|
||||||
BGP_CLEAR_SOFT_IN_ORF_PREFIX
|
BGP_CLEAR_SOFT_IN_ORF_PREFIX,
|
||||||
|
BGP_CLEAR_SOFT_RSCLIENT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Macros. */
|
/* 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_set (struct bgp *, u_int32_t);
|
||||||
int bgp_default_local_preference_unset (struct bgp *);
|
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_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
|
||||||
int peer_group_remote_as (struct bgp *, char *, as_t *);
|
int peer_group_remote_as (struct bgp *, char *, as_t *);
|
||||||
int peer_delete (struct peer *peer);
|
int peer_delete (struct peer *peer);
|
||||||
|
|
131
lib/routemap.c
131
lib/routemap.c
|
@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "routemap.h"
|
#include "routemap.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/* Vector for route match rules. */
|
/* Vector for route match rules. */
|
||||||
static vector route_match_vec;
|
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);
|
rule->cmd->str, rule->rule_str, VTY_NEWLINE);
|
||||||
|
|
||||||
vty_out (vty, " Action:%s", VTY_NEWLINE);
|
vty_out (vty, " Action:%s", VTY_NEWLINE);
|
||||||
if (index->exitpolicy == RMAP_GOTO)
|
|
||||||
|
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);
|
vty_out (vty, " Goto %d%s", index->nextpref, VTY_NEWLINE);
|
||||||
|
|
||||||
else if (index->exitpolicy == RMAP_NEXT)
|
else if (index->exitpolicy == RMAP_NEXT)
|
||||||
{
|
{
|
||||||
vty_out (vty, " Goto next, (entry ");
|
vty_out (vty, " Goto next, (entry ");
|
||||||
|
@ -298,6 +301,10 @@ route_map_index_delete (struct route_map_index *index, int notify)
|
||||||
else
|
else
|
||||||
index->map->head = index->next;
|
index->map->head = index->next;
|
||||||
|
|
||||||
|
/* Free 'char *nextrm' if not NULL */
|
||||||
|
if (index->nextrm)
|
||||||
|
free (index->nextrm);
|
||||||
|
|
||||||
/* Execute event hook. */
|
/* Execute event hook. */
|
||||||
if (route_map_master.event_hook && notify)
|
if (route_map_master.event_hook && notify)
|
||||||
(*route_map_master.event_hook) (RMAP_EVENT_INDEX_DELETED,
|
(*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
|
deny deny | cont
|
||||||
|
|
|
|
||||||
|
|
||||||
action) Apply Set statements, accept route
|
action)
|
||||||
If NEXT is specified, goto NEXT statement
|
-Apply Set statements, accept route
|
||||||
If GOTO is specified, goto the first clause where pref > nextpref
|
-If Call statement is present jump to the specified route-map, if it
|
||||||
If nothing is specified, do as Cisco and finish
|
denies the route we finish.
|
||||||
deny) If NEXT is specified, goto NEXT statement
|
-If NEXT is specified, goto NEXT statement
|
||||||
If nothing is specified, finally will be denied by route-map.
|
-If GOTO is specified, goto the first clause where pref > nextpref
|
||||||
cont) Goto Next index
|
-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
|
If we get no matches after we've processed all updates, then the route
|
||||||
is dropped too.
|
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
|
on-match next - If this clause is matched, then the set statements
|
||||||
are executed and then we drop through to the next clause
|
are executed and then we drop through to the next clause
|
||||||
on-match goto n - If this clause is matched, then the set statments
|
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_apply (struct route_map *map, struct prefix *prefix,
|
||||||
route_map_object_t type, void *object)
|
route_map_object_t type, void *object)
|
||||||
{
|
{
|
||||||
|
static int recursion = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct route_map_index *index;
|
struct route_map_index *index;
|
||||||
struct route_map_rule *set;
|
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)
|
if (map == NULL)
|
||||||
return RMAP_DENYMATCH;
|
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)
|
for (set = index->set_list.head; set; set = set->next)
|
||||||
ret = (*set->cmd->func_apply) (set->value, prefix,
|
ret = (*set->cmd->func_apply) (set->value, prefix,
|
||||||
type, object);
|
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)
|
switch (index->exitpolicy)
|
||||||
{
|
{
|
||||||
case RMAP_EXIT:
|
case RMAP_EXIT:
|
||||||
|
@ -781,8 +825,9 @@ route_map_apply (struct route_map *map, struct prefix *prefix,
|
||||||
{
|
{
|
||||||
/* Find the next clause to jump to */
|
/* Find the next clause to jump to */
|
||||||
struct route_map_index *next = index->next;
|
struct route_map_index *next = index->next;
|
||||||
|
int nextpref = index->nextpref;
|
||||||
|
|
||||||
while (next && next->pref < index->nextpref)
|
while (next && next->pref < nextpref)
|
||||||
{
|
{
|
||||||
index = next;
|
index = next;
|
||||||
next = next->next;
|
next = next->next;
|
||||||
|
@ -798,9 +843,6 @@ route_map_apply (struct route_map *map, struct prefix *prefix,
|
||||||
else if (index->type == RMAP_DENY)
|
else if (index->type == RMAP_DENY)
|
||||||
/* 'deny' */
|
/* 'deny' */
|
||||||
{
|
{
|
||||||
if (index->exitpolicy == RMAP_NEXT)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
return RMAP_DENYMATCH;
|
return RMAP_DENYMATCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1088,7 @@ DEFUN (no_rmap_onmatch_goto,
|
||||||
"no on-match goto",
|
"no on-match goto",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Exit policy on matches\n"
|
"Exit policy on matches\n"
|
||||||
"Next clause\n")
|
"Goto Clause number\n")
|
||||||
{
|
{
|
||||||
struct route_map_index *index;
|
struct route_map_index *index;
|
||||||
|
|
||||||
|
@ -1103,6 +1145,49 @@ DEFUN (rmap_show_name,
|
||||||
return vty_show_route_map (vty, argv[0]);
|
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. */
|
/* Configuration write function. */
|
||||||
int
|
int
|
||||||
route_map_config_write (struct vty *vty)
|
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,
|
vty_out (vty, " set %s %s%s", rule->cmd->str,
|
||||||
rule->rule_str ? rule->rule_str : "",
|
rule->rule_str ? rule->rule_str : "",
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
|
if (index->nextrm)
|
||||||
|
vty_out (vty, " call %s%s", index->nextrm, VTY_NEWLINE);
|
||||||
if (index->exitpolicy == RMAP_GOTO)
|
if (index->exitpolicy == RMAP_GOTO)
|
||||||
vty_out (vty, " on-match goto %d%s", index->nextpref,
|
vty_out (vty, " on-match goto %d%s", index->nextpref, VTY_NEWLINE);
|
||||||
VTY_NEWLINE);
|
|
||||||
if (index->exitpolicy == RMAP_NEXT)
|
if (index->exitpolicy == RMAP_NEXT)
|
||||||
vty_out (vty," on-match next%s", VTY_NEWLINE);
|
vty_out (vty," on-match next%s", VTY_NEWLINE);
|
||||||
|
|
||||||
|
@ -1173,7 +1259,16 @@ route_map_init_vty ()
|
||||||
install_element (RMAP_NODE, &no_rmap_onmatch_next_cmd);
|
install_element (RMAP_NODE, &no_rmap_onmatch_next_cmd);
|
||||||
install_element (RMAP_NODE, &rmap_onmatch_goto_cmd);
|
install_element (RMAP_NODE, &rmap_onmatch_goto_cmd);
|
||||||
install_element (RMAP_NODE, &no_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 show command */
|
||||||
install_element (ENABLE_NODE, &rmap_show_cmd);
|
install_element (ENABLE_NODE, &rmap_show_cmd);
|
||||||
install_element (ENABLE_NODE, &rmap_show_name_cmd);
|
install_element (ENABLE_NODE, &rmap_show_name_cmd);
|
||||||
|
|
|
@ -67,6 +67,9 @@ typedef enum
|
||||||
RMAP_EVENT_INDEX_DELETED
|
RMAP_EVENT_INDEX_DELETED
|
||||||
} route_map_event_t;
|
} 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. */
|
/* Route map rule structure for matching and setting. */
|
||||||
struct route_map_rule_cmd
|
struct route_map_rule_cmd
|
||||||
{
|
{
|
||||||
|
@ -118,6 +121,9 @@ struct route_map_index
|
||||||
/* If we're using "GOTO", to where do we go? */
|
/* If we're using "GOTO", to where do we go? */
|
||||||
int nextpref;
|
int nextpref;
|
||||||
|
|
||||||
|
/* If we're using "CALL", to which route-map do ew go? */
|
||||||
|
char *nextrm;
|
||||||
|
|
||||||
/* Matching rule list. */
|
/* Matching rule list. */
|
||||||
struct route_map_rule_list match_list;
|
struct route_map_rule_list match_list;
|
||||||
struct route_map_rule_list set_list;
|
struct route_map_rule_list set_list;
|
||||||
|
|
Loading…
Reference in a new issue