diff options
| author | Andrew Certain <certain@amazon.com> | 2012-11-07 23:50:07 +0000 | 
|---|---|---|
| committer | David Lamparter <equinox@opensourcerouting.org> | 2012-11-30 21:10:00 +0100 | 
| commit | 9d3f9705d8b386ccf006c106967c700141e5d049 (patch) | |
| tree | 9edfe2653741fa0f49ffef15bd66f5a522dcd025 | |
| parent | 3b96b78136d04ddb7e39d86577cad75acb25237a (diff) | |
bgpd: add replace-as modifier for BGP neighbor
Added replace-as modifier for BGP neighbors when using
local-as. If the replace-as modifier is specified, only the
replacement AS as specified by the local-as modifier is
prepended to the AS_PATH, not the process's AS.
In bgp_attr.c, I decided that
if (peer->change_local_as) {
  /* If replace-as is specified, we only use the change_local_as when
     advertising routes. */
  if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) {
    aspath = aspath_add_seq (aspath, peer->local_as);
  }
  aspath = aspath_add_seq (aspath, peer->change_local_as);
} else {
  aspath = aspath_add_seq (aspath, peer->local_as);
}
was clearer than the alternative that didn't duplicate the prepending of the
process's AS:
/* First, append the process local AS unless we have an alternate local_as
 * and we're replacing it (as opposed to just prepending it). */
