diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/grpc_server.go | 61 | ||||
-rw-r--r-- | server/server.go | 110 |
2 files changed, 93 insertions, 78 deletions
diff --git a/server/grpc_server.go b/server/grpc_server.go index 44c3562d..0ff61b47 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -43,11 +43,6 @@ const ( REQ_NEIGHBOR_POLICY REQ_MOD_NEIGHBOR_POLICY REQ_GLOBAL_RIB - REQ_POLICY_ROUTEPOLICIES - REQ_POLICY_ROUTEPOLICY - REQ_POLICY_ROUTEPOLICY_ADD - REQ_POLICY_ROUTEPOLICY_DELETE - REQ_POLICY_ROUTEPOLICIES_DELETE REQ_MONITOR_GLOBAL_BEST_CHANGED REQ_MONITOR_NEIGHBOR_PEER_STATE REQ_MRT_GLOBAL_RIB @@ -64,6 +59,7 @@ const ( REQ_STATEMENT REQ_MOD_STATEMENT REQ_POLICY + REQ_MOD_POLICY ) const GRPC_PORT = 8080 @@ -291,57 +287,6 @@ func (s *Server) ModNeighborPolicy(stream api.GobgpApi_ModNeighborPolicyServer) } } -func (s *Server) modPolicy(arg *api.PolicyArguments, stream interface{}) error { - var rf bgp.RouteFamily - var reqType int - var err error - switch arg.Resource { - case api.Resource_POLICY_ROUTEPOLICY: - switch arg.Operation { - case api.Operation_ADD: - reqType = REQ_POLICY_ROUTEPOLICY_ADD - case api.Operation_DEL: - reqType = REQ_POLICY_ROUTEPOLICY_DELETE - case api.Operation_DEL_ALL: - reqType = REQ_POLICY_ROUTEPOLICIES_DELETE - default: - return fmt.Errorf("unsupported operation: %s", arg.Operation) - } - default: - return fmt.Errorf("unsupported resource type: %v", arg.Resource) - } - req := NewGrpcRequest(reqType, "", rf, arg.PolicyDefinition) - s.bgpServerCh <- req - - res := <-req.ResponseCh - if err := res.Err(); err != nil { - log.Debug(err.Error()) - return err - } - err = stream.(api.GobgpApi_ModPolicyRoutePolicyServer).Send(&api.Error{ - Code: api.Error_SUCCESS, - }) - if err != nil { - return err - } - return nil -} - -func (s *Server) ModPolicyRoutePolicy(stream api.GobgpApi_ModPolicyRoutePolicyServer) error { - for { - arg, err := stream.Recv() - if err == io.EOF { - return nil - } else if err != nil { - return err - } - if err := s.modPolicy(arg, stream); err != nil { - return err - } - return nil - } -} - func (s *Server) GetMrt(arg *api.MrtArguments, stream api.GobgpApi_GetMrtServer) error { var reqType int switch arg.Resource { @@ -467,6 +412,10 @@ func (s *Server) GetPolicies(arg *api.Policy, stream api.GobgpApi_GetPoliciesSer }) } +func (s *Server) ModPolicy(ctx context.Context, arg *api.ModPolicyArguments) (*api.Error, error) { + return s.mod(REQ_MOD_POLICY, arg) +} + type GrpcRequest struct { RequestType int Name string diff --git a/server/server.go b/server/server.go index 91466753..171bee55 100644 --- a/server/server.go +++ b/server/server.go @@ -1663,28 +1663,10 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { } } close(grpcReq.ResponseCh) - case REQ_POLICY_ROUTEPOLICY, REQ_POLICY_ROUTEPOLICIES: - info := server.policy.PolicyMap - typ := grpcReq.RequestType - arg := grpcReq.Data.(*api.PolicyArguments) - result := &GrpcResponse{} - if len(info) > 0 { - for _, i := range info { - if typ == REQ_POLICY_ROUTEPOLICY && i.Name() != arg.Name { - continue - } - d := i.ToApiStruct() - result = &GrpcResponse{ - Data: d, - } - grpcReq.ResponseCh <- result - if typ == REQ_POLICY_ROUTEPOLICY { - break - } - } - } else { - result.ResponseErr = fmt.Errorf("Route Policy doesn't exist.") - grpcReq.ResponseCh <- result + case REQ_MOD_POLICY: + err := server.handleGrpcModPolicy(grpcReq) + grpcReq.ResponseCh <- &GrpcResponse{ + ResponseErr: err, } close(grpcReq.ResponseCh) case REQ_MONITOR_GLOBAL_BEST_CHANGED, REQ_MONITOR_NEIGHBOR_PEER_STATE: @@ -1805,6 +1787,9 @@ func (server *BgpServer) handleGrpcModStatement(grpcReq *GrpcRequest) error { m := server.policy.StatementMap name := s.Name d, ok := m[name] + if arg.Operation != api.Operation_ADD && !ok { + return fmt.Errorf("not found statement: %s", name) + } switch arg.Operation { case api.Operation_ADD: if ok { @@ -1848,6 +1833,87 @@ func (server *BgpServer) handleGrpcGetPolicy(grpcReq *GrpcRequest) error { return nil } +func (server *BgpServer) policyInUse(x *table.Policy) bool { + for _, peer := range server.neighborMap { + for _, dir := range []table.PolicyDirection{table.POLICY_DIRECTION_IN, table.POLICY_DIRECTION_EXPORT, table.POLICY_DIRECTION_EXPORT} { + for _, y := range peer.GetPolicy(dir) { + if x.Name() == y.Name() { + return true + } + } + } + } + for _, dir := range []table.PolicyDirection{table.POLICY_DIRECTION_EXPORT, table.POLICY_DIRECTION_EXPORT} { + for _, y := range server.globalRib.GetPolicy(dir) { + if x.Name() == y.Name() { + return true + } + } + } + return false +} + +func (server *BgpServer) handleGrpcModPolicy(grpcReq *GrpcRequest) error { + arg := grpcReq.Data.(*api.ModPolicyArguments) + x, err := table.NewPolicyFromApiStruct(arg.Policy, server.policy.DefinedSetMap) + if err != nil { + return err + } + pMap := server.policy.PolicyMap + sMap := server.policy.StatementMap + name := x.Name() + y, ok := pMap[name] + if arg.Operation != api.Operation_ADD && !ok { + return fmt.Errorf("not found policy: %s", name) + } + switch arg.Operation { + case api.Operation_ADD, api.Operation_REPLACE: + if arg.ReferExistingStatements { + err = x.FillUp(sMap) + if err != nil { + return err + } + } else { + for _, s := range x.Statements { + if _, ok := sMap[s.Name]; ok { + return fmt.Errorf("statement %s already defined", s.Name) + } + sMap[s.Name] = s + } + } + if arg.Operation == api.Operation_REPLACE { + err = y.Replace(x) + } else if ok { + err = y.Add(x) + } else { + pMap[name] = x + } + case api.Operation_DEL: + err = y.Remove(x) + case api.Operation_DEL_ALL: + if server.policyInUse(y) { + return fmt.Errorf("can't delete. policy %s is in use", name) + } + log.WithFields(log.Fields{ + "Topic": "Policy", + "Key": name, + }).Debug("delete policy") + delete(pMap, name) + } + if err == nil && arg.Operation != api.Operation_ADD && !arg.PreserveStatements { + for _, s := range y.Statements { + if !server.policy.StatementInUse(s) { + log.WithFields(log.Fields{ + "Topic": "Policy", + "Key": s.Name, + }).Debug("delete unused statement") + delete(sMap, s.Name) + } + } + } + return err +} + func (server *BgpServer) handleMrt(grpcReq *GrpcRequest) { now := uint32(time.Now().Unix()) view := "" |