From a7521827e1d8c964f1c9f342dc39d02f45660c49 Mon Sep 17 00:00:00 2001 From: ISHIDA Wataru Date: Sat, 21 May 2016 15:00:41 +0000 Subject: server/table: fix intra-AS RTC route distribution Signed-off-by: ISHIDA Wataru --- server/peer.go | 68 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'server/peer.go') diff --git a/server/peer.go b/server/peer.go index c985d771..f75b6d57 100644 --- a/server/peer.go +++ b/server/peer.go @@ -130,28 +130,48 @@ func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path { return peer.adjRibIn.PathList(rfList, true) } -func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*table.Path) { - pathList := []*table.Path{} - filtered := []*table.Path{} +func (peer *Peer) filterpath(path *table.Path) *table.Path { + // special handling for RTC nlri + // see comments in (*Destination).Calculate() + if path != nil && path.GetRouteFamily() == bgp.RF_RTC_UC && !path.IsWithdraw { + // if we already sent the same nlri, ignore this + if peer.adjRibOut.Exists(path) { + return nil + } + dst := peer.localRib.GetDestination(path) + path = nil + // we send a path even if it is not a best path + for _, p := range dst.GetKnownPathList(peer.TableID()) { + // just take care not to send back it + if peer.ID() != p.GetSource().Address.String() { + path = p + break + } + } + } + if filterpath(peer, path) == nil { + return nil + } + if !peer.isRouteServerClient() { + path = path.Clone(path.IsWithdraw) + path.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf) + } options := &table.PolicyOptions{ Neighbor: peer.fsm.peerInfo.Address, } + return peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options) +} + +func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*table.Path) { + pathList := []*table.Path{} + filtered := []*table.Path{} for _, path := range peer.localRib.GetBestPathList(peer.TableID(), rfList) { - if filterpath(peer, path) == nil { - continue - } - p := path - if !peer.isRouteServerClient() { - p = path.Clone(p.IsWithdraw) - p.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf) - } - p = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, p, options) - if p == nil { + if p := peer.filterpath(path); p != nil { + pathList = append(pathList, p) + } else { filtered = append(filtered, path) - continue } - pathList = append(pathList, p) } if peer.isGracefulRestartEnabled() { for _, family := range rfList { @@ -189,24 +209,10 @@ func (peer *Peer) processOutgoingPaths(paths, withdrawals []*table.Path) []*tabl } } - options := &table.PolicyOptions{ - Neighbor: peer.fsm.peerInfo.Address, - } for _, path := range paths { - if filterpath(peer, path) == nil { - continue - } - if !peer.isRouteServerClient() { - path = path.Clone(path.IsWithdraw) - path.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf) + if p := peer.filterpath(path); p != nil { + outgoing = append(outgoing, p) } - - path = peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, path, options) - if path == nil { - continue - } - - outgoing = append(outgoing, path) } peer.adjRibOut.Update(outgoing) -- cgit v1.2.3