bgpd: bgpd-restart-bit-fix.patch

ISSUE:

Quagga BGP doesn't send or use the restart-bit via the Graceful-Restart(GR)
capability. GR capability implementation isn't complete as per the RFC.

PATCH:

Patch uses BGP instance creation as the beginning of the startup period,
and 'restart_time' is taken as the startup period. As a result, BGP will
set the restart bit in the GR capability of the OPEN messages during the
startup period.

As an indication of quagga implementation's capability of sending End-Of-RIB,
helping a restarting neighbor, quagga BGP will now send global GR capability
irrespective of the graceful-restart config in BGP and the address-family
specific GR capability will be sent only if the GR config is present.
Forwarding bit is not set assuming its not preserved.

Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2015-05-19 17:40:32 -07:00
parent a6cdbcfd68
commit fe7d2a4834
4 changed files with 64 additions and 10 deletions

View File

@ -344,7 +344,10 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
restart_flag_time = stream_getw(s);
if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
restart_bit = 1;
{
SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
restart_bit = 1;
}
UNSET_FLAG (restart_flag_time, 0xF000);
peer->v_gr_restart = restart_flag_time;
@ -898,10 +901,11 @@ void
bgp_open_capability (struct stream *s, struct peer *peer)
{
u_char len;
unsigned long cp;
unsigned long cp, capp, rcapp;
afi_t afi;
safi_t safi;
as_t local_as;
u_int32_t restart_time;
/* Remember current pointer for Opt Parm Len. */
cp = stream_get_endp (s);
@ -1020,16 +1024,43 @@ bgp_open_capability (struct stream *s, struct peer *peer)
stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
}
/* Graceful restart capability */
/* Sending base graceful-restart capability irrespective of the config */
SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP);
capp = stream_get_endp (s); /* Set Capability Len Pointer */
stream_putc (s, 0); /* Capability Length */
stream_putc (s, CAPABILITY_CODE_RESTART);
rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
stream_putc (s, 0);
restart_time = peer->bgp->restart_time;
if (peer->bgp->t_startup)
{
SET_FLAG (restart_time, RESTART_R_BIT);
SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
}
stream_putw (s, restart_time);
/* Send address-family specific graceful-restart capability only when GR config
is present */
if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
{
SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
stream_putc (s, CAPABILITY_CODE_RESTART);
stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
stream_putw (s, peer->bgp->restart_time);
}
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
if (peer->afc[afi][safi])
{
stream_putw (s, afi);
stream_putc (s, safi);
stream_putc (s, 0); //Forwarding is not retained as of now.
}
}
/* Total Graceful restart capability Len. */
len = stream_get_endp (s) - rcapp - 1;
stream_putc_at (s, rcapp, len);
/* Total Capability Len. */
len = stream_get_endp (s) - capp - 1;
stream_putc_at (s, capp, len);
/* Total Opt Parm Len. */
len = stream_get_endp (s) - cp - 1;

View File

@ -614,6 +614,10 @@ bgp_write_packet (struct peer *peer)
{
if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
&& CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
&& ! (CHECK_FLAG (adv->binfo->peer->cap,
PEER_CAP_RESTART_BIT_RCV) &&
CHECK_FLAG (adv->binfo->peer->cap,
PEER_CAP_RESTART_BIT_ADV))
&& ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
&& safi != SAFI_MPLS_VPN)
{

View File

@ -1927,6 +1927,18 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
return 0;
}
static int
bgp_startup_timer_expire (struct thread *thread)
{
struct bgp *bgp;
bgp = THREAD_ARG (thread);
bgp->t_startup = NULL;
return 0;
}
/* BGP instance creation by `router bgp' commands. */
static struct bgp *
bgp_create (as_t *as, const char *name)
@ -1972,6 +1984,9 @@ bgp_create (as_t *as, const char *name)
if (name)
bgp->name = strdup (name);
THREAD_TIMER_ON (master, bgp->t_startup, bgp_startup_timer_expire,
bgp, bgp->restart_time);
return bgp;
}

View File

@ -104,6 +104,8 @@ struct bgp
as_t *confed_peers;
int confed_peers_cnt;
struct thread *t_startup;
/* BGP flags. */
u_int16_t flags;
#define BGP_FLAG_ALWAYS_COMPARE_MED (1 << 0)
@ -368,6 +370,8 @@ struct peer
#define PEER_CAP_RESTART_RCV (1 << 6) /* restart received */
#define PEER_CAP_AS4_ADV (1 << 7) /* as4 advertised */
#define PEER_CAP_AS4_RCV (1 << 8) /* as4 received */
#define PEER_CAP_RESTART_BIT_ADV (1 << 9) /* sent restart state */
#define PEER_CAP_RESTART_BIT_RCV (1 << 10) /* peer restart state */
/* Capability flags (reset in bgp_stop) */
u_int16_t af_cap[AFI_MAX][SAFI_MAX];