diff options
-rw-r--r-- | table/table_manager.go | 309 |
1 files changed, 124 insertions, 185 deletions
diff --git a/table/table_manager.go b/table/table_manager.go index a0a80b76..b59912f6 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -133,268 +133,207 @@ func (attr AttributeType) String() string { } } -type TableManager struct { - Tables map[RouteFamily]Table - Counter map[PeerCounterName]int - localAsn uint32 -} - type ProcessMessage struct { innerMessage *bgp.BGPMessage fromPeer *PeerInfo } -func NewTableManager() *TableManager { - t := &TableManager{} - t.Tables = make(map[RouteFamily]Table) - t.Tables[RF_IPv4_UC] = NewIPv4Table(0) - t.Tables[RF_IPv6_UC] = NewIPv6Table(0) - // initialize prefix counter - t.Counter = make(map[PeerCounterName]int) - t.Counter[RECV_PREFIXES] = 0 - return t -} - -func setLogger(loggerInstance *log.Logger) { - logger = loggerInstance -} - -func (manager *TableManager) incrCounter(name PeerCounterName, step int) { - val := manager.Counter[name] - val += step - manager.Counter[name] = val -} - -// create destination list from nlri -func (manager *TableManager) handleNlri(p *ProcessMessage) ([]Destination, error) { - +func (p *ProcessMessage) nlri2Path() []Path { updateMsg := p.innerMessage.Body.(*bgp.BGPUpdate) - nlriList := updateMsg.NLRI // NLRI is an array of NLRInfo. pathAttributes := updateMsg.PathAttributes - - destList := make([]Destination, 0) - for _, nlri_info := range nlriList { - + pathList := make([]Path, 0) + for _, nlri_info := range updateMsg.NLRI { // define local variable to pass nlri's address to CreatePath var nlri bgp.NLRInfo = nlri_info // create Path object path := CreatePath(p.fromPeer, &nlri, pathAttributes, false) - // TODO process filter - - rf := path.getRouteFamily() - // push Path into table - destination := insert(manager.Tables[rf], path) - destList = append(destList, destination) - manager.incrCounter(RECV_PREFIXES, len(nlriList)) + pathList = append(pathList, path) } - - logger.Debugf("destinationList contains %d destinations from nlri_info", len(destList)) - - return destList, nil + return pathList } -// create destination list from withdrawn routes -func (manager *TableManager) handleWithdraw(p *ProcessMessage) ([]Destination, error) { - +func (p *ProcessMessage) withdraw2Path() []Path { updateMsg := p.innerMessage.Body.(*bgp.BGPUpdate) pathAttributes := updateMsg.PathAttributes - withdrawnRoutes := updateMsg.WithdrawnRoutes - - wDestList := make([]Destination, 0) - - // process withdraw path - for _, nlriWithdraw := range withdrawnRoutes { + pathList := make([]Path, 0) + for _, nlriWithdraw := range updateMsg.WithdrawnRoutes { // define local variable to pass nlri's address to CreatePath var w bgp.WithdrawnRoute = nlriWithdraw // create withdrawn Path object path := CreatePath(p.fromPeer, &w, pathAttributes, true) - rf := path.getRouteFamily() - // push Path into table - destination := insert(manager.Tables[rf], path) - wDestList = append(wDestList, destination) + pathList = append(pathList, path) } - - logger.Debugf("destinationList contains %d withdrawn destinations", len(wDestList)) - return wDestList, nil + return pathList } -// create destination list from nlri -func (manager *TableManager) handleMPReachNlri(p *ProcessMessage) ([]Destination, error) { - +func (p *ProcessMessage) mpreachNlri2Path() []Path { updateMsg := p.innerMessage.Body.(*bgp.BGPUpdate) pathAttributes := updateMsg.PathAttributes attrList := []*bgp.PathAttributeMpReachNLRI{} -LOOP: for _, attr := range pathAttributes { - switch a := attr.(type) { - case *bgp.PathAttributeMpReachNLRI: + a, ok := attr.(*bgp.PathAttributeMpReachNLRI) + if ok { attrList = append(attrList, a) - break LOOP + break } } + pathList := make([]Path, 0) - destList := make([]Destination, 0) for _, mp := range attrList { nlri_info := mp.Value - for _, nlri := range nlri_info { path := CreatePath(p.fromPeer, nlri, pathAttributes, false) - // TODO process filter - - rf := path.getRouteFamily() - // push Path into table - destination := insert(manager.Tables[rf], path) - - destList = append(destList, destination) - manager.incrCounter(RECV_PREFIXES, len(nlri_info)) + pathList = append(pathList, path) } } - logger.Debugf("destinationList contains %d destinations from MpReachNLRI", len(destList)) - - return destList, nil + return pathList } -// create destination list from nlri -func (manager *TableManager) handleMPUNReachNlri(p *ProcessMessage) ([]Destination, error) { - +func (p *ProcessMessage) mpunreachNlri2Path() []Path { updateMsg := p.innerMessage.Body.(*bgp.BGPUpdate) pathAttributes := updateMsg.PathAttributes attrList := []*bgp.PathAttributeMpUnreachNLRI{} -LOOP: for _, attr := range pathAttributes { - switch a := attr.(type) { - case *bgp.PathAttributeMpUnreachNLRI: + a, ok := attr.(*bgp.PathAttributeMpUnreachNLRI) + if ok { attrList = append(attrList, a) - break LOOP + break } } + pathList := make([]Path, 0) - destList := make([]Destination, 0) for _, mp := range attrList { nlri_info := mp.Value for _, nlri := range nlri_info { path := CreatePath(p.fromPeer, nlri, pathAttributes, true) - // TODO process filter - - rf := path.getRouteFamily() - // push Path into table - destination := insert(manager.Tables[rf], path) - - destList = append(destList, destination) - manager.incrCounter(RECV_PREFIXES, len(nlri_info)) + pathList = append(pathList, path) } } - logger.Debugf("destinationList contains %d destinations from MpUnreachNLRI", len(destList)) - return destList, nil + return pathList } -// process BGPUpdate message -// this function processes only BGPUpdate -func (manager *TableManager) ProcessUpdate(fromPeer *PeerInfo, message *bgp.BGPMessage) ([]Path, []Destination, error) { +func (p *ProcessMessage) ToPathList() []Path { + pathList := make([]Path, 0) + pathList = append(pathList, p.nlri2Path()...) + pathList = append(pathList, p.withdraw2Path()...) + pathList = append(pathList, p.mpreachNlri2Path()...) + pathList = append(pathList, p.mpunreachNlri2Path()...) + return pathList +} - var bestPaths []Path = make([]Path, 0) - var lostDest []Destination = make([]Destination, 0) +type TableManager struct { + Tables map[RouteFamily]Table + Counter map[PeerCounterName]int + localAsn uint32 +} - // check msg's type if it's BGPUpdate - body := message.Body - switch body.(type) { - case *bgp.BGPUpdate: +func NewTableManager() *TableManager { + t := &TableManager{} + t.Tables = make(map[RouteFamily]Table) + t.Tables[RF_IPv4_UC] = NewIPv4Table(0) + t.Tables[RF_IPv6_UC] = NewIPv6Table(0) + // initialize prefix counter + t.Counter = make(map[PeerCounterName]int) + t.Counter[RECV_PREFIXES] = 0 + return t +} - msg := &ProcessMessage{ - innerMessage: message, - fromPeer: fromPeer, - } +func setLogger(loggerInstance *log.Logger) { + logger = loggerInstance +} - // get destination list - destList, err := manager.handleNlri(msg) - if err != nil { - logger.Error(err) - return nil, nil, err - } +func (manager *TableManager) incrCounter(name PeerCounterName, step int) { + val := manager.Counter[name] + val += step + manager.Counter[name] = val +} - wDestList, err := manager.handleWithdraw(msg) - if err != nil { - logger.Error(err) - return nil, nil, err - } +func (manager *TableManager) processUpdate(pathList []Path) ([]Path, []Destination, error) { + bestPaths := make([]Path, 0) + lostDest := make([]Destination, 0) - mpreachDestList, err := manager.handleMPReachNlri(msg) - if err != nil { - logger.Error(err) - return nil, nil, err - } + destinationList := make([]Destination, 0) + for _, path := range pathList { + rf := path.getRouteFamily() + // push Path into table + destination := insert(manager.Tables[rf], path) + destinationList = append(destinationList, destination) + } - mpunreachDestList, err := manager.handleMPUNReachNlri(msg) + for _, destination := range destinationList { + // compute best path + logger.Infof("Processing destination: %v", destination.String()) + newBestPath, reason, err := destination.Calculate(manager.localAsn) + + logger.Debugf("new best path: %v, reason=%v", newBestPath, reason) if err != nil { logger.Error(err) - return nil, nil, err + continue } - // merge destList and wDestList - destinationList := append(destList, wDestList...) - destinationList = append(destinationList, mpreachDestList...) - destinationList = append(destinationList, mpunreachDestList...) - - // check best path changed - if destinationList != nil { - for _, destination := range destinationList { - // compute best path - logger.Infof("Processing destination: %v", destination.String()) - newBestPath, reason, err := destination.Calculate(manager.localAsn) - - logger.Debugf("new best path: %v, reason=%v", newBestPath, reason) - if err != nil { - logger.Error(err) - continue - } - destination.setBestPathReason(reason) - currentBestPath := destination.getBestPath() + destination.setBestPathReason(reason) + currentBestPath := destination.getBestPath() - if newBestPath != nil && currentBestPath == newBestPath { - // best path is not changed - logger.Debug("best path is not changed") - continue - } - - if newBestPath == nil { - logger.Debug("best path is nil") - if len(destination.getKnownPathList()) == 0 { - // create withdraw path - if currentBestPath != nil { - logger.Debug("best path is lost") - destination.setOldBestPath(destination.getBestPath()) - lostDest = append(lostDest, destination) - } - destination.setBestPath(nil) - } else { - logger.Error("known path list is not empty") - } - } else { - logger.Debugf("new best path: NLRI: %v, next_hop=%v, reason=%v", - newBestPath.getPrefix().String(), - newBestPath.getNexthop().String(), - reason) - - bestPaths = append(bestPaths, newBestPath) - destination.setBestPath(newBestPath) - } + if newBestPath != nil && currentBestPath == newBestPath { + // best path is not changed + logger.Debug("best path is not changed") + continue + } - if len(destination.getKnownPathList()) == 0 && destination.getBestPath() == nil { - rf := destination.getRouteFamily() - t := manager.Tables[rf] - deleteDest(t, destination) - logger.Debugf("destination removed route_family=%v, destination=%v", rf, destination) + if newBestPath == nil { + logger.Debug("best path is nil") + if len(destination.getKnownPathList()) == 0 { + // create withdraw path + if currentBestPath != nil { + logger.Debug("best path is lost") + destination.setOldBestPath(destination.getBestPath()) + lostDest = append(lostDest, destination) } + destination.setBestPath(nil) + } else { + logger.Error("known path list is not empty") } + } else { + logger.Debugf("new best path: NLRI: %v, next_hop=%v, reason=%v", + newBestPath.getPrefix().String(), + newBestPath.getNexthop().String(), + reason) + + bestPaths = append(bestPaths, newBestPath) + destination.setBestPath(newBestPath) } - default: + + if len(destination.getKnownPathList()) == 0 && destination.getBestPath() == nil { + rf := destination.getRouteFamily() + t := manager.Tables[rf] + deleteDest(t, destination) + logger.Debugf("destination removed route_family=%v, destination=%v", rf, destination) + } + } + return bestPaths, lostDest, nil +} + +// process BGPUpdate message +// this function processes only BGPUpdate +func (manager *TableManager) ProcessUpdate(fromPeer *PeerInfo, message *bgp.BGPMessage) ([]Path, []Destination, error) { + var bestPaths []Path = make([]Path, 0) + var lostDest []Destination = make([]Destination, 0) + + // check msg's type if it's BGPUpdate + if message.Header.Type != bgp.BGP_MSG_UPDATE { logger.Warn("message is not BGPUpdate") + return bestPaths, lostDest, nil } - return bestPaths, lostDest, nil + msg := &ProcessMessage{ + innerMessage: message, + fromPeer: fromPeer, + } + + return manager.processUpdate(msg.ToPathList()) } type AdjRib struct { |