diff options
Diffstat (limited to 'server/server.go')
-rw-r--r-- | server/server.go | 281 |
1 files changed, 146 insertions, 135 deletions
diff --git a/server/server.go b/server/server.go index 5d04d365..47f9e3da 100644 --- a/server/server.go +++ b/server/server.go @@ -27,7 +27,6 @@ import ( log "github.com/Sirupsen/logrus" "github.com/armon/go-radix" "github.com/eapache/channels" - api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" @@ -593,9 +592,14 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { peer.fsm.peerInfo.LocalAddress = net.ParseIP(laddr) deferralExpiredFunc := func(family bgp.RouteFamily) func() { return func() { - req := NewGrpcRequest(REQ_DEFERRAL_TIMER_EXPIRED, peer.ID(), family, nil) - server.GrpcReqCh <- req - <-req.ResponseCh + ch := make(chan struct{}) + defer func() { <-ch }() + + server.mgmtCh <- func() { + defer close(ch) + + server.softResetOut(peer.fsm.pConf.Config.NeighborAddress, bgp.RouteFamily(0), true) + } } } if !peer.fsm.pConf.GracefulRestart.State.LocalRestarting { @@ -1256,159 +1260,166 @@ func (s *BgpServer) Stop() (err error) { return nil } -func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { - logOp := func(addr string, action string) { - log.WithFields(log.Fields{ - "Topic": "Operation", - "Key": addr, - }).Info(action) +func (s *BgpServer) softResetIn(addr string, family bgp.RouteFamily) error { + peers, err := s.addrToPeers(addr) + if err != nil { + return err } - - reqToPeers := func(grpcReq *GrpcRequest) ([]*Peer, error) { - peers := make([]*Peer, 0) - if grpcReq.Name == "all" { - for _, p := range server.neighborMap { - peers = append(peers, p) + for _, peer := range peers { + pathList := []*table.Path{} + families := []bgp.RouteFamily{family} + if family == bgp.RouteFamily(0) { + families = peer.configuredRFlist() + } + for _, path := range peer.adjRibIn.PathList(families, false) { + exResult := path.Filtered(peer.ID()) + path.Filter(peer.ID(), table.POLICY_DIRECTION_NONE) + if s.policy.ApplyPolicy(peer.ID(), table.POLICY_DIRECTION_IN, path, nil) != nil { + pathList = append(pathList, path.Clone(false)) + // this path still in rib's + // knownPathList. We can't + // drop + // table.POLICY_DIRECTION_IMPORT + // flag here. Otherwise, this + // path could be the old best + // path. + if peer.isRouteServerClient() { + path.Filter(peer.ID(), table.POLICY_DIRECTION_IMPORT) + } + } else { + path.Filter(peer.ID(), table.POLICY_DIRECTION_IN) + if exResult != table.POLICY_DIRECTION_IN { + pathList = append(pathList, path.Clone(true)) + } } - return peers, nil } - peer, err := server.checkNeighborRequest(grpcReq) - return []*Peer{peer}, err + peer.adjRibIn.RefreshAcceptedNumber(families) + s.propagateUpdate(peer, pathList) } + return err +} - if server.bgpConfig.Global.Config.As == 0 && grpcReq.RequestType != REQ_START_SERVER { - grpcReq.ResponseCh <- &GrpcResponse{ - ResponseErr: fmt.Errorf("bgpd main loop is not started yet"), - } - close(grpcReq.ResponseCh) - return +func (s *BgpServer) softResetOut(addr string, family bgp.RouteFamily, deferral bool) error { + peers, err := s.addrToPeers(addr) + if err != nil { + return err } + for _, peer := range peers { + if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED { + continue + } - var err error - - switch grpcReq.RequestType { - case REQ_NEIGHBOR_SOFT_RESET, REQ_NEIGHBOR_SOFT_RESET_IN: - peers, err := reqToPeers(grpcReq) - if err != nil { - break + families := []bgp.RouteFamily{family} + if family == bgp.RouteFamily(0) { + families = peer.configuredRFlist() } - if grpcReq.RequestType == REQ_NEIGHBOR_SOFT_RESET { - logOp(grpcReq.Name, "Neighbor soft reset") - } else { - logOp(grpcReq.Name, "Neighbor soft reset in") + + if deferral { + if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { + peer.fsm.pConf.GracefulRestart.State.LocalRestarting = false + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.ID(), + "Families": families, + }).Debug("deferral timer expired") + } else if c := config.GetAfiSafi(peer.fsm.pConf, bgp.RF_RTC_UC); peer.fsm.rfMap[bgp.RF_RTC_UC] && !c.MpGracefulRestart.State.EndOfRibReceived { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.ID(), + "Families": families, + }).Debug("route-target deferral timer expired") + } else { + continue + } } - for _, peer := range peers { - pathList := []*table.Path{} - families := []bgp.RouteFamily{grpcReq.RouteFamily} - if families[0] == bgp.RouteFamily(0) { - families = peer.configuredRFlist() - } - for _, path := range peer.adjRibIn.PathList(families, false) { - exResult := path.Filtered(peer.ID()) - path.Filter(peer.ID(), table.POLICY_DIRECTION_NONE) - if server.policy.ApplyPolicy(peer.ID(), table.POLICY_DIRECTION_IN, path, nil) != nil { - pathList = append(pathList, path.Clone(false)) - // this path still in rib's - // knownPathList. We can't - // drop - // table.POLICY_DIRECTION_IMPORT - // flag here. Otherwise, this - // path could be the old best - // path. - if peer.isRouteServerClient() { - path.Filter(peer.ID(), table.POLICY_DIRECTION_IMPORT) - } - } else { - path.Filter(peer.ID(), table.POLICY_DIRECTION_IN) - if exResult != table.POLICY_DIRECTION_IN { - pathList = append(pathList, path.Clone(true)) + sentPathList := peer.adjRibOut.PathList(families, false) + peer.adjRibOut.Drop(families) + pathList, filtered := peer.getBestFromLocal(families) + if len(pathList) > 0 { + peer.adjRibOut.Update(pathList) + sendFsmOutgoingMsg(peer, pathList, nil, false) + } + if deferral == false && len(filtered) > 0 { + withdrawnList := make([]*table.Path, 0, len(filtered)) + for _, p := range filtered { + found := false + for _, sentPath := range sentPathList { + if p.GetNlri() == sentPath.GetNlri() { + found = true + break } } + if found { + withdrawnList = append(withdrawnList, p.Clone(true)) + } } - peer.adjRibIn.RefreshAcceptedNumber(families) - server.propagateUpdate(peer, pathList) + sendFsmOutgoingMsg(peer, withdrawnList, nil, false) } + } + return nil +} - if grpcReq.RequestType == REQ_NEIGHBOR_SOFT_RESET_IN { - grpcReq.ResponseCh <- &GrpcResponse{Data: &api.SoftResetNeighborResponse{}} - close(grpcReq.ResponseCh) - break - } - fallthrough - case REQ_NEIGHBOR_SOFT_RESET_OUT, REQ_DEFERRAL_TIMER_EXPIRED: - peers, err := reqToPeers(grpcReq) - if err != nil { - break - } - if grpcReq.RequestType == REQ_NEIGHBOR_SOFT_RESET_OUT { - logOp(grpcReq.Name, "Neighbor soft reset out") - } - for _, peer := range peers { - if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED { - continue - } +func (s *BgpServer) SoftResetIn(addr string, family bgp.RouteFamily) (err error) { + ch := make(chan struct{}) + defer func() { <-ch }() - families := []bgp.RouteFamily{grpcReq.RouteFamily} - if families[0] == bgp.RouteFamily(0) { - families = peer.configuredRFlist() - } + log.WithFields(log.Fields{ + "Topic": "Operation", + "Key": addr, + }).Info("Neighbor soft reset in") - if grpcReq.RequestType == REQ_DEFERRAL_TIMER_EXPIRED { - if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { - peer.fsm.pConf.GracefulRestart.State.LocalRestarting = false - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.ID(), - "Families": families, - }).Debug("deferral timer expired") - } else if c := config.GetAfiSafi(peer.fsm.pConf, bgp.RF_RTC_UC); peer.fsm.rfMap[bgp.RF_RTC_UC] && !c.MpGracefulRestart.State.EndOfRibReceived { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.ID(), - "Families": families, - }).Debug("route-target deferral timer expired") - } else { - continue - } - } + s.mgmtCh <- func() { + defer close(ch) + err = s.softResetIn(addr, family) + } + return err +} - sentPathList := peer.adjRibOut.PathList(families, false) - peer.adjRibOut.Drop(families) - pathList, filtered := peer.getBestFromLocal(families) - if len(pathList) > 0 { - peer.adjRibOut.Update(pathList) - sendFsmOutgoingMsg(peer, pathList, nil, false) - } - if grpcReq.RequestType != REQ_DEFERRAL_TIMER_EXPIRED && len(filtered) > 0 { - withdrawnList := make([]*table.Path, 0, len(filtered)) - for _, p := range filtered { - found := false - for _, sentPath := range sentPathList { - if p.GetNlri() == sentPath.GetNlri() { - found = true - break - } - } - if found { - withdrawnList = append(withdrawnList, p.Clone(true)) - } - } - sendFsmOutgoingMsg(peer, withdrawnList, nil, false) - } +func (s *BgpServer) SoftResetOut(addr string, family bgp.RouteFamily) (err error) { + ch := make(chan struct{}) + defer func() { <-ch }() + + log.WithFields(log.Fields{ + "Topic": "Operation", + "Key": addr, + }).Info("Neighbor soft reset out") + + s.mgmtCh <- func() { + defer close(ch) + err = s.softResetOut(addr, family, false) + } + return err +} + +func (s *BgpServer) SoftReset(addr string, family bgp.RouteFamily) (err error) { + ch := make(chan struct{}) + defer func() { <-ch }() + + log.WithFields(log.Fields{ + "Topic": "Operation", + "Key": addr, + }).Info("Neighbor soft reset") + + s.mgmtCh <- func() { + defer close(ch) + err = s.softResetIn(addr, family) + err = s.softResetOut(addr, family, false) + } + return err +} + +func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { + if server.bgpConfig.Global.Config.As == 0 && grpcReq.RequestType != REQ_START_SERVER { + grpcReq.ResponseCh <- &GrpcResponse{ + ResponseErr: fmt.Errorf("bgpd main loop is not started yet"), } - grpcReq.ResponseCh <- &GrpcResponse{Data: &api.SoftResetNeighborResponse{}} close(grpcReq.ResponseCh) - default: - err = fmt.Errorf("Unknown request type: %v", grpcReq.RequestType) - goto ERROR + return } - return -ERROR: - grpcReq.ResponseCh <- &GrpcResponse{ - ResponseErr: err, + + switch grpcReq.RequestType { } - close(grpcReq.ResponseCh) return } |