diff options
-rw-r--r-- | config/bgp_configs.go | 9 | ||||
-rw-r--r-- | docs/sources/configuration.md | 2 | ||||
-rw-r--r-- | server/peer.go | 10 | ||||
-rw-r--r-- | server/server.go | 47 | ||||
-rw-r--r-- | table/adj.go | 73 | ||||
-rw-r--r-- | table/table_manager.go | 19 | ||||
-rw-r--r-- | tools/pyang_plugins/gobgp.yang | 11 |
7 files changed, 125 insertions, 46 deletions
diff --git a/config/bgp_configs.go b/config/bgp_configs.go index 4191bbd2..17baf726 100644 --- a/config/bgp_configs.go +++ b/config/bgp_configs.go @@ -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 diff --git a/docs/sources/configuration.md b/docs/sources/configuration.md index 4866d950..26985d2e 100644 --- a/docs/sources/configuration.md +++ b/docs/sources/configuration.md @@ -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] diff --git a/server/peer.go b/server/peer.go index bf4f2928..967a0e5d 100644 --- a/server/peer.go +++ b/server/peer.go @@ -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) } diff --git a/server/server.go b/server/server.go index c8aba0d9..4dfb2ba2 100644 --- a/server/server.go +++ b/server/server.go @@ -896,18 +896,21 @@ 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 + if len(sendPathList) == 0 { + return msgs, alteredPathList + } + server.broadcastBests(sendPathList) } - server.broadcastBests(sendPathList) - for _, targetPeer := range server.neighborMap { if targetPeer.isRouteServerClient() || targetPeer.fsm.state != bgp.BGP_FSM_ESTABLISHED { continue @@ -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 { diff --git a/table/adj.go b/table/adj.go index 65d9d161..ee9cf549 100644 --- a/table/adj.go +++ b/table/adj.go @@ -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 } } diff --git a/table/table_manager.go b/table/table_manager.go index f21acef0..ebfd0beb 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -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 } diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index 0a60ac6f..1760ad28 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -668,6 +668,17 @@ module gobgp { } 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; } |