diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-07-25 10:28:50 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-07-26 08:09:02 +0900 |
commit | 0730e0f9dd6a00a89da85df29fd7db18a1e0f857 (patch) | |
tree | 4398855e4069508ec1bc82ea7c6f39034bd0215d | |
parent | b53944902472a3442f4a0c073458e773da019723 (diff) |
add addpath send support
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | docs/sources/configuration.md | 1 | ||||
-rw-r--r-- | server/peer.go | 31 | ||||
-rw-r--r-- | server/server.go | 73 | ||||
-rw-r--r-- | server/server_test.go | 2 | ||||
-rw-r--r-- | table/destination.go | 14 |
5 files changed, 87 insertions, 34 deletions
diff --git a/docs/sources/configuration.md b/docs/sources/configuration.md index 562a48ce..74aab7ce 100644 --- a/docs/sources/configuration.md +++ b/docs/sources/configuration.md @@ -71,6 +71,7 @@ route-reflector-client = true route-reflector-cluster-id = "192.168.0.1" [neighbors.add-paths.config] + send-max = 8 receive = true [neighbors.graceful-restart.config] enabled = true diff --git a/server/peer.go b/server/peer.go index e51efc93..4d2d1ceb 100644 --- a/server/peer.go +++ b/server/peer.go @@ -17,13 +17,14 @@ package server import ( "fmt" + "net" + "time" + "github.com/eapache/channels" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" log "github.com/sirupsen/logrus" - "net" - "time" ) const ( @@ -143,6 +144,13 @@ func (peer *Peer) isGracefulRestartEnabled() bool { return peer.fsm.pConf.GracefulRestart.State.Enabled } +func (peer *Peer) isAddPathSendEnabled(family bgp.RouteFamily) bool { + if mode, y := peer.fsm.rfMap[family]; y && (mode&bgp.BGP_ADD_PATH_SEND) > 0 { + return true + } + return false +} + func (peer *Peer) isDynamicNeighbor() bool { return peer.fsm.pConf.Config.NeighborAddress == "" && peer.fsm.pConf.Config.NeighborInterface == "" } @@ -380,13 +388,20 @@ func (peer *Peer) filterpath(path, old *table.Path) *table.Path { 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(), peer.toGlobalFamilies(rfList)) { - if p := peer.filterpath(path, nil); p != nil { - pathList = append(pathList, p) - } else { - filtered = append(filtered, path) + for _, family := range peer.toGlobalFamilies(rfList) { + pl := func() []*table.Path { + if peer.isAddPathSendEnabled(family) { + return peer.localRib.GetPathList(peer.TableID(), []bgp.RouteFamily{family}) + } + return peer.localRib.GetBestPathList(peer.TableID(), []bgp.RouteFamily{family}) + }() + for _, path := range pl { + if p := peer.filterpath(path, nil); p != nil { + pathList = append(pathList, p) + } else { + filtered = append(filtered, path) + } } - } if peer.isGracefulRestartEnabled() { for _, family := range rfList { diff --git a/server/server.go b/server/server.go index fa606c44..ac435172 100644 --- a/server/server.go +++ b/server/server.go @@ -520,24 +520,31 @@ func (server *BgpServer) notifyPostPolicyUpdateWatcher(peer *Peer, pathList []*t server.notifyWatcher(WATCH_EVENT_TYPE_POST_UPDATE, ev) } -func dstsToPaths(id string, dsts []*table.Destination) ([]*table.Path, []*table.Path, [][]*table.Path) { +func dstsToPaths(id string, dsts []*table.Destination, addpath bool) ([]*table.Path, []*table.Path, [][]*table.Path) { bestList := make([]*table.Path, 0, len(dsts)) oldList := make([]*table.Path, 0, len(dsts)) mpathList := make([][]*table.Path, 0, len(dsts)) for _, dst := range dsts { - best, old, mpath := dst.GetChanges(id, false) - bestList = append(bestList, best) - oldList = append(oldList, old) - if mpath != nil { - mpathList = append(mpathList, mpath) + if addpath { + bestList = append(bestList, dst.GetAddPathChanges(id)...) + } else { + best, old, mpath := dst.GetChanges(id, false) + bestList = append(bestList, best) + oldList = append(oldList, old) + if mpath != nil { + mpathList = append(mpathList, mpath) + } } } + if addpath { + oldList = nil + } return bestList, oldList, mpathList } func (server *BgpServer) dropPeerAllRoutes(peer *Peer, families []bgp.RouteFamily) { - var bestList []*table.Path + var gBestList, bestList []*table.Path var mpathList [][]*table.Path families = peer.toGlobalFamilies(families) rib := server.globalRib @@ -547,16 +554,20 @@ func (server *BgpServer) dropPeerAllRoutes(peer *Peer, families []bgp.RouteFamil for _, rf := range families { dsts := rib.DeletePathsByPeer(peer.fsm.peerInfo, rf) if !peer.isRouteServerClient() { - bestList, _, mpathList = dstsToPaths(table.GLOBAL_RIB_NAME, dsts) - server.notifyBestWatcher(bestList, mpathList) + gBestList, _, mpathList = dstsToPaths(table.GLOBAL_RIB_NAME, dsts, false) + server.notifyBestWatcher(gBestList, mpathList) } for _, targetPeer := range server.neighborMap { if peer.isRouteServerClient() != targetPeer.isRouteServerClient() || targetPeer == peer { continue } - if targetPeer.isRouteServerClient() { - bestList, _, _ = dstsToPaths(targetPeer.TableID(), dsts) + if targetPeer.isAddPathSendEnabled(rf) { + bestList, _, _ = dstsToPaths(targetPeer.TableID(), dsts, true) + } else if targetPeer.isRouteServerClient() { + bestList, _, _ = dstsToPaths(targetPeer.TableID(), dsts, false) + } else { + bestList = gBestList } if paths := targetPeer.processOutgoingPaths(bestList, nil); len(paths) > 0 { sendFsmOutgoingMsg(targetPeer, paths, nil, false) @@ -648,7 +659,7 @@ func (server *BgpServer) RSimportPaths(peer *Peer, pathList []*table.Path) []*ta func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) { var dsts []*table.Destination - var bestList, oldList []*table.Path + var gBestList, gOldList, bestList, oldList []*table.Path var mpathList [][]*table.Path rib := server.globalRib @@ -729,22 +740,34 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) { server.notifyPostPolicyUpdateWatcher(peer, pathList) dsts = rib.ProcessPaths(pathList) - bestList, oldList, mpathList = dstsToPaths(table.GLOBAL_RIB_NAME, dsts) - if len(bestList) == 0 { - return - } - server.notifyBestWatcher(bestList, mpathList) + gBestList, gOldList, mpathList = dstsToPaths(table.GLOBAL_RIB_NAME, dsts, false) + server.notifyBestWatcher(gBestList, mpathList) } - for _, targetPeer := range server.neighborMap { - if (peer == nil && targetPeer.isRouteServerClient()) || (peer != nil && peer.isRouteServerClient() != targetPeer.isRouteServerClient()) { - continue - } - if targetPeer.isRouteServerClient() { - bestList, oldList, _ = dstsToPaths(targetPeer.TableID(), dsts) + families := make(map[bgp.RouteFamily][]*table.Destination) + for _, dst := range dsts { + if families[dst.Family()] == nil { + families[dst.Family()] = make([]*table.Destination, 0, len(dsts)) } - if paths := targetPeer.processOutgoingPaths(bestList, oldList); len(paths) > 0 { - sendFsmOutgoingMsg(targetPeer, paths, nil, false) + families[dst.Family()] = append(families[dst.Family()], dst) + } + + for family, l := range families { + for _, targetPeer := range server.neighborMap { + if (peer == nil && targetPeer.isRouteServerClient()) || (peer != nil && peer.isRouteServerClient() != targetPeer.isRouteServerClient()) { + continue + } + if targetPeer.isAddPathSendEnabled(family) { + bestList, oldList, _ = dstsToPaths(targetPeer.TableID(), l, true) + } else if targetPeer.isRouteServerClient() { + bestList, oldList, _ = dstsToPaths(targetPeer.TableID(), l, false) + } else { + bestList = gBestList + oldList = gOldList + } + if paths := targetPeer.processOutgoingPaths(bestList, oldList); len(paths) > 0 { + sendFsmOutgoingMsg(targetPeer, paths, nil, false) + } } } } diff --git a/server/server_test.go b/server/server_test.go index b8dc58f5..ac762176 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -215,7 +215,7 @@ func newPeerandInfo(myAs, as uint32, address string, rib *table.TableManager) (* } func process(rib *table.TableManager, l []*table.Path) (*table.Path, *table.Path) { - news, olds, _ := dstsToPaths(table.GLOBAL_RIB_NAME, rib.ProcessPaths(l)) + news, olds, _ := dstsToPaths(table.GLOBAL_RIB_NAME, rib.ProcessPaths(l), false) if len(news) != 1 { panic("can't handle multiple paths") } diff --git a/table/destination.go b/table/destination.go index 78e0ac6b..c465e9f8 100644 --- a/table/destination.go +++ b/table/destination.go @@ -228,6 +228,17 @@ func (dd *Destination) GetMultiBestPath(id string) []*Path { return getMultiBestPath(id, &dd.knownPathList) } +func (dd *Destination) GetAddPathChanges(id string) []*Path { + l := make([]*Path, 0, len(dd.newPathList)+len(dd.withdrawList)) + for _, p := range dd.newPathList { + l = append(l, p) + } + for _, p := range dd.withdrawList { + l = append(l, p.Clone(true)) + } + return l +} + func (dd *Destination) GetChanges(id string, peerDown bool) (*Path, *Path, []*Path) { best, old := func(id string) (*Path, *Path) { old := getBestPath(id, &dd.oldKnownPathList) @@ -318,6 +329,7 @@ func (dd *Destination) validatePath(path *Path) { // paths from known paths. Also, adds new paths to known paths. func (dest *Destination) Calculate() *Destination { oldKnownPathList := dest.knownPathList + newPathList := dest.newPathList // First remove the withdrawn paths. withdrawn := dest.explicitWithdraw() // Do implicit withdrawal @@ -346,6 +358,8 @@ func (dest *Destination) Calculate() *Destination { nlri: dest.nlri, knownPathList: dest.knownPathList, oldKnownPathList: oldKnownPathList, + newPathList: newPathList, + withdrawList: withdrawn, } } |