diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-10-18 20:36:57 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-10-20 10:33:10 +0900 |
commit | 9362bba919c03b2f193714b47a7432ab521ecf98 (patch) | |
tree | 379d50ba4efdca5cc09b1cacb48605825f6a9023 | |
parent | 95e68a8d8824874d0919435d7829fdfd2afdc6bc (diff) |
api: support policy modification via grpc
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | api/gobgp.pb.go | 136 | ||||
-rw-r--r-- | api/gobgp.proto | 15 | ||||
-rw-r--r-- | server/grpc_server.go | 61 | ||||
-rw-r--r-- | server/server.go | 110 | ||||
-rw-r--r-- | table/policy.go | 59 |
5 files changed, 228 insertions, 153 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index e1c6309a..53aa0f7b 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -17,6 +17,7 @@ It has these top-level messages: ModVrfArguments ModDefinedSetArguments ModStatementArguments + ModPolicyArguments Path Destination PeerConf @@ -318,6 +319,31 @@ func (m *ModStatementArguments) GetStatement() *Statement { return nil } +type ModPolicyArguments struct { + Operation Operation `protobuf:"varint,1,opt,name=operation,enum=gobgpapi.Operation" json:"operation,omitempty"` + Policy *Policy `protobuf:"bytes,2,opt,name=policy" json:"policy,omitempty"` + // if this flag is set, gobgpd won't define new statements + // but refer existing statements using statement's names. + // if you use this flag don't put any conditions/actions to + // each statements and only set name. + ReferExistingStatements bool `protobuf:"varint,3,opt,name=refer_existing_statements" json:"refer_existing_statements,omitempty"` + // if this flag is set, gobgpd won't delete any statements + // even if the policy containing some statements are deleted. + // this flag means nothing if it is used with Operation_ADD + PreserveStatements bool `protobuf:"varint,4,opt,name=preserve_statements" json:"preserve_statements,omitempty"` +} + +func (m *ModPolicyArguments) Reset() { *m = ModPolicyArguments{} } +func (m *ModPolicyArguments) String() string { return proto.CompactTextString(m) } +func (*ModPolicyArguments) ProtoMessage() {} + +func (m *ModPolicyArguments) GetPolicy() *Policy { + if m != nil { + return m.Policy + } + return nil +} + type Path struct { Nlri []byte `protobuf:"bytes,1,opt,name=nlri,proto3" json:"nlri,omitempty"` Pattrs [][]byte `protobuf:"bytes,2,rep,name=pattrs,proto3" json:"pattrs,omitempty"` @@ -743,7 +769,6 @@ type GobgpApiClient interface { ModPath(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModPathClient, error) GetNeighborPolicy(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (*ApplyPolicy, error) ModNeighborPolicy(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModNeighborPolicyClient, error) - ModPolicyRoutePolicy(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModPolicyRoutePolicyClient, error) MonitorBestChanged(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorBestChangedClient, error) MonitorPeerState(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorPeerStateClient, error) GetMrt(ctx context.Context, in *MrtArguments, opts ...grpc.CallOption) (GobgpApi_GetMrtClient, error) @@ -759,6 +784,7 @@ type GobgpApiClient interface { ModStatement(ctx context.Context, in *ModStatementArguments, opts ...grpc.CallOption) (*Error, error) GetPolicy(ctx context.Context, in *Policy, opts ...grpc.CallOption) (*Policy, error) GetPolicies(ctx context.Context, in *Policy, opts ...grpc.CallOption) (GobgpApi_GetPoliciesClient, error) + ModPolicy(ctx context.Context, in *ModPolicyArguments, opts ...grpc.CallOption) (*Error, error) } type gobgpApiClient struct { @@ -979,39 +1005,8 @@ func (x *gobgpApiModNeighborPolicyClient) Recv() (*Error, error) { return m, nil } -func (c *gobgpApiClient) ModPolicyRoutePolicy(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModPolicyRoutePolicyClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[4], c.cc, "/gobgpapi.GobgpApi/ModPolicyRoutePolicy", opts...) - if err != nil { - return nil, err - } - x := &gobgpApiModPolicyRoutePolicyClient{stream} - return x, nil -} - -type GobgpApi_ModPolicyRoutePolicyClient interface { - Send(*PolicyArguments) error - Recv() (*Error, error) - grpc.ClientStream -} - -type gobgpApiModPolicyRoutePolicyClient struct { - grpc.ClientStream -} - -func (x *gobgpApiModPolicyRoutePolicyClient) Send(m *PolicyArguments) error { - return x.ClientStream.SendMsg(m) -} - -func (x *gobgpApiModPolicyRoutePolicyClient) Recv() (*Error, error) { - m := new(Error) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - func (c *gobgpApiClient) MonitorBestChanged(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorBestChangedClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[5], c.cc, "/gobgpapi.GobgpApi/MonitorBestChanged", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[4], c.cc, "/gobgpapi.GobgpApi/MonitorBestChanged", opts...) if err != nil { return nil, err } @@ -1043,7 +1038,7 @@ func (x *gobgpApiMonitorBestChangedClient) Recv() (*Destination, error) { } func (c *gobgpApiClient) MonitorPeerState(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorPeerStateClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[6], c.cc, "/gobgpapi.GobgpApi/MonitorPeerState", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[5], c.cc, "/gobgpapi.GobgpApi/MonitorPeerState", opts...) if err != nil { return nil, err } @@ -1075,7 +1070,7 @@ func (x *gobgpApiMonitorPeerStateClient) Recv() (*Peer, error) { } func (c *gobgpApiClient) GetMrt(ctx context.Context, in *MrtArguments, opts ...grpc.CallOption) (GobgpApi_GetMrtClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[7], c.cc, "/gobgpapi.GobgpApi/GetMrt", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[6], c.cc, "/gobgpapi.GobgpApi/GetMrt", opts...) if err != nil { return nil, err } @@ -1107,7 +1102,7 @@ func (x *gobgpApiGetMrtClient) Recv() (*MrtMessage, error) { } func (c *gobgpApiClient) GetRPKI(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetRPKIClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[8], c.cc, "/gobgpapi.GobgpApi/GetRPKI", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[7], c.cc, "/gobgpapi.GobgpApi/GetRPKI", opts...) if err != nil { return nil, err } @@ -1139,7 +1134,7 @@ func (x *gobgpApiGetRPKIClient) Recv() (*RPKI, error) { } func (c *gobgpApiClient) GetROA(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetROAClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[9], c.cc, "/gobgpapi.GobgpApi/GetROA", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[8], c.cc, "/gobgpapi.GobgpApi/GetROA", opts...) if err != nil { return nil, err } @@ -1171,7 +1166,7 @@ func (x *gobgpApiGetROAClient) Recv() (*ROA, error) { } func (c *gobgpApiClient) GetVrfs(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetVrfsClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[10], c.cc, "/gobgpapi.GobgpApi/GetVrfs", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[9], c.cc, "/gobgpapi.GobgpApi/GetVrfs", opts...) if err != nil { return nil, err } @@ -1221,7 +1216,7 @@ func (c *gobgpApiClient) GetDefinedSet(ctx context.Context, in *DefinedSet, opts } func (c *gobgpApiClient) GetDefinedSets(ctx context.Context, in *DefinedSet, opts ...grpc.CallOption) (GobgpApi_GetDefinedSetsClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[11], c.cc, "/gobgpapi.GobgpApi/GetDefinedSets", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[10], c.cc, "/gobgpapi.GobgpApi/GetDefinedSets", opts...) if err != nil { return nil, err } @@ -1271,7 +1266,7 @@ func (c *gobgpApiClient) GetStatement(ctx context.Context, in *Statement, opts . } func (c *gobgpApiClient) GetStatements(ctx context.Context, in *Statement, opts ...grpc.CallOption) (GobgpApi_GetStatementsClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[12], c.cc, "/gobgpapi.GobgpApi/GetStatements", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[11], c.cc, "/gobgpapi.GobgpApi/GetStatements", opts...) if err != nil { return nil, err } @@ -1321,7 +1316,7 @@ func (c *gobgpApiClient) GetPolicy(ctx context.Context, in *Policy, opts ...grpc } func (c *gobgpApiClient) GetPolicies(ctx context.Context, in *Policy, opts ...grpc.CallOption) (GobgpApi_GetPoliciesClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[13], c.cc, "/gobgpapi.GobgpApi/GetPolicies", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[12], c.cc, "/gobgpapi.GobgpApi/GetPolicies", opts...) if err != nil { return nil, err } @@ -1352,6 +1347,15 @@ func (x *gobgpApiGetPoliciesClient) Recv() (*Policy, error) { return m, nil } +func (c *gobgpApiClient) ModPolicy(ctx context.Context, in *ModPolicyArguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/ModPolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for GobgpApi service type GobgpApiServer interface { @@ -1368,7 +1372,6 @@ type GobgpApiServer interface { ModPath(GobgpApi_ModPathServer) error GetNeighborPolicy(context.Context, *PolicyArguments) (*ApplyPolicy, error) ModNeighborPolicy(GobgpApi_ModNeighborPolicyServer) error - ModPolicyRoutePolicy(GobgpApi_ModPolicyRoutePolicyServer) error MonitorBestChanged(*Arguments, GobgpApi_MonitorBestChangedServer) error MonitorPeerState(*Arguments, GobgpApi_MonitorPeerStateServer) error GetMrt(*MrtArguments, GobgpApi_GetMrtServer) error @@ -1384,6 +1387,7 @@ type GobgpApiServer interface { ModStatement(context.Context, *ModStatementArguments) (*Error, error) GetPolicy(context.Context, *Policy) (*Policy, error) GetPolicies(*Policy, GobgpApi_GetPoliciesServer) error + ModPolicy(context.Context, *ModPolicyArguments) (*Error, error) } func RegisterGobgpApiServer(s *grpc.Server, srv GobgpApiServer) { @@ -1592,32 +1596,6 @@ func (x *gobgpApiModNeighborPolicyServer) Recv() (*PolicyArguments, error) { return m, nil } -func _GobgpApi_ModPolicyRoutePolicy_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(GobgpApiServer).ModPolicyRoutePolicy(&gobgpApiModPolicyRoutePolicyServer{stream}) -} - -type GobgpApi_ModPolicyRoutePolicyServer interface { - Send(*Error) error - Recv() (*PolicyArguments, error) - grpc.ServerStream -} - -type gobgpApiModPolicyRoutePolicyServer struct { - grpc.ServerStream -} - -func (x *gobgpApiModPolicyRoutePolicyServer) Send(m *Error) error { - return x.ServerStream.SendMsg(m) -} - -func (x *gobgpApiModPolicyRoutePolicyServer) Recv() (*PolicyArguments, error) { - m := new(PolicyArguments) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - func _GobgpApi_MonitorBestChanged_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(Arguments) if err := stream.RecvMsg(m); err != nil { @@ -1879,6 +1857,18 @@ func (x *gobgpApiGetPoliciesServer) Send(m *Policy) error { return x.ServerStream.SendMsg(m) } +func _GobgpApi_ModPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { + in := new(ModPolicyArguments) + if err := dec(in); err != nil { + return nil, err + } + out, err := srv.(GobgpApiServer).ModPolicy(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + var _GobgpApi_serviceDesc = grpc.ServiceDesc{ ServiceName: "gobgpapi.GobgpApi", HandlerType: (*GobgpApiServer)(nil), @@ -1943,6 +1933,10 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{ MethodName: "GetPolicy", Handler: _GobgpApi_GetPolicy_Handler, }, + { + MethodName: "ModPolicy", + Handler: _GobgpApi_ModPolicy_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -1967,12 +1961,6 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{ ClientStreams: true, }, { - StreamName: "ModPolicyRoutePolicy", - Handler: _GobgpApi_ModPolicyRoutePolicy_Handler, - ServerStreams: true, - ClientStreams: true, - }, - { StreamName: "MonitorBestChanged", Handler: _GobgpApi_MonitorBestChanged_Handler, ServerStreams: true, diff --git a/api/gobgp.proto b/api/gobgp.proto index d72baaae..a1cce0a2 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -33,7 +33,6 @@ service GobgpApi { rpc ModPath(stream ModPathArguments) returns (Error) {} rpc GetNeighborPolicy(PolicyArguments) returns (ApplyPolicy) {} rpc ModNeighborPolicy(stream PolicyArguments) returns (stream Error) {} - rpc ModPolicyRoutePolicy(stream PolicyArguments) returns (stream Error) {} rpc MonitorBestChanged(Arguments) returns (stream Destination) {} rpc MonitorPeerState(Arguments) returns (stream Peer) {} rpc GetMrt(MrtArguments) returns (stream MrtMessage) {} @@ -49,6 +48,7 @@ service GobgpApi { rpc ModStatement(ModStatementArguments) returns (Error) {} rpc GetPolicy(Policy) returns (Policy) {} rpc GetPolicies(Policy) returns (stream Policy) {} + rpc ModPolicy(ModPolicyArguments) returns (Error) {} } message Error { @@ -103,6 +103,19 @@ message ModStatementArguments { Statement statement = 2; } +message ModPolicyArguments { + Operation operation = 1; + Policy policy = 2; + // if this flag is set, gobgpd won't define new statements + // but refer existing statements using statement's names. + // this flag only works with Operation_ADD + bool refer_existing_statements = 3; + // if this flag is set, gobgpd won't delete any statements + // even if the policy containing some statements are deleted. + // this flag means nothing if it is used with Operation_ADD + bool preserve_statements = 4; +} + enum Resource { GLOBAL = 0; LOCAL = 1; 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 := "" diff --git a/table/policy.go b/table/policy.go index 06c58df5..2b16ef65 100644 --- a/table/policy.go +++ b/table/policy.go @@ -2262,6 +2262,65 @@ func (p *Policy) ToApiStruct() *api.Policy { } } +func (p *Policy) FillUp(m map[string]*Statement) error { + stmts := make([]*Statement, 0, len(p.Statements)) + for _, x := range p.Statements { + y, ok := m[x.Name] + if !ok { + return fmt.Errorf("not found statement %s", x.Name) + } + stmts = append(stmts, y) + } + p.Statements = stmts + return nil +} + +func (lhs *Policy) Add(rhs *Policy) error { + lhs.Statements = append(lhs.Statements, rhs.Statements...) + return nil +} + +func (lhs *Policy) Remove(rhs *Policy) error { + stmts := make([]*Statement, 0, len(lhs.Statements)-len(rhs.Statements)) + for _, x := range lhs.Statements { + found := false + for _, y := range rhs.Statements { + if x.Name == y.Name { + found = true + break + } + } + if !found { + stmts = append(stmts, x) + } + } + lhs.Statements = stmts + return nil +} + +func (lhs *Policy) Replace(rhs *Policy) error { + lhs.Statements = rhs.Statements + return nil +} + +func NewPolicyFromApiStruct(a *api.Policy, dmap DefinedSetMap) (*Policy, error) { + if a.Name == "" { + return nil, fmt.Errorf("empty policy name") + } + stmts := make([]*Statement, 0, len(a.Statements)) + for _, x := range a.Statements { + y, err := NewStatementFromApiStruct(x, dmap) + if err != nil { + return nil, err + } + stmts = append(stmts, y) + } + return &Policy{ + name: a.Name, + Statements: stmts, + }, nil +} + func NewPolicy(c config.PolicyDefinition, dmap DefinedSetMap) (*Policy, error) { if c.Name == "" { return nil, fmt.Errorf("empty policy name") |