diff options
-rw-r--r-- | server/fsm.go | 2 | ||||
-rw-r--r-- | server/fsm_test.go | 11 | ||||
-rw-r--r-- | server/peer.go | 56 | ||||
-rw-r--r-- | server/server.go | 71 |
4 files changed, 66 insertions, 74 deletions
diff --git a/server/fsm.go b/server/fsm.go index 5d42cdd1..34c8b187 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -201,6 +201,8 @@ func NewFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingP if pConf.State.AdminDown { adminState = ADMIN_STATE_DOWN } + pConf.State.SessionState = config.IntToSessionStateMap[int(bgp.BGP_FSM_IDLE)] + pConf.Timers.State.Downtime = time.Now().Unix() fsm := &FSM{ gConf: gConf, pConf: pConf, diff --git a/server/fsm_test.go b/server/fsm_test.go index afe66a0f..42c61919 100644 --- a/server/fsm_test.go +++ b/server/fsm_test.go @@ -284,18 +284,11 @@ func TestFSMHandlerEstablished_HoldtimeZero(t *testing.T) { } func makePeerAndHandler() (*Peer, *FSMHandler) { - gConf := config.Global{} - pConf := config.Neighbor{} - p := &Peer{ - gConf: gConf, - conf: pConf, + fsm: NewFSM(&config.Global{}, &config.Neighbor{}, table.NewRoutingPolicy()), + outgoing: make(chan *FsmOutgoingMsg, 4096), } - p.fsm = NewFSM(&gConf, &pConf, table.NewRoutingPolicy()) - - p.outgoing = make(chan *FsmOutgoingMsg, 4096) - h := &FSMHandler{ fsm: p.fsm, errorCh: make(chan FsmStateReason, 2), diff --git a/server/peer.go b/server/peer.go index dfdfdc37..2b878b6f 100644 --- a/server/peer.go +++ b/server/peer.go @@ -34,8 +34,6 @@ const ( type Peer struct { tableId string - gConf config.Global - conf config.Neighbor fsm *FSM adjRibIn *table.AdjRib adjRibOut *table.AdjRib @@ -45,31 +43,27 @@ type Peer struct { prefixLimitWarned map[bgp.RouteFamily]bool } -func NewPeer(g config.Global, conf config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *Peer { +func NewPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *Peer { peer := &Peer{ - gConf: g, - conf: conf, outgoing: make(chan *FsmOutgoingMsg, 128), localRib: loc, policy: policy, + fsm: NewFSM(g, conf, policy), prefixLimitWarned: make(map[bgp.RouteFamily]bool), } - tableId := table.GLOBAL_RIB_NAME if peer.isRouteServerClient() { - tableId = conf.Config.NeighborAddress + peer.tableId = conf.Config.NeighborAddress + } else { + peer.tableId = table.GLOBAL_RIB_NAME } - peer.tableId = tableId - conf.State.SessionState = config.IntToSessionStateMap[int(bgp.BGP_FSM_IDLE)] - conf.Timers.State.Downtime = time.Now().Unix() rfs, _ := config.AfiSafis(conf.AfiSafis).ToRfList() peer.adjRibIn = table.NewAdjRib(peer.ID(), rfs, g.Collector.Enabled) peer.adjRibOut = table.NewAdjRib(peer.ID(), rfs, g.Collector.Enabled) - peer.fsm = NewFSM(&g, &conf, policy) return peer } func (peer *Peer) ID() string { - return peer.conf.Config.NeighborAddress + return peer.fsm.pConf.Config.NeighborAddress } func (peer *Peer) TableID() string { @@ -77,15 +71,15 @@ func (peer *Peer) TableID() string { } func (peer *Peer) isIBGPPeer() bool { - return peer.conf.Config.PeerAs == peer.gConf.Config.As + return peer.fsm.pConf.Config.PeerAs == peer.fsm.gConf.Config.As } func (peer *Peer) isRouteServerClient() bool { - return peer.conf.RouteServer.Config.RouteServerClient + return peer.fsm.pConf.RouteServer.Config.RouteServerClient } func (peer *Peer) isRouteReflectorClient() bool { - return peer.conf.RouteReflector.Config.RouteReflectorClient + return peer.fsm.pConf.RouteReflector.Config.RouteReflectorClient } func (peer *Peer) isGracefulRestartEnabled() bool { @@ -102,7 +96,7 @@ func (peer *Peer) recvedAllEOR() bool { } func (peer *Peer) configuredRFlist() []bgp.RouteFamily { - rfs, _ := config.AfiSafis(peer.conf.AfiSafis).ToRfList() + rfs, _ := config.AfiSafis(peer.fsm.pConf.AfiSafis).ToRfList() return rfs } @@ -142,7 +136,7 @@ func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []* Neighbor: peer.fsm.peerInfo.Address, } var source []*table.Path - if peer.gConf.Collector.Enabled { + if peer.fsm.gConf.Collector.Enabled { source = peer.localRib.GetPathList(peer.TableID(), rfList) } else { source = peer.localRib.GetBestPathList(peer.TableID(), rfList) @@ -153,9 +147,9 @@ func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []* filtered = append(filtered, path) continue } - if !peer.gConf.Collector.Enabled && !peer.isRouteServerClient() { + if !peer.fsm.gConf.Collector.Enabled && !peer.isRouteServerClient() { p = p.Clone(p.IsWithdraw) - p.UpdatePathAttrs(&peer.gConf, &peer.conf) + p.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf) } pathList = append(pathList, p) } @@ -174,7 +168,7 @@ func (peer *Peer) processOutgoingPaths(paths, withdrawals []*table.Path) []*tabl if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debug("now syncing, suppress sending updates") return nil } @@ -194,9 +188,9 @@ func (peer *Peer) processOutgoingPaths(paths, withdrawals []*table.Path) []*tabl if path == nil { continue } - if !peer.isRouteServerClient() && !peer.gConf.Collector.Enabled { + if !peer.isRouteServerClient() && !peer.fsm.gConf.Collector.Enabled { path = path.Clone(path.IsWithdraw) - path.UpdatePathAttrs(&peer.gConf, &peer.conf) + path.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf) } outgoing = append(outgoing, path) } @@ -212,7 +206,7 @@ func (peer *Peer) handleRouteRefresh(e *FsmMsg) []*table.Path { if _, ok := peer.fsm.rfMap[rf]; !ok { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.ID(), "Data": rf, }).Warn("Route family isn't supported") return nil @@ -220,7 +214,7 @@ func (peer *Peer) handleRouteRefresh(e *FsmMsg) []*table.Path { if _, ok := peer.fsm.capMap[bgp.BGP_CAP_ROUTE_REFRESH]; !ok { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.ID(), }).Warn("ROUTE_REFRESH received but the capability wasn't advertised") return nil } @@ -239,10 +233,10 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg m := e.MsgData.(*bgp.BGPMessage) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, "data": m, }).Debug("received") - peer.conf.Timers.State.UpdateRecvTime = time.Now().Unix() + peer.fsm.pConf.Timers.State.UpdateRecvTime = time.Now().Unix() if len(e.PathList) > 0 { peer.adjRibIn.Update(e.PathList) for _, family := range peer.fsm.pConf.AfiSafis { @@ -254,14 +248,14 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg peer.prefixLimitWarned[k] = true log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.ID(), "AddressFamily": family.AfiSafiName, }).Warnf("prefix limit %d%% reached", pct) } if count > maxPrefixes { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.ID(), "AddressFamily": family.AfiSafiName, }).Warnf("prefix limit reached") return nil, nil, bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_MAXIMUM_NUMBER_OF_PREFIXES_REACHED, nil) @@ -275,7 +269,7 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg family := path.GetRouteFamily() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.ID(), "AddressFamily": family, }).Debug("EOR received") eor = append(eor, family) @@ -305,7 +299,7 @@ func (peer *Peer) PassConn(conn *net.TCPConn) { conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.ID(), }).Warn("accepted conn is closed to avoid be blocked") } } @@ -327,7 +321,7 @@ func (peer *Peer) ToApiStruct() *api.Peer { } } - caps := capabilitiesFromConfig(&peer.conf) + caps := capabilitiesFromConfig(peer.fsm.pConf) localCap := make([][]byte, 0, len(caps)) for _, c := range caps { buf, _ := c.Serialize() diff --git a/server/server.go b/server/server.go index a2bd40e8..0ddedcf7 100644 --- a/server/server.go +++ b/server/server.go @@ -284,7 +284,7 @@ func (server *BgpServer) Serve() { return false } return true - }(net.ParseIP(peer.conf.Transport.Config.LocalAddress)) + }(net.ParseIP(peer.fsm.pConf.Transport.Config.LocalAddress)) if localAddrValid == false { conn.Close() return @@ -331,7 +331,10 @@ func (server *BgpServer) Serve() { case config := <-server.updatedPeerCh: addr := config.Config.NeighborAddress peer := server.neighborMap[addr] - peer.conf = config + // FIXME: check updated values and restart bgp + // session with new value as needed + // e.g. timer, supported afi-safi etc. + peer.fsm.pConf = &config server.setPolicyByConfig(peer.ID(), config.ApplyPolicy) case e, ok := <-server.fsmincomingCh.Out(): if !ok { @@ -368,7 +371,7 @@ func newSenderMsg(peer *Peer, paths []*table.Path, notification *bgp.BGPMessage, func isASLoop(peer *Peer, path *table.Path) bool { for _, as := range path.GetAsList() { - if as == peer.conf.Config.PeerAs { + if as == peer.fsm.pConf.Config.PeerAs { return true } } @@ -383,7 +386,7 @@ func filterpath(peer *Peer, path *table.Path) *table.Path { return nil } - remoteAddr := peer.conf.Config.NeighborAddress + remoteAddr := peer.fsm.pConf.Config.NeighborAddress //iBGP handling if !path.IsLocal() && peer.isIBGPPeer() { @@ -391,13 +394,13 @@ func filterpath(peer *Peer, path *table.Path) *table.Path { info := path.GetSource() //if the path comes from eBGP peer - if info.AS != peer.conf.Config.PeerAs { + if info.AS != peer.fsm.pConf.Config.PeerAs { ignore = false } // RFC4456 8. Avoiding Routing Information Loops // A router that recognizes the ORIGINATOR_ID attribute SHOULD // ignore a route received with its BGP Identifier as the ORIGINATOR_ID. - if id := path.GetOriginatorID(); peer.gConf.Config.RouterId == id.String() { + if id := path.GetOriginatorID(); peer.fsm.gConf.Config.RouterId == id.String() { log.WithFields(log.Fields{ "Topic": "Peer", "Key": remoteAddr, @@ -573,7 +576,7 @@ func (server *BgpServer) broadcastPeerState(peer *Peer, oldState bgp.FSMState) { default: } ignore := req.RequestType != REQ_MONITOR_NEIGHBOR_PEER_STATE - ignore = ignore || (req.Name != "" && req.Name != peer.conf.Config.NeighborAddress) + ignore = ignore || (req.Name != "" && req.Name != peer.fsm.pConf.Config.NeighborAddress) if ignore { remainReqs = append(remainReqs, req) continue @@ -758,14 +761,14 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { switch e.MsgType { case FSM_MSG_STATE_CHANGE: nextState := e.MsgData.(bgp.FSMState) - oldState := bgp.FSMState(peer.conf.State.SessionState.ToInt()) - peer.conf.State.SessionState = config.IntToSessionStateMap[int(nextState)] + oldState := bgp.FSMState(peer.fsm.pConf.State.SessionState.ToInt()) + peer.fsm.pConf.State.SessionState = config.IntToSessionStateMap[int(nextState)] peer.fsm.StateChange(nextState) if oldState == bgp.BGP_FSM_ESTABLISHED { t := time.Now() - if t.Sub(time.Unix(peer.conf.Timers.State.Uptime, 0)) < FLOP_THRESHOLD { - peer.conf.State.Flops++ + if t.Sub(time.Unix(peer.fsm.pConf.Timers.State.Uptime, 0)) < FLOP_THRESHOLD { + peer.fsm.pConf.State.Flops++ } var drop []bgp.RouteFamily if peer.fsm.reason == FSM_GRACEFUL_RESTART { @@ -794,7 +797,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { if nextState == bgp.BGP_FSM_ESTABLISHED { // update for export policy laddr, _ := peer.fsm.LocalHostPort() - peer.conf.Transport.Config.LocalAddress = laddr + peer.fsm.pConf.Transport.Config.LocalAddress = laddr if !peer.fsm.pConf.GracefulRestart.State.LocalRestarting { pathList, _ := peer.getBestFromLocal(peer.configuredRFlist()) if len(pathList) > 0 { @@ -811,10 +814,10 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { deferral := peer.fsm.pConf.GracefulRestart.Config.DeferralTime log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debugf("now syncing, suppress sending updates. start deferral timer(%d)", deferral) time.AfterFunc(time.Second*time.Duration(deferral), func() { - req := NewGrpcRequest(REQ_DEFERRAL_TIMER_EXPIRED, peer.conf.Config.NeighborAddress, bgp.RouteFamily(0), nil) + req := NewGrpcRequest(REQ_DEFERRAL_TIMER_EXPIRED, peer.fsm.pConf.Config.NeighborAddress, bgp.RouteFamily(0), nil) server.GrpcReqCh <- req <-req.ResponseCh }) @@ -832,12 +835,12 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { os.Exit(0) } } - peer.conf.Timers.State.Downtime = time.Now().Unix() + peer.fsm.pConf.Timers.State.Downtime = time.Now().Unix() } // clear counter if peer.fsm.adminState == ADMIN_STATE_DOWN { - peer.conf.State = config.NeighborState{} - peer.conf.Timers.State = config.TimersState{} + peer.fsm.pConf.State = config.NeighborState{} + peer.fsm.pConf.Timers.State = config.TimersState{} } peer.startFSMHandler(server.fsmincomingCh, server.fsmStateCh) server.broadcastPeerState(peer, oldState) @@ -946,7 +949,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { pathList := peer.adjRibIn.DropStale(peer.configuredRFlist()) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debugf("withdraw %d stale routes", len(pathList)) m, _ := server.propagateUpdate(peer, pathList) msgs = append(msgs, m...) @@ -956,7 +959,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { default: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, "Data": e.MsgData, }).Panic("unknown msg type") } @@ -1127,9 +1130,9 @@ func (server *BgpServer) handlePolicy(pl config.RoutingPolicy) error { for _, peer := range server.neighborMap { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Info("call set policy") - server.setPolicyByConfig(peer.ID(), peer.conf.ApplyPolicy) + server.setPolicyByConfig(peer.ID(), peer.fsm.pConf.ApplyPolicy) } return nil } @@ -1858,7 +1861,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { _, rport := peer.fsm.RemoteHostPort() sentOpen := buildopen(peer.fsm.gConf, peer.fsm.pConf) info := peer.fsm.peerInfo - timestamp := peer.conf.Timers.State.Uptime + timestamp := peer.fsm.pConf.Timers.State.Uptime msg := bmpPeerUp(laddr, lport, rport, sentOpen, peer.fsm.recvOpen, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, timestamp) msgs = append(msgs, msg) } @@ -1982,7 +1985,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { logOp(grpcReq.Name, "Neighbor reset") m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, nil) for _, peer := range peers { - peer.fsm.idleHoldTime = peer.conf.Timers.Config.IdleHoldTimeAfterReset + peer.fsm.idleHoldTime = peer.fsm.pConf.Timers.Config.IdleHoldTimeAfterReset msgs = append(msgs, newSenderMsg(peer, nil, m, false)) } grpcReq.ResponseCh <- &GrpcResponse{} @@ -2046,7 +2049,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { peer.fsm.pConf.GracefulRestart.State.LocalRestarting = false log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debug("deferral timer expired") } else { continue @@ -2096,12 +2099,12 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { case peer.fsm.adminStateCh <- ADMIN_STATE_UP: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debug("ADMIN_STATE_UP requested") err.Code = api.Error_SUCCESS err.Msg = "ADMIN_STATE_UP" default: - log.Warning("previous request is still remaining. : ", peer.conf.Config.NeighborAddress) + log.Warning("previous request is still remaining. : ", peer.fsm.pConf.Config.NeighborAddress) err.Code = api.Error_FAIL err.Msg = "previous request is still remaining" } @@ -2110,12 +2113,12 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { case peer.fsm.adminStateCh <- ADMIN_STATE_DOWN: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debug("ADMIN_STATE_DOWN requested") err.Code = api.Error_SUCCESS err.Msg = "ADMIN_STATE_DOWN" default: - log.Warning("previous request is still remaining. : ", peer.conf.Config.NeighborAddress) + log.Warning("previous request is still remaining. : ", peer.fsm.pConf.Config.NeighborAddress) err.Code = api.Error_FAIL err.Msg = "previous request is still remaining" } @@ -2276,7 +2279,7 @@ func (server *BgpServer) handleAddNeighbor(c *config.Neighbor) ([]*SenderMsg, er } } - peer := NewPeer(server.bgpConfig.Global, *c, server.globalRib, server.policy) + peer := NewPeer(&server.bgpConfig.Global, c, server.globalRib, server.policy) server.setPolicyByConfig(peer.ID(), c.ApplyPolicy) if peer.isRouteServerClient() { pathList := make([]*table.Path, 0) @@ -2327,8 +2330,8 @@ func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) ([]*SenderM arg := grpcReq.Data.(*api.ModNeighborArguments) switch arg.Operation { case api.Operation_ADD: - apitoConfig := func(a *api.Peer) (config.Neighbor, error) { - var pconf config.Neighbor + apitoConfig := func(a *api.Peer) (*config.Neighbor, error) { + pconf := &config.Neighbor{} if a.Conf != nil { pconf.NeighborAddress = a.Conf.NeighborAddress pconf.Config.NeighborAddress = a.Conf.NeighborAddress @@ -2422,7 +2425,7 @@ func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) ([]*SenderM if err != nil { return nil, err } - return server.handleAddNeighbor(&c) + return server.handleAddNeighbor(c) case api.Operation_DEL: return server.handleDelNeighbor(&config.Neighbor{NeighborAddress: arg.Peer.Conf.NeighborAddress}) default: @@ -2970,8 +2973,8 @@ func (server *BgpServer) mkMrtPeerIndexTableMsg(t uint32, view string) (*mrt.MRT peers := make([]*mrt.Peer, 0, len(server.neighborMap)) for _, peer := range server.neighborMap { id := peer.fsm.peerInfo.ID.To4().String() - ipaddr := peer.conf.Config.NeighborAddress - asn := peer.conf.Config.PeerAs + ipaddr := peer.fsm.pConf.Config.NeighborAddress + asn := peer.fsm.pConf.Config.PeerAs peers = append(peers, mrt.NewPeer(id, ipaddr, asn, true)) } bgpid := server.bgpConfig.Global.Config.RouterId |