mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user