bgpd: Rollback "always send OPEN" a little, to workaround test suite issues
* "bgpd: Send OPEN immediately on inbound connections" doesn't play well with
some partial BGP implementations, test and conformance suites e.g., which
have rigid expectations about ordering and don't implement much of CD.
roll back, but only a little, by deferring OPEN sending on outbound till
receive.
* bgpd.h: (struct peer) add PEER_STATUS_OPEN_DEFERRED status flag.
Kind of a sub-fsm. Main FSM does not allow transition functions to
signal next-state - next-state is inflexibly fixed in the table -
so can't handle it cleanly at that level.
* bgp_fsm.c: (bgp_connect_success) Defer sending open if the peer is
an accept-peer/inbound and there appears to be an outbound connection
in progress. Set PEER_STATUS_OPEN_DEFERRED to signal to bgp_open_receive
that an OPEN still must be sent.
* bgp_packet.c: (bgp_open_receive) Send the OPEN here, when deferred.
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 84fddeb..4198a8e 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -656,6 +656,8 @@
static int
bgp_connect_success (struct peer *peer)
{
+ struct peer *realpeer;
+
if (peer->fd < 0)
{
zlog_err ("bgp_connect_success peer's fd is negative value %d",
@@ -677,7 +679,28 @@
else
zlog_debug ("%s passive open", peer->host);
}
-
+
+ /* Generally we want to send OPEN ASAP. Except, some partial BGP
+ * implementations out there (e.g., conformance test tools / BGP
+ * traffic generators) seem to be a bit funny about connection collisions,
+ * and OPENs before they have sent.
+ *
+ * As a hack, delay sending OPEN on an inbound accept-peer session
+ * _IF_ we locally have an outbound connection in progress, i.e.
+ * we're in middle of a connection collision. If we delay, we delay until
+ * an Open is received - as per old Quagga behaviour.
+ */
+ if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ {
+ realpeer = peer_lookup (peer->bgp, &peer->su);
+
+ if (realpeer->status > Idle && realpeer->status <= Established)
+ {
+ SET_FLAG (peer->sflags, PEER_STATUS_OPEN_DEFERRED);
+ return 0;
+ }
+ }
+
bgp_open_send (peer);
return 0;