diff options
-rw-r--r-- | server/peer.go | 14 | ||||
-rw-r--r-- | server/server.go | 18 | ||||
-rw-r--r-- | table/destination.go | 25 | ||||
-rw-r--r-- | table/destination_test.go | 14 | ||||
-rw-r--r-- | table/table_manager.go | 14 |
5 files changed, 43 insertions, 42 deletions
diff --git a/server/peer.go b/server/peer.go index 4c76248c..15c25353 100644 --- a/server/peer.go +++ b/server/peer.go @@ -233,7 +233,7 @@ func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path { return peer.adjRibIn.PathList(rfList, true) } -func (peer *Peer) filterpath(path *table.Path, withdrawals []*table.Path) *table.Path { +func (peer *Peer) filterpath(path, old *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 { @@ -268,7 +268,7 @@ func (peer *Peer) filterpath(path *table.Path, withdrawals []*table.Path) *table } } - if path = filterpath(peer, path, withdrawals); path == nil { + if path = filterpath(peer, path, old); path == nil { return nil } @@ -324,7 +324,7 @@ func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []* return pathList, filtered } -func (peer *Peer) processOutgoingPaths(paths, withdrawals []*table.Path) []*table.Path { +func (peer *Peer) processOutgoingPaths(paths, olds []*table.Path) []*table.Path { if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED { return nil } @@ -338,8 +338,12 @@ func (peer *Peer) processOutgoingPaths(paths, withdrawals []*table.Path) []*tabl outgoing := make([]*table.Path, 0, len(paths)) - for _, path := range paths { - if p := peer.filterpath(path, withdrawals); p != nil { + for idx, path := range paths { + var old *table.Path + if olds != nil { + old = olds[idx] + } + if p := peer.filterpath(path, old); p != nil { outgoing = append(outgoing, p) } } diff --git a/server/server.go b/server/server.go index 263bc00c..e97fd7f6 100644 --- a/server/server.go +++ b/server/server.go @@ -269,7 +269,7 @@ func isASLoop(peer *Peer, path *table.Path) bool { return false } -func filterpath(peer *Peer, path *table.Path, withdrawals []*table.Path) *table.Path { +func filterpath(peer *Peer, path, old *table.Path) *table.Path { if path == nil { return nil } @@ -377,10 +377,8 @@ func filterpath(peer *Peer, path *table.Path, withdrawals []*table.Path) *table. // the withdrawal path. // Thing is same when peer A and we advertized prefix P (as local // route), then, we withdraws the prefix. - for _, w := range withdrawals { - if path.GetNlri().String() == w.GetNlri().String() { - return w - } + if old != nil { + return old.Clone(true) } } log.WithFields(log.Fields{ @@ -512,8 +510,8 @@ func (server *BgpServer) RSimportPaths(peer *Peer, pathList []*table.Path) []*ta func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []*table.Path { rib := server.globalRib - var alteredPathList, withdrawn []*table.Path - var best map[string][]*table.Path + var alteredPathList []*table.Path + var best, old map[string][]*table.Path if peer != nil && peer.fsm.pConf.Config.Vrf != "" { vrf := server.globalRib.Vrfs[peer.fsm.pConf.Config.Vrf] @@ -544,7 +542,7 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []* ids = append(ids, targetPeer.TableID()) } } - best, withdrawn, _ = rib.ProcessPaths(ids, append(pathList, moded...)) + best, old, _ = rib.ProcessPaths(ids, append(pathList, moded...)) } else { for idx, path := range pathList { path = server.policy.ApplyPolicy(table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_IMPORT, path, nil) @@ -596,7 +594,7 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []* } alteredPathList = pathList var multipath [][]*table.Path - best, withdrawn, multipath = rib.ProcessPaths([]string{table.GLOBAL_RIB_NAME}, pathList) + best, old, multipath = rib.ProcessPaths([]string{table.GLOBAL_RIB_NAME}, pathList) if len(best[table.GLOBAL_RIB_NAME]) == 0 { return alteredPathList } @@ -607,7 +605,7 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []* if (peer == nil && targetPeer.isRouteServerClient()) || (peer != nil && peer.isRouteServerClient() != targetPeer.isRouteServerClient()) { continue } - if paths := targetPeer.processOutgoingPaths(best[targetPeer.TableID()], withdrawn); len(paths) > 0 { + if paths := targetPeer.processOutgoingPaths(best[targetPeer.TableID()], old[targetPeer.TableID()]); len(paths) > 0 { sendFsmOutgoingMsg(targetPeer, paths, nil, false) } } diff --git a/table/destination.go b/table/destination.go index 2d081682..f9ed0e2f 100644 --- a/table/destination.go +++ b/table/destination.go @@ -206,11 +206,12 @@ func (dd *Destination) validatePath(path *Path) { // // Modifies destination's state related to stored paths. Removes withdrawn // paths from known paths. Also, adds new paths to known paths. -func (dest *Destination) Calculate(ids []string) (map[string]*Path, []*Path, []*Path) { - best := make(map[string]*Path, len(ids)) +func (dest *Destination) Calculate(ids []string) (map[string]*Path, map[string]*Path, []*Path) { + bestList := make(map[string]*Path, len(ids)) + oldList := make(map[string]*Path, len(ids)) oldKnownPathList := dest.knownPathList // First remove the withdrawn paths. - withdrawnList := dest.explicitWithdraw() + dest.explicitWithdraw() // Do implicit withdrawal dest.implicitWithdraw() // Collect all new paths into known paths. @@ -220,7 +221,7 @@ func (dest *Destination) Calculate(ids []string) (map[string]*Path, []*Path, []* // Compute new best path dest.computeKnownBestPath() - f := func(id string) *Path { + f := func(id string) (*Path, *Path) { old := func() *Path { for _, p := range oldKnownPathList { if p.Filtered(id) == POLICY_DIRECTION_NONE { @@ -237,22 +238,22 @@ func (dest *Destination) Calculate(ids []string) (map[string]*Path, []*Path, []* // given RT prefix, for building the outbound route filter, and not just // the best path. if best.GetRouteFamily() == bgp.RF_RTC_UC { - return best + return best, old } - return nil + return nil, old } if best == nil { if old == nil { - return nil + return nil, nil } - return old.Clone(true) + return old.Clone(true), old } - return best + return best, old } var multi []*Path for _, id := range ids { - best[id] = f(id) + bestList[id], oldList[id] = f(id) if id == GLOBAL_RIB_NAME && UseMultiplePaths.Enabled { multipath := func(paths []*Path) []*Path { mp := make([]*Path, 0, len(paths)) @@ -285,13 +286,13 @@ func (dest *Destination) Calculate(ids []string) (map[string]*Path, []*Path, []* if diff(oldM, newM) { multi = newM if len(newM) == 0 { - multi = []*Path{best[id]} + multi = []*Path{bestList[id]} } } } } - return best, withdrawnList, multi + return bestList, oldList, multi } // Removes withdrawn paths. diff --git a/table/destination_test.go b/table/destination_test.go index 7cace89e..7bcf6599 100644 --- a/table/destination_test.go +++ b/table/destination_test.go @@ -438,17 +438,17 @@ func TestMultipath(t *testing.T) { d.AddNewPath(path1) d.AddNewPath(path2) - best, w, multi := d.Calculate([]string{GLOBAL_RIB_NAME}) + best, old, multi := d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) - assert.Equal(t, len(w), 0) + assert.Equal(t, old[GLOBAL_RIB_NAME], (*Path)(nil)) assert.Equal(t, len(multi), 2) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 2) path3 := path2.Clone(true) d.AddWithdraw(path3) - best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) + best, old, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) - assert.Equal(t, len(w), 1) + assert.Equal(t, old[GLOBAL_RIB_NAME], path1) assert.Equal(t, len(multi), 1) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 1) @@ -465,9 +465,8 @@ func TestMultipath(t *testing.T) { path4 := ProcessMessage(updateMsg, peer3, time.Now())[0] d.AddNewPath(path4) - best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) + best, _, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) - assert.Equal(t, len(w), 0) assert.Equal(t, len(multi), 1) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 2) @@ -482,9 +481,8 @@ func TestMultipath(t *testing.T) { path5 := ProcessMessage(updateMsg, peer2, time.Now())[0] d.AddNewPath(path5) - best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) + best, _, multi = d.Calculate([]string{GLOBAL_RIB_NAME}) assert.Equal(t, len(best), 1) - assert.Equal(t, len(w), 0) assert.Equal(t, len(multi), 2) assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 3) diff --git a/table/table_manager.go b/table/table_manager.go index 4b52e745..ae00d3ce 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -185,9 +185,9 @@ func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) { return msgs, nil } -func (manager *TableManager) calculate(ids []string, destinations []*Destination) (map[string][]*Path, []*Path, [][]*Path) { - withdrawn := make([]*Path, 0, len(destinations)) +func (manager *TableManager) calculate(ids []string, destinations []*Destination) (map[string][]*Path, map[string][]*Path, [][]*Path) { best := make(map[string][]*Path, len(ids)) + old := make(map[string][]*Path, len(ids)) emptyDsts := make([]*Destination, 0, len(destinations)) var multi [][]*Path @@ -200,11 +200,11 @@ func (manager *TableManager) calculate(ids []string, destinations []*Destination "Topic": "table", "Key": dst.GetNlri().String(), }).Debug("Processing destination") - paths, w, m := dst.Calculate(ids) + paths, olds, m := dst.Calculate(ids) for id, path := range paths { best[id] = append(best[id], path) + old[id] = append(old[id], olds[id]) } - withdrawn = append(withdrawn, w...) if m != nil { multi = append(multi, m) } @@ -218,10 +218,10 @@ func (manager *TableManager) calculate(ids []string, destinations []*Destination t := manager.Tables[dst.Family()] t.deleteDest(dst) } - return best, withdrawn, multi + return best, old, multi } -func (manager *TableManager) DeletePathsByPeer(ids []string, info *PeerInfo, rf bgp.RouteFamily) (map[string][]*Path, []*Path, [][]*Path) { +func (manager *TableManager) DeletePathsByPeer(ids []string, info *PeerInfo, rf bgp.RouteFamily) (map[string][]*Path, map[string][]*Path, [][]*Path) { if t, ok := manager.Tables[rf]; ok { dsts := t.DeleteDestByPeer(info) return manager.calculate(ids, dsts) @@ -229,7 +229,7 @@ func (manager *TableManager) DeletePathsByPeer(ids []string, info *PeerInfo, rf return nil, nil, nil } -func (manager *TableManager) ProcessPaths(ids []string, pathList []*Path) (map[string][]*Path, []*Path, [][]*Path) { +func (manager *TableManager) ProcessPaths(ids []string, pathList []*Path) (map[string][]*Path, map[string][]*Path, [][]*Path) { m := make(map[string]bool, len(pathList)) dsts := make([]*Destination, 0, len(pathList)) for _, path := range pathList { |