add addpath send support

Signed-off-by: FUJITA Tomonori <[email protected]>
This commit is contained in:
FUJITA Tomonori
2017-07-26 08:09:02 +09:00
parent b539449024
commit 0730e0f9dd
5 changed files with 87 additions and 34 deletions
+1
View File
@@ -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
+23 -8
View File
@@ -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 {
+48 -25
View File
@@ -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
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 targetPeer.isRouteServerClient() {
bestList, oldList, _ = dstsToPaths(targetPeer.TableID(), 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)
}
}
}
}
+1 -1
View File
@@ -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")
}
+14
View File
@@ -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,
}
}