if (! (peer->change_local_as
       && CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) ) {
  aspath = aspath_add_seq (aspath, peer->local_as);
}
if (peer->change_local_as)
  aspath = aspath_add_seq (aspath, peer->change_local_as);
}
But I could be convinced otherwise.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
| -rw-r--r-- | bgpd/bgp_attr.c | 11 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 45 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 29 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 4 | 
4 files changed, 78 insertions, 11 deletions
| diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index cdc99ab3..f48a5438 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2085,9 +2085,16 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,  	}        else  	{ -	  aspath = aspath_add_seq (aspath, peer->local_as); -	  if (peer->change_local_as) +	  if (peer->change_local_as) { +            /* If replace-as is specified, we only use the change_local_as when +               advertising routes. */ +            if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) { +              aspath = aspath_add_seq (aspath, peer->local_as); +            }  	    aspath = aspath_add_seq (aspath, peer->change_local_as); +          } else { +            aspath = aspath_add_seq (aspath, peer->local_as); +          }  	}      }    else if (peer->sort == BGP_PEER_CONFED) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index cb7ff1fa..0f288948 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1570,7 +1570,7 @@ DEFUN (neighbor_local_as,    if (! peer)      return CMD_WARNING; -  ret = peer_local_as_set (peer, atoi (argv[1]), 0); +  ret = peer_local_as_set (peer, atoi (argv[1]), 0, 0);    return bgp_vty_return (vty, ret);  } @@ -1590,10 +1590,32 @@ DEFUN (neighbor_local_as_no_prepend,    if (! peer)      return CMD_WARNING; -  ret = peer_local_as_set (peer, atoi (argv[1]), 1); +  ret = peer_local_as_set (peer, atoi (argv[1]), 1, 0);    return bgp_vty_return (vty, ret);  } +DEFUN (neighbor_local_as_no_prepend_replace_as, +       neighbor_local_as_no_prepend_replace_as_cmd, +       NEIGHBOR_CMD2 "local-as " CMD_AS_RANGE " no-prepend replace-as", +       NEIGHBOR_STR +       NEIGHBOR_ADDR_STR2 +       "Specify a local-as number\n" +       "AS number used as local AS\n" +       "Do not prepend local-as to updates from ebgp peers\n" +       "Do not prepend local-as to updates from ibgp peers\n") +{ +  struct peer *peer; +  int ret; + +  peer = peer_and_group_lookup_vty (vty, argv[0]); +  if (! peer) +    return CMD_WARNING; + +  ret = peer_local_as_set (peer, atoi (argv[1]), 1, 1); +  return bgp_vty_return (vty, ret); +} + +  DEFUN (no_neighbor_local_as,         no_neighbor_local_as_cmd,         NO_NEIGHBOR_CMD2 "local-as", @@ -1631,6 +1653,17 @@ ALIAS (no_neighbor_local_as,         "Specify a local-as number\n"         "AS number used as local AS\n"         "Do not prepend local-as to updates from ebgp peers\n") + +ALIAS (no_neighbor_local_as, +       no_neighbor_local_as_val3_cmd, +       NO_NEIGHBOR_CMD2 "local-as " CMD_AS_RANGE " no-prepend replace-as", +       NO_STR +       NEIGHBOR_STR +       NEIGHBOR_ADDR_STR2 +       "Specify a local-as number\n" +       "AS number used as local AS\n" +       "Do not prepend local-as to updates from ebgp peers\n" +       "Do not prepend local-as to updates from ibgp peers\n")  DEFUN (neighbor_password,         neighbor_password_cmd, @@ -7494,10 +7527,12 @@ bgp_show_peer (struct vty *vty, struct peer *p)    /* Configured IP address. */    vty_out (vty, "BGP neighbor is %s, ", p->host);    vty_out (vty, "remote AS %u, ", p->as); -  vty_out (vty, "local AS %u%s, ", +  vty_out (vty, "local AS %u%s%s, ",  	   p->change_local_as ? p->change_local_as : p->local_as,  	   CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ? -	   " no-prepend" : ""); +	   " no-prepend" : "", +	   CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ? +	   " replace-as" : "");    vty_out (vty, "%s link%s",  	   p->as == p->local_as ? "internal" : "external",  	   VTY_NEWLINE); @@ -9175,9 +9210,11 @@ bgp_vty_init (void)    /* "neighbor local-as" commands. */    install_element (BGP_NODE, &neighbor_local_as_cmd);    install_element (BGP_NODE, &neighbor_local_as_no_prepend_cmd); +  install_element (BGP_NODE, &neighbor_local_as_no_prepend_replace_as_cmd);    install_element (BGP_NODE, &no_neighbor_local_as_cmd);    install_element (BGP_NODE, &no_neighbor_local_as_val_cmd);    install_element (BGP_NODE, &no_neighbor_local_as_val2_cmd); +  install_element (BGP_NODE, &no_neighbor_local_as_val3_cmd);    /* "neighbor password" commands. */    install_element (BGP_NODE, &neighbor_password_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 69c8c0a3..908bdd94 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -962,6 +962,7 @@ peer_as_change (struct peer *peer, as_t as)      {        peer->change_local_as = 0;        UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); +      UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);      }  } @@ -1830,6 +1831,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,  	{  	  group->conf->change_local_as = 0;  	  UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); +	  UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);  	}      } @@ -3405,7 +3407,7 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)  }  int -peer_local_as_set (struct peer *peer, as_t as, int no_prepend) +peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)  {    struct bgp *bgp = peer->bgp;    struct peer_group *group; @@ -3421,9 +3423,14 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend)    if (peer_group_active (peer))      return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; +  if (peer->as == as) +    return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; +    if (peer->change_local_as == as &&        ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend) -       || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend))) +       || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) && +      ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as) +       || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))      return 0;    peer->change_local_as = as; @@ -3432,6 +3439,11 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend)    else      UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); +  if (replace_as) +    SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); +  else +    UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); +    if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))      {        if (peer->status == Established) @@ -3455,6 +3467,11 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend)        else  	UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); +      if (replace_as) +        SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); +      else +        UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); +        if (peer->status == Established)         {           peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; @@ -3482,6 +3499,7 @@ peer_local_as_unset (struct peer *peer)    peer->change_local_as = 0;    UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); +  UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);    if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))      { @@ -3502,6 +3520,7 @@ peer_local_as_unset (struct peer *peer)      {        peer->change_local_as = 0;        UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); +      UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);        if (peer->status == Established)         { @@ -4770,10 +4789,12 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,        /* local-as. */        if (peer->change_local_as)  	if (! peer_group_active (peer)) -	  vty_out (vty, " neighbor %s local-as %u%s%s", addr, +	  vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,  		   peer->change_local_as,  		   CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ? -		   " no-prepend" : "", VTY_NEWLINE); +		   " no-prepend" : "", +		   CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ? +		   " replace-as" : "", VTY_NEWLINE);        /* Description. */        if (peer->desc) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 63e326af..0746f0dd 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -381,6 +381,7 @@ struct peer  #define PEER_FLAG_DYNAMIC_CAPABILITY        (1 << 5) /* dynamic capability */  #define PEER_FLAG_DISABLE_CONNECTED_CHECK   (1 << 6) /* disable-connected-check */  #define PEER_FLAG_LOCAL_AS_NO_PREPEND       (1 << 7) /* local-as no-prepend */ +#define PEER_FLAG_LOCAL_AS_REPLACE_AS       (1 << 8) /* local-as no-prepend replace-as */    /* NSF mode (graceful restart) */    u_char nsf[AFI_MAX][SAFI_MAX]; @@ -814,6 +815,7 @@ enum bgp_clear_type  #define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK	-30  #define BGP_ERR_NO_IBGP_WITH_TTLHACK		-31  #define BGP_ERR_MAX				-32 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS    -33  extern struct bgp_master *bm; @@ -941,7 +943,7 @@ extern int peer_distribute_unset (struct peer *, afi_t, safi_t, int);  extern int peer_allowas_in_set (struct peer *, afi_t, safi_t, int);  extern int peer_allowas_in_unset (struct peer *, afi_t, safi_t); -extern int peer_local_as_set (struct peer *, as_t, int); +extern int peer_local_as_set (struct peer *, as_t, int, int);  extern int peer_local_as_unset (struct peer *);  extern int peer_prefix_list_set (struct peer *, afi_t, safi_t, int, const char *); | 
