From e6eb1da279769bd3d56364ab685b4fb2e0b029a7 Mon Sep 17 00:00:00 2001 From: Jordan Whited Date: Fri, 7 Aug 2020 13:30:39 -0700 Subject: fix stuck route --- pkg/server/peer.go | 26 +++++++++++++++++++++++++- pkg/server/server_test.go | 3 ++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/pkg/server/peer.go b/pkg/server/peer.go index a3f2be7b..4a7d5922 100644 --- a/pkg/server/peer.go +++ b/pkg/server/peer.go @@ -131,6 +131,15 @@ func (peer *peer) ID() string { return peer.fsm.pConf.State.NeighborAddress } +func (peer *peer) RouterID() string { + peer.fsm.lock.RLock() + defer peer.fsm.lock.RUnlock() + if peer.fsm.peerInfo.ID != nil { + return peer.fsm.peerInfo.ID.String() + } + return "" +} + func (peer *peer) TableID() string { return peer.tableId } @@ -348,7 +357,22 @@ func (peer *peer) stopPeerRestarting() { } func (peer *peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path { - if peer.ID() != path.GetSource().Address.String() { + // Consider 3 peers - A, B, C and prefix P originated by C. Parallel eBGP + // sessions exist between A & B, and both have a single session with C. + // + // When A receives the withdraw from C, we enter this func for each peer of + // A, with the following: + // peer: [C, B #1, B #2] + // path: new best for P facing B + // old: old best for P facing C + // + // Our comparison between peer identifier and path source ID must be router + // ID-based (not neighbor address), otherwise we will return early. If we + // return early for one of the two sessions facing B + // (whichever is not the new best path), we fail to send a withdraw towards + // B, and the route is "stuck". + // TODO: considerations for RFC6286 + if peer.RouterID() != path.GetSource().ID.String() { return path } diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 6f70f38a..39b10657 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -706,10 +706,11 @@ func newPeerandInfo(myAs, as uint32, address string, rib *table.TableManager) (* nConf, rib, policy) + p.fsm.peerInfo.ID = net.ParseIP(address) for _, f := range rib.GetRFlist() { p.fsm.rfMap[f] = bgp.BGP_ADD_PATH_NONE } - return p, &table.PeerInfo{AS: as, Address: net.ParseIP(address)} + return p, &table.PeerInfo{AS: as, Address: net.ParseIP(address), ID: net.ParseIP(address)} } func process(rib *table.TableManager, l []*table.Path) (*table.Path, *table.Path) { -- cgit v1.2.3