Fix BGP's use of restart bit.
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.
Incorporated feedback from David Lamparter via the quagga-dev mailing list.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
Reviewed-by: Paul Jakma <paul@opensourcerouting.org>
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 7bf3501..fe741aa 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -344,7 +344,10 @@
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 @@
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 @@
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;