diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-07-29 00:07:26 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-07-29 00:07:26 +0900 |
commit | 0147728f77aa1871714b5dd23260732caeceb7ed (patch) | |
tree | 3e7570a99d1e7c78f32cb6aba94ccd73b528fd2e | |
parent | c3560d1224f7759455b6916843341b20355dbfe5 (diff) |
move gRPC-related code for SoftReset to grpc_server.go
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | gobgpd/main.go | 16 | ||||
-rw-r--r-- | server/grpc_server.go | 19 | ||||
-rw-r--r-- | server/server.go | 281 |
3 files changed, 159 insertions, 157 deletions
diff --git a/gobgpd/main.go b/gobgpd/main.go index 4c083953..d76735d7 100644 --- a/gobgpd/main.go +++ b/gobgpd/main.go @@ -22,6 +22,7 @@ import ( p "github.com/kr/pretty" "github.com/osrg/gobgp/config" ops "github.com/osrg/gobgp/openswitch" + "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/server" "io/ioutil" "log/syslog" @@ -276,20 +277,7 @@ func main() { } if updatePolicy { - // TODO: we want to apply the new policies to the existing - // routes here. Sending SOFT_RESET_IN to all the peers works - // for the change of in and import policies. SOFT_RESET_OUT is - // necessary for the export policy but we can't blindly - // execute SOFT_RESET_OUT because we unnecessarily advertize - // the existing routes. Needs to investigate the changes of - // policies and handle only affected peers. - ch := make(chan *server.GrpcResponse) - bgpServer.GrpcReqCh <- &server.GrpcRequest{ - RequestType: server.REQ_NEIGHBOR_SOFT_RESET_IN, - Name: "all", - ResponseCh: ch, - } - <-ch + bgpServer.SoftResetIn("", bgp.RouteFamily(0)) } case sig := <-sigCh: switch sig { diff --git a/server/grpc_server.go b/server/grpc_server.go index 00e8e263..b16990c1 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -447,18 +447,21 @@ func (s *Server) ResetNeighbor(ctx context.Context, arg *api.ResetNeighborReques } func (s *Server) SoftResetNeighbor(ctx context.Context, arg *api.SoftResetNeighborRequest) (*api.SoftResetNeighborResponse, error) { - op := REQ_NEIGHBOR_SOFT_RESET + var err error + addr := arg.Address + if addr == "all" { + addr = "" + } + family := bgp.RouteFamily(0) switch arg.Direction { case api.SoftResetNeighborRequest_IN: - op = REQ_NEIGHBOR_SOFT_RESET_IN + err = s.bgpServer.SoftResetIn(addr, family) case api.SoftResetNeighborRequest_OUT: - op = REQ_NEIGHBOR_SOFT_RESET_OUT - } - d, err := s.neighbor(op, arg.Address, arg) - if err != nil { - return nil, err + err = s.bgpServer.SoftResetOut(addr, family) + default: + err = s.bgpServer.SoftReset(addr, family) } - return d.(*api.SoftResetNeighborResponse), err + return &api.SoftResetNeighborResponse{}, err } func (s *Server) ShutdownNeighbor(ctx context.Context, arg *api.ShutdownNeighborRequest) (*api.ShutdownNeighborResponse, error) { 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 } |