add route collector feature support

like openbgp's route collector, sends all updates (not only best).

Signed-off-by: FUJITA Tomonori <[email protected]>
This commit is contained in:
FUJITA Tomonori
2016-02-06 15:07:36 -08:00
parent fa6c8fe58b
commit d280168106
7 changed files with 125 additions and 46 deletions
+9
View File
@@ -1503,6 +1503,13 @@ type BmpServer struct {
State BmpServerState `mapstructure:"state"`
}
//struct for container gobgp:collector
type Collector struct {
// original -> gobgp:enabled
//gobgp:enabled's original type is boolean
Enabled bool `mapstructure:"enabled"`
}
//struct for container bgp-mp:l2vpn-evpn
type L2vpnEvpn struct {
// original -> bgp-mp:prefix-limit
@@ -2031,6 +2038,8 @@ type Global struct {
AfiSafis []AfiSafi `mapstructure:"afi-safis"`
// original -> rpol:apply-policy
ApplyPolicy ApplyPolicy `mapstructure:"apply-policy"`
// original -> gobgp:collector
Collector Collector `mapstructure:"collector"`
// original -> gobgp:bmp-servers
BmpServers []BmpServer `mapstructure:"bmp-servers"`
// original -> gobgp:mrt
+2
View File
@@ -30,6 +30,8 @@
# listen address list (by default "0.0.0.0" and "::")
local-address-list = ["192.168.10.1", "2001:db8::1"]
[global.collector]
enabled = true
[[rpki-servers]]
[rpki-servers.config]
+8 -2
View File
@@ -108,13 +108,19 @@ func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*
options := &table.PolicyOptions{
Neighbor: peer.fsm.peerInfo.Address,
}
for _, path := range peer.localRib.GetBestPathList(peer.TableID(), rfList) {
var source []*table.Path
if peer.gConf.Collector.Enabled {
source = peer.localRib.GetPathList(peer.TableID(), rfList)
} else {
source = peer.localRib.GetBestPathList(peer.TableID(), rfList)
}
for _, path := range source {
p := peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, filterpath(peer, path), options)
if p == nil {
filtered = append(filtered, path)
continue
}
if !peer.isRouteServerClient() {
if !peer.gConf.Collector.Enabled && !peer.isRouteServerClient() {
p = p.Clone(p.IsWithdraw)
p.UpdatePathAttrs(&peer.gConf, &peer.conf)
}
+27 -20
View File
@@ -896,17 +896,20 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) ([]
dsts := rib.ProcessPaths(pathList)
server.validatePaths(dsts, false)
sendPathList := make([]*table.Path, 0, len(dsts))
for _, dst := range dsts {
path := dst.NewFeed(table.GLOBAL_RIB_NAME)
if path != nil {
sendPathList = append(sendPathList, path)
if server.bgpConfig.Global.Collector.Enabled {
sendPathList = pathList
} else {
for _, dst := range dsts {
path := dst.NewFeed(table.GLOBAL_RIB_NAME)
if path != nil {
sendPathList = append(sendPathList, path)
}
}
if len(sendPathList) == 0 {
return msgs, alteredPathList
}
server.broadcastBests(sendPathList)
}
if len(sendPathList) == 0 {
return msgs, alteredPathList
}
server.broadcastBests(sendPathList)
for _, targetPeer := range server.neighborMap {
if targetPeer.isRouteServerClient() || targetPeer.fsm.state != bgp.BGP_FSM_ESTABLISHED {
@@ -917,7 +920,7 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) ([]
options.Neighbor = targetPeer.fsm.peerInfo.Address
for idx, path := range pathList {
path = server.policy.ApplyPolicy(table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_EXPORT, filterpath(targetPeer, path), options)
if path != nil {
if path != nil && !server.bgpConfig.Global.Collector.Enabled {
path = path.Clone(path.IsWithdraw)
path.UpdatePathAttrs(&server.bgpConfig.Global, &targetPeer.conf)
}
@@ -1357,11 +1360,9 @@ func (server *BgpServer) handleModPathRequest(grpcReq *GrpcRequest) []*table.Pat
case api.Operation_DEL:
if len(arg.Uuid) > 0 {
path := func() *table.Path {
for _, rf := range server.globalRib.GetRFlist() {
for _, path := range server.globalRib.GetPathList(table.GLOBAL_RIB_NAME, rf) {
if len(path.UUID()) > 0 && bytes.Equal(path.UUID(), arg.Uuid) {
return path
}
for _, path := range server.globalRib.GetPathList(table.GLOBAL_RIB_NAME, server.globalRib.GetRFlist()) {
if len(path.UUID()) > 0 && bytes.Equal(path.UUID(), arg.Uuid) {
return path
}
}
return nil
@@ -1488,7 +1489,7 @@ func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path {
result.ResponseErr = fmt.Errorf("unsupported route family: %s", bgp.RouteFamily(arg.Family))
break
}
paths := rib.GetPathList(table.GLOBAL_RIB_NAME, rf)
paths := rib.GetPathList(table.GLOBAL_RIB_NAME, []bgp.RouteFamily{rf})
dsts := make([]*api.Destination, 0, len(paths))
for _, path := range paths {
ok := table.CanImportToVrf(vrfs[name], path)
@@ -1828,10 +1829,16 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
}
if found {
r.Insert(table.CidrToRadixkey(key), &api.Destination{
Prefix: key,
Paths: []*api.Path{p.ToApiStruct(peer.TableID())},
})
b, _ := r.Get(table.CidrToRadixkey(key))
if b == nil {
r.Insert(table.CidrToRadixkey(key), &api.Destination{
Prefix: key,
Paths: []*api.Path{p.ToApiStruct(peer.TableID())},
})
} else {
d := b.(*api.Destination)
d.Paths = append(d.Paths, p.ToApiStruct(peer.TableID()))
}
}
}
r.Walk(func(s string, v interface{}) bool {
+54 -19
View File
@@ -20,16 +20,20 @@ import (
"reflect"
)
type Dest struct {
pathList []*Path
}
type AdjRib struct {
id string
accepted map[bgp.RouteFamily]int
table map[bgp.RouteFamily]map[string]*Path
table map[bgp.RouteFamily]map[string]*Dest
}
func NewAdjRib(id string, rfList []bgp.RouteFamily) *AdjRib {
table := make(map[bgp.RouteFamily]map[string]*Path)
table := make(map[bgp.RouteFamily]map[string]*Dest)
for _, rf := range rfList {
table[rf] = make(map[string]*Path)
table[rf] = make(map[string]*Dest)
}
return &AdjRib{
id: id,
@@ -45,17 +49,35 @@ func (adj *AdjRib) Update(pathList []*Path) {
}
rf := path.GetRouteFamily()
key := path.getPrefix()
old, found := adj.table[rf][key]
dst := adj.table[rf][key]
var old *Path
oldIdx := 0
if dst == nil {
dst = &Dest{}
dst.pathList = make([]*Path, 0)
adj.table[rf][key] = dst
} else {
for i, known := range dst.pathList {
if known.GetSource() == path.GetSource() {
old = known
oldIdx = i
}
}
}
if path.IsWithdraw {
if found {
delete(adj.table[rf], key)
if old != nil {
dst.pathList = append(dst.pathList[:oldIdx], dst.pathList[oldIdx+1:]...)
if len(dst.pathList) == 0 {
delete(adj.table[rf], key)
}
if old.Filtered(adj.id) == POLICY_DIRECTION_NONE {
adj.accepted[rf]--
}
}
} else {
n := path.Filtered(adj.id)
if found {
if old != nil {
o := old.Filtered(adj.id)
if o == POLICY_DIRECTION_IN && n == POLICY_DIRECTION_NONE {
adj.accepted[rf]++
@@ -67,10 +89,17 @@ func (adj *AdjRib) Update(pathList []*Path) {
adj.accepted[rf]++
}
}
if found && reflect.DeepEqual(old.GetPathAttrs(), path.GetPathAttrs()) {
path.setTimestamp(old.GetTimestamp())
if old != nil {
dst.pathList[oldIdx] = path
// avoid updating timestamp for the
// exact same message due to soft
// reset, etc
if reflect.DeepEqual(old.GetPathAttrs(), path.GetPathAttrs()) {
path.setTimestamp(old.GetTimestamp())
}
} else {
dst.pathList = append(dst.pathList, path)
}
adj.table[rf][key] = path
}
}
}
@@ -78,9 +107,11 @@ func (adj *AdjRib) Update(pathList []*Path) {
func (adj *AdjRib) RefreshAcceptedNumber(rfList []bgp.RouteFamily) {
for _, rf := range rfList {
adj.accepted[rf] = 0
for _, p := range adj.table[rf] {
if p.Filtered(adj.id) != POLICY_DIRECTION_IN {
adj.accepted[rf]++
for _, d := range adj.table[rf] {
for _, p := range d.pathList {
if p.Filtered(adj.id) != POLICY_DIRECTION_IN {
adj.accepted[rf]++
}
}
}
}
@@ -89,11 +120,13 @@ func (adj *AdjRib) RefreshAcceptedNumber(rfList []bgp.RouteFamily) {
func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
pathList := make([]*Path, 0, adj.Count(rfList))
for _, rf := range rfList {
for _, rr := range adj.table[rf] {
if accepted && rr.Filtered(adj.id) > POLICY_DIRECTION_NONE {
continue
for _, d := range adj.table[rf] {
for _, p := range d.pathList {
if accepted && p.Filtered(adj.id) > POLICY_DIRECTION_NONE {
continue
}
pathList = append(pathList, p)
}
pathList = append(pathList, rr)
}
}
return pathList
@@ -103,7 +136,9 @@ func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int {
count := 0
for _, rf := range rfList {
if table, ok := adj.table[rf]; ok {
count += len(table)
for _, d := range table {
count += len(d.pathList)
}
}
}
return count
@@ -122,7 +157,7 @@ func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int {
func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) {
for _, rf := range rfList {
if _, ok := adj.table[rf]; ok {
adj.table[rf] = make(map[string]*Path)
adj.table[rf] = make(map[string]*Dest)
adj.accepted[rf] = 0
}
}
+14 -5
View File
@@ -276,7 +276,7 @@ func (manager *TableManager) handleMacMobility(path *Path) []*Destination {
if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
return nil
}
for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, bgp.RF_EVPN) {
for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, []bgp.RouteFamily{bgp.RF_EVPN}) {
if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
continue
}
@@ -323,9 +323,18 @@ func (manager *TableManager) GetBestPathList(id string, rfList []bgp.RouteFamily
return paths
}
func (manager *TableManager) GetPathList(id string, rf bgp.RouteFamily) []*Path {
if t, ok := manager.Tables[rf]; ok {
return t.GetKnownPathList(id)
func (manager *TableManager) GetPathList(id string, rfList []bgp.RouteFamily) []*Path {
c := 0
for _, rf := range rfList {
if t, ok := manager.Tables[rf]; ok {
c += len(t.destinations)
}
}
return nil
paths := make([]*Path, 0, c)
for _, rf := range rfList {
if t, ok := manager.Tables[rf]; ok {
paths = append(paths, t.GetKnownPathList(id)...)
}
}
return paths
}
+11
View File
@@ -667,6 +667,17 @@ module gobgp {
uses gobgp-rpki-servers;
}
augment "/bgp:bgp/bgp:global" {
description "route collector mode";
container collector {
leaf enabled {
type boolean;
description
"Configure enabling route-collector mode.";
}
}
}
augment "/bgp:bgp/bgp:global" {
description "additional bmp configuration";
uses gobgp-bmp-servers;