mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
add addpath send support
Signed-off-by: FUJITA Tomonori <[email protected]>
This commit is contained in:
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user