summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--config/bgp_configs.go9
-rw-r--r--docs/sources/configuration.md2
-rw-r--r--server/peer.go10
-rw-r--r--server/server.go47
-rw-r--r--table/adj.go73
-rw-r--r--table/table_manager.go19
-rw-r--r--tools/pyang_plugins/gobgp.yang11
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;
}