summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-10-18 20:36:57 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-10-20 10:33:10 +0900
commit9362bba919c03b2f193714b47a7432ab521ecf98 (patch)
tree379d50ba4efdca5cc09b1cacb48605825f6a9023
parent95e68a8d8824874d0919435d7829fdfd2afdc6bc (diff)
api: support policy modification via grpc
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go136
-rw-r--r--api/gobgp.proto15
-rw-r--r--server/grpc_server.go61
-rw-r--r--server/server.go110
-rw-r--r--table/policy.go59
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")