summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/sources/lib.md2
-rw-r--r--gobgpd/main.go2
-rw-r--r--server/grpc_server.go505
-rw-r--r--server/server.go1064
-rw-r--r--server/server_test.go50
-rw-r--r--table/policy.go620
-rw-r--r--table/policy_test.go59
7 files changed, 1149 insertions, 1153 deletions
diff --git a/docs/sources/lib.md b/docs/sources/lib.md
index 4fac54de..b1f80ca1 100644
--- a/docs/sources/lib.md
+++ b/docs/sources/lib.md
@@ -25,7 +25,7 @@ func main() {
// start grpc api server. this is not mandatory
// but you will be able to use `gobgp` cmd with this.
- g := gobgp.NewGrpcServer(":50051", s.GrpcReqCh)
+ g := gobgp.NewGrpcServer(s, ":50051", s.GrpcReqCh)
go g.Serve()
// global configuration
diff --git a/gobgpd/main.go b/gobgpd/main.go
index 7ad48f83..31029635 100644
--- a/gobgpd/main.go
+++ b/gobgpd/main.go
@@ -178,7 +178,7 @@ func main() {
go bgpServer.Serve()
// start grpc Server
- grpcServer := server.NewGrpcServer(opts.GrpcHosts, bgpServer.GrpcReqCh)
+ grpcServer := server.NewGrpcServer(bgpServer, opts.GrpcHosts, bgpServer.GrpcReqCh)
go func() {
if err := grpcServer.Serve(); err != nil {
log.Fatalf("failed to listen grpc port: %s", err)
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)
diff --git a/table/policy.go b/table/policy.go
index 09c4ea19..37aa4355 100644
--- a/table/policy.go
+++ b/table/policy.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation.
+// Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/armon/go-radix"
- api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet/bgp"
)
@@ -96,34 +95,6 @@ func (o MatchOption) String() string {
}
}
-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
-}
-
type MedActionType int
const (
@@ -255,23 +226,6 @@ func (lhs *Prefix) Equal(rhs *Prefix) bool {
return lhs.Prefix.String() == rhs.Prefix.String() && lhs.MasklengthRangeMin == rhs.MasklengthRangeMin && lhs.MasklengthRangeMax == rhs.MasklengthRangeMax
}
-func NewPrefixFromApiStruct(a *api.Prefix) (*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 &Prefix{
- Prefix: prefix,
- AddressFamily: rf,
- MasklengthRangeMin: uint8(a.MaskLengthMin),
- MasklengthRangeMax: uint8(a.MaskLengthMax),
- }, nil
-}
-
func NewPrefix(c config.Prefix) (*Prefix, error) {
addr, prefix, err := net.ParseCIDR(c.IpPrefix)
if err != nil {
@@ -371,20 +325,16 @@ func (s *PrefixSet) ToConfig() *config.PrefixSet {
}
}
-func NewPrefixSetFromApiStruct(a *api.DefinedSet) (*PrefixSet, error) {
- if a.Name == "" {
+func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, error) {
+ if name == "" {
return nil, fmt.Errorf("empty prefix set name")
}
tree := radix.New()
- for _, x := range a.Prefixes {
- y, err := NewPrefixFromApiStruct(x)
- if err != nil {
- return nil, err
- }
- tree.Insert(CidrToRadixkey(y.Prefix.String()), y)
+ for _, x := range prefixes {
+ tree.Insert(CidrToRadixkey(x.Prefix.String()), x)
}
return &PrefixSet{
- name: a.Name,
+ name: name,
tree: tree,
}, nil
}
@@ -475,20 +425,9 @@ func (s *NeighborSet) ToConfig() *config.NeighborSet {
}
}
-func NewNeighborSetFromApiStruct(a *api.DefinedSet) (*NeighborSet, error) {
- if a.Name == "" {
- return nil, fmt.Errorf("empty neighbor set name")
- }
- 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)
- }
+func NewNeighborSetFromApiStruct(name string, list []net.IP) (*NeighborSet, error) {
return &NeighborSet{
- name: a.Name,
+ name: name,
list: list,
}, nil
}
@@ -691,14 +630,6 @@ func (s *AsPathSet) ToConfig() *config.AsPathSet {
}
}
-func NewAsPathSetFromApiStruct(a *api.DefinedSet) (*AsPathSet, error) {
- c := config.AsPathSet{
- AsPathSetName: a.Name,
- AsPathList: a.List,
- }
- return NewAsPathSet(c)
-}
-
func NewAsPathSet(c config.AsPathSet) (*AsPathSet, error) {
name := c.AsPathSetName
if name == "" {
@@ -906,14 +837,6 @@ func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *reg
return subtype, exp, err
}
-func NewCommunitySetFromApiStruct(a *api.DefinedSet) (*CommunitySet, error) {
- c := config.CommunitySet{
- CommunitySetName: a.Name,
- CommunityList: a.List,
- }
- return NewCommunitySet(c)
-}
-
func NewCommunitySet(c config.CommunitySet) (*CommunitySet, error) {
name := c.CommunitySetName
if name == "" {
@@ -967,14 +890,6 @@ func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet {
}
}
-func NewExtCommunitySetFromApiStruct(a *api.DefinedSet) (*ExtCommunitySet, error) {
- c := config.ExtCommunitySet{
- ExtCommunitySetName: a.Name,
- ExtCommunityList: a.List,
- }
- return NewExtCommunitySet(c)
-}
-
func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
name := c.ExtCommunitySetName
if name == "" {
@@ -1003,30 +918,15 @@ func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
}, nil
}
-func NewDefinedSetFromApiStruct(a *api.DefinedSet) (DefinedSet, error) {
- switch DefinedType(a.Type) {
- case DEFINED_TYPE_PREFIX:
- return NewPrefixSetFromApiStruct(a)
- case DEFINED_TYPE_NEIGHBOR:
- return NewNeighborSetFromApiStruct(a)
- case DEFINED_TYPE_AS_PATH:
- return NewAsPathSetFromApiStruct(a)
- case DEFINED_TYPE_COMMUNITY:
- return NewCommunitySetFromApiStruct(a)
- case DEFINED_TYPE_EXT_COMMUNITY:
- return NewExtCommunitySetFromApiStruct(a)
- default:
- return nil, fmt.Errorf("invalid defined type")
- }
-}
-
type Condition interface {
+ Name() string
Type() ConditionType
Evaluate(*Path, *PolicyOptions) bool
Set() DefinedSet
}
type PrefixCondition struct {
+ name string
set *PrefixSet
option MatchOption
}
@@ -1080,44 +980,24 @@ func (c *PrefixCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
-func NewPrefixConditionFromApiStruct(a *api.MatchSet, m map[string]DefinedSet) (*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 NewPrefixCondition(c, m)
-}
+func (c *PrefixCondition) Name() string { return c.name }
-func NewPrefixCondition(c config.MatchPrefixSet, m map[string]DefinedSet) (*PrefixCondition, error) {
+func NewPrefixCondition(c config.MatchPrefixSet) (*PrefixCondition, error) {
if c.PrefixSet == "" {
return nil, nil
}
- i, ok := m[c.PrefixSet]
- if !ok {
- return nil, fmt.Errorf("not found prefix set %s", c.PrefixSet)
- }
- s, ok := i.(*PrefixSet)
- if !ok {
- return nil, fmt.Errorf("type assert from DefinedSet to *PrefixSet failed")
- }
o, err := NewMatchOption(c.MatchSetOptions)
if err != nil {
return nil, err
}
return &PrefixCondition{
- set: s,
+ name: c.PrefixSet,
option: o,
}, nil
}
type NeighborCondition struct {
+ name string
set *NeighborSet
option MatchOption
}
@@ -1167,44 +1047,24 @@ func (c *NeighborCondition) Evaluate(path *Path, options *PolicyOptions) bool {
return result
}
-func NewNeighborConditionFromApiStruct(a *api.MatchSet, m map[string]DefinedSet) (*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 NewNeighborCondition(c, m)
-}
+func (c *NeighborCondition) Name() string { return c.name }
-func NewNeighborCondition(c config.MatchNeighborSet, m map[string]DefinedSet) (*NeighborCondition, error) {
+func NewNeighborCondition(c config.MatchNeighborSet) (*NeighborCondition, error) {
if c.NeighborSet == "" {
return nil, nil
}
- i, ok := m[c.NeighborSet]
- if !ok {
- return nil, fmt.Errorf("not found neighbor set %s", c.NeighborSet)
- }
- s, ok := i.(*NeighborSet)
- if !ok {
- return nil, fmt.Errorf("type assert from DefinedSet to *NeighborSet failed")
- }
o, err := NewMatchOption(c.MatchSetOptions)
if err != nil {
return nil, err
}
return &NeighborCondition{
- set: s,
+ name: c.NeighborSet,
option: o,
}, nil
}
type AsPathCondition struct {
+ name string
set *AsPathSet
option MatchOption
}
@@ -1258,44 +1118,24 @@ func (c *AsPathCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return true
}
-func NewAsPathConditionFromApiStruct(a *api.MatchSet, m map[string]DefinedSet) (*AsPathCondition, error) {
- if a == nil {
- return nil, nil
- }
- typ, err := toConfigMatchSetOption(a.Type)
- if err != nil {
- return nil, err
- }
- c := config.MatchAsPathSet{
- AsPathSet: a.Name,
- MatchSetOptions: typ,
- }
- return NewAsPathCondition(c, m)
-}
+func (c *AsPathCondition) Name() string { return c.name }
-func NewAsPathCondition(c config.MatchAsPathSet, m map[string]DefinedSet) (*AsPathCondition, error) {
+func NewAsPathCondition(c config.MatchAsPathSet) (*AsPathCondition, error) {
if c.AsPathSet == "" {
return nil, nil
}
- i, ok := m[c.AsPathSet]
- if !ok {
- return nil, fmt.Errorf("not found as path set %s", c.AsPathSet)
- }
- s, ok := i.(*AsPathSet)
- if !ok {
- return nil, fmt.Errorf("type assert from DefinedSet to *AsPathSet failed")
- }
o, err := NewMatchOption(c.MatchSetOptions)
if err != nil {
return nil, err
}
return &AsPathCondition{
- set: s,
+ name: c.AsPathSet,
option: o,
}, nil
}
type CommunityCondition struct {
+ name string
set *CommunitySet
option MatchOption
}
@@ -1336,44 +1176,24 @@ func (c *CommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
-func NewCommunityConditionFromApiStruct(a *api.MatchSet, m map[string]DefinedSet) (*CommunityCondition, error) {
- if a == nil {
- return nil, nil
- }
- typ, err := toConfigMatchSetOption(a.Type)
- if err != nil {
- return nil, err
- }
- c := config.MatchCommunitySet{
- CommunitySet: a.Name,
- MatchSetOptions: typ,
- }
- return NewCommunityCondition(c, m)
-}
+func (c *CommunityCondition) Name() string { return c.name }
-func NewCommunityCondition(c config.MatchCommunitySet, m map[string]DefinedSet) (*CommunityCondition, error) {
+func NewCommunityCondition(c config.MatchCommunitySet) (*CommunityCondition, error) {
if c.CommunitySet == "" {
return nil, nil
}
- i, ok := m[c.CommunitySet]
- if !ok {
- return nil, fmt.Errorf("not found community set %s", c.CommunitySet)
- }
- s, ok := i.(*CommunitySet)
- if !ok {
- return nil, fmt.Errorf("type assert from DefinedSet to *CommunitySet failed")
- }
o, err := NewMatchOption(c.MatchSetOptions)
if err != nil {
return nil, err
}
return &CommunityCondition{
- set: s,
+ name: c.CommunitySet,
option: o,
}, nil
}
type ExtCommunityCondition struct {
+ name string
set *ExtCommunitySet
option MatchOption
}
@@ -1419,39 +1239,18 @@ func (c *ExtCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
-func NewExtCommunityConditionFromApiStruct(a *api.MatchSet, m map[string]DefinedSet) (*ExtCommunityCondition, error) {
- if a == nil {
- return nil, nil
- }
- typ, err := toConfigMatchSetOption(a.Type)
- if err != nil {
- return nil, err
- }
- c := config.MatchExtCommunitySet{
- ExtCommunitySet: a.Name,
- MatchSetOptions: typ,
- }
- return NewExtCommunityCondition(c, m)
-}
+func (c *ExtCommunityCondition) Name() string { return c.name }
-func NewExtCommunityCondition(c config.MatchExtCommunitySet, m map[string]DefinedSet) (*ExtCommunityCondition, error) {
+func NewExtCommunityCondition(c config.MatchExtCommunitySet) (*ExtCommunityCondition, error) {
if c.ExtCommunitySet == "" {
return nil, nil
}
- i, ok := m[c.ExtCommunitySet]
- if !ok {
- return nil, fmt.Errorf("not found ext-community set %s", c.ExtCommunitySet)
- }
- s, ok := i.(*ExtCommunitySet)
- if !ok {
- return nil, fmt.Errorf("type assert from DefinedSet to *ExtCommunitySet failed")
- }
o, err := NewMatchOption(c.MatchSetOptions)
if err != nil {
return nil, err
}
return &ExtCommunityCondition{
- set: s,
+ name: c.ExtCommunitySet,
option: o,
}, nil
}
@@ -1487,15 +1286,7 @@ func (c *AsPathLengthCondition) Set() DefinedSet {
return nil
}
-func NewAsPathLengthConditionFromApiStruct(a *api.AsPathLength) (*AsPathLengthCondition, error) {
- if a == nil {
- return nil, nil
- }
- return &AsPathLengthCondition{
- length: a.Length,
- operator: AttributeComparison(a.Type),
- }, nil
-}
+func (c *AsPathLengthCondition) Name() string { return "" }
func NewAsPathLengthCondition(c config.AsPathLength) (*AsPathLengthCondition, error) {
if c.Value == 0 && c.Operator == "" {
@@ -1531,12 +1322,7 @@ func (c *RpkiValidationCondition) Set() DefinedSet {
return nil
}
-func NewRpkiValidationConditionFromApiStruct(a int32) (*RpkiValidationCondition, error) {
- if a < 1 {
- return nil, nil
- }
- return NewRpkiValidationCondition(config.IntToRpkiValidationResultTypeMap[int(a)])
-}
+func (c *RpkiValidationCondition) Name() string { return "" }
func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidationCondition, error) {
if c == config.RPKI_VALIDATION_RESULT_TYPE_NONE {
@@ -1567,19 +1353,6 @@ func (a *RoutingAction) Apply(path *Path, _ *PolicyOptions) *Path {
return nil
}
-func NewRoutingActionFromApiStruct(a api.RouteAction) (*RoutingAction, error) {
- if a == api.RouteAction_NONE {
- return nil, nil
- }
- accept := false
- if a == api.RouteAction_ACCEPT {
- accept = true
- }
- return &RoutingAction{
- AcceptRoute: accept,
- }, nil
-}
-
func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) {
if c.AcceptRoute == c.RejectRoute && c.AcceptRoute {
return nil, fmt.Errorf("invalid route disposition")
@@ -1672,40 +1445,6 @@ func (a *CommunityAction) ToConfig() *config.SetCommunity {
}
}
-func NewCommunityActionFromApiStruct(a *api.CommunityAction) (*CommunityAction, error) {
- if a == nil {
- return nil, nil
- }
- var list []uint32
- var removeList []*regexp.Regexp
- op := config.IntToBgpSetCommunityOptionTypeMap[int(a.Type)]
- if op == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- removeList = make([]*regexp.Regexp, 0, len(a.Communities))
- } else {
- list = make([]uint32, 0, len(a.Communities))
- }
- for _, x := range a.Communities {
- if op == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- exp, err := ParseCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- removeList = append(removeList, exp)
- } else {
- comm, err := ParseCommunity(x)
- if err != nil {
- return nil, err
- }
- list = append(list, comm)
- }
- }
- return &CommunityAction{
- action: op,
- list: list,
- removeList: removeList,
- }, nil
-}
-
func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) {
a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
if !ok {
@@ -1794,45 +1533,6 @@ func (a *ExtCommunityAction) ToConfig() *config.SetExtCommunity {
}
}
-func NewExtCommunityActionFromApiStruct(a *api.CommunityAction) (*ExtCommunityAction, error) {
- if a == nil {
- return nil, nil
- }
- var list []bgp.ExtendedCommunityInterface
- var removeList []*regexp.Regexp
- subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(a.Communities))
- op := config.IntToBgpSetCommunityOptionTypeMap[int(a.Type)]
- if op == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- removeList = make([]*regexp.Regexp, 0, len(a.Communities))
- } else {
- list = make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities))
- }
- for _, x := range a.Communities {
- if op == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- subtype, exp, err := ParseExtCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- removeList = append(removeList, exp)
- subtypeList = append(subtypeList, subtype)
- } else {
- comm, err := ParseExtCommunity(x)
- if err != nil {
- return nil, err
- }
- list = append(list, comm)
- _, subtype := comm.GetTypes()
- subtypeList = append(subtypeList, subtype)
- }
- }
- return &ExtCommunityAction{
- action: op,
- list: list,
- removeList: removeList,
- subtypeList: subtypeList,
- }, nil
-}
-
func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error) {
a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
if !ok {
@@ -1909,16 +1609,6 @@ func (a *MedAction) ToConfig() config.BgpSetMedType {
return config.BgpSetMedType(fmt.Sprintf("%d", a.value))
}
-func NewMedActionFromApiStruct(a *api.MedAction) (*MedAction, error) {
- if a == nil {
- return nil, nil
- }
- return &MedAction{
- action: MedActionType(a.Type),
- value: int(a.Value),
- }, nil
-}
-
func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
if string(c) == "" {
return nil, nil
@@ -1940,6 +1630,10 @@ func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
}, nil
}
+func NewMedActionFromApiStruct(action MedActionType, value int) *MedAction {
+ return &MedAction{action: action, value: value}
+}
+
type LocalPrefAction struct {
value uint32
}
@@ -1957,15 +1651,6 @@ func (a *LocalPrefAction) ToConfig() uint32 {
return a.value
}
-func NewLocalPrefActionFromApiStruct(a *api.LocalPrefAction) (*LocalPrefAction, error) {
- if a == nil || a.Value == 0 {
- return nil, nil
- }
- return &LocalPrefAction{
- value: a.Value,
- }, nil
-}
-
func NewLocalPrefAction(value uint32) (*LocalPrefAction, error) {
if value == 0 {
return nil, nil
@@ -2025,17 +1710,6 @@ func (a *AsPathPrependAction) ToConfig() *config.SetAsPathPrepend {
}
}
-func NewAsPathPrependActionFromApiStruct(a *api.AsPrependAction) (*AsPathPrependAction, error) {
- if a == nil {
- return nil, nil
- }
- return &AsPathPrependAction{
- asn: a.Asn,
- useLeftMost: a.UseLeftMost,
- repeat: uint8(a.Repeat),
- }, nil
-}
-
// NewAsPathPrependAction creates AsPathPrependAction object.
// If ASN cannot be parsed, nil will be returned.
func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependAction, error) {
@@ -2087,16 +1761,6 @@ func (a *NexthopAction) ToConfig() config.BgpNextHopType {
return config.BgpNextHopType(a.value.String())
}
-func NewNexthopActionFromApiStruct(a *api.NexthopAction) (*NexthopAction, error) {
- if a == nil {
- return nil, nil
- }
- return &NexthopAction{
- value: net.ParseIP(a.Address),
- self: a.Self,
- }, nil
-}
-
func NewNexthopAction(c config.BgpNextHopType) (*NexthopAction, error) {
switch string(c) {
case "":
@@ -2338,94 +2002,7 @@ func (lhs *Statement) Replace(rhs *Statement) error {
return lhs.mod(REPLACE, rhs)
}
-func NewStatementFromApiStruct(a *api.Statement, dmap DefinedSetMap) (*Statement, error) {
- if a.Name == "" {
- return nil, fmt.Errorf("empty statement name")
- }
- var ra Action
- var as []Action
- var cs []Condition
- var err error
- if a.Conditions != nil {
- cfs := []func() (Condition, error){
- func() (Condition, error) {
- return NewPrefixConditionFromApiStruct(a.Conditions.PrefixSet, dmap[DEFINED_TYPE_PREFIX])
- },
- func() (Condition, error) {
- return NewNeighborConditionFromApiStruct(a.Conditions.NeighborSet, dmap[DEFINED_TYPE_NEIGHBOR])
- },
- func() (Condition, error) {
- return NewAsPathLengthConditionFromApiStruct(a.Conditions.AsPathLength)
- },
- func() (Condition, error) {
- return NewRpkiValidationConditionFromApiStruct(a.Conditions.RpkiResult)
- },
- func() (Condition, error) {
- return NewAsPathConditionFromApiStruct(a.Conditions.AsPathSet, dmap[DEFINED_TYPE_AS_PATH])
- },
- func() (Condition, error) {
- return NewCommunityConditionFromApiStruct(a.Conditions.CommunitySet, dmap[DEFINED_TYPE_COMMUNITY])
- },
- func() (Condition, error) {
- return NewExtCommunityConditionFromApiStruct(a.Conditions.ExtCommunitySet, dmap[DEFINED_TYPE_EXT_COMMUNITY])
- },
- }
- cs = make([]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() (Action, error){
- func() (Action, error) {
- return NewCommunityActionFromApiStruct(a.Actions.Community)
- },
- func() (Action, error) {
- return NewExtCommunityActionFromApiStruct(a.Actions.ExtCommunity)
- },
- func() (Action, error) {
- return NewMedActionFromApiStruct(a.Actions.Med)
- },
- func() (Action, error) {
- return NewLocalPrefActionFromApiStruct(a.Actions.LocalPref)
- },
- func() (Action, error) {
- return NewAsPathPrependActionFromApiStruct(a.Actions.AsPrepend)
- },
- func() (Action, error) {
- return NewNexthopActionFromApiStruct(a.Actions.Nexthop)
- },
- }
- as = make([]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 &Statement{
- Name: a.Name,
- Conditions: cs,
- RouteAction: ra,
- ModActions: as,
- }, nil
-}
-
-func NewStatement(c config.Statement, dmap DefinedSetMap) (*Statement, error) {
+func NewStatement(c config.Statement) (*Statement, error) {
if c.Name == "" {
return nil, fmt.Errorf("empty statement name")
}
@@ -2435,10 +2012,10 @@ func NewStatement(c config.Statement, dmap DefinedSetMap) (*Statement, error) {
var err error
cfs := []func() (Condition, error){
func() (Condition, error) {
- return NewPrefixCondition(c.Conditions.MatchPrefixSet, dmap[DEFINED_TYPE_PREFIX])
+ return NewPrefixCondition(c.Conditions.MatchPrefixSet)
},
func() (Condition, error) {
- return NewNeighborCondition(c.Conditions.MatchNeighborSet, dmap[DEFINED_TYPE_NEIGHBOR])
+ return NewNeighborCondition(c.Conditions.MatchNeighborSet)
},
func() (Condition, error) {
return NewAsPathLengthCondition(c.Conditions.BgpConditions.AsPathLength)
@@ -2447,13 +2024,13 @@ func NewStatement(c config.Statement, dmap DefinedSetMap) (*Statement, error) {
return NewRpkiValidationCondition(c.Conditions.BgpConditions.RpkiValidationResult)
},
func() (Condition, error) {
- return NewAsPathCondition(c.Conditions.BgpConditions.MatchAsPathSet, dmap[DEFINED_TYPE_AS_PATH])
+ return NewAsPathCondition(c.Conditions.BgpConditions.MatchAsPathSet)
},
func() (Condition, error) {
- return NewCommunityCondition(c.Conditions.BgpConditions.MatchCommunitySet, dmap[DEFINED_TYPE_COMMUNITY])
+ return NewCommunityCondition(c.Conditions.BgpConditions.MatchCommunitySet)
},
func() (Condition, error) {
- return NewExtCommunityCondition(c.Conditions.BgpConditions.MatchExtCommunitySet, dmap[DEFINED_TYPE_EXT_COMMUNITY])
+ return NewExtCommunityCondition(c.Conditions.BgpConditions.MatchExtCommunitySet)
},
}
cs = make([]Condition, 0, len(cfs))
@@ -2509,14 +2086,10 @@ func NewStatement(c config.Statement, dmap DefinedSetMap) (*Statement, error) {
}
type Policy struct {
- name string
+ Name string
Statements []*Statement
}
-func (p *Policy) Name() string {
- return p.name
-}
-
// Compare path with a policy's condition in stored order in the policy.
// If a condition match, then this function stops evaluation and
// subsequent conditions are skipped.
@@ -2537,7 +2110,7 @@ func (p *Policy) ToConfig() *config.PolicyDefinition {
ss = append(ss, *s.ToConfig())
}
return &config.PolicyDefinition{
- Name: p.name,
+ Name: p.Name,
Statements: ss,
}
}
@@ -2583,28 +2156,7 @@ func (lhs *Policy) Replace(rhs *Policy) error {
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 idx, x := range a.Statements {
- if x.Name == "" {
- x.Name = fmt.Sprintf("%s_stmt%d", a.Name, idx)
- }
- 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) {
+func NewPolicy(c config.PolicyDefinition) (*Policy, error) {
if c.Name == "" {
return nil, fmt.Errorf("empty policy name")
}
@@ -2616,7 +2168,7 @@ func NewPolicy(c config.PolicyDefinition, dmap DefinedSetMap) (*Policy, error) {
if stmt.Name == "" {
stmt.Name = fmt.Sprintf("%s_stmt%d", c.Name, idx)
}
- s, err := NewStatement(stmt, dmap)
+ s, err := NewStatement(stmt)
if err != nil {
return nil, err
}
@@ -2624,7 +2176,7 @@ func NewPolicy(c config.PolicyDefinition, dmap DefinedSetMap) (*Policy, error) {
}
}
return &Policy{
- name: c.Name,
+ Name: c.Name,
Statements: st,
}, nil
}
@@ -2780,6 +2332,54 @@ func (r *RoutingPolicy) GetAssignmentFromConfig(dir PolicyDirection, a config.Ap
return ps, def, nil
}
+func (r *RoutingPolicy) ValidateCondition(v Condition) (err error) {
+ switch v.Type() {
+ case CONDITION_PREFIX:
+ m := r.DefinedSetMap[DEFINED_TYPE_PREFIX]
+ if i, ok := m[v.Name()]; !ok {
+ return fmt.Errorf("not found prefix set %s", v.Name())
+ } else {
+ c := v.(*PrefixCondition)
+ c.set = i.(*PrefixSet)
+ }
+ case CONDITION_NEIGHBOR:
+ m := r.DefinedSetMap[DEFINED_TYPE_NEIGHBOR]
+ if i, ok := m[v.Name()]; !ok {
+ return fmt.Errorf("not found neighbor set %s", v.Name())
+ } else {
+ c := v.(*NeighborCondition)
+ c.set = i.(*NeighborSet)
+ }
+ case CONDITION_AS_PATH:
+ m := r.DefinedSetMap[DEFINED_TYPE_AS_PATH]
+ if i, ok := m[v.Name()]; !ok {
+ return fmt.Errorf("not found as path set %s", v.Name())
+ } else {
+ c := v.(*AsPathCondition)
+ c.set = i.(*AsPathSet)
+ }
+ case CONDITION_COMMUNITY:
+ m := r.DefinedSetMap[DEFINED_TYPE_COMMUNITY]
+ if i, ok := m[v.Name()]; !ok {
+ return fmt.Errorf("not found community set %s", v.Name())
+ } else {
+ c := v.(*CommunityCondition)
+ c.set = i.(*CommunitySet)
+ }
+ case CONDITION_EXT_COMMUNITY:
+ m := r.DefinedSetMap[DEFINED_TYPE_EXT_COMMUNITY]
+ if i, ok := m[v.Name()]; !ok {
+ return fmt.Errorf("not found ext-community set %s", v.Name())
+ } else {
+ c := v.(*ExtCommunityCondition)
+ c.set = i.(*ExtCommunitySet)
+ }
+ case CONDITION_AS_PATH_LENGTH:
+ case CONDITION_RPKI:
+ }
+ return nil
+}
+
func (r *RoutingPolicy) InUse(d DefinedSet) bool {
name := d.Name()
for _, p := range r.PolicyMap {
@@ -2875,14 +2475,14 @@ func (r *RoutingPolicy) Reload(c config.RoutingPolicy) error {
pmap := make(map[string]*Policy)
smap := make(map[string]*Statement)
for _, x := range c.PolicyDefinitions {
- y, err := NewPolicy(x, dmap)
+ y, err := NewPolicy(x)
if err != nil {
return err
}
- if _, ok := pmap[y.Name()]; ok {
+ if _, ok := pmap[y.Name]; ok {
return fmt.Errorf("duplicated policy name. policy name must be unique.")
}
- pmap[y.Name()] = y
+ pmap[y.Name] = y
for _, s := range y.Statements {
_, ok := smap[s.Name]
if ok {
@@ -2891,6 +2491,21 @@ func (r *RoutingPolicy) Reload(c config.RoutingPolicy) error {
smap[s.Name] = s
}
}
+
+ // hacky
+ oldMap := r.DefinedSetMap
+ r.DefinedSetMap = dmap
+ for _, y := range pmap {
+ for _, s := range y.Statements {
+ for _, c := range s.Conditions {
+ if err := r.ValidateCondition(c); err != nil {
+ r.DefinedSetMap = oldMap
+ return err
+ }
+ }
+ }
+ }
+
r.DefinedSetMap = dmap
r.PolicyMap = pmap
r.StatementMap = smap
@@ -2923,14 +2538,7 @@ func CanImportToVrf(v *Vrf, path *Path) bool {
ExtCommunitySet: v.Name,
MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
}
- c, _ := NewExtCommunityCondition(matchSet, map[string]DefinedSet{v.Name: set})
+ c, _ := NewExtCommunityCondition(matchSet)
+ c.set = set
return c.Evaluate(path, nil)
}
-
-func PoliciesToString(ps []*api.Policy) []string {
- names := make([]string, 0, len(ps))
- for _, p := range ps {
- names = append(names, p.Name)
- }
- return names
-}
diff --git a/table/policy_test.go b/table/policy_test.go
index e5bc52c9..ff52e3c7 100644
--- a/table/policy_test.go
+++ b/table/policy_test.go
@@ -612,6 +612,14 @@ func TestAs4PathLengthConditionEvaluate(t *testing.T) {
assert.Equal(t, false, c.Evaluate(path, nil))
}
+func addPolicy(r *RoutingPolicy, x *Policy) {
+ for _, s := range x.Statements {
+ for _, c := range s.Conditions {
+ r.ValidateCondition(c)
+ }
+ }
+}
+
func TestAs4PathLengthConditionWithOtherCondition(t *testing.T) {
// setup
// create path
@@ -663,7 +671,8 @@ func TestAs4PathLengthConditionWithOtherCondition(t *testing.T) {
//test
r := NewRoutingPolicy()
r.Reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0], r.DefinedSetMap)
+ p, _ := NewPolicy(pl.PolicyDefinitions[0])
+ addPolicy(r, p)
pType, newPath := p.Apply(path, nil)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -739,7 +748,10 @@ func TestAsPathConditionEvaluate(t *testing.T) {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet, m)
+ p, _ := NewAsPathCondition(matchSet)
+ if v, ok := m[name]; ok {
+ p.set = v.(*AsPathSet)
+ }
return p
}
@@ -839,7 +851,10 @@ func TestMultipleAsPathConditionEvaluate(t *testing.T) {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet, m)
+ p, _ := NewAsPathCondition(matchSet)
+ if v, ok := m[name]; ok {
+ p.set = v.(*AsPathSet)
+ }
return p
}
@@ -931,7 +946,8 @@ func TestAsPathCondition(t *testing.T) {
c, _ := NewAsPathCondition(config.MatchAsPathSet{
AsPathSet: k,
MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
- }, map[string]DefinedSet{k: s})
+ })
+ c.set = s
for _, a := range v {
result := c.Evaluate(a.path, nil)
if a.result != result {
@@ -1082,7 +1098,10 @@ func TestAs4PathConditionEvaluate(t *testing.T) {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet, m)
+ p, _ := NewAsPathCondition(matchSet)
+ if v, ok := m[name]; ok {
+ p.set = v.(*AsPathSet)
+ }
return p
}
@@ -1203,7 +1222,10 @@ func TestMultipleAs4PathConditionEvaluate(t *testing.T) {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet, m)
+ p, _ := NewAsPathCondition(matchSet)
+ if v, ok := m[name]; ok {
+ p.set = v.(*AsPathSet)
+ }
return p
}
@@ -1282,7 +1304,8 @@ func TestAs4PathConditionWithOtherCondition(t *testing.T) {
//test
r := NewRoutingPolicy()
r.Reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0], r.DefinedSetMap)
+ p, _ := NewPolicy(pl.PolicyDefinitions[0])
+ addPolicy(r, p)
pType, newPath := p.Apply(path, nil)
assert.Equal(t, ROUTE_TYPE_REJECT, pType)
assert.Equal(t, newPath, path)
@@ -1364,7 +1387,10 @@ func TestAs4PathConditionEvaluateMixedWith2byteAS(t *testing.T) {
matchSet := config.MatchAsPathSet{}
matchSet.AsPathSet = name
matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet, m)
+ p, _ := NewAsPathCondition(matchSet)
+ if v, ok := m[name]; ok {
+ p.set = v.(*AsPathSet)
+ }
return p
}
@@ -1499,7 +1525,10 @@ func TestCommunityConditionEvaluate(t *testing.T) {
matchSet := config.MatchCommunitySet{}
matchSet.CommunitySet = name
matchSet.MatchSetOptions = option
- c, _ := NewCommunityCondition(matchSet, m)
+ c, _ := NewCommunityCondition(matchSet)
+ if v, ok := m[name]; ok {
+ c.set = v.(*CommunitySet)
+ }
return c
}
@@ -2027,7 +2056,11 @@ func TestExtCommunityConditionEvaluate(t *testing.T) {
matchSet := config.MatchExtCommunitySet{}
matchSet.ExtCommunitySet = name
matchSet.MatchSetOptions = option
- c, _ := NewExtCommunityCondition(matchSet, m)
+ c, _ := NewExtCommunityCondition(matchSet)
+ if v, ok := m[name]; ok {
+ c.set = v.(*ExtCommunitySet)
+ }
+
return c
}
@@ -2590,7 +2623,8 @@ func TestPolicyAs4PathPrepend(t *testing.T) {
//test
r := NewRoutingPolicy()
r.Reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0], r.DefinedSetMap)
+ p, _ := NewPolicy(pl.PolicyDefinitions[0])
+ addPolicy(r, p)
pType, newPath := p.Apply(path, nil)
assert.Equal(ROUTE_TYPE_ACCEPT, pType)
@@ -2645,7 +2679,8 @@ func TestPolicyAs4PathPrependLastAs(t *testing.T) {
//test
r := NewRoutingPolicy()
r.Reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0], r.DefinedSetMap)
+ p, _ := NewPolicy(pl.PolicyDefinitions[0])
+ addPolicy(r, p)
pType, newPath := p.Apply(path, nil)
assert.Equal(ROUTE_TYPE_ACCEPT, pType)