diff options
-rw-r--r-- | api/gobgp.pb.go | 29 | ||||
-rw-r--r-- | api/gobgp.proto | 11 | ||||
-rw-r--r-- | gobgp/common.go | 16 | ||||
-rw-r--r-- | gobgp/policy.go | 179 | ||||
-rw-r--r-- | policy/policy.go | 78 | ||||
-rw-r--r-- | server/grpc_server.go | 20 | ||||
-rw-r--r-- | server/server.go | 100 |
7 files changed, 412 insertions, 21 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index 78a9b6a3..32ace22d 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -37,6 +37,7 @@ It has these top-level messages: Neighbor NeighborSet AsPathLength + AsPathSet Conditions Actions Statement @@ -68,7 +69,8 @@ const ( Resource_ADJ_OUT Resource = 3 Resource_POLICY_PREFIX Resource = 4 Resource_POLICY_NEIGHBOR Resource = 5 - Resource_POLICY_ROUTEPOLICY Resource = 6 + Resource_POLICY_ASPATH Resource = 6 + Resource_POLICY_ROUTEPOLICY Resource = 7 ) var Resource_name = map[int32]string{ @@ -78,7 +80,8 @@ var Resource_name = map[int32]string{ 3: "ADJ_OUT", 4: "POLICY_PREFIX", 5: "POLICY_NEIGHBOR", - 6: "POLICY_ROUTEPOLICY", + 6: "POLICY_ASPATH", + 7: "POLICY_ROUTEPOLICY", } var Resource_value = map[string]int32{ "GLOBAL": 0, @@ -87,7 +90,8 @@ var Resource_value = map[string]int32{ "ADJ_OUT": 3, "POLICY_PREFIX": 4, "POLICY_NEIGHBOR": 5, - "POLICY_ROUTEPOLICY": 6, + "POLICY_ASPATH": 6, + "POLICY_ROUTEPOLICY": 7, } func (x Resource) String() string { @@ -994,11 +998,21 @@ func (m *AsPathLength) Reset() { *m = AsPathLength{} } func (m *AsPathLength) String() string { return proto.CompactTextString(m) } func (*AsPathLength) ProtoMessage() {} +type AsPathSet struct { + AsPathSetName string `protobuf:"bytes,1,opt,name=as_path_set_name" json:"as_path_set_name,omitempty"` + AsPathMembers []string `protobuf:"bytes,2,rep,name=as_path_members" json:"as_path_members,omitempty"` +} + +func (m *AsPathSet) Reset() { *m = AsPathSet{} } +func (m *AsPathSet) String() string { return proto.CompactTextString(m) } +func (*AsPathSet) ProtoMessage() {} + type Conditions struct { MatchPrefixSet *PrefixSet `protobuf:"bytes,1,opt,name=match_prefix_set" json:"match_prefix_set,omitempty"` MatchNeighborSet *NeighborSet `protobuf:"bytes,2,opt,name=match_neighbor_set" json:"match_neighbor_set,omitempty"` MatchAsPathLength *AsPathLength `protobuf:"bytes,3,opt,name=match_as_path_length" json:"match_as_path_length,omitempty"` - MatchSetOptions string `protobuf:"bytes,4,opt,name=match_set_options" json:"match_set_options,omitempty"` + MatchAsPathSet *AsPathSet `protobuf:"bytes,4,opt,name=match_as_path_set" json:"match_as_path_set,omitempty"` + MatchSetOptions string `protobuf:"bytes,5,opt,name=match_set_options" json:"match_set_options,omitempty"` } func (m *Conditions) Reset() { *m = Conditions{} } @@ -1026,6 +1040,13 @@ func (m *Conditions) GetMatchAsPathLength() *AsPathLength { return nil } +func (m *Conditions) GetMatchAsPathSet() *AsPathSet { + if m != nil { + return m.MatchAsPathSet + } + return nil +} + type Actions struct { RouteAction string `protobuf:"bytes,1,opt,name=route_action" json:"route_action,omitempty"` } diff --git a/api/gobgp.proto b/api/gobgp.proto index 29038ea8..e61c2243 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -75,7 +75,8 @@ enum Resource { ADJ_OUT = 3; POLICY_PREFIX = 4; POLICY_NEIGHBOR = 5; - POLICY_ROUTEPOLICY = 6; + POLICY_ASPATH = 6; + POLICY_ROUTEPOLICY = 7; } enum Operation { @@ -373,11 +374,17 @@ message AsPathLength { string operator = 2; } +message AsPathSet { + string as_path_set_name = 1; + repeated string as_path_members = 2; +} + message Conditions { PrefixSet match_prefix_set = 1; NeighborSet match_neighbor_set = 2; AsPathLength match_as_path_length = 3; - string match_set_options = 4; + AsPathSet match_as_path_set = 4; + string match_set_options = 5; } message Actions { diff --git a/gobgp/common.go b/gobgp/common.go index f50be075..1d47ea1e 100644 --- a/gobgp/common.go +++ b/gobgp/common.go @@ -45,6 +45,7 @@ const ( CMD_ENABLE = "enable" CMD_DISABLE = "disable" CMD_PREFIX = "prefix" + CMD_ASPATH = "aspath" CMD_ROUTEPOLICY = "routepolicy" CMD_CONDITIONS = "conditions" CMD_ACTIONS = "actions" @@ -63,6 +64,7 @@ var neighborsOpts struct { var conditionOpts struct { Prefix string `long:"prefix" description:"specifying a prefix set name of policy"` Neighbor string `long:"neighbor" description:"specifying a neighbor set name of policy"` + AsPath string `long:"aspath" description:"specifying an as set name of policy"` AsPathLength string `long:"aspath-len" description:"specifying an as path length of policy (<operator>,<numeric>)"` Option string `long:"option" description:"specifying an option of policy (any | all | invert)"` } @@ -197,6 +199,20 @@ func (n neighbors) Less(i, j int) bool { return n[i].NeighborSetName < n[j].NeighborSetName } +type aspaths []*api.AsPathSet + +func (a aspaths) Len() int { + return len(a) +} + +func (a aspaths) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} + +func (a aspaths) Less(i, j int) bool { + return a[i].AsPathSetName < a[j].AsPathSetName +} + type policyDefinitions []*api.PolicyDefinition func (p policyDefinitions) Len() int { diff --git a/gobgp/policy.go b/gobgp/policy.go index 86f9e691..1939a12d 100644 --- a/gobgp/policy.go +++ b/gobgp/policy.go @@ -27,6 +27,7 @@ import ( "sort" "strconv" "strings" + "regexp" ) func formatPolicyPrefix(prefixSetList []*api.PrefixSet) (string, string) { @@ -192,6 +193,8 @@ func modPolicy(resource api.Resource, op api.Operation, data interface{}) error co.MatchPrefixSet = data.(*api.PrefixSet) case api.Resource_POLICY_NEIGHBOR: co.MatchNeighborSet = data.(*api.NeighborSet) + case api.Resource_POLICY_ASPATH: + co.MatchAsPathSet = data.(*api.AsPathSet) } pd.StatementList = []*api.Statement{{Conditions: co}} } else { @@ -423,6 +426,156 @@ func modPolicyNeighbor(modtype string, eArgs []string) error { return nil } +func formatPolicyAsPath(asPathSetList []*api.AsPathSet) string { + maxNameLen := len("Name") + maxPathLen := len("AsPath") + for _, as := range asPathSetList { + if len(as.AsPathSetName) > maxNameLen { + maxNameLen = len(as.AsPathSetName) + } + for _, m := range as.AsPathMembers { + if len(m) > maxPathLen { + maxPathLen = len(m) + } + } + } + format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxPathLen) + "s\n" + return format +} + + +func showPolicyAsPaths() error { + arg := &api.PolicyArguments{ + Resource: api.Resource_POLICY_ASPATH, + } + stream, e := client.GetPolicyRoutePolicies(context.Background(), arg) + if e != nil { + return e + } + m := aspaths{} + for { + a, e := stream.Recv() + if e == io.EOF { + break + } else if e != nil { + return e + } + m = append(m, a.StatementList[0].Conditions.MatchAsPathSet) + } + if globalOpts.Json { + j, _ := json.Marshal(m) + fmt.Println(string(j)) + return nil + } + if globalOpts.Quiet { + for _, a := range m { + fmt.Println(a.AsPathSetName) + } + return nil + } + sort.Sort(m) + + format := formatPolicyAsPath(m) + fmt.Printf(format, "Name", "AsPath") + for _, as := range m { + for i, m := range as.AsPathMembers { + if i == 0 { + fmt.Printf(format, as.AsPathSetName, m) + } else { + fmt.Printf(format, "", m) + } + } + } + return nil +} + +func showPolicyAsPath(args []string) error { + arg := &api.PolicyArguments{ + Resource: api.Resource_POLICY_ASPATH, + Name: args[0], + } + pd, e := client.GetPolicyRoutePolicy(context.Background(), arg) + if e != nil { + return e + } + as := pd.StatementList[0].Conditions.MatchAsPathSet + if globalOpts.Json { + j, _ := json.Marshal(as) + fmt.Println(string(j)) + return nil + } + if globalOpts.Quiet { + for _, a := range as.AsPathMembers { + fmt.Println(a) + } + return nil + } + format := formatPolicyAsPath([]*api.AsPathSet{as}) + fmt.Printf(format, "Name", "AsPath") + for i, m := range as.AsPathMembers { + if i == 0 { + fmt.Printf(format, as.AsPathSetName, m) + } else { + fmt.Printf(format, "", m) + } + } + return nil +} + +func parseAsPathSet(eArgs []string) (*api.AsPathSet, error) { + regAsn, _ := regexp.Compile("^(\\^?)([0-9]+)(\\$?)$") + if !regAsn.MatchString(eArgs[1]) { + return nil, fmt.Errorf("invalid aspath: %s\nplease enter aspath format", eArgs[1]) + } + asPathSet := &api.AsPathSet{ + AsPathSetName: eArgs[0], + AsPathMembers: []string{eArgs[1]}, + } + return asPathSet, nil +} + +func modPolicyAsPath(modtype string, eArgs []string) error { + asPathSet := &api.AsPathSet{} + var e error + var operation api.Operation + + switch modtype { + case CMD_ADD: + if len(eArgs) < 2 { + return fmt.Errorf("usage: policy aspath add <aspath set name> <aspath>") + } + if asPathSet, e = parseAsPathSet(eArgs); e != nil { + return e + } + operation = api.Operation_ADD + case CMD_DEL: + if len(eArgs) == 0 { + return fmt.Errorf("usage: policy aspath del <aspath set name> [<aspath>]") + } else if len(eArgs) == 1 { + asPathSet = &api.AsPathSet{ + AsPathSetName: eArgs[0], + AsPathMembers: nil, + } + } else { + if asPathSet, e = parseAsPathSet(eArgs); e != nil { + return e + } + } + operation = api.Operation_DEL + case CMD_ALL: + if len(eArgs) > 0 { + return fmt.Errorf("Argument can not be entered: %s", eArgs[0:]) + } + operation = api.Operation_DEL_ALL + default: + return fmt.Errorf("invalid modType %s", modtype) + } + if e = modPolicy(api.Resource_POLICY_ASPATH, operation, asPathSet); e != nil { + return e + } + return nil +} + func showPolicyStatement(head string, pd *api.PolicyDefinition) { for _, st := range pd.StatementList { fmt.Printf("%s StatementName %s:\n", head, st.StatementNeme) @@ -457,6 +610,20 @@ func showPolicyStatement(head string, pd *api.PolicyDefinition) { } else { fmt.Print("\n") } + asPathSet := st.Conditions.MatchAsPathSet + fmt.Printf("%s AsPathSet: %s ", head, asPathSet.AsPathSetName) + if len(asPathSet.AsPathMembers) != 0 { + nameFormat := "%-" + fmt.Sprint(len(asPathSet.AsPathSetName)+2) + "s" + for i, asPath := range asPathSet.AsPathMembers { + if i != 0 { + fmt.Printf("%s ", head) + fmt.Printf(nameFormat, "") + } + fmt.Println(asPath) + } + } else { + fmt.Print("\n") + } asPathLentgh := st.Conditions.MatchAsPathLength fmt.Printf("%s AsPathLength: %s %s\n", head, asPathLentgh.Operator, asPathLentgh.Value) fmt.Printf("%s MatchOption: %s\n", head, st.Conditions.MatchSetOptions) @@ -545,6 +712,11 @@ func parseConditions() (*api.Conditions, error) { NeighborSetName: conditionOpts.Neighbor, } } + if conditionOpts.AsPath != "" { + conditions.MatchAsPathSet = &api.AsPathSet{ + AsPathSetName: conditionOpts.AsPath, + } + } if conditionOpts.AsPathLength != "" { asPathLen := conditionOpts.AsPathLength idx := strings.Index(asPathLen, ",") @@ -656,6 +828,7 @@ func NewPolicyAddCmd(v string, mod func(string, []string) error) *cobra.Command if v == CMD_ROUTEPOLICY { policyAddCmd.Flags().StringVarP(&conditionOpts.Prefix, "c-prefix", "", "", "a prefix set name of policy condition") policyAddCmd.Flags().StringVarP(&conditionOpts.Neighbor, "c-neighbor", "", "", "a neighbor set name of policy condition") + policyAddCmd.Flags().StringVarP(&conditionOpts.Neighbor, "c-aspath", "", "", "as set name of policy condition") policyAddCmd.Flags().StringVarP(&conditionOpts.AsPathLength, "c-aslen", "", "", "an as path length of policy condition (<operator>,<numeric>)") policyAddCmd.Flags().StringVarP(&conditionOpts.Option, "c-option", "", "", "an option of policy condition") policyAddCmd.Flags().StringVarP(&actionOpts.RouteAction, "a-route", "", "", "a route action of policy action (accept | reject)") @@ -693,7 +866,7 @@ func NewPolicyCmd() *cobra.Command { Use: CMD_POLICY, } - for _, v := range []string{CMD_PREFIX, CMD_NEIGHBOR, CMD_ROUTEPOLICY} { + for _, v := range []string{CMD_PREFIX, CMD_NEIGHBOR, CMD_ASPATH, CMD_ROUTEPOLICY} { var showAll func() error var showOne func([]string) error var mod func(string, []string) error @@ -706,6 +879,10 @@ func NewPolicyCmd() *cobra.Command { showAll = showPolicyNeighbors showOne = showPolicyNeighbor mod = modPolicyNeighbor + case CMD_ASPATH: + showAll = showPolicyAsPaths + showOne = showPolicyAsPath + mod = modPolicyAsPath case CMD_ROUTEPOLICY: showAll = showPolicyRoutePolicies showOne = showPolicyRoutePolicy diff --git a/policy/policy.go b/policy/policy.go index cff79aae..27dc3c53 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -986,6 +986,29 @@ func IndexOfNeighborSet(conNeighborSetList []config.NeighborSet, reqNeighborSet return idxNeighborSet, idxNeighbor } +// find index AsPathSet of request from AsPathSet of configuration file. +// Return the idxAsPathSet of the location where the name of AsPathSet matches, +// and idxAsPath of the location where element of AsPathSet matches +func IndexOfAsPathSet(conAsPathSetList []config.AsPathSet, reqAsPathSet config.AsPathSet) (int, int) { + idxAsPathSet := -1 + idxAsPath := -1 + for i, conAsPathSet := range conAsPathSetList { + if conAsPathSet.AsPathSetName == reqAsPathSet.AsPathSetName { + idxAsPathSet = i + if len(reqAsPathSet.AsPathSetMembers) == 0 { + return idxAsPathSet, idxAsPath + } + for j, conAsPath := range conAsPathSet.AsPathSetMembers { + if conAsPath == reqAsPathSet.AsPathSetMembers[0] { + idxAsPath = j + return idxAsPathSet, idxAsPath + } + } + } + } + return idxAsPathSet, idxAsPath +} + // find index PolicyDefinition of request from PolicyDefinition of configuration file. // Return the idxPolicyDefinition of the location where the name of PolicyDefinition matches, // and idxStatement of the location where Statement of PolicyDefinition matches @@ -1091,15 +1114,28 @@ func NeighborSetToConfigStruct(reqNeighborSet *api.NeighborSet) (bool, config.Ne return isReqNeighborSet, neighborSet } -func AsPathLengthToConfigStruct(reqAsPathLength *api.AsPathLength) config.AsPathLength { - operator := reqAsPathLength.Operator - value := reqAsPathLength.Value - valueUint, _ := strconv.ParseUint(value, 10, 32) - asPathLength := config.AsPathLength{ - Operator: operator, - Value: uint32(valueUint), +func AsPathSetToApiStruct(as config.AsPathSet) *api.AsPathSet { + resAsPathMembers := make([]string, 0) + for _, m := range as.AsPathSetMembers { + resAsPathMembers = append(resAsPathMembers, m) } - return asPathLength + resAsPathSet := &api.AsPathSet{ + AsPathSetName: as.AsPathSetName, + AsPathMembers: resAsPathMembers, + } + return resAsPathSet +} + +func AsPathSetToConfigStruct(reqAsPathSet *api.AsPathSet) (bool, config.AsPathSet) { + isAsPathSetSet := true + if len(reqAsPathSet.AsPathMembers) == 0 { + isAsPathSetSet = false + } + asPathSet := config.AsPathSet{ + AsPathSetName: reqAsPathSet.AsPathSetName, + AsPathSetMembers: reqAsPathSet.AsPathMembers, + } + return isAsPathSetSet, asPathSet } func AsPathLengthToApiStruct(asPathLength config.AsPathLength) *api.AsPathLength { @@ -1114,6 +1150,17 @@ func AsPathLengthToApiStruct(asPathLength config.AsPathLength) *api.AsPathLength return resAsPathLength } +func AsPathLengthToConfigStruct(reqAsPathLength *api.AsPathLength) config.AsPathLength { + operator := reqAsPathLength.Operator + value := reqAsPathLength.Value + valueUint, _ := strconv.ParseUint(value, 10, 32) + asPathLength := config.AsPathLength{ + Operator: operator, + Value: uint32(valueUint), + } + return asPathLength +} + func ConditionsToConfigStruct(reqConditions *api.Conditions) config.Conditions { conditions := config.Conditions{} if reqConditions.MatchPrefixSet != nil { @@ -1122,6 +1169,9 @@ func ConditionsToConfigStruct(reqConditions *api.Conditions) config.Conditions { if reqConditions.MatchNeighborSet != nil { conditions.MatchNeighborSet = reqConditions.MatchNeighborSet.NeighborSetName } + if reqConditions.MatchAsPathSet != nil { + conditions.BgpConditions.MatchAsPathSet = reqConditions.MatchAsPathSet.AsPathSetName + } if reqConditions.MatchAsPathLength != nil { conditions.BgpConditions.AsPathLength = AsPathLengthToConfigStruct(reqConditions.MatchAsPathLength) @@ -1180,6 +1230,7 @@ func PolicyDefinitionToConfigStruct(reqPolicy *api.PolicyDefinition) (bool, conf func PolicyDefinitionToApiStruct(pd config.PolicyDefinition, df config.DefinedSets) *api.PolicyDefinition { conPrefixSetList := df.PrefixSetList conNeighborSetList := df.NeighborSetList + conAsPathSetList := df.BgpDefinedSets.AsPathSetList resStatementList := make([]*api.Statement, 0) for _, st := range pd.StatementList { conditions := st.Conditions @@ -1191,20 +1242,29 @@ func PolicyDefinitionToApiStruct(pd config.PolicyDefinition, df config.DefinedSe neighborSet := &api.NeighborSet{ NeighborSetName: conditions.MatchNeighborSet, } + asPathSet := &api.AsPathSet{ + AsPathSetName: conditions.BgpConditions.MatchAsPathSet, + } + // consider later whether treatment of here need _, conPrefixSet := PrefixSetToConfigStruct(prefixSet) _, conNeighborSet := NeighborSetToConfigStruct(neighborSet) + _, conAsPathSet := AsPathSetToConfigStruct(asPathSet) idxPrefixSet, _ := IndexOfPrefixSet(conPrefixSetList, conPrefixSet) idxNeighborSet, _ := IndexOfNeighborSet(conNeighborSetList, conNeighborSet) - + idxAsPathSet, _ := IndexOfAsPathSet(conAsPathSetList, conAsPathSet) if idxPrefixSet != -1 { prefixSet = PrefixSetToApiStruct(conPrefixSetList[idxPrefixSet]) } if idxNeighborSet != -1 { neighborSet = NeighborSetToApiStruct(conNeighborSetList[idxNeighborSet]) } + if idxAsPathSet != -1 { + asPathSet = AsPathSetToApiStruct(conAsPathSetList[idxAsPathSet]) + } resConditions := &api.Conditions{ MatchPrefixSet: prefixSet, MatchNeighborSet: neighborSet, + MatchAsPathSet: asPathSet, MatchAsPathLength: AsPathLengthToApiStruct(st.Conditions.BgpConditions.AsPathLength), MatchSetOptions: MatchSetOptionToString(conditions.MatchSetOptions), } diff --git a/server/grpc_server.go b/server/grpc_server.go index 618344fd..8f2ca497 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -58,6 +58,11 @@ const ( REQ_POLICY_NEIGHBOR_ADD REQ_POLICY_NEIGHBOR_DELETE REQ_POLICY_NEIGHBORS_DELETE + REQ_POLICY_ASPATH + REQ_POLICY_ASPATHS + REQ_POLICY_ASPATH_ADD + REQ_POLICY_ASPATH_DELETE + REQ_POLICY_ASPATHS_DELETE REQ_POLICY_ROUTEPOLICIES REQ_POLICY_ROUTEPOLICY REQ_POLICY_ROUTEPOLICY_ADD @@ -373,6 +378,17 @@ func (s *Server) modPolicy(arg *api.PolicyArguments, stream interface{}) error { default: return fmt.Errorf("unsupported operation: %s", arg.Operation) } + case api.Resource_POLICY_ASPATH: + switch arg.Operation { + case api.Operation_ADD: + reqType = REQ_POLICY_ASPATH_ADD + case api.Operation_DEL: + reqType = REQ_POLICY_ASPATH_DELETE + case api.Operation_DEL_ALL: + reqType = REQ_POLICY_ASPATHS_DELETE + default: + return fmt.Errorf("unsupported operation: %s", arg.Operation) + } case api.Resource_POLICY_ROUTEPOLICY: switch arg.Operation { case api.Operation_ADD: @@ -410,6 +426,8 @@ func (s *Server) GetPolicyRoutePolicies(arg *api.PolicyArguments, stream api.Grp reqType = REQ_POLICY_PREFIXES case api.Resource_POLICY_NEIGHBOR: reqType = REQ_POLICY_NEIGHBORS + case api.Resource_POLICY_ASPATH: + reqType = REQ_POLICY_ASPATHS case api.Resource_POLICY_ROUTEPOLICY: reqType = REQ_POLICY_ROUTEPOLICIES default: @@ -437,6 +455,8 @@ func (s *Server) GetPolicyRoutePolicy(ctx context.Context, arg *api.PolicyArgume reqType = REQ_POLICY_PREFIX case api.Resource_POLICY_NEIGHBOR: reqType = REQ_POLICY_NEIGHBOR + case api.Resource_POLICY_ASPATH: + reqType = REQ_POLICY_ASPATH case api.Resource_POLICY_ROUTEPOLICY: reqType = REQ_POLICY_ROUTEPOLICY default: diff --git a/server/server.go b/server/server.go index 3ff104d5..78cd5c8f 100644 --- a/server/server.go +++ b/server/server.go @@ -1048,15 +1048,15 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { grpcReq.ResponseCh <- &GrpcResponse{} close(grpcReq.ResponseCh) - case REQ_POLICY_PREFIXES, REQ_POLICY_NEIGHBORS, REQ_POLICY_ROUTEPOLICIES: + case REQ_POLICY_PREFIXES, REQ_POLICY_NEIGHBORS, REQ_POLICY_ASPATHS, REQ_POLICY_ROUTEPOLICIES: server.handleGrpcShowPolicies(grpcReq) - case REQ_POLICY_PREFIX, REQ_POLICY_NEIGHBOR, REQ_POLICY_ROUTEPOLICY: + case REQ_POLICY_PREFIX, REQ_POLICY_NEIGHBOR, REQ_POLICY_ASPATH, REQ_POLICY_ROUTEPOLICY: server.handleGrpcShowPolicy(grpcReq) - case REQ_POLICY_PREFIX_ADD, REQ_POLICY_NEIGHBOR_ADD, REQ_POLICY_ROUTEPOLICY_ADD: + case REQ_POLICY_PREFIX_ADD, REQ_POLICY_NEIGHBOR_ADD, REQ_POLICY_ASPATH_ADD, REQ_POLICY_ROUTEPOLICY_ADD: server.handleGrpcAddPolicy(grpcReq) - case REQ_POLICY_PREFIX_DELETE, REQ_POLICY_NEIGHBOR_DELETE, REQ_POLICY_ROUTEPOLICY_DELETE: + case REQ_POLICY_PREFIX_DELETE, REQ_POLICY_NEIGHBOR_DELETE, REQ_POLICY_ASPATH_DELETE, REQ_POLICY_ROUTEPOLICY_DELETE: server.handleGrpcDelPolicy(grpcReq) - case REQ_POLICY_PREFIXES_DELETE, REQ_POLICY_NEIGHBORS_DELETE, REQ_POLICY_ROUTEPOLICIES_DELETE: + case REQ_POLICY_PREFIXES_DELETE, REQ_POLICY_NEIGHBORS_DELETE, REQ_POLICY_ASPATHS_DELETE, REQ_POLICY_ROUTEPOLICIES_DELETE: server.handleGrpcDelPolicies(grpcReq) default: errmsg := "Unknown request type" @@ -1104,6 +1104,22 @@ func (server *BgpServer) handleGrpcShowPolicies(grpcReq *GrpcRequest) { result.ResponseErr = fmt.Errorf("Policy neighbor doesn't exist.") grpcReq.ResponseCh <- result } + case REQ_POLICY_ASPATHS: + info := server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList + if len(info) > 0 { + for _, as := range info { + resAsPathSet := policy.AsPathSetToApiStruct(as) + pd := &api.PolicyDefinition{} + pd.StatementList = []*api.Statement{{Conditions: &api.Conditions{MatchAsPathSet: resAsPathSet}}} + result = &GrpcResponse{ + Data: pd, + } + grpcReq.ResponseCh <- result + } + } else { + result.ResponseErr = fmt.Errorf("Policy aspath doesn't exist.") + grpcReq.ResponseCh <- result + } case REQ_POLICY_ROUTEPOLICIES: info := server.routingPolicy.PolicyDefinitionList df := server.routingPolicy.DefinedSets @@ -1163,6 +1179,24 @@ func (server *BgpServer) handleGrpcShowPolicy(grpcReq *GrpcRequest) { } else { result.ResponseErr = fmt.Errorf("policy neighbor that has %v doesn't exist.", name) } + case REQ_POLICY_ASPATH: + info := server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList + resAsPathSet := &api.AsPathSet{} + for _, as := range info { + if as.AsPathSetName == name { + resAsPathSet = policy.AsPathSetToApiStruct(as) + break + } + } + if len(resAsPathSet.AsPathMembers) > 0 { + pd := &api.PolicyDefinition{} + pd.StatementList = []*api.Statement{{Conditions: &api.Conditions{MatchAsPathSet: resAsPathSet}}} + result = &GrpcResponse{ + Data: pd, + } + } else { + result.ResponseErr = fmt.Errorf("policy aspath that has %v doesn't exist.", name) + } case REQ_POLICY_ROUTEPOLICY: log.Error("IN RoutePolicy") info := server.routingPolicy.PolicyDefinitionList @@ -1232,6 +1266,27 @@ func (server *BgpServer) handleGrpcAddPolicy(grpcReq *GrpcRequest) { } } server.routingPolicy.DefinedSets.NeighborSetList = conNeighborSetList + case REQ_POLICY_ASPATH_ADD: + reqAsPathSet := grpcReq.Data.(*api.PolicyDefinition).StatementList[0].Conditions.MatchAsPathSet + conAsPathSetList := server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList + isReqAsPathSet, asPathSet := policy.AsPathSetToConfigStruct(reqAsPathSet) + if !isReqAsPathSet { + result.ResponseErr = fmt.Errorf("doesn't reqest of policy aspath.") + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) + } + // If the same NeighborSet is not set, add NeighborSet of request to the end. + // If only name of the NeighborSet is same, overwrite with NeighborSet of request + idxAsPathSet, idxAsPath := policy.IndexOfAsPathSet(conAsPathSetList, asPathSet) + if idxAsPathSet == -1 { + conAsPathSetList = append(conAsPathSetList, asPathSet) + } else { + if idxAsPath == -1 { + conAsPathSetList[idxAsPathSet].AsPathSetMembers = + append(conAsPathSetList[idxAsPathSet].AsPathSetMembers, asPathSet.AsPathSetMembers[0]) + } + } + server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList = conAsPathSetList case REQ_POLICY_ROUTEPOLICY_ADD: reqPolicy := grpcReq.Data.(*api.PolicyDefinition) reqConditions := reqPolicy.StatementList[0].Conditions @@ -1258,6 +1313,9 @@ func (server *BgpServer) handleGrpcAddPolicy(grpcReq *GrpcRequest) { if reqConditions.MatchSetOptions != "" { conStatement.Conditions.MatchSetOptions = statement.Conditions.MatchSetOptions } + if reqConditions.MatchAsPathSet != nil { + conStatement.Conditions.BgpConditions.MatchAsPathSet = statement.Conditions.BgpConditions.MatchAsPathSet + } if reqConditions.MatchAsPathLength != nil { conStatement.Conditions.BgpConditions.AsPathLength = statement.Conditions.BgpConditions.AsPathLength } @@ -1353,6 +1411,36 @@ func (server *BgpServer) handleGrpcDelPolicy(grpcReq *GrpcRequest) { } } server.routingPolicy.DefinedSets.NeighborSetList = conNeighborSetList + case REQ_POLICY_ASPATH_DELETE: + reqAsPathSet := grpcReq.Data.(*api.PolicyDefinition).StatementList[0].Conditions.MatchAsPathSet + conAsPathSetList := server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList + result := &GrpcResponse{} + isReqAsPathSet, asPathSet := policy.AsPathSetToConfigStruct(reqAsPathSet) + // If only name of the NeighborSet is same, delete all of the elements of the NeighborSet. + // If the same element NeighborSet, delete the it's element from NeighborSet. + idxAsPathSet, idxAsPath := policy.IndexOfAsPathSet(conAsPathSetList, asPathSet) + if isReqAsPathSet { + if idxAsPathSet == -1 { + result.ResponseErr = fmt.Errorf("Policy aspath that has %v %v doesn't exist.", asPathSet.AsPathSetName, + asPathSet.AsPathSetMembers[0]) + } else { + if idxAsPath == -1 { + result.ResponseErr = fmt.Errorf("Policy aspath that has %v %v doesn't exist.", asPathSet.AsPathSetName, + asPathSet.AsPathSetMembers[0]) + } else { + conAsPathSetList[idxAsPathSet].AsPathSetMembers = + append(conAsPathSetList[idxAsPathSet].AsPathSetMembers[:idxAsPath], + conAsPathSetList[idxAsPathSet].AsPathSetMembers[idxAsPath+1:]...) + } + } + } else { + if idxAsPathSet == -1 { + result.ResponseErr = fmt.Errorf("Policy aspath %v doesn't exist.", asPathSet.AsPathSetName) + } else { + conAsPathSetList = append(conAsPathSetList[:idxAsPathSet], conAsPathSetList[idxAsPathSet+1:]...) + } + } + server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList = conAsPathSetList case REQ_POLICY_ROUTEPOLICY_DELETE: reqPolicy := grpcReq.Data.(*api.PolicyDefinition) conPolicyList := server.routingPolicy.PolicyDefinitionList @@ -1398,6 +1486,8 @@ func (server *BgpServer) handleGrpcDelPolicies(grpcReq *GrpcRequest) { server.routingPolicy.DefinedSets.PrefixSetList = make([]config.PrefixSet, 0) case REQ_POLICY_NEIGHBORS_DELETE: server.routingPolicy.DefinedSets.NeighborSetList = make([]config.NeighborSet, 0) + case REQ_POLICY_ASPATHS_DELETE: + server.routingPolicy.DefinedSets.BgpDefinedSets.AsPathSetList = make([]config.AsPathSet, 0) case REQ_POLICY_ROUTEPOLICIES_DELETE: server.routingPolicy.PolicyDefinitionList = make([]config.PolicyDefinition, 0) } |