summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-07-20 06:50:15 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-07-20 06:50:15 +0900
commit4635014cbb1f403d4582698f1b0a23f5a879d5d0 (patch)
tree39a4a770865d576aca7278f2a8b33dac1eefa657 /server
parentc7c8f5612bb726ca8fe85389c688bb5d412e8fdb (diff)
remove gRPC dependency from table/
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'server')
-rw-r--r--server/grpc_server.go505
-rw-r--r--server/server.go1064
-rw-r--r--server/server_test.go50
3 files changed, 986 insertions, 633 deletions
diff --git a/server/grpc_server.go b/server/grpc_server.go
index d0103736..12337403 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -26,6 +26,7 @@ import (
"google.golang.org/grpc"
"io"
"net"
+ "reflect"
"regexp"
"strconv"
"strings"
@@ -103,6 +104,7 @@ const (
)
type Server struct {
+ bgpServer *BgpServer
grpcServer *grpc.Server
bgpServerCh chan *GrpcRequest
hosts string
@@ -804,13 +806,74 @@ func (s *Server) DeleteNeighbor(ctx context.Context, arg *api.DeleteNeighborRequ
return d.(*api.DeleteNeighborResponse), err
}
+func NewPrefixFromApiStruct(a *api.Prefix) (*table.Prefix, error) {
+ addr, prefix, err := net.ParseCIDR(a.IpPrefix)
+ if err != nil {
+ return nil, err
+ }
+ rf := bgp.RF_IPv4_UC
+ if addr.To4() == nil {
+ rf = bgp.RF_IPv6_UC
+ }
+ return &table.Prefix{
+ Prefix: prefix,
+ AddressFamily: rf,
+ MasklengthRangeMin: uint8(a.MaskLengthMin),
+ MasklengthRangeMax: uint8(a.MaskLengthMax),
+ }, nil
+}
+
+func NewDefinedSetFromApiStruct(a *api.DefinedSet) (table.DefinedSet, error) {
+ if a.Name == "" {
+ return nil, fmt.Errorf("empty neighbor set name")
+ }
+ switch table.DefinedType(a.Type) {
+ case table.DEFINED_TYPE_PREFIX:
+ prefixes := make([]*table.Prefix, 0, len(a.Prefixes))
+ for _, p := range a.Prefixes {
+ prefix, err := NewPrefixFromApiStruct(p)
+ if err != nil {
+ return nil, err
+ }
+ prefixes = append(prefixes, prefix)
+ }
+ return table.NewPrefixSetFromApiStruct(a.Name, prefixes)
+ case table.DEFINED_TYPE_NEIGHBOR:
+ list := make([]net.IP, 0, len(a.List))
+ for _, x := range a.List {
+ addr := net.ParseIP(x)
+ if addr == nil {
+ return nil, fmt.Errorf("invalid ip address format: %s", x)
+ }
+ list = append(list, addr)
+ }
+ return table.NewNeighborSetFromApiStruct(a.Name, list)
+ case table.DEFINED_TYPE_AS_PATH:
+ return table.NewAsPathSet(config.AsPathSet{
+ AsPathSetName: a.Name,
+ AsPathList: a.List,
+ })
+ case table.DEFINED_TYPE_COMMUNITY:
+ return table.NewCommunitySet(config.CommunitySet{
+ CommunitySetName: a.Name,
+ CommunityList: a.List,
+ })
+ case table.DEFINED_TYPE_EXT_COMMUNITY:
+ return table.NewExtCommunitySet(config.ExtCommunitySet{
+ ExtCommunitySetName: a.Name,
+ ExtCommunityList: a.List,
+ })
+ default:
+ return nil, fmt.Errorf("invalid defined type")
+ }
+}
+
func (s *Server) GetDefinedSet(ctx context.Context, arg *api.GetDefinedSetRequest) (*api.GetDefinedSetResponse, error) {
- d, err := s.get(REQ_GET_DEFINED_SET, arg)
+ cd, err := s.bgpServer.GetDefinedSet(table.DefinedType(arg.Type))
if err != nil {
return nil, err
}
sets := make([]*api.DefinedSet, 0)
- cd := d.(*config.DefinedSets)
for _, cs := range cd.PrefixSets {
ad := &api.DefinedSet{
Type: api.DefinedType_PREFIX,
@@ -868,27 +931,27 @@ func (s *Server) GetDefinedSet(ctx context.Context, arg *api.GetDefinedSetReques
}
func (s *Server) AddDefinedSet(ctx context.Context, arg *api.AddDefinedSetRequest) (*api.AddDefinedSetResponse, error) {
- d, err := s.get(REQ_ADD_DEFINED_SET, arg)
+ set, err := NewDefinedSetFromApiStruct(arg.Set)
if err != nil {
return nil, err
}
- return d.(*api.AddDefinedSetResponse), err
+ return &api.AddDefinedSetResponse{}, s.bgpServer.AddDefinedSet(set)
}
func (s *Server) DeleteDefinedSet(ctx context.Context, arg *api.DeleteDefinedSetRequest) (*api.DeleteDefinedSetResponse, error) {
- d, err := s.get(REQ_DELETE_DEFINED_SET, arg)
+ set, err := NewDefinedSetFromApiStruct(arg.Set)
if err != nil {
return nil, err
}
- return d.(*api.DeleteDefinedSetResponse), err
+ return &api.DeleteDefinedSetResponse{}, s.bgpServer.DeleteDefinedSet(set, arg.All)
}
func (s *Server) ReplaceDefinedSet(ctx context.Context, arg *api.ReplaceDefinedSetRequest) (*api.ReplaceDefinedSetResponse, error) {
- d, err := s.get(REQ_REPLACE_DEFINED_SET, arg)
+ set, err := NewDefinedSetFromApiStruct(arg.Set)
if err != nil {
return nil, err
}
- return d.(*api.ReplaceDefinedSetResponse), err
+ return &api.ReplaceDefinedSetResponse{}, s.bgpServer.ReplaceDefinedSet(set)
}
func toStatementApi(s *config.Statement) *api.Statement {
@@ -1016,41 +1079,323 @@ func toStatementApi(s *config.Statement) *api.Statement {
}
}
-func (s *Server) GetStatement(ctx context.Context, arg *api.GetStatementRequest) (*api.GetStatementResponse, error) {
- d, err := s.get(REQ_GET_STATEMENT, arg)
+func toConfigMatchSetOption(a api.MatchType) (config.MatchSetOptionsType, error) {
+ var typ config.MatchSetOptionsType
+ switch a {
+ case api.MatchType_ANY:
+ typ = config.MATCH_SET_OPTIONS_TYPE_ANY
+ case api.MatchType_ALL:
+ typ = config.MATCH_SET_OPTIONS_TYPE_ALL
+ case api.MatchType_INVERT:
+ typ = config.MATCH_SET_OPTIONS_TYPE_INVERT
+ default:
+ return typ, fmt.Errorf("invalid match type")
+ }
+ return typ, nil
+}
+
+func toConfigMatchSetOptionRestricted(a api.MatchType) (config.MatchSetOptionsRestrictedType, error) {
+ var typ config.MatchSetOptionsRestrictedType
+ switch a {
+ case api.MatchType_ANY:
+ typ = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY
+ case api.MatchType_INVERT:
+ typ = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT
+ default:
+ return typ, fmt.Errorf("invalid match type")
+ }
+ return typ, nil
+}
+
+func NewPrefixConditionFromApiStruct(a *api.MatchSet) (*table.PrefixCondition, error) {
+ if a == nil {
+ return nil, nil
+ }
+ typ, err := toConfigMatchSetOptionRestricted(a.Type)
if err != nil {
return nil, err
}
+ c := config.MatchPrefixSet{
+ PrefixSet: a.Name,
+ MatchSetOptions: typ,
+ }
+ return table.NewPrefixCondition(c)
+}
- l := make([]*api.Statement, 0)
- for _, s := range d.([]*config.Statement) {
- l = append(l, toStatementApi(s))
+func NewNeighborConditionFromApiStruct(a *api.MatchSet) (*table.NeighborCondition, error) {
+ if a == nil {
+ return nil, nil
+ }
+ typ, err := toConfigMatchSetOptionRestricted(a.Type)
+ if err != nil {
+ return nil, err
+ }
+ c := config.MatchNeighborSet{
+ NeighborSet: a.Name,
+ MatchSetOptions: typ,
}
- return &api.GetStatementResponse{Statements: l}, err
+ return table.NewNeighborCondition(c)
}
-func (s *Server) AddStatement(ctx context.Context, arg *api.AddStatementRequest) (*api.AddStatementResponse, error) {
- d, err := s.get(REQ_ADD_STATEMENT, arg)
+func NewAsPathLengthConditionFromApiStruct(a *api.AsPathLength) (*table.AsPathLengthCondition, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return table.NewAsPathLengthCondition(config.AsPathLength{
+ Operator: config.IntToAttributeComparisonMap[int(a.Type)],
+ Value: a.Length,
+ })
+}
+
+func NewAsPathConditionFromApiStruct(a *api.MatchSet) (*table.AsPathCondition, error) {
+ if a == nil {
+ return nil, nil
+ }
+ typ, err := toConfigMatchSetOption(a.Type)
if err != nil {
return nil, err
}
- return d.(*api.AddStatementResponse), err
+ c := config.MatchAsPathSet{
+ AsPathSet: a.Name,
+ MatchSetOptions: typ,
+ }
+ return table.NewAsPathCondition(c)
}
-func (s *Server) DeleteStatement(ctx context.Context, arg *api.DeleteStatementRequest) (*api.DeleteStatementResponse, error) {
- d, err := s.get(REQ_DELETE_STATEMENT, arg)
+func NewRpkiValidationConditionFromApiStruct(a int32) (*table.RpkiValidationCondition, error) {
+ if a < 1 {
+ return nil, nil
+ }
+ return table.NewRpkiValidationCondition(config.IntToRpkiValidationResultTypeMap[int(a)])
+}
+
+func NewCommunityConditionFromApiStruct(a *api.MatchSet) (*table.CommunityCondition, error) {
+ if a == nil {
+ return nil, nil
+ }
+ typ, err := toConfigMatchSetOption(a.Type)
if err != nil {
return nil, err
}
- return d.(*api.DeleteStatementResponse), err
+ c := config.MatchCommunitySet{
+ CommunitySet: a.Name,
+ MatchSetOptions: typ,
+ }
+ return table.NewCommunityCondition(c)
}
-func (s *Server) ReplaceStatement(ctx context.Context, arg *api.ReplaceStatementRequest) (*api.ReplaceStatementResponse, error) {
- d, err := s.get(REQ_REPLACE_STATEMENT, arg)
+func NewExtCommunityConditionFromApiStruct(a *api.MatchSet) (*table.ExtCommunityCondition, error) {
+ if a == nil {
+ return nil, nil
+ }
+ typ, err := toConfigMatchSetOption(a.Type)
if err != nil {
return nil, err
}
- return d.(*api.ReplaceStatementResponse), err
+ c := config.MatchExtCommunitySet{
+ ExtCommunitySet: a.Name,
+ MatchSetOptions: typ,
+ }
+ return table.NewExtCommunityCondition(c)
+}
+
+func NewRoutingActionFromApiStruct(a api.RouteAction) (*table.RoutingAction, error) {
+ if a == api.RouteAction_NONE {
+ return nil, nil
+ }
+ accept := false
+ if a == api.RouteAction_ACCEPT {
+ accept = true
+ }
+ return &table.RoutingAction{
+ AcceptRoute: accept,
+ }, nil
+}
+
+func NewCommunityActionFromApiStruct(a *api.CommunityAction) (*table.CommunityAction, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return table.NewCommunityAction(config.SetCommunity{
+ Options: string(config.IntToBgpSetCommunityOptionTypeMap[int(a.Type)]),
+ SetCommunityMethod: config.SetCommunityMethod{
+ CommunitiesList: a.Communities,
+ },
+ })
+}
+
+func NewExtCommunityActionFromApiStruct(a *api.CommunityAction) (*table.ExtCommunityAction, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return table.NewExtCommunityAction(config.SetExtCommunity{
+ Options: string(config.IntToBgpSetCommunityOptionTypeMap[int(a.Type)]),
+ SetExtCommunityMethod: config.SetExtCommunityMethod{
+ CommunitiesList: a.Communities,
+ },
+ })
+}
+
+func NewMedActionFromApiStruct(a *api.MedAction) (*table.MedAction, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return table.NewMedActionFromApiStruct(table.MedActionType(a.Type), int(a.Value)), nil
+}
+
+func NewLocalPrefActionFromApiStruct(a *api.LocalPrefAction) (*table.LocalPrefAction, error) {
+ if a == nil || a.Value == 0 {
+ return nil, nil
+ }
+ return table.NewLocalPrefAction(a.Value)
+}
+
+func NewAsPathPrependActionFromApiStruct(a *api.AsPrependAction) (*table.AsPathPrependAction, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return table.NewAsPathPrependAction(config.SetAsPathPrepend{
+ RepeatN: uint8(a.Repeat),
+ As: func() string {
+ if a.UseLeftMost {
+ return "last-as"
+ }
+ return fmt.Sprintf("%d", a.Asn)
+ }(),
+ })
+}
+
+func NewNexthopActionFromApiStruct(a *api.NexthopAction) (*table.NexthopAction, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return table.NewNexthopAction(config.BgpNextHopType(
+ func() string {
+ if a.Self {
+ return "self"
+ }
+ return a.Address
+ }(),
+ ))
+}
+
+func NewStatementFromApiStruct(a *api.Statement) (*table.Statement, error) {
+ if a.Name == "" {
+ return nil, fmt.Errorf("empty statement name")
+ }
+ var ra table.Action
+ var as []table.Action
+ var cs []table.Condition
+ var err error
+ if a.Conditions != nil {
+ cfs := []func() (table.Condition, error){
+ func() (table.Condition, error) {
+ return NewPrefixConditionFromApiStruct(a.Conditions.PrefixSet)
+ },
+ func() (table.Condition, error) {
+ return NewNeighborConditionFromApiStruct(a.Conditions.NeighborSet)
+ },
+ func() (table.Condition, error) {
+ return NewAsPathLengthConditionFromApiStruct(a.Conditions.AsPathLength)
+ },
+ func() (table.Condition, error) {
+ return NewRpkiValidationConditionFromApiStruct(a.Conditions.RpkiResult)
+ },
+ func() (table.Condition, error) {
+ return NewAsPathConditionFromApiStruct(a.Conditions.AsPathSet)
+ },
+ func() (table.Condition, error) {
+ return NewCommunityConditionFromApiStruct(a.Conditions.CommunitySet)
+ },
+ func() (table.Condition, error) {
+ return NewExtCommunityConditionFromApiStruct(a.Conditions.ExtCommunitySet)
+ },
+ }
+ cs = make([]table.Condition, 0, len(cfs))
+ for _, f := range cfs {
+ c, err := f()
+ if err != nil {
+ return nil, err
+ }
+ if !reflect.ValueOf(c).IsNil() {
+ cs = append(cs, c)
+ }
+ }
+ }
+ if a.Actions != nil {
+ ra, err = NewRoutingActionFromApiStruct(a.Actions.RouteAction)
+ if err != nil {
+ return nil, err
+ }
+ afs := []func() (table.Action, error){
+ func() (table.Action, error) {
+ return NewCommunityActionFromApiStruct(a.Actions.Community)
+ },
+ func() (table.Action, error) {
+ return NewExtCommunityActionFromApiStruct(a.Actions.ExtCommunity)
+ },
+ func() (table.Action, error) {
+ return NewMedActionFromApiStruct(a.Actions.Med)
+ },
+ func() (table.Action, error) {
+ return NewLocalPrefActionFromApiStruct(a.Actions.LocalPref)
+ },
+ func() (table.Action, error) {
+ return NewAsPathPrependActionFromApiStruct(a.Actions.AsPrepend)
+ },
+ func() (table.Action, error) {
+ return NewNexthopActionFromApiStruct(a.Actions.Nexthop)
+ },
+ }
+ as = make([]table.Action, 0, len(afs))
+ for _, f := range afs {
+ a, err := f()
+ if err != nil {
+ return nil, err
+ }
+ if !reflect.ValueOf(a).IsNil() {
+ as = append(as, a)
+ }
+ }
+ }
+ return &table.Statement{
+ Name: a.Name,
+ Conditions: cs,
+ RouteAction: ra,
+ ModActions: as,
+ }, nil
+}
+
+func (s *Server) GetStatement(ctx context.Context, arg *api.GetStatementRequest) (*api.GetStatementResponse, error) {
+ l := make([]*api.Statement, 0)
+ for _, s := range s.bgpServer.GetStatement() {
+ l = append(l, toStatementApi(s))
+ }
+ return &api.GetStatementResponse{Statements: l}, nil
+}
+
+func (s *Server) AddStatement(ctx context.Context, arg *api.AddStatementRequest) (*api.AddStatementResponse, error) {
+ st, err := NewStatementFromApiStruct(arg.Statement)
+ if err == nil {
+ err = s.bgpServer.AddStatement(st)
+ }
+ return &api.AddStatementResponse{}, err
+}
+
+func (s *Server) DeleteStatement(ctx context.Context, arg *api.DeleteStatementRequest) (*api.DeleteStatementResponse, error) {
+ st, err := NewStatementFromApiStruct(arg.Statement)
+ if err == nil {
+ err = s.bgpServer.DeleteStatement(st, arg.All)
+ }
+ return &api.DeleteStatementResponse{}, err
+}
+
+func (s *Server) ReplaceStatement(ctx context.Context, arg *api.ReplaceStatementRequest) (*api.ReplaceStatementResponse, error) {
+ st, err := NewStatementFromApiStruct(arg.Statement)
+ if err == nil {
+ err = s.bgpServer.ReplaceStatement(st)
+ }
+ return &api.ReplaceStatementResponse{}, err
}
func toPolicyApi(p *config.PolicyDefinition) *api.Policy {
@@ -1066,52 +1411,100 @@ func toPolicyApi(p *config.PolicyDefinition) *api.Policy {
}
}
-func (s *Server) GetPolicy(ctx context.Context, arg *api.GetPolicyRequest) (*api.GetPolicyResponse, error) {
- d, err := s.get(REQ_GET_POLICY, arg)
- if err != nil {
- return nil, err
+func NewPolicyFromApiStruct(a *api.Policy) (*table.Policy, error) {
+ if a.Name == "" {
+ return nil, fmt.Errorf("empty policy name")
+ }
+ stmts := make([]*table.Statement, 0, len(a.Statements))
+ for idx, x := range a.Statements {
+ if x.Name == "" {
+ x.Name = fmt.Sprintf("%s_stmt%d", a.Name, idx)
+ }
+ y, err := NewStatementFromApiStruct(x)
+ if err != nil {
+ return nil, err
+ }
+ stmts = append(stmts, y)
}
+ return &table.Policy{
+ Name: a.Name,
+ Statements: stmts,
+ }, nil
+}
+
+func (s *Server) GetPolicy(ctx context.Context, arg *api.GetPolicyRequest) (*api.GetPolicyResponse, error) {
l := make([]*api.Policy, 0)
- for _, p := range d.([]*config.PolicyDefinition) {
+ for _, p := range s.bgpServer.GetPolicy() {
l = append(l, toPolicyApi(p))
}
- return &api.GetPolicyResponse{Policies: l}, err
+ return &api.GetPolicyResponse{Policies: l}, nil
}
func (s *Server) AddPolicy(ctx context.Context, arg *api.AddPolicyRequest) (*api.AddPolicyResponse, error) {
- d, err := s.get(REQ_ADD_POLICY, arg)
+ x, err := NewPolicyFromApiStruct(arg.Policy)
if err != nil {
return nil, err
}
- return d.(*api.AddPolicyResponse), err
+ return &api.AddPolicyResponse{}, s.bgpServer.AddPolicy(x, arg.ReferExistingStatements)
}
func (s *Server) DeletePolicy(ctx context.Context, arg *api.DeletePolicyRequest) (*api.DeletePolicyResponse, error) {
- d, err := s.get(REQ_DELETE_POLICY, arg)
+ x, err := NewPolicyFromApiStruct(arg.Policy)
if err != nil {
return nil, err
}
- return d.(*api.DeletePolicyResponse), err
+ return &api.DeletePolicyResponse{}, s.bgpServer.DeletePolicy(x, arg.All, arg.PreserveStatements)
}
func (s *Server) ReplacePolicy(ctx context.Context, arg *api.ReplacePolicyRequest) (*api.ReplacePolicyResponse, error) {
- d, err := s.get(REQ_REPLACE_POLICY, arg)
+ x, err := NewPolicyFromApiStruct(arg.Policy)
if err != nil {
return nil, err
}
- return d.(*api.ReplacePolicyResponse), err
+ return &api.ReplacePolicyResponse{}, s.bgpServer.ReplacePolicy(x, arg.ReferExistingStatements, arg.PreserveStatements)
+}
+
+func toPolicyAssignmentName(a *api.PolicyAssignment) (string, table.PolicyDirection, error) {
+ switch a.Resource {
+ case api.Resource_GLOBAL:
+ switch a.Type {
+ case api.PolicyType_IMPORT:
+ return "", table.POLICY_DIRECTION_IMPORT, nil
+ case api.PolicyType_EXPORT:
+ return "", table.POLICY_DIRECTION_EXPORT, nil
+ default:
+ return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid policy type")
+ }
+ case api.Resource_LOCAL:
+ switch a.Type {
+ case api.PolicyType_IN:
+ return a.Name, table.POLICY_DIRECTION_IN, nil
+ case api.PolicyType_IMPORT:
+ return a.Name, table.POLICY_DIRECTION_IMPORT, nil
+ case api.PolicyType_EXPORT:
+ return a.Name, table.POLICY_DIRECTION_EXPORT, nil
+ default:
+ return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid policy type")
+ }
+ default:
+ return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid resource type")
+ }
+
}
func (s *Server) GetPolicyAssignment(ctx context.Context, arg *api.GetPolicyAssignmentRequest) (*api.GetPolicyAssignmentResponse, error) {
- d, err := s.get(REQ_GET_POLICY_ASSIGNMENT, arg)
+ name, dir, err := toPolicyAssignmentName(arg.Assignment)
+ if err != nil {
+ return nil, err
+ }
+ d, a, err := s.bgpServer.GetPolicyAssignment(name, dir)
if err != nil {
return nil, err
}
- a := d.(*PolicyAssignment)
return &api.GetPolicyAssignmentResponse{
Assignment: &api.PolicyAssignment{
Default: func() api.RouteAction {
- switch a.Default {
+ switch d {
case table.ROUTE_TYPE_ACCEPT:
return api.RouteAction_ACCEPT
case table.ROUTE_TYPE_REJECT:
@@ -1122,7 +1515,7 @@ func (s *Server) GetPolicyAssignment(ctx context.Context, arg *api.GetPolicyAssi
}(),
Policies: func() []*api.Policy {
l := make([]*api.Policy, 0)
- for _, p := range a.PolicyDefinitions {
+ for _, p := range a {
l = append(l, toPolicyApi(p))
}
return l
@@ -1131,28 +1524,47 @@ func (s *Server) GetPolicyAssignment(ctx context.Context, arg *api.GetPolicyAssi
}, err
}
+func defaultRouteType(d api.RouteAction) table.RouteType {
+ switch d {
+ case api.RouteAction_ACCEPT:
+ return table.ROUTE_TYPE_ACCEPT
+ case api.RouteAction_REJECT:
+ return table.ROUTE_TYPE_REJECT
+ default:
+ return table.ROUTE_TYPE_NONE
+ }
+}
+
+func toPolicyDefinition(policies []*api.Policy) []*config.PolicyDefinition {
+ l := make([]*config.PolicyDefinition, 0, len(policies))
+ for _, p := range policies {
+ l = append(l, &config.PolicyDefinition{Name: p.Name})
+ }
+ return l
+}
+
func (s *Server) AddPolicyAssignment(ctx context.Context, arg *api.AddPolicyAssignmentRequest) (*api.AddPolicyAssignmentResponse, error) {
- d, err := s.get(REQ_ADD_POLICY_ASSIGNMENT, arg)
+ name, dir, err := toPolicyAssignmentName(arg.Assignment)
if err != nil {
return nil, err
}
- return d.(*api.AddPolicyAssignmentResponse), err
+ return &api.AddPolicyAssignmentResponse{}, s.bgpServer.AddPolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), defaultRouteType(arg.Assignment.Default))
}
func (s *Server) DeletePolicyAssignment(ctx context.Context, arg *api.DeletePolicyAssignmentRequest) (*api.DeletePolicyAssignmentResponse, error) {
- d, err := s.get(REQ_DELETE_POLICY_ASSIGNMENT, arg)
+ name, dir, err := toPolicyAssignmentName(arg.Assignment)
if err != nil {
return nil, err
}
- return d.(*api.DeletePolicyAssignmentResponse), err
+ return &api.DeletePolicyAssignmentResponse{}, s.bgpServer.DeletePolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), arg.All)
}
func (s *Server) ReplacePolicyAssignment(ctx context.Context, arg *api.ReplacePolicyAssignmentRequest) (*api.ReplacePolicyAssignmentResponse, error) {
- d, err := s.get(REQ_REPLACE_POLICY_ASSIGNMENT, arg)
+ name, dir, err := toPolicyAssignmentName(arg.Assignment)
if err != nil {
return nil, err
}
- return d.(*api.ReplacePolicyAssignmentResponse), err
+ return &api.ReplacePolicyAssignmentResponse{}, s.bgpServer.ReplacePolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), defaultRouteType(arg.Assignment.Default))
}
func (s *Server) GetServer(ctx context.Context, arg *api.GetServerRequest) (*api.GetServerResponse, error) {
@@ -1220,10 +1632,11 @@ func (r *GrpcResponse) Err() error {
return r.ResponseErr
}
-func NewGrpcServer(hosts string, bgpServerCh chan *GrpcRequest) *Server {
+func NewGrpcServer(b *BgpServer, hosts string, bgpServerCh chan *GrpcRequest) *Server {
grpc.EnableTracing = false
grpcServer := grpc.NewServer()
server := &Server{
+ bgpServer: b,
grpcServer: grpcServer,
bgpServerCh: bgpServerCh,
hosts: hosts,
diff --git a/server/server.go b/server/server.go
index 09d63259..381f1f61 100644
--- a/server/server.go
+++ b/server/server.go
@@ -945,15 +945,16 @@ func (server *BgpServer) Shutdown() {
// TODO: call fsmincomingCh.Close()
}
-func (server *BgpServer) UpdatePolicy(policy config.RoutingPolicy) error {
- ch := make(chan *GrpcResponse)
- server.GrpcReqCh <- &GrpcRequest{
- RequestType: REQ_RELOAD_POLICY,
- Data: policy,
- ResponseCh: ch,
+func (s *BgpServer) UpdatePolicy(policy config.RoutingPolicy) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ defer close(ch)
+
+ err = s.handlePolicy(policy)
}
- res := <-ch
- return res.Err()
+ return err
}
// This function MUST be called with policyMutex locked.
@@ -1942,118 +1943,6 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) {
ResponseErr: err,
}
close(grpcReq.ResponseCh)
- case REQ_GET_DEFINED_SET:
- rsp, err := server.handleGrpcGetDefinedSet(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: rsp,
- }
- close(grpcReq.ResponseCh)
- case REQ_ADD_DEFINED_SET:
- rsp, err := server.handleGrpcAddDefinedSet(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: rsp,
- }
- close(grpcReq.ResponseCh)
- case REQ_DELETE_DEFINED_SET:
- rsp, err := server.handleGrpcDeleteDefinedSet(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: rsp,
- }
- close(grpcReq.ResponseCh)
- case REQ_REPLACE_DEFINED_SET:
- rsp, err := server.handleGrpcReplaceDefinedSet(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: rsp,
- }
- close(grpcReq.ResponseCh)
- case REQ_GET_STATEMENT:
- rsp, err := server.handleGrpcGetStatement(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: rsp,
- }
- close(grpcReq.ResponseCh)
- case REQ_ADD_STATEMENT:
- data, err := server.handleGrpcAddStatement(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_DELETE_STATEMENT:
- data, err := server.handleGrpcDeleteStatement(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_REPLACE_STATEMENT:
- data, err := server.handleGrpcReplaceStatement(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_GET_POLICY:
- rsp, err := server.handleGrpcGetPolicy(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: rsp,
- }
- close(grpcReq.ResponseCh)
- case REQ_ADD_POLICY:
- data, err := server.handleGrpcAddPolicy(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_DELETE_POLICY:
- data, err := server.handleGrpcDeletePolicy(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_REPLACE_POLICY:
- data, err := server.handleGrpcReplacePolicy(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_GET_POLICY_ASSIGNMENT:
- data, err := server.handleGrpcGetPolicyAssignment(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_ADD_POLICY_ASSIGNMENT:
- data, err := server.handleGrpcAddPolicyAssignment(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_DELETE_POLICY_ASSIGNMENT:
- data, err := server.handleGrpcDeletePolicyAssignment(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
- case REQ_REPLACE_POLICY_ASSIGNMENT:
- data, err := server.handleGrpcReplacePolicyAssignment(grpcReq)
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- Data: data,
- }
- close(grpcReq.ResponseCh)
case REQ_MONITOR_RIB, REQ_MONITOR_NEIGHBOR_PEER_STATE:
if grpcReq.Name != "" {
if _, err = server.checkNeighborRequest(grpcReq); err != nil {
@@ -2095,12 +1984,6 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) {
if len(pathList) > 0 {
server.propagateUpdate(nil, pathList)
}
- case REQ_RELOAD_POLICY:
- err := server.handlePolicy(grpcReq.Data.(config.RoutingPolicy))
- grpcReq.ResponseCh <- &GrpcResponse{
- ResponseErr: err,
- }
- close(grpcReq.ResponseCh)
case REQ_INITIALIZE_ZEBRA:
c := grpcReq.Data.(*config.ZebraConfig)
protos := make([]string, 0, len(c.RedistributeRouteTypeList))
@@ -2287,200 +2170,260 @@ func (server *BgpServer) handleUpdateNeighbor(c *config.Neighbor) (bool, error)
return policyUpdated, err
}
-func (server *BgpServer) handleGrpcGetDefinedSet(grpcReq *GrpcRequest) (*config.DefinedSets, error) {
- arg := grpcReq.Data.(*api.GetDefinedSetRequest)
- typ := table.DefinedType(arg.Type)
- set, ok := server.policy.DefinedSetMap[typ]
- if !ok {
- return nil, fmt.Errorf("invalid defined-set type: %d", typ)
- }
- sets := config.DefinedSets{
- PrefixSets: make([]config.PrefixSet, 0),
- NeighborSets: make([]config.NeighborSet, 0),
- BgpDefinedSets: config.BgpDefinedSets{
- CommunitySets: make([]config.CommunitySet, 0),
- ExtCommunitySets: make([]config.ExtCommunitySet, 0),
- AsPathSets: make([]config.AsPathSet, 0),
- },
- }
- for _, s := range set {
- switch s.(type) {
- case *table.PrefixSet:
- sets.PrefixSets = append(sets.PrefixSets, *s.(*table.PrefixSet).ToConfig())
- case *table.NeighborSet:
- sets.NeighborSets = append(sets.NeighborSets, *s.(*table.NeighborSet).ToConfig())
- case *table.CommunitySet:
- sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *s.(*table.CommunitySet).ToConfig())
- case *table.ExtCommunitySet:
- sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *s.(*table.ExtCommunitySet).ToConfig())
- case *table.AsPathSet:
- sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *s.(*table.AsPathSet).ToConfig())
+func (s *BgpServer) GetDefinedSet(typ table.DefinedType) (sets *config.DefinedSets, err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ set, ok := s.policy.DefinedSetMap[typ]
+ if !ok {
+ err = fmt.Errorf("invalid defined-set type: %d", typ)
+ return
+ }
+ sets = &config.DefinedSets{
+ PrefixSets: make([]config.PrefixSet, 0),
+ NeighborSets: make([]config.NeighborSet, 0),
+ BgpDefinedSets: config.BgpDefinedSets{
+ CommunitySets: make([]config.CommunitySet, 0),
+ ExtCommunitySets: make([]config.ExtCommunitySet, 0),
+ AsPathSets: make([]config.AsPathSet, 0),
+ },
+ }
+ for _, s := range set {
+ switch s.(type) {
+ case *table.PrefixSet:
+ sets.PrefixSets = append(sets.PrefixSets, *s.(*table.PrefixSet).ToConfig())
+ case *table.NeighborSet:
+ sets.NeighborSets = append(sets.NeighborSets, *s.(*table.NeighborSet).ToConfig())
+ case *table.CommunitySet:
+ sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *s.(*table.CommunitySet).ToConfig())
+ case *table.ExtCommunitySet:
+ sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *s.(*table.ExtCommunitySet).ToConfig())
+ case *table.AsPathSet:
+ sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *s.(*table.AsPathSet).ToConfig())
+ }
}
}
- return &sets, nil
+ return sets, nil
}
-func (server *BgpServer) handleGrpcAddDefinedSet(grpcReq *GrpcRequest) (*api.AddDefinedSetResponse, error) {
- arg := grpcReq.Data.(*api.AddDefinedSetRequest)
- set := arg.Set
- typ := table.DefinedType(set.Type)
- name := set.Name
- var err error
- m, ok := server.policy.DefinedSetMap[typ]
- if !ok {
- return nil, fmt.Errorf("invalid defined-set type: %d", typ)
- }
- d, ok := m[name]
- s, err := table.NewDefinedSetFromApiStruct(set)
- if err != nil {
- return nil, err
- }
- if ok {
- err = d.Append(s)
- } else {
- m[name] = s
+func (s *BgpServer) AddDefinedSet(a table.DefinedSet) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ if m, ok := s.policy.DefinedSetMap[a.Type()]; !ok {
+ err = fmt.Errorf("invalid defined-set type: %d", a.Type())
+ } else {
+ if d, ok := m[a.Name()]; ok {
+ err = d.Append(a)
+ } else {
+ m[a.Name()] = a
+ }
+ }
}
- return &api.AddDefinedSetResponse{}, err
+ return err
}
-func (server *BgpServer) handleGrpcDeleteDefinedSet(grpcReq *GrpcRequest) (*api.DeleteDefinedSetResponse, error) {
- arg := grpcReq.Data.(*api.DeleteDefinedSetRequest)
- set := arg.Set
- typ := table.DefinedType(set.Type)
- name := set.Name
- var err error
- m, ok := server.policy.DefinedSetMap[typ]
- if !ok {
- return nil, fmt.Errorf("invalid defined-set type: %d", typ)
- }
- d, ok := m[name]
- if !ok {
- return nil, fmt.Errorf("not found defined-set: %s", name)
- }
- s, err := table.NewDefinedSetFromApiStruct(set)
- if err != nil {
- return nil, err
- }
- if arg.All {
- if server.policy.InUse(d) {
- return nil, fmt.Errorf("can't delete. defined-set %s is in use", name)
+func (s *BgpServer) DeleteDefinedSet(a table.DefinedSet, all bool) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ if m, ok := s.policy.DefinedSetMap[a.Type()]; !ok {
+ err = fmt.Errorf("invalid defined-set type: %d", a.Type())
+ } else {
+ d, ok := m[a.Name()]
+ if !ok {
+ err = fmt.Errorf("not found defined-set: %s", a.Name())
+ return
+ }
+ if all {
+ if s.policy.InUse(d) {
+ err = fmt.Errorf("can't delete. defined-set %s is in use", a.Name())
+ } else {
+ delete(m, a.Name())
+ }
+ } else {
+ err = d.Remove(a)
+ }
}
- delete(m, name)
- } else {
- err = d.Remove(s)
}
- return &api.DeleteDefinedSetResponse{}, err
+ return err
}
-func (server *BgpServer) handleGrpcReplaceDefinedSet(grpcReq *GrpcRequest) (*api.ReplaceDefinedSetResponse, error) {
- arg := grpcReq.Data.(*api.ReplaceDefinedSetRequest)
- set := arg.Set
- typ := table.DefinedType(set.Type)
- name := set.Name
- var err error
- m, ok := server.policy.DefinedSetMap[typ]
- if !ok {
- return nil, fmt.Errorf("invalid defined-set type: %d", typ)
- }
- d, ok := m[name]
- if !ok {
- return nil, fmt.Errorf("not found defined-set: %s", name)
- }
- s, err := table.NewDefinedSetFromApiStruct(set)
- if err != nil {
- return nil, err
+func (s *BgpServer) ReplaceDefinedSet(a table.DefinedSet) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ if m, ok := s.policy.DefinedSetMap[a.Type()]; !ok {
+ err = fmt.Errorf("invalid defined-set type: %d", a.Type())
+ } else {
+ if d, ok := m[a.Name()]; !ok {
+ err = fmt.Errorf("not found defined-set: %s", a.Name())
+ } else {
+ err = d.Replace(a)
+ }
+ }
}
- return &api.ReplaceDefinedSetResponse{}, d.Replace(s)
+ return err
}
-func (server *BgpServer) handleGrpcGetStatement(grpcReq *GrpcRequest) ([]*config.Statement, error) {
- l := make([]*config.Statement, 0)
- for _, s := range server.policy.StatementMap {
- l = append(l, s.ToConfig())
+func (s *BgpServer) GetStatement() (l []*config.Statement) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ l = make([]*config.Statement, 0, len(s.policy.StatementMap))
+ for _, st := range s.policy.StatementMap {
+ l = append(l, st.ToConfig())
+ }
}
- return l, nil
+ return l
}
-func (server *BgpServer) handleGrpcAddStatement(grpcReq *GrpcRequest) (*api.AddStatementResponse, error) {
- var err error
- arg := grpcReq.Data.(*api.AddStatementRequest)
- s, err := table.NewStatementFromApiStruct(arg.Statement, server.policy.DefinedSetMap)
- if err != nil {
- return nil, err
- }
- m := server.policy.StatementMap
- name := s.Name
- if d, ok := m[name]; ok {
- err = d.Add(s)
- } else {
- m[name] = s
+func (s *BgpServer) AddStatement(st *table.Statement) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ for _, c := range st.Conditions {
+ if err = s.policy.ValidateCondition(c); err != nil {
+ return
+ }
+ }
+ m := s.policy.StatementMap
+ name := st.Name
+ if d, ok := m[name]; ok {
+ err = d.Add(st)
+ } else {
+ m[name] = st
+ }
}
- return &api.AddStatementResponse{}, err
+ return err
}
-func (server *BgpServer) handleGrpcDeleteStatement(grpcReq *GrpcRequest) (*api.DeleteStatementResponse, error) {
- var err error
- arg := grpcReq.Data.(*api.DeleteStatementRequest)
- s, err := table.NewStatementFromApiStruct(arg.Statement, server.policy.DefinedSetMap)
- if err != nil {
- return nil, err
- }
- m := server.policy.StatementMap
- name := s.Name
- if d, ok := m[name]; ok {
- if arg.All {
- if server.policy.StatementInUse(d) {
- err = fmt.Errorf("can't delete. statement %s is in use", name)
+func (s *BgpServer) DeleteStatement(st *table.Statement, all bool) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ m := s.policy.StatementMap
+ name := st.Name
+ if d, ok := m[name]; ok {
+ if all {
+ if s.policy.StatementInUse(d) {
+ err = fmt.Errorf("can't delete. statement %s is in use", name)
+ } else {
+ delete(m, name)
+ }
} else {
- delete(m, name)
+ err = d.Remove(st)
}
} else {
- err = d.Remove(s)
+ err = fmt.Errorf("not found statement: %s", name)
}
- } else {
- err = fmt.Errorf("not found statement: %s", name)
}
- return &api.DeleteStatementResponse{}, err
+ return err
}
-func (server *BgpServer) handleGrpcReplaceStatement(grpcReq *GrpcRequest) (*api.ReplaceStatementResponse, error) {
- var err error
- arg := grpcReq.Data.(*api.ReplaceStatementRequest)
- s, err := table.NewStatementFromApiStruct(arg.Statement, server.policy.DefinedSetMap)
- if err != nil {
- return nil, err
- }
- m := server.policy.StatementMap
- name := s.Name
- if d, ok := m[name]; ok {
- err = d.Replace(s)
- } else {
- err = fmt.Errorf("not found statement: %s", name)
+func (s *BgpServer) ReplaceStatement(st *table.Statement) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ m := s.policy.StatementMap
+ name := st.Name
+ if d, ok := m[name]; ok {
+ err = d.Replace(st)
+ } else {
+ err = fmt.Errorf("not found statement: %s", name)
+ }
}
- return &api.ReplaceStatementResponse{}, err
+ return err
}
-func (server *BgpServer) handleGrpcGetPolicy(grpcReq *GrpcRequest) ([]*config.PolicyDefinition, error) {
- policies := make([]*config.PolicyDefinition, 0, len(server.policy.PolicyMap))
- for _, s := range server.policy.PolicyMap {
- policies = append(policies, s.ToConfig())
+func (s *BgpServer) GetPolicy() (l []*config.PolicyDefinition) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ l := make([]*config.PolicyDefinition, 0, len(s.policy.PolicyMap))
+ for _, p := range s.policy.PolicyMap {
+ l = append(l, p.ToConfig())
+ }
}
- return policies, nil
+ return l
}
-func (server *BgpServer) policyInUse(x *table.Policy) bool {
- for _, peer := range server.neighborMap {
+func (s *BgpServer) policyInUse(x *table.Policy) bool {
+ for _, peer := range s.neighborMap {
for _, dir := range []table.PolicyDirection{table.POLICY_DIRECTION_IN, table.POLICY_DIRECTION_EXPORT, table.POLICY_DIRECTION_EXPORT} {
- for _, y := range server.policy.GetPolicy(peer.ID(), dir) {
- if x.Name() == y.Name() {
+ for _, y := range s.policy.GetPolicy(peer.ID(), 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.policy.GetPolicy(table.GLOBAL_RIB_NAME, dir) {
- if x.Name() == y.Name() {
+ for _, y := range s.policy.GetPolicy(table.GLOBAL_RIB_NAME, dir) {
+ if x.Name == y.Name {
return true
}
}
@@ -2488,326 +2431,353 @@ func (server *BgpServer) policyInUse(x *table.Policy) bool {
return false
}
-func (server *BgpServer) handleGrpcAddPolicy(grpcReq *GrpcRequest) (*api.AddPolicyResponse, error) {
- policyMutex.Lock()
- defer policyMutex.Unlock()
- rsp := &api.AddPolicyResponse{}
- arg := grpcReq.Data.(*api.AddPolicyRequest)
- x, err := table.NewPolicyFromApiStruct(arg.Policy, server.policy.DefinedSetMap)
- if err != nil {
- return rsp, err
- }
- pMap := server.policy.PolicyMap
- sMap := server.policy.StatementMap
- name := x.Name()
- y, ok := pMap[name]
- if arg.ReferExistingStatements {
- err = x.FillUp(sMap)
- } else {
- for _, s := range x.Statements {
- if _, ok := sMap[s.Name]; ok {
- return rsp, fmt.Errorf("statement %s already defined", s.Name)
+func (s *BgpServer) AddPolicy(x *table.Policy, refer bool) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ for _, st := range x.Statements {
+ for _, c := range st.Conditions {
+ if err = s.policy.ValidateCondition(c); err != nil {
+ return
+ }
}
- sMap[s.Name] = s
+ }
+
+ pMap := s.policy.PolicyMap
+ sMap := s.policy.StatementMap
+ name := x.Name
+ y, ok := pMap[name]
+ if refer {
+ err = x.FillUp(sMap)
+ } else {
+ for _, st := range x.Statements {
+ if _, ok := sMap[st.Name]; ok {
+ err = fmt.Errorf("statement %s already defined", st.Name)
+ return
+ }
+ sMap[st.Name] = st
+ }
+ }
+ if ok {
+ err = y.Add(x)
+ } else {
+ pMap[name] = x
}
}
- if ok {
- err = y.Add(x)
- } else {
- pMap[name] = x
- }
- return &api.AddPolicyResponse{}, err
+ return err
}
-func (server *BgpServer) handleGrpcDeletePolicy(grpcReq *GrpcRequest) (*api.DeletePolicyResponse, error) {
- policyMutex.Lock()
- defer policyMutex.Unlock()
- rsp := &api.DeletePolicyResponse{}
- arg := grpcReq.Data.(*api.DeletePolicyRequest)
- x, err := table.NewPolicyFromApiStruct(arg.Policy, server.policy.DefinedSetMap)
- if err != nil {
- return rsp, err
- }
- pMap := server.policy.PolicyMap
- sMap := server.policy.StatementMap
- name := x.Name()
- y, ok := pMap[name]
- if !ok {
- return rsp, fmt.Errorf("not found policy: %s", name)
- }
- if arg.All {
- if server.policyInUse(y) {
- return rsp, fmt.Errorf("can't delete. policy %s is in use", name)
+func (s *BgpServer) DeletePolicy(x *table.Policy, all, preserve bool) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ pMap := s.policy.PolicyMap
+ sMap := s.policy.StatementMap
+ name := x.Name
+ y, ok := pMap[name]
+ if !ok {
+ err = fmt.Errorf("not found policy: %s", name)
+ return
}
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Key": name,
- }).Debug("delete policy")
- delete(pMap, name)
- } else {
- err = y.Remove(x)
- }
- if err == nil && !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)
+ if all {
+ if s.policyInUse(y) {
+ err = fmt.Errorf("can't delete. policy %s is in use", name)
+ return
+ }
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Key": name,
+ }).Debug("delete policy")
+ delete(pMap, name)
+ } else {
+ err = y.Remove(x)
+ }
+ if err == nil && !preserve {
+ for _, st := range y.Statements {
+ if !s.policy.StatementInUse(st) {
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Key": st.Name,
+ }).Debug("delete unused statement")
+ delete(sMap, st.Name)
+ }
}
}
}
- return rsp, err
+ return err
}
-func (server *BgpServer) handleGrpcReplacePolicy(grpcReq *GrpcRequest) (*api.ReplacePolicyResponse, error) {
- policyMutex.Lock()
- defer policyMutex.Unlock()
- rsp := &api.ReplacePolicyResponse{}
- arg := grpcReq.Data.(*api.ReplacePolicyRequest)
- x, err := table.NewPolicyFromApiStruct(arg.Policy, server.policy.DefinedSetMap)
- if err != nil {
- return rsp, err
- }
- pMap := server.policy.PolicyMap
- sMap := server.policy.StatementMap
- name := x.Name()
- y, ok := pMap[name]
- if !ok {
- return rsp, fmt.Errorf("not found policy: %s", name)
- }
- if arg.ReferExistingStatements {
- if err = x.FillUp(sMap); err != nil {
- return rsp, err
+func (s *BgpServer) ReplacePolicy(x *table.Policy, refer, preserve bool) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ for _, st := range x.Statements {
+ for _, c := range st.Conditions {
+ if err = s.policy.ValidateCondition(c); err != nil {
+ return
+ }
+ }
}
- } else {
- for _, s := range x.Statements {
- if _, ok := sMap[s.Name]; ok {
- return rsp, fmt.Errorf("statement %s already defined", s.Name)
+
+ pMap := s.policy.PolicyMap
+ sMap := s.policy.StatementMap
+ name := x.Name
+ y, ok := pMap[name]
+ if !ok {
+ err = fmt.Errorf("not found policy: %s", name)
+ return
+ }
+ if refer {
+ if err = x.FillUp(sMap); err != nil {
+ return
+ }
+ } else {
+ for _, st := range x.Statements {
+ if _, ok := sMap[st.Name]; ok {
+ err = fmt.Errorf("statement %s already defined", st.Name)
+ return
+ }
+ sMap[st.Name] = st
}
- sMap[s.Name] = s
}
- }
- err = y.Replace(x)
- if err == nil && !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)
+ err = y.Replace(x)
+ if err == nil && !preserve {
+ for _, st := range y.Statements {
+ if !s.policy.StatementInUse(st) {
+ log.WithFields(log.Fields{
+ "Topic": "Policy",
+ "Key": st.Name,
+ }).Debug("delete unused statement")
+ delete(sMap, st.Name)
+ }
}
}
}
- return rsp, err
+ return err
}
-func (server *BgpServer) getPolicyInfo(a *api.PolicyAssignment) (string, table.PolicyDirection, error) {
- switch a.Resource {
- case api.Resource_GLOBAL:
- switch a.Type {
- case api.PolicyType_IMPORT:
- return table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_IMPORT, nil
- case api.PolicyType_EXPORT:
- return table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_EXPORT, nil
- default:
- return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid policy type")
+func (server *BgpServer) toPolicyInfo(name string, dir table.PolicyDirection) (string, error) {
+ if name == "" {
+ switch dir {
+ case table.POLICY_DIRECTION_IMPORT, table.POLICY_DIRECTION_EXPORT:
+ return table.GLOBAL_RIB_NAME, nil
}
- case api.Resource_LOCAL:
- peer, ok := server.neighborMap[a.Name]
+ return "", fmt.Errorf("invalid policy type")
+ } else {
+ peer, ok := server.neighborMap[name]
if !ok {
- return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("not found peer %s", a.Name)
+ return "", fmt.Errorf("not found peer %s", name)
}
if !peer.isRouteServerClient() {
- return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("non-rs-client peer %s doesn't have per peer policy", a.Name)
- }
- switch a.Type {
- case api.PolicyType_IN:
- return peer.ID(), table.POLICY_DIRECTION_IN, nil
- case api.PolicyType_IMPORT:
- return peer.ID(), table.POLICY_DIRECTION_IMPORT, nil
- case api.PolicyType_EXPORT:
- return peer.ID(), table.POLICY_DIRECTION_EXPORT, nil
- default:
- return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid policy type")
+ return "", fmt.Errorf("non-rs-client peer %s doesn't have per peer policy", name)
}
- default:
- return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid resource type")
+ return peer.ID(), nil
}
-
}
-// temporarily
-type PolicyAssignment struct {
- Default table.RouteType
- PolicyDefinitions []*config.PolicyDefinition
-}
+func (s *BgpServer) GetPolicyAssignment(name string, dir table.PolicyDirection) (rt table.RouteType, l []*config.PolicyDefinition, err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
-func (server *BgpServer) handleGrpcGetPolicyAssignment(grpcReq *GrpcRequest) (*PolicyAssignment, error) {
- id, dir, err := server.getPolicyInfo(grpcReq.Data.(*api.GetPolicyAssignmentRequest).Assignment)
- if err != nil {
- return nil, err
- }
- return &PolicyAssignment{
- Default: server.policy.GetDefaultPolicy(id, dir),
- PolicyDefinitions: func() []*config.PolicyDefinition {
- ps := server.policy.GetPolicy(id, dir)
- l := make([]*config.PolicyDefinition, 0, len(ps))
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ var id string
+ id, err = s.toPolicyInfo(name, dir)
+ if err != nil {
+ rt = table.ROUTE_TYPE_NONE
+ } else {
+ rt = s.policy.GetDefaultPolicy(id, dir)
+
+ ps := s.policy.GetPolicy(id, dir)
+ l = make([]*config.PolicyDefinition, 0, len(ps))
for _, p := range ps {
l = append(l, p.ToConfig())
}
- return l
- }(),
- }, nil
+ }
+ }
+ return rt, l, err
}
-func (server *BgpServer) handleGrpcAddPolicyAssignment(grpcReq *GrpcRequest) (*api.AddPolicyAssignmentResponse, error) {
- var err error
- var dir table.PolicyDirection
- var id string
- rsp := &api.AddPolicyAssignmentResponse{}
- policyMutex.Lock()
- defer policyMutex.Unlock()
- arg := grpcReq.Data.(*api.AddPolicyAssignmentRequest)
- assignment := arg.Assignment
- id, dir, err = server.getPolicyInfo(assignment)
- if err != nil {
- return rsp, err
- }
- ps := make([]*table.Policy, 0, len(assignment.Policies))
- seen := make(map[string]bool)
- for _, x := range assignment.Policies {
- p, ok := server.policy.PolicyMap[x.Name]
- if !ok {
- return rsp, fmt.Errorf("not found policy %s", x.Name)
+func (s *BgpServer) AddPolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, def table.RouteType) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ var id string
+ id, err = s.toPolicyInfo(name, dir)
+ if err != nil {
+ return
}
- if seen[x.Name] {
- return rsp, fmt.Errorf("duplicated policy %s", x.Name)
+
+ ps := make([]*table.Policy, 0, len(policies))
+ seen := make(map[string]bool)
+ for _, x := range policies {
+ p, ok := s.policy.PolicyMap[x.Name]
+ if !ok {
+ err = fmt.Errorf("not found policy %s", x.Name)
+ return
+ }
+ if seen[x.Name] {
+ err = fmt.Errorf("duplicated policy %s", x.Name)
+ return
+ }
+ seen[x.Name] = true
+ ps = append(ps, p)
}
- seen[x.Name] = true
- ps = append(ps, p)
- }
- cur := server.policy.GetPolicy(id, dir)
- if cur == nil {
- err = server.policy.SetPolicy(id, dir, ps)
- } else {
- seen = make(map[string]bool)
- ps = append(cur, ps...)
- for _, x := range ps {
- if seen[x.Name()] {
- return rsp, fmt.Errorf("duplicated policy %s", x.Name())
+ cur := s.policy.GetPolicy(id, dir)
+ if cur == nil {
+ err = s.policy.SetPolicy(id, dir, ps)
+ } else {
+ seen = make(map[string]bool)
+ ps = append(cur, ps...)
+ for _, x := range ps {
+ if seen[x.Name] {
+ err = fmt.Errorf("duplicated policy %s", x.Name)
+ return
+ }
+ seen[x.Name] = true
}
- seen[x.Name()] = true
+ err = s.policy.SetPolicy(id, dir, ps)
+ }
+ if err == nil && def != table.ROUTE_TYPE_NONE {
+ err = s.policy.SetDefaultPolicy(id, dir, def)
}
- err = server.policy.SetPolicy(id, dir, ps)
- }
- if err != nil {
- return rsp, err
- }
-
- switch assignment.Default {
- case api.RouteAction_ACCEPT:
- err = server.policy.SetDefaultPolicy(id, dir, table.ROUTE_TYPE_ACCEPT)
- case api.RouteAction_REJECT:
- err = server.policy.SetDefaultPolicy(id, dir, table.ROUTE_TYPE_REJECT)
}
- return rsp, err
+ return err
}
-func (server *BgpServer) handleGrpcDeletePolicyAssignment(grpcReq *GrpcRequest) (*api.DeletePolicyAssignmentResponse, error) {
- var err error
- var dir table.PolicyDirection
- var id string
- policyMutex.Lock()
- defer policyMutex.Unlock()
- rsp := &api.DeletePolicyAssignmentResponse{}
- arg := grpcReq.Data.(*api.DeletePolicyAssignmentRequest)
- assignment := arg.Assignment
- id, dir, err = server.getPolicyInfo(assignment)
- if err != nil {
- return rsp, err
- }
- ps := make([]*table.Policy, 0, len(assignment.Policies))
- seen := make(map[string]bool)
- for _, x := range assignment.Policies {
- p, ok := server.policy.PolicyMap[x.Name]
- if !ok {
- return rsp, fmt.Errorf("not found policy %s", x.Name)
- }
- if seen[x.Name] {
- return rsp, fmt.Errorf("duplicated policy %s", x.Name)
- }
- seen[x.Name] = true
- ps = append(ps, p)
- }
- cur := server.policy.GetPolicy(id, dir)
+func (s *BgpServer) DeletePolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, all bool) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
- if arg.All {
- err = server.policy.SetPolicy(id, dir, nil)
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ var id string
+ id, err = s.toPolicyInfo(name, dir)
if err != nil {
- return rsp, err
+ return
}
- err = server.policy.SetDefaultPolicy(id, dir, table.ROUTE_TYPE_NONE)
- } else {
- n := make([]*table.Policy, 0, len(cur)-len(ps))
- for _, y := range cur {
- found := false
- for _, x := range ps {
- if x.Name() == y.Name() {
- found = true
- break
- }
+
+ ps := make([]*table.Policy, 0, len(policies))
+ seen := make(map[string]bool)
+ for _, x := range policies {
+ p, ok := s.policy.PolicyMap[x.Name]
+ if !ok {
+ err = fmt.Errorf("not found policy %s", x.Name)
+ return
}
- if !found {
- n = append(n, y)
+ if seen[x.Name] {
+ err = fmt.Errorf("duplicated policy %s", x.Name)
+ return
+ }
+ seen[x.Name] = true
+ ps = append(ps, p)
+ }
+ cur := s.policy.GetPolicy(id, dir)
+
+ if all {
+ err = s.policy.SetPolicy(id, dir, nil)
+ if err != nil {
+ return
+ }
+ err = s.policy.SetDefaultPolicy(id, dir, table.ROUTE_TYPE_NONE)
+ } else {
+ n := make([]*table.Policy, 0, len(cur)-len(ps))
+ for _, y := range cur {
+ found := false
+ for _, x := range ps {
+ if x.Name == y.Name {
+ found = true
+ break
+ }
+ }
+ if !found {
+ n = append(n, y)
+ }
}
+ err = s.policy.SetPolicy(id, dir, n)
}
- err = server.policy.SetPolicy(id, dir, n)
}
- return rsp, err
+ return err
}
-func (server *BgpServer) handleGrpcReplacePolicyAssignment(grpcReq *GrpcRequest) (*api.ReplacePolicyAssignmentResponse, error) {
- var err error
- var dir table.PolicyDirection
- var id string
- policyMutex.Lock()
- defer policyMutex.Unlock()
- rsp := &api.ReplacePolicyAssignmentResponse{}
- arg := grpcReq.Data.(*api.ReplacePolicyAssignmentRequest)
- assignment := arg.Assignment
- id, dir, err = server.getPolicyInfo(assignment)
- if err != nil {
- return rsp, err
- }
- ps := make([]*table.Policy, 0, len(assignment.Policies))
- seen := make(map[string]bool)
- for _, x := range assignment.Policies {
- p, ok := server.policy.PolicyMap[x.Name]
- if !ok {
- return rsp, fmt.Errorf("not found policy %s", x.Name)
+func (s *BgpServer) ReplacePolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, def table.RouteType) (err error) {
+ ch := make(chan struct{})
+ defer func() { <-ch }()
+
+ s.mgmtCh <- func() {
+ policyMutex.Lock()
+ defer func() {
+ policyMutex.Unlock()
+ close(ch)
+ }()
+
+ var id string
+ id, err = s.toPolicyInfo(name, dir)
+ if err != nil {
+ return
}
- if seen[x.Name] {
- return rsp, fmt.Errorf("duplicated policy %s", x.Name)
+
+ ps := make([]*table.Policy, 0, len(policies))
+ seen := make(map[string]bool)
+ for _, x := range policies {
+ p, ok := s.policy.PolicyMap[x.Name]
+ if !ok {
+ err = fmt.Errorf("not found policy %s", x.Name)
+ return
+ }
+ if seen[x.Name] {
+ err = fmt.Errorf("duplicated policy %s", x.Name)
+ return
+ }
+ seen[x.Name] = true
+ ps = append(ps, p)
+ }
+ s.policy.GetPolicy(id, dir)
+ err = s.policy.SetPolicy(id, dir, ps)
+ if err == nil && def != table.ROUTE_TYPE_NONE {
+ err = s.policy.SetDefaultPolicy(id, dir, def)
}
- seen[x.Name] = true
- ps = append(ps, p)
- }
- server.policy.GetPolicy(id, dir)
- err = server.policy.SetPolicy(id, dir, ps)
- if err != nil {
- return rsp, err
- }
- switch assignment.Default {
- case api.RouteAction_ACCEPT:
- err = server.policy.SetDefaultPolicy(id, dir, table.ROUTE_TYPE_ACCEPT)
- case api.RouteAction_REJECT:
- err = server.policy.SetDefaultPolicy(id, dir, table.ROUTE_TYPE_REJECT)
}
- return rsp, err
+ return err
}
func grpcDone(grpcReq *GrpcRequest, e error) {
diff --git a/server/server_test.go b/server/server_test.go
index 48d7e52d..9a55f775 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -16,7 +16,6 @@
package server
import (
- api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/table"
"github.com/stretchr/testify/assert"
@@ -33,50 +32,21 @@ func TestModPolicyAssign(t *testing.T) {
RouterId: "1.1.1.1",
},
})
- _, err := s.handleGrpcAddPolicy(&GrpcRequest{
- Data: &api.AddPolicyRequest{
- Policy: &api.Policy{
- Name: "p1",
- },
- },
- })
+ err := s.AddPolicy(&table.Policy{Name: "p1"}, false)
assert.Nil(err)
- _, err = s.handleGrpcAddPolicy(&GrpcRequest{
- Data: &api.AddPolicyRequest{
- Policy: &api.Policy{
- Name: "p2",
- },
- },
- })
+
+ err = s.AddPolicy(&table.Policy{Name: "p2"}, false)
assert.Nil(err)
- _, err = s.handleGrpcAddPolicy(&GrpcRequest{
- Data: &api.AddPolicyRequest{
- Policy: &api.Policy{
- Name: "p3",
- },
- },
- })
+
+ err = s.AddPolicy(&table.Policy{Name: "p3"}, false)
assert.Nil(err)
- _, err = s.handleGrpcAddPolicyAssignment(&GrpcRequest{
- Data: &api.AddPolicyAssignmentRequest{
- Assignment: &api.PolicyAssignment{
- Type: api.PolicyType_IMPORT,
- Resource: api.Resource_GLOBAL,
- Policies: []*api.Policy{&api.Policy{Name: "p1"}, &api.Policy{Name: "p2"}, &api.Policy{Name: "p3"}},
- },
- },
- })
+
+ err = s.AddPolicyAssignment("", table.POLICY_DIRECTION_IMPORT,
+ []*config.PolicyDefinition{&config.PolicyDefinition{Name: "p1"}, &config.PolicyDefinition{Name: "p2"}, &config.PolicyDefinition{Name: "p3"}}, table.ROUTE_TYPE_ACCEPT)
assert.Nil(err)
- _, err = s.handleGrpcDeletePolicyAssignment(&GrpcRequest{
- Data: &api.DeletePolicyAssignmentRequest{
- Assignment: &api.PolicyAssignment{
- Type: api.PolicyType_IMPORT,
- Resource: api.Resource_GLOBAL,
- Policies: []*api.Policy{&api.Policy{Name: "p1"}},
- },
- },
- })
+ err = s.DeletePolicyAssignment("", table.POLICY_DIRECTION_IMPORT,
+ []*config.PolicyDefinition{&config.PolicyDefinition{Name: "p1"}}, false)
assert.Nil(err)
ps := s.policy.GetPolicy(table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_IMPORT)