Add replace-as option to remove-private-as

This commit is contained in:
Donald Sharp 2015-05-19 17:57:34 -07:00
parent cd92e54816
commit 5000f21c25
6 changed files with 303 additions and 34 deletions

View file

@ -463,13 +463,11 @@ aspath_highest (struct aspath *aspath)
struct assegment *seg = aspath->segments;
as_t highest = 0;
unsigned int i;
while (seg)
{
for (i = 0; i < seg->length; i++)
if (seg->as[i] > highest
&& (seg->as[i] < BGP_PRIVATE_AS_MIN
|| seg->as[i] > BGP_PRIVATE_AS_MAX))
if (seg->as[i] > highest && !BGP_AS_IS_PRIVATE(seg->as[i]))
highest = seg->as[i];
seg = seg->next;
}
@ -1128,22 +1126,19 @@ int
aspath_private_as_check (struct aspath *aspath)
{
struct assegment *seg;
if ( !(aspath && aspath->segments) )
return 0;
seg = aspath->segments;
while (seg)
{
int i;
for (i = 0; i < seg->length; i++)
{
if ( (seg->as[i] < BGP_PRIVATE_AS_MIN)
|| (seg->as[i] > BGP_PRIVATE_AS_MAX &&
seg->as[i] < BGP_PRIVATE_AS4_MIN)
|| (seg->as[i] > BGP_PRIVATE_AS4_MAX))
if (!BGP_AS_IS_PRIVATE(seg->as[i]))
return 0;
}
seg = seg->next;
@ -1151,6 +1146,105 @@ aspath_private_as_check (struct aspath *aspath)
return 1;
}
/* Replace all private ASNs with our own ASN */
struct aspath *
aspath_replace_private_asns (struct aspath *aspath, as_t asn)
{
struct aspath *new;
struct assegment *seg;
new = aspath_dup(aspath);
seg = new->segments;
while (seg)
{
int i;
for (i = 0; i < seg->length; i++)
{
if (BGP_AS_IS_PRIVATE(seg->as[i]))
seg->as[i] = asn;
}
seg = seg->next;
}
aspath_str_update(new);
return new;
}
/* Remove all private ASNs */
struct aspath *
aspath_remove_private_asns (struct aspath *aspath)
{
struct aspath *new;
struct assegment *seg;
struct assegment *new_seg;
struct assegment *last_new_seg;
int i;
int j;
int public = 0;
new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
new_seg = NULL;
last_new_seg = NULL;
seg = aspath->segments;
while (seg)
{
public = 0;
for (i = 0; i < seg->length; i++)
{
// ASN is public
if (!BGP_AS_IS_PRIVATE(seg->as[i]))
{
public++;
}
}
// The entire segment is private so skip it
if (!public)
{
seg = seg->next;
continue;
}
// The entire segment is public so copy it
else if (public == seg->length)
{
new_seg = assegment_dup (seg);
}
// The segment is a mix of public and private ASNs. Copy as many spots as
// there are public ASNs then come back and fill in only the public ASNs.
else
{
new_seg = assegment_new (seg->type, public);
j = 0;
for (i = 0; i < seg->length; i++)
{
// ASN is public
if (!BGP_AS_IS_PRIVATE(seg->as[i]))
{
new_seg->as[j] = seg->as[i];
j++;
}
}
}
// This is the first segment so set the aspath segments pointer to this one
if (!last_new_seg)
new->segments = new_seg;
else
last_new_seg->next = new_seg;
last_new_seg = new_seg;
seg = seg->next;
}
aspath_str_update(new);
return new;
}
/* AS path confed check. If aspath contains confed set or sequence then return 1. */
int
aspath_confed_check (struct aspath *aspath)

View file

@ -41,6 +41,10 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
/* Transition 16Bit AS as defined by IANA */
#define BGP_AS_TRANS 23456U
#define BGP_AS_IS_PRIVATE(ASN) \
(((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \
((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
/* AS_PATH segment data in abstracted form, no limit is placed on length */
struct assegment
{
@ -93,6 +97,8 @@ extern void aspath_print_all_vty (struct vty *);
extern unsigned int aspath_key_make (void *);
extern int aspath_loop_check (struct aspath *, as_t);
extern int aspath_private_as_check (struct aspath *);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn);
extern struct aspath *aspath_remove_private_asns (struct aspath *aspath);
extern int aspath_firstas_check (struct aspath *, as_t);
extern int aspath_confed_check (struct aspath *);
extern int aspath_left_confed_check (struct aspath *);

View file

@ -863,6 +863,42 @@ bgp_import_modifier (struct peer *rsclient, struct peer *peer,
return RMAP_PERMIT;
}
/* If this is an EBGP peer with remove-private-AS */
void
bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
struct peer *peer, struct attr *attr)
{
if (peer->sort == BGP_PEER_EBGP &&
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))
{
// Take action on the entire aspath
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
{
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as);
// The entire aspath consists of private ASNs so create an empty aspath
else if (aspath_private_as_check (attr->aspath))
attr->aspath = aspath_empty_get ();
// There are some public and some private ASNs, remove the private ASNs
else
attr->aspath = aspath_remove_private_asns (attr->aspath);
}
// 'all' was not specified so the entire aspath must be private ASNs
// for us to do anything
else if (aspath_private_as_check (attr->aspath))
{
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as);
else
attr->aspath = aspath_empty_get ();
}
}
}
static int
bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi)
@ -1128,11 +1164,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
}
#endif /* HAVE_IPV6 */
/* If this is EBGP peer and remove-private-AS is set. */
if (peer->sort == BGP_PEER_EBGP
&& peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
&& aspath_private_as_check (attr->aspath))
attr->aspath = aspath_empty_get ();
bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME (filter)
@ -1184,9 +1216,11 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
struct bgp_info info;
struct peer *from;
struct attr *riattr;
struct bgp *bgp;
from = ri->peer;
filter = &rsclient->filter[afi][safi];
bgp = rsclient->bgp;
riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
if (DISABLE_BGP_ANNOUNCE)
@ -1340,12 +1374,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
}
#endif /* HAVE_IPV6 */
/* If this is EBGP peer and remove-private-AS is set. */
if (rsclient->sort == BGP_PEER_EBGP
&& peer_af_flag_check (rsclient, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
&& aspath_private_as_check (attr->aspath))
attr->aspath = aspath_empty_get ();
bgp_peer_remove_private_as(bgp, afi, safi, rsclient, attr);
/* Route map & unsuppress-map apply. */
if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) )

View file

@ -215,7 +215,7 @@ bgp_vty_return (struct vty *vty, int ret)
str = "Invalid command. Not an internal neighbor";
break;
case BGP_ERR_REMOVE_PRIVATE_AS:
str = "Private AS cannot be removed for IBGP peers";
str = "remove-private-AS cannot be configured for IBGP peers";
break;
case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP:
str = "Local-AS allowed only for EBGP peers";
@ -2663,26 +2663,111 @@ DEFUN (neighbor_remove_private_as,
NEIGHBOR_CMD2 "remove-private-AS",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private AS number from outbound updates\n")
"Remove private ASNs in outbound updates\n")
{
peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS);
}
DEFUN (neighbor_remove_private_as_all,
neighbor_remove_private_as_all_cmd,
NEIGHBOR_CMD2 "remove-private-AS all",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n"
"Apply to all AS numbers")
{
peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
}
DEFUN (neighbor_remove_private_as_replace_as,
neighbor_remove_private_as_replace_as_cmd,
NEIGHBOR_CMD2 "remove-private-AS replace-AS",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n"
"Replace private ASNs with our ASN in outbound updates\n")
{
peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
}
DEFUN (neighbor_remove_private_as_all_replace_as,
neighbor_remove_private_as_all_replace_as_cmd,
NEIGHBOR_CMD2 "remove-private-AS all replace-AS",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n"
"Apply to all AS numbers"
"Replace private ASNs with our ASN in outbound updates\n")
{
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
}
DEFUN (no_neighbor_remove_private_as,
no_neighbor_remove_private_as_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private AS number from outbound updates\n")
"Remove private ASNs in outbound updates\n")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS);
PEER_FLAG_REMOVE_PRIVATE_AS|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
}
ALIAS (no_neighbor_remove_private_as,
no_neighbor_remove_private_as_all_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS all",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n"
"Apply to all AS numbers")
ALIAS (no_neighbor_remove_private_as,
no_neighbor_remove_private_as_replace_as_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS replace-AS",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n"
"Replace private ASNs with our ASN in outbound updates\n")
ALIAS (no_neighbor_remove_private_as,
no_neighbor_remove_private_as_all_replace_as_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS all replace-AS",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n"
"Apply to all AS numbers"
"Replace private ASNs with our ASN in outbound updates\n")
/* neighbor send-community. */
DEFUN (neighbor_send_community,
neighbor_send_community_cmd,
@ -8154,9 +8239,13 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi)
vty_out (vty, " Route-Server Client%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
vty_out (vty, " Inbound soft reconfiguration allowed%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
vty_out (vty, " Private AS number removed from updates to this neighbor%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF))
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
vty_out (vty, " Private AS numbers replaced in updates to this neighbor%s", VTY_NEWLINE);
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
vty_out (vty, " Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) ||
CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF_ALL))
vty_out (vty, " NEXT_HOP is always this router%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED))
vty_out (vty, " AS_PATH is propagated unchanged to this neighbor%s", VTY_NEWLINE);
@ -10226,16 +10315,52 @@ bgp_vty_init (void)
/* "neighbor remove-private-AS" commands. */
install_element (BGP_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_NODE, &neighbor_remove_private_as_all_cmd);
install_element (BGP_NODE, &no_neighbor_remove_private_as_all_cmd);
install_element (BGP_NODE, &neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_cmd);
install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd);
install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd);
install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd);
install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_cmd);
install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
/* "neighbor send-community" commands.*/
install_element (BGP_NODE, &neighbor_send_community_cmd);

View file

@ -2643,6 +2643,8 @@ static const struct peer_flag_action peer_af_flag_action_list[] =
{ PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
{ PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
{ PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
{ PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
{ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
{ 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 },
@ -5440,11 +5442,22 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
" all" : "", VTY_NEWLINE);
/* Remove private AS. */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
&& ! peer->af_group[afi][safi])
vty_out (vty, " neighbor %s remove-private-AS%s",
addr, VTY_NEWLINE);
/* remove-private-AS */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi])
{
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) &&
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE);
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
vty_out (vty, " neighbor %s remove-private-AS replace-AS%s", addr, VTY_NEWLINE);
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
vty_out (vty, " neighbor %s remove-private-AS all%s", addr, VTY_NEWLINE);
else
vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE);
}
/* send-community print. */
if (! peer->af_group[afi][safi])

View file

@ -482,6 +482,8 @@ struct peer
#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 */
#define PEER_FLAG_NEXTHOP_SELF_ALL (1 << 17) /* next-hop-self all */
#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1 << 18) /* remove-private-as all */
#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */
/* MD5 password */
char *password;