diff options
-rw-r--r-- | config/util.go | 18 | ||||
-rw-r--r-- | server/peer.go | 61 | ||||
-rw-r--r-- | server/server.go | 23 | ||||
-rw-r--r-- | table/adj.go | 114 | ||||
-rw-r--r-- | table/table_manager.go | 118 | ||||
-rw-r--r-- | table/table_manager_test.go | 17 |
6 files changed, 174 insertions, 177 deletions
diff --git a/config/util.go b/config/util.go index a3606682..50d1b833 100644 --- a/config/util.go +++ b/config/util.go @@ -34,11 +34,23 @@ func IsEBGPPeer(g *Global, p *Neighbor) bool { return p.NeighborConfig.PeerAs != g.GlobalConfig.As } +func (c AfiSafis) ToRfList() ([]bgp.RouteFamily, error) { + rfs := make([]bgp.RouteFamily, 0, len(c.AfiSafiList)) + for _, rf := range c.AfiSafiList { + k, err := bgp.GetRouteFamily(rf.AfiSafiName) + if err != nil { + return nil, err + } + rfs = append(rfs, k) + } + return rfs, nil +} + func CreateRfMap(p *Neighbor) map[bgp.RouteFamily]bool { + rfs, _ := p.AfiSafis.ToRfList() rfMap := make(map[bgp.RouteFamily]bool) - for _, rf := range p.AfiSafis.AfiSafiList { - k, _ := bgp.GetRouteFamily(rf.AfiSafiName) - rfMap[k] = true + for _, rf := range rfs { + rfMap[rf] = true } return rfMap } diff --git a/server/peer.go b/server/peer.go index ac3c2409..8f43299e 100644 --- a/server/peer.go +++ b/server/peer.go @@ -37,28 +37,29 @@ type Peer struct { fsm *FSM rfMap map[bgp.RouteFamily]bool capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface - adjRib *table.AdjRib + adjRibIn *table.AdjRib + adjRibOut *table.AdjRib outgoing chan *bgp.BGPMessage inPolicies []*table.Policy defaultInPolicy table.RouteType - accepted uint32 - staleAccepted bool recvOpen *bgp.BGPMessage localRib *table.TableManager } func NewPeer(g config.Global, conf config.Neighbor, loc *table.TableManager) *Peer { + rfs, _ := conf.AfiSafis.ToRfList() peer := &Peer{ - gConf: g, - conf: conf, - rfMap: make(map[bgp.RouteFamily]bool), - capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface), - outgoing: make(chan *bgp.BGPMessage, 128), - localRib: loc, + gConf: g, + conf: conf, + rfMap: make(map[bgp.RouteFamily]bool), + capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface), + outgoing: make(chan *bgp.BGPMessage, 128), + adjRibIn: table.NewAdjRib(rfs), + adjRibOut: table.NewAdjRib(rfs), + localRib: loc, } conf.NeighborState.SessionState = uint32(bgp.BGP_FSM_IDLE) conf.Timers.TimersState.Downtime = time.Now().Unix() - peer.adjRib = table.NewAdjRib(peer.configuredRFlist()) peer.fsm = NewFSM(&g, &conf, peer) return peer } @@ -84,22 +85,12 @@ func (peer *Peer) isRouteReflectorClient() bool { } func (peer *Peer) configuredRFlist() []bgp.RouteFamily { - return peer.localRib.GetRFlist() -} - -func (peer *Peer) updateAccepted(accepted uint32) { - peer.accepted = accepted - peer.staleAccepted = false + rfs, _ := peer.conf.AfiSafis.ToRfList() + return rfs } func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path { - var pathList []*table.Path - for _, path := range peer.adjRib.GetInPathList(rfList) { - if path.Filtered == false { - pathList = append(pathList, path) - } - } - return pathList + return peer.adjRibIn.PathList(rfList, true) } func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*table.Path) { @@ -184,9 +175,9 @@ func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, bool, []*bgp.BGPMe } if _, ok := peer.capMap[bgp.BGP_CAP_ROUTE_REFRESH]; ok { rfList := []bgp.RouteFamily{rf} - peer.adjRib.DropOut(rfList) + peer.adjRibOut.Drop(rfList) accepted, filtered := peer.getBestFromLocal(rfList) - peer.adjRib.UpdateOut(accepted) + peer.adjRibOut.Update(accepted) pathList = append(pathList, accepted...) for _, path := range filtered { path.IsWithdraw = true @@ -203,9 +194,8 @@ func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, bool, []*bgp.BGPMe update = true peer.conf.Timers.TimersState.UpdateRecvTime = time.Now().Unix() if len(e.PathList) > 0 { + peer.adjRibIn.Update(e.PathList) pathList = e.PathList - peer.staleAccepted = true - peer.adjRib.UpdateIn(pathList) } case bgp.BGP_MSG_NOTIFICATION: body := m.Body.(*bgp.BGPNotification) @@ -284,14 +274,9 @@ func (peer *Peer) ToApiStruct() *api.Peer { accepted := uint32(0) if f.state == bgp.BGP_FSM_ESTABLISHED { rfList := peer.configuredRFlist() - advertized = uint32(peer.adjRib.GetOutCount(rfList)) - received = uint32(peer.adjRib.GetInCount(rfList)) - if peer.staleAccepted { - accepted = uint32(len(peer.getAccepted(rfList))) - peer.updateAccepted(accepted) - } else { - accepted = peer.accepted - } + advertized = uint32(peer.adjRibOut.Count(rfList)) + received = uint32(peer.adjRibIn.Count(rfList)) + accepted = uint32(peer.adjRibIn.Accepted(rfList)) } uptime := int64(0) @@ -448,8 +433,6 @@ func (peer *Peer) ApplyPolicy(d table.PolicyDirection, paths []*table.Path) ([]* } func (peer *Peer) DropAll(rfList []bgp.RouteFamily) { - peer.adjRib.DropIn(rfList) - peer.adjRib.DropOut(rfList) - peer.staleAccepted = false - peer.accepted = 0 + peer.adjRibIn.Drop(rfList) + peer.adjRibOut.Drop(rfList) } diff --git a/server/server.go b/server/server.go index 3bd4b448..a09b7d02 100644 --- a/server/server.go +++ b/server/server.go @@ -329,7 +329,7 @@ func (server *BgpServer) Serve() { if targetPeer.fsm.state != bgp.BGP_FSM_ESTABLISHED { continue } - for _, p := range targetPeer.adjRib.GetInPathList(targetPeer.configuredRFlist()) { + for _, p := range targetPeer.adjRibIn.PathList(targetPeer.configuredRFlist(), false) { // avoid to merge for timestamp u := table.CreateUpdateMsgFromPaths([]*table.Path{p}) buf, _ := u[0].Serialize() @@ -560,7 +560,7 @@ func (server *BgpServer) dropPeerAllRoutes(peer *Peer) []*SenderMsg { } msgList := table.CreateUpdateMsgFromPaths(pathList) msgs = append(msgs, newSenderMsg(targetPeer, msgList)) - targetPeer.adjRib.UpdateOut(pathList) + targetPeer.adjRibOut.Update(pathList) } } else { rib := server.globalRib @@ -579,7 +579,7 @@ func (server *BgpServer) dropPeerAllRoutes(peer *Peer) []*SenderMsg { if _, ok := targetPeer.rfMap[rf]; !ok { continue } - targetPeer.adjRib.UpdateOut(pathList) + targetPeer.adjRibOut.Update(pathList) msgs = append(msgs, newSenderMsg(targetPeer, msgList)) } } @@ -678,7 +678,7 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []* continue } msgList := table.CreateUpdateMsgFromPaths(sendPathList) - targetPeer.adjRib.UpdateOut(sendPathList) + targetPeer.adjRibOut.Update(sendPathList) msgs = append(msgs, newSenderMsg(targetPeer, msgList)) } } else { @@ -702,9 +702,8 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []* for _, path := range f { path.UpdatePathAttrs(&server.bgpConfig.Global, &targetPeer.conf) } - targetPeer.adjRib.UpdateOut(f) + targetPeer.adjRibOut.Update(f) msgList := table.CreateUpdateMsgFromPaths(f) - msgs = append(msgs, newSenderMsg(targetPeer, msgList)) } } @@ -755,7 +754,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg, incoming chan * } pathList, _ := peer.getBestFromLocal(peer.configuredRFlist()) if len(pathList) > 0 { - peer.adjRib.UpdateOut(pathList) + peer.adjRibOut.Update(pathList) msgs = append(msgs, newSenderMsg(peer, table.CreateUpdateMsgFromPaths(pathList))) } } else { @@ -1517,10 +1516,10 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { rf := bgp.RouteFamily(arg.Family) var paths []*table.Path if grpcReq.RequestType == REQ_ADJ_RIB_IN { - paths = peer.adjRib.GetInPathList([]bgp.RouteFamily{rf}) + paths = peer.adjRibIn.PathList([]bgp.RouteFamily{rf}, false) log.Debugf("RouteFamily=%v adj-rib-in found : %d", rf.String(), len(paths)) } else { - paths = peer.adjRib.GetOutPathList([]bgp.RouteFamily{rf}) + paths = peer.adjRibOut.PathList([]bgp.RouteFamily{rf}, false) log.Debugf("RouteFamily=%v adj-rib-out found : %d", rf.String(), len(paths)) } @@ -1602,7 +1601,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { } for _, peer := range peers { - pathList := peer.adjRib.GetInPathList([]bgp.RouteFamily{grpcReq.RouteFamily}) + pathList := peer.adjRibIn.PathList([]bgp.RouteFamily{grpcReq.RouteFamily}, false) if peer.isRouteServerClient() { pathList, _ = peer.ApplyPolicy(table.POLICY_DIRECTION_IN, pathList) } @@ -1625,10 +1624,10 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { } for _, peer := range peers { rfList := peer.configuredRFlist() - peer.adjRib.DropOut(rfList) + peer.adjRibOut.Drop(rfList) pathList, filtered := peer.getBestFromLocal(rfList) if len(pathList) > 0 { - peer.adjRib.UpdateOut(pathList) + peer.adjRibOut.Update(pathList) msgs = append(msgs, newSenderMsg(peer, table.CreateUpdateMsgFromPaths(pathList))) } if len(filtered) > 0 { diff --git a/table/adj.go b/table/adj.go new file mode 100644 index 00000000..019ad3c8 --- /dev/null +++ b/table/adj.go @@ -0,0 +1,114 @@ +// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package table + +import ( + "github.com/osrg/gobgp/packet" + "reflect" +) + +type AdjRib struct { + accepted map[bgp.RouteFamily]int + table map[bgp.RouteFamily]map[string]*Path +} + +func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib { + table := make(map[bgp.RouteFamily]map[string]*Path) + for _, rf := range rfList { + table[rf] = make(map[string]*Path) + } + return &AdjRib{ + table: table, + accepted: make(map[bgp.RouteFamily]int), + } +} + +func (adj *AdjRib) Update(pathList []*Path) { + for _, path := range pathList { + if path == nil { + continue + } + rf := path.GetRouteFamily() + key := path.getPrefix() + old, found := adj.table[rf][key] + if path.IsWithdraw { + if found { + delete(adj.table[rf], key) + if !old.Filtered { + adj.accepted[rf]-- + } + } + } else { + if found { + if old.Filtered && !path.Filtered { + adj.accepted[rf]++ + } else if !old.Filtered && path.Filtered { + adj.accepted[rf]-- + } + } else { + if !path.Filtered { + adj.accepted[rf]++ + } + } + if found && reflect.DeepEqual(old.GetPathAttrs(), path.GetPathAttrs()) { + path.setTimestamp(old.GetTimestamp()) + } + adj.table[rf][key] = path + } + } +} + +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 { + continue + } + pathList = append(pathList, rr) + } + } + return pathList +} + +func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int { + count := 0 + for _, rf := range rfList { + if table, ok := adj.table[rf]; ok { + count += len(table) + } + } + return count +} + +func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int { + count := 0 + for _, rf := range rfList { + if n, ok := adj.accepted[rf]; ok { + count += n + } + } + return count +} + +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.accepted[rf] = 0 + } + } +} diff --git a/table/table_manager.go b/table/table_manager.go index 03d8ed83..637299b9 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -21,7 +21,6 @@ import ( log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet" "net" - "reflect" "time" ) @@ -489,120 +488,3 @@ func (manager *TableManager) GetBestPathList(rfList []bgp.RouteFamily) []*Path { } return paths } - -// process BGPUpdate message -// this function processes only BGPUpdate -func (manager *TableManager) ProcessUpdate(fromPeer *PeerInfo, message *bgp.BGPMessage) ([]*Path, error) { - // check msg's type if it's BGPUpdate - if message.Header.Type != bgp.BGP_MSG_UPDATE { - log.WithFields(log.Fields{ - "Topic": "table", - "Owner": manager.owner, - "key": fromPeer.Address.String(), - "Type": message.Header.Type, - }).Warn("message is not BGPUpdate") - return []*Path{}, nil - } - - return manager.ProcessPaths(ProcessMessage(message, fromPeer, time.Now())) -} - -type AdjRib struct { - adjRibIn map[bgp.RouteFamily]map[string]*Path - adjRibOut map[bgp.RouteFamily]map[string]*Path -} - -func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib { - r := &AdjRib{ - adjRibIn: make(map[bgp.RouteFamily]map[string]*Path), - adjRibOut: make(map[bgp.RouteFamily]map[string]*Path), - } - for _, rf := range rfList { - r.adjRibIn[rf] = make(map[string]*Path) - r.adjRibOut[rf] = make(map[string]*Path) - } - return r -} - -func (adj *AdjRib) update(rib map[bgp.RouteFamily]map[string]*Path, pathList []*Path) { - for _, path := range pathList { - rf := path.GetRouteFamily() - key := path.getPrefix() - old, found := rib[rf][key] - if path.IsWithdraw { - if found { - delete(rib[rf], key) - } - } else { - if found && reflect.DeepEqual(old.GetPathAttrs(), path.GetPathAttrs()) { - path.setTimestamp(old.GetTimestamp()) - } - rib[rf][key] = path - } - } -} - -func (adj *AdjRib) UpdateIn(pathList []*Path) { - adj.update(adj.adjRibIn, pathList) -} - -func (adj *AdjRib) UpdateOut(pathList []*Path) { - adj.update(adj.adjRibOut, pathList) -} - -func (adj *AdjRib) GetInPathList(rfList []bgp.RouteFamily) []*Path { - pathList := make([]*Path, 0, adj.GetInCount(rfList)) - for _, rf := range rfList { - for _, rr := range adj.adjRibIn[rf] { - pathList = append(pathList, rr) - } - } - return pathList -} - -func (adj *AdjRib) GetOutPathList(rfList []bgp.RouteFamily) []*Path { - pathList := make([]*Path, 0, adj.GetOutCount(rfList)) - for _, rf := range rfList { - for _, rr := range adj.adjRibOut[rf] { - pathList = append(pathList, rr) - } - } - return pathList -} - -func (adj *AdjRib) GetInCount(rfList []bgp.RouteFamily) int { - count := 0 - for _, rf := range rfList { - if _, ok := adj.adjRibIn[rf]; ok { - count += len(adj.adjRibIn[rf]) - - } - } - return count -} - -func (adj *AdjRib) GetOutCount(rfList []bgp.RouteFamily) int { - count := 0 - for _, rf := range rfList { - if _, ok := adj.adjRibOut[rf]; ok { - count += len(adj.adjRibOut[rf]) - } - } - return count -} - -func (adj *AdjRib) DropIn(rfList []bgp.RouteFamily) { - for _, rf := range rfList { - if _, ok := adj.adjRibIn[rf]; ok { - adj.adjRibIn[rf] = make(map[string]*Path) - } - } -} - -func (adj *AdjRib) DropOut(rfList []bgp.RouteFamily) { - for _, rf := range rfList { - if _, ok := adj.adjRibIn[rf]; ok { - adj.adjRibOut[rf] = make(map[string]*Path) - } - } -} diff --git a/table/table_manager_test.go b/table/table_manager_test.go index 8a4f67f9..f0e465b2 100644 --- a/table/table_manager_test.go +++ b/table/table_manager_test.go @@ -26,6 +26,13 @@ import ( "time" ) +// process BGPUpdate message +// this function processes only BGPUpdate +func (manager *TableManager) ProcessUpdate(fromPeer *PeerInfo, message *bgp.BGPMessage) ([]*Path, error) { + paths := ProcessMessage(message, fromPeer, time.Now()) + return manager.ProcessPaths(paths) +} + func getLogger(lv log.Level) *log.Logger { var l *log.Logger = &log.Logger{ Out: os.Stderr, @@ -2147,15 +2154,15 @@ func TestProcessBGPUpdate_Timestamp(t *testing.T) { pList1 := ProcessMessage(m1, peer, time.Now()) path1 := pList1[0] t1 := path1.timestamp - adjRib.UpdateIn(pList1) + adjRib.Update(pList1) m2 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) pList2 := ProcessMessage(m2, peer, time.Now()) //path2 := pList2[0].(*IPv4Path) //t2 = path2.timestamp - adjRib.UpdateIn(pList2) + adjRib.Update(pList2) - inList := adjRib.GetInPathList([]bgp.RouteFamily{bgp.RF_IPv4_UC}) + inList := adjRib.PathList([]bgp.RouteFamily{bgp.RF_IPv4_UC}, false) assert.Equal(t, len(inList), 1) assert.Equal(t, inList[0].GetTimestamp(), t1) @@ -2170,9 +2177,9 @@ func TestProcessBGPUpdate_Timestamp(t *testing.T) { m3 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri) pList3 := ProcessMessage(m3, peer, time.Now()) t3 := pList3[0].GetTimestamp() - adjRib.UpdateIn(pList3) + adjRib.Update(pList3) - inList = adjRib.GetInPathList([]bgp.RouteFamily{bgp.RF_IPv4_UC}) + inList = adjRib.PathList([]bgp.RouteFamily{bgp.RF_IPv4_UC}, false) assert.Equal(t, len(inList), 1) assert.Equal(t, inList[0].GetTimestamp(), t3) } |