summaryrefslogtreecommitdiffhomepage
path: root/server
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 /server
parent95e68a8d8824874d0919435d7829fdfd2afdc6bc (diff)
api: support policy modification via grpc
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server')
-rw-r--r--server/grpc_server.go61
-rw-r--r--server/server.go110
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 := ""