diff options
-rw-r--r-- | api/gobgp.pb.go | 225 | ||||
-rw-r--r-- | api/gobgp.proto | 29 | ||||
-rw-r--r-- | gobgp/main.go | 291 | ||||
-rw-r--r-- | server/grpc_server.go | 21 | ||||
-rw-r--r-- | server/server.go | 161 |
5 files changed, 629 insertions, 98 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index 809e8d50..8a54a2c7 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -35,6 +35,11 @@ It has these top-level messages: PrefixSet Neighbor NeighborSet + Conditions + Actions + Statement + PolicyDefinition + RoutingPolicy */ package api @@ -55,12 +60,13 @@ var _ = proto.Marshal type Resource int32 const ( - Resource_GLOBAL Resource = 0 - Resource_LOCAL Resource = 1 - Resource_ADJ_IN Resource = 2 - Resource_ADJ_OUT Resource = 3 - Resource_POLICY_PREFIX Resource = 4 - Resource_POLICY_NEIGHBOR Resource = 5 + Resource_GLOBAL Resource = 0 + Resource_LOCAL Resource = 1 + Resource_ADJ_IN Resource = 2 + Resource_ADJ_OUT Resource = 3 + Resource_POLICY_PREFIX Resource = 4 + Resource_POLICY_NEIGHBOR Resource = 5 + Resource_POLICY_ROUTEPOLICY Resource = 6 ) var Resource_name = map[int32]string{ @@ -70,14 +76,16 @@ var Resource_name = map[int32]string{ 3: "ADJ_OUT", 4: "POLICY_PREFIX", 5: "POLICY_NEIGHBOR", + 6: "POLICY_ROUTEPOLICY", } var Resource_value = map[string]int32{ - "GLOBAL": 0, - "LOCAL": 1, - "ADJ_IN": 2, - "ADJ_OUT": 3, - "POLICY_PREFIX": 4, - "POLICY_NEIGHBOR": 5, + "GLOBAL": 0, + "LOCAL": 1, + "ADJ_IN": 2, + "ADJ_OUT": 3, + "POLICY_PREFIX": 4, + "POLICY_NEIGHBOR": 5, + "POLICY_ROUTEPOLICY": 6, } func (x Resource) String() string { @@ -511,11 +519,12 @@ func (m *ModPathArguments) GetPath() *Path { } type PolicyArguments struct { - Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"` - Operation Operation `protobuf:"varint,2,opt,name=operation,enum=api.Operation" json:"operation,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` - PrefixSet *PrefixSet `protobuf:"bytes,4,opt,name=prefix_set" json:"prefix_set,omitempty"` - NeighborSet *NeighborSet `protobuf:"bytes,5,opt,name=neighbor_set" json:"neighbor_set,omitempty"` + Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"` + Operation Operation `protobuf:"varint,2,opt,name=operation,enum=api.Operation" json:"operation,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` + PrefixSet *PrefixSet `protobuf:"bytes,4,opt,name=prefix_set" json:"prefix_set,omitempty"` + NeighborSet *NeighborSet `protobuf:"bytes,5,opt,name=neighbor_set" json:"neighbor_set,omitempty"` + PolicyDifinition *PolicyDefinition `protobuf:"bytes,6,opt,name=policy_difinition" json:"policy_difinition,omitempty"` } func (m *PolicyArguments) Reset() { *m = PolicyArguments{} } @@ -536,6 +545,13 @@ func (m *PolicyArguments) GetNeighborSet() *NeighborSet { return nil } +func (m *PolicyArguments) GetPolicyDifinition() *PolicyDefinition { + if m != nil { + return m.PolicyDifinition + } + return nil +} + type AddressFamily struct { Afi AFI `protobuf:"varint,1,opt,enum=api.AFI" json:"Afi,omitempty"` Safi SAFI `protobuf:"varint,2,opt,enum=api.SAFI" json:"Safi,omitempty"` @@ -958,6 +974,94 @@ func (m *NeighborSet) GetNeighborList() []*Neighbor { return nil } +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"` + MatchSetOptions int64 `protobuf:"varint,3,opt,name=match_set_options" json:"match_set_options,omitempty"` +} + +func (m *Conditions) Reset() { *m = Conditions{} } +func (m *Conditions) String() string { return proto.CompactTextString(m) } +func (*Conditions) ProtoMessage() {} + +func (m *Conditions) GetMatchPrefixSet() *PrefixSet { + if m != nil { + return m.MatchPrefixSet + } + return nil +} + +func (m *Conditions) GetMatchNeighborSet() *NeighborSet { + if m != nil { + return m.MatchNeighborSet + } + return nil +} + +type Actions struct { + AcceptRoute bool `protobuf:"varint,1,opt,name=accept_route" json:"accept_route,omitempty"` + RejectRoute bool `protobuf:"varint,2,opt,name=reject_route" json:"reject_route,omitempty"` +} + +func (m *Actions) Reset() { *m = Actions{} } +func (m *Actions) String() string { return proto.CompactTextString(m) } +func (*Actions) ProtoMessage() {} + +type Statement struct { + StatementNeme string `protobuf:"bytes,1,opt,name=statement_neme" json:"statement_neme,omitempty"` + Conditions *Conditions `protobuf:"bytes,2,opt,name=conditions" json:"conditions,omitempty"` + Actions *Actions `protobuf:"bytes,3,opt,name=actions" json:"actions,omitempty"` +} + +func (m *Statement) Reset() { *m = Statement{} } +func (m *Statement) String() string { return proto.CompactTextString(m) } +func (*Statement) ProtoMessage() {} + +func (m *Statement) GetConditions() *Conditions { + if m != nil { + return m.Conditions + } + return nil +} + +func (m *Statement) GetActions() *Actions { + if m != nil { + return m.Actions + } + return nil +} + +type PolicyDefinition struct { + PolicyDefinitionName string `protobuf:"bytes,1,opt,name=policy_definition_name" json:"policy_definition_name,omitempty"` + StatementList []*Statement `protobuf:"bytes,2,rep,name=statement_list" json:"statement_list,omitempty"` +} + +func (m *PolicyDefinition) Reset() { *m = PolicyDefinition{} } +func (m *PolicyDefinition) String() string { return proto.CompactTextString(m) } +func (*PolicyDefinition) ProtoMessage() {} + +func (m *PolicyDefinition) GetStatementList() []*Statement { + if m != nil { + return m.StatementList + } + return nil +} + +type RoutingPolicy struct { + PolicyDifinition []*PolicyDefinition `protobuf:"bytes,1,rep,name=policy_difinition" json:"policy_difinition,omitempty"` +} + +func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} } +func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) } +func (*RoutingPolicy) ProtoMessage() {} + +func (m *RoutingPolicy) GetPolicyDifinition() []*PolicyDefinition { + if m != nil { + return m.PolicyDifinition + } + return nil +} + func init() { proto.RegisterEnum("api.Resource", Resource_name, Resource_value) proto.RegisterEnum("api.Operation", Operation_name, Operation_value) @@ -994,6 +1098,8 @@ type GrpcClient interface { ModPolicyPrefix(ctx context.Context, opts ...grpc.CallOption) (Grpc_ModPolicyPrefixClient, error) GetPolicyNeighbors(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (Grpc_GetPolicyNeighborsClient, error) GetPolicyNeighbor(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (*NeighborSet, error) + GetPolicyRoutePolicies(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (Grpc_GetPolicyRoutePoliciesClient, error) + GetPolicyRoutePolicy(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (*PolicyDefinition, error) } type grpcClient struct { @@ -1316,6 +1422,47 @@ func (c *grpcClient) GetPolicyNeighbor(ctx context.Context, in *PolicyArguments, return out, nil } +func (c *grpcClient) GetPolicyRoutePolicies(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (Grpc_GetPolicyRoutePoliciesClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[7], c.cc, "/api.Grpc/GetPolicyRoutePolicies", opts...) + if err != nil { + return nil, err + } + x := &grpcGetPolicyRoutePoliciesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Grpc_GetPolicyRoutePoliciesClient interface { + Recv() (*PolicyDefinition, error) + grpc.ClientStream +} + +type grpcGetPolicyRoutePoliciesClient struct { + grpc.ClientStream +} + +func (x *grpcGetPolicyRoutePoliciesClient) Recv() (*PolicyDefinition, error) { + m := new(PolicyDefinition) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *grpcClient) GetPolicyRoutePolicy(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (*PolicyDefinition, error) { + out := new(PolicyDefinition) + err := grpc.Invoke(ctx, "/api.Grpc/GetPolicyRoutePolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Grpc service type GrpcServer interface { @@ -1336,6 +1483,8 @@ type GrpcServer interface { ModPolicyPrefix(Grpc_ModPolicyPrefixServer) error GetPolicyNeighbors(*PolicyArguments, Grpc_GetPolicyNeighborsServer) error GetPolicyNeighbor(context.Context, *PolicyArguments) (*NeighborSet, error) + GetPolicyRoutePolicies(*PolicyArguments, Grpc_GetPolicyRoutePoliciesServer) error + GetPolicyRoutePolicy(context.Context, *PolicyArguments) (*PolicyDefinition, error) } func RegisterGrpcServer(s *grpc.Server, srv GrpcServer) { @@ -1619,6 +1768,39 @@ func _Grpc_GetPolicyNeighbor_Handler(srv interface{}, ctx context.Context, codec return out, nil } +func _Grpc_GetPolicyRoutePolicies_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PolicyArguments) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GrpcServer).GetPolicyRoutePolicies(m, &grpcGetPolicyRoutePoliciesServer{stream}) +} + +type Grpc_GetPolicyRoutePoliciesServer interface { + Send(*PolicyDefinition) error + grpc.ServerStream +} + +type grpcGetPolicyRoutePoliciesServer struct { + grpc.ServerStream +} + +func (x *grpcGetPolicyRoutePoliciesServer) Send(m *PolicyDefinition) error { + return x.ServerStream.SendMsg(m) +} + +func _Grpc_GetPolicyRoutePolicy_Handler(srv interface{}, ctx context.Context, codec grpc.Codec, buf []byte) (interface{}, error) { + in := new(PolicyArguments) + if err := codec.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).GetPolicyRoutePolicy(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + var _Grpc_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Grpc", HandlerType: (*GrpcServer)(nil), @@ -1663,6 +1845,10 @@ var _Grpc_serviceDesc = grpc.ServiceDesc{ MethodName: "GetPolicyNeighbor", Handler: _Grpc_GetPolicyNeighbor_Handler, }, + { + MethodName: "GetPolicyRoutePolicy", + Handler: _Grpc_GetPolicyRoutePolicy_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -1702,5 +1888,10 @@ var _Grpc_serviceDesc = grpc.ServiceDesc{ Handler: _Grpc_GetPolicyNeighbors_Handler, ServerStreams: true, }, + { + StreamName: "GetPolicyRoutePolicies", + Handler: _Grpc_GetPolicyRoutePolicies_Handler, + ServerStreams: true, + }, }, } diff --git a/api/gobgp.proto b/api/gobgp.proto index 7ee47965..98a72228 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -37,6 +37,8 @@ service Grpc { rpc ModPolicyPrefix(stream PolicyArguments) returns (stream Error) {} rpc GetPolicyNeighbors(PolicyArguments) returns (stream NeighborSet) {} rpc GetPolicyNeighbor(PolicyArguments) returns (NeighborSet) {} + rpc GetPolicyRoutePolicies(PolicyArguments) returns (stream PolicyDefinition) {} + rpc GetPolicyRoutePolicy(PolicyArguments) returns (PolicyDefinition) {} } message Error { @@ -65,6 +67,7 @@ message PolicyArguments { string name = 3; PrefixSet prefix_set = 4; NeighborSet neighbor_set = 5; + PolicyDefinition policy_difinition = 6; } enum Resource { @@ -74,6 +77,7 @@ enum Resource { ADJ_OUT = 3; POLICY_PREFIX = 4; POLICY_NEIGHBOR = 5; + POLICY_ROUTEPOLICY = 6; } enum Operation { @@ -361,3 +365,28 @@ message NeighborSet { repeated Neighbor neighbor_list = 2; } +message Conditions { + PrefixSet match_prefix_set = 1; + NeighborSet match_neighbor_set = 2; + int64 match_set_options = 3; +} + +message Actions { + bool accept_route = 1; + bool reject_route = 2; +} + +message Statement { + string statement_neme = 1; + Conditions conditions = 2; + Actions actions = 3; +} + +message PolicyDefinition{ + string policy_definition_name = 1; + repeated Statement statement_list = 2; +} + +message RoutingPolicy { + repeated PolicyDefinition policy_difinition = 1; +} diff --git a/gobgp/main.go b/gobgp/main.go index 434cd68f..9a89e4db 100644 --- a/gobgp/main.go +++ b/gobgp/main.go @@ -39,6 +39,7 @@ const ( CMD_RIB = "rib" CMD_ADD = "add" CMD_DEL = "del" + CMD_ALL = "all" CMD_LOCAL = "local" CMD_ADJ_IN = "adj-in" CMD_ADJ_OUT = "adj-out" @@ -50,7 +51,7 @@ const ( CMD_ENABLE = "enable" CMD_DISABLE = "disable" CMD_PREFIX = "prefix" - CMD_ALL = "all" + CMD_ROUTEPOLICY = "routepolicy" ) func formatTimedelta(d int64) string { @@ -165,6 +166,20 @@ func (n neighbors) Less(i, j int) bool { return n[i].NeighborSetName < n[j].NeighborSetName } +type policyDefinitions []*api.PolicyDefinition + +func (p policyDefinitions) Len() int { + return len(p) +} + +func (p policyDefinitions) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func (p policyDefinitions) Less(i, j int) bool { + return p[i].PolicyDefinitionName < p[j].PolicyDefinitionName +} + func connGrpc() *grpc.ClientConn { timeout := grpc.WithTimeout(time.Second) @@ -237,6 +252,12 @@ func requestGrpc(cmd string, eArgs []string, remoteIP net.IP) error { } else { return showPolicyNeighbor(eArgs) } + case CMD_POLICY + "_" + CMD_ROUTEPOLICY: + if len(eArgs) == 0 { + return showPolicyRoutePolicies() + } else { + return showPolicyRoutePolicy(eArgs) + } } return nil } @@ -1112,6 +1133,7 @@ func (x *PolicyCommand) Execute(args []string) error { parser.Usage = "policy" parser.AddCommand(CMD_PREFIX, "subcommand for prefix of policy", "", &PolicyPrefixCommand{}) parser.AddCommand(CMD_NEIGHBOR, "subcommand for prefix of neighbor", "", &PolicyNeighborCommand{}) + parser.AddCommand(CMD_ROUTEPOLICY, "subcommand for prefix of routepolicy", "", &PolicyRoutePolicyCommand{}) if _, err := parser.ParseArgs(eArgs); err != nil { os.Exit(1) } @@ -1120,6 +1142,27 @@ func (x *PolicyCommand) Execute(args []string) error { type PolicyPrefixCommand struct{} +func formatPolicyPrefix(prefixSetList []*api.PrefixSet) string { + maxNameLen := len("Name") + maxPrefixLen := len("Prefix") + maxRangeLen := len("MaskRange") + for _, ps := range prefixSetList { + if len(ps.PrefixSetName) > maxNameLen { + maxNameLen = len(ps.PrefixSetName) + } + for _, p := range ps.PrefixList { + if len(p.Address)+len(fmt.Sprint(p.MaskLength))+1 > maxPrefixLen { + maxPrefixLen = len(p.Address) + len(fmt.Sprint(p.MaskLength)) + 1 + } + if len(p.MaskLengthRange) > maxRangeLen { + maxRangeLen = len(p.MaskLengthRange) + } + } + } + format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxPrefixLen) + "s %-" + fmt.Sprint(maxRangeLen) + "s\n" + return format +} + func showPolicyPrefixes() error { arg := &api.PolicyArguments{ Resource: api.Resource_POLICY_PREFIX, @@ -1152,27 +1195,9 @@ func showPolicyPrefixes() error { } return nil } - maxnamelen := len("Name") - maxprefixlen := len("Prefix") - maxrangelen := len("MaskRange") - sort.Sort(m) - for _, ps := range m { - if len(ps.PrefixSetName) > maxnamelen { - maxnamelen = len(ps.PrefixSetName) - } - for _, p := range ps.PrefixList { - if len(p.Address)+len(fmt.Sprint(p.MaskLength)) > maxprefixlen { - maxprefixlen = len(p.Address) + len(fmt.Sprint(p.MaskLength)) - } - if len(p.MaskLengthRange) > maxrangelen { - maxrangelen = len(p.MaskLengthRange) - } - } - } - var format string - format = "%" + fmt.Sprint(maxnamelen) + "s %-" + fmt.Sprint(maxprefixlen) + "s %-" + fmt.Sprint(maxrangelen) + "s\n" + format := formatPolicyPrefix(m) fmt.Printf(format, "Name", "Prefix", "MaskRange") for _, ps := range m { for i, p := range ps.PrefixList { @@ -1203,24 +1228,15 @@ func showPolicyPrefix(args []string) error { return nil } - maxprefixlen := len("Prefix") - maxrangelen := len("MaskRange") - - for _, p := range ps.PrefixList { - if len(p.Address)+len(fmt.Sprint(p.MaskLength)) > maxprefixlen { - maxprefixlen = len(p.Address) + len(fmt.Sprint(p.MaskLength)) - } - if len(p.MaskLengthRange) > maxrangelen { - maxrangelen = len(p.MaskLengthRange) - } - } - var format string - format = "%-" + fmt.Sprint(maxprefixlen) + "s %-" + fmt.Sprint(maxrangelen) + "s\n" - fmt.Printf(format, "Prefix", "MaskRange") - - for _, p := range ps.PrefixList { + format := formatPolicyPrefix([]*api.PrefixSet{ps}) + fmt.Printf(format, "Name", "Prefix", "MaskRange") + for i, p := range ps.PrefixList { prefix := fmt.Sprintf("%s/%d", p.Address, p.MaskLength) - fmt.Printf(format, prefix, p.MaskLengthRange) + if i == 0 { + fmt.Printf(format, ps.PrefixSetName, prefix, p.MaskLengthRange) + } else { + fmt.Printf(format, "", prefix, p.MaskLengthRange) + } } return nil } @@ -1410,6 +1426,23 @@ func (x *PolicyPrefixDelAllCommand) Execute(args []string) error { type PolicyNeighborCommand struct{} +func formatPolicyNeighbor(neighborSetList []*api.NeighborSet) string { + maxNameLen := len("Name") + maxAddressLen := len("Address") + for _, ns := range neighborSetList { + if len(ns.NeighborSetName) > maxNameLen { + maxNameLen = len(ns.NeighborSetName) + } + for _, n := range ns.NeighborList { + if len(n.Address) > maxAddressLen { + maxAddressLen = len(n.Address) + } + } + } + format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxAddressLen) + "s\n" + return format +} + func showPolicyNeighbors() error { arg := &api.PolicyArguments{ Resource: api.Resource_POLICY_NEIGHBOR, @@ -1442,23 +1475,9 @@ func showPolicyNeighbors() error { } return nil } - maxnamelen := len("Name") - maxaddresslen := len("Address") - sort.Sort(m) - for _, ns := range m { - if len(ns.NeighborSetName) > maxnamelen { - maxnamelen = len(ns.NeighborSetName) - } - for _, n := range ns.NeighborList { - if len(n.Address) > maxaddresslen { - maxaddresslen = len(n.Address) - } - } - } - var format string - format = "%" + fmt.Sprint(maxnamelen) + "s %-" + fmt.Sprint(maxaddresslen) + "s\n" + format := formatPolicyNeighbor(m) fmt.Printf(format, "Name", "Address") for _, ns := range m { for i, n := range ns.NeighborList { @@ -1488,20 +1507,16 @@ func showPolicyNeighbor(args []string) error { return nil } - maxaddresslen := len("Address") + format := formatPolicyNeighbor([]*api.NeighborSet{ns}) + fmt.Printf(format, "Name", "Address") + for i, n := range ns.NeighborList { + if i == 0 { + fmt.Printf(format, ns.NeighborSetName, n.Address) + } else { + fmt.Printf(format, "", n.Address) - for _, n := range ns.NeighborList { - if len(n.Address) > maxaddresslen { - maxaddresslen = len(n.Address) } } - var format string - format = "%-" + fmt.Sprint(maxaddresslen) + "s\n" - fmt.Printf(format, "Address") - - for _, n := range ns.NeighborList { - fmt.Printf(format, n.Address) - } return nil } @@ -1520,8 +1535,148 @@ func (x *PolicyNeighborCommand) Execute(args []string) error { } parser := flags.NewParser(nil, flags.Default) parser.Usage = "policy neighbor [OPTIONS]\n gobgp policy neighbor" - //parser.AddCommand(CMD_ADD, "subcommand for add route to policy neighbor", "", &PolicyNeighborAddCommand{}) - //parser.AddCommand(CMD_DEL, "subcommand for delete route from policy neighbor", "", &PolicyNeighborDelCommand{}) + //parser.AddCommand(CMD_ADD, "subcommand for add policy of neighbor", "", &PolicyNeighborAddCommand{}) + //parser.AddCommand(CMD_DEL, "subcommand for delete policy of neighbor", "", &PolicyNeighborDelCommand{}) + parser.ParseArgs(eArgs) + return nil +} + +type PolicyRoutePolicyCommand struct{} + +func showPolicyStatement(pd *api.PolicyDefinition) { + for _, st := range pd.StatementList { + fmt.Printf(" StatementName %s:\n", st.StatementNeme) + fmt.Println(" Conditions:") + prefixSet := st.Conditions.MatchPrefixSet + fmt.Print(" PrefixSet: ") + if len(prefixSet.PrefixList) != 0 { + format := formatPolicyPrefix([]*api.PrefixSet{st.Conditions.MatchPrefixSet}) + for i, prefix := range prefixSet.PrefixList { + p := fmt.Sprintf("%s/%d", prefix.Address, prefix.MaskLength) + if i == 0 { + fmt.Printf(format, prefixSet.PrefixSetName, p, prefix.MaskLengthRange) + } else { + fmt.Print(" ") + fmt.Printf(format, "", p, prefix.MaskLengthRange) + } + + } + } else { + fmt.Print("\n") + } + neighborSet := st.Conditions.MatchNeighborSet + fmt.Print(" NeighborSet: ") + if len(neighborSet.NeighborList) != 0 { + format := formatPolicyNeighbor([]*api.NeighborSet{st.Conditions.MatchNeighborSet}) + for i, neighbor := range neighborSet.NeighborList { + if i == 0 { + fmt.Printf(format, neighborSet.NeighborSetName, neighbor.Address) + } else { + fmt.Print(" ") + fmt.Printf(format, "", neighbor.Address) + } + + } + } else { + fmt.Print("\n") + } + var option string + switch st.Conditions.MatchSetOptions { + case 0: + option = "ANY" + case 1: + option = "ALL" + case 2: + option = "INVERT" + } + fmt.Printf(" MatchOption: %s\n", option) + fmt.Println(" Actions:") + action := "REJECT" + if st.Actions.AcceptRoute { + action = "ACCEPT" + } + fmt.Printf(" %s\n", action) + } + +} + +func showPolicyRoutePolicies() error { + arg := &api.PolicyArguments{ + Resource: api.Resource_POLICY_ROUTEPOLICY, + } + stream, e := client.GetPolicyRoutePolicies(context.Background(), arg) + if e != nil { + fmt.Println(e) + return e + } + m := policyDefinitions{} + for { + n, e := stream.Recv() + if e == io.EOF { + break + } else if e != nil { + return e + } + m = append(m, n) + } + + if globalOpts.Json { + j, _ := json.Marshal(m) + fmt.Println(string(j)) + return nil + } + if globalOpts.Quiet { + for _, p := range m { + fmt.Println(p.PolicyDefinitionName) + } + return nil + } + sort.Sort(m) + + for _, pd := range m { + fmt.Printf("PolicyName %s:\n", pd.PolicyDefinitionName) + showPolicyStatement(pd) + } + return nil +} + +func showPolicyRoutePolicy(args []string) error { + arg := &api.PolicyArguments{ + Resource: api.Resource_POLICY_ROUTEPOLICY, + Name: args[0], + } + pd, e := client.GetPolicyRoutePolicy(context.Background(), arg) + if e != nil { + return e + } + + if globalOpts.Json { + j, _ := json.Marshal(pd) + fmt.Println(string(j)) + return nil + } + fmt.Printf("PolicyName %s:\n", pd.PolicyDefinitionName) + showPolicyStatement(pd) + return nil +} + +func (x *PolicyRoutePolicyCommand) Execute(args []string) error { + eArgs := extractArgs(CMD_ROUTEPOLICY) + if len(eArgs) == 0 { + if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY, eArgs, nil); err != nil { + return err + } + return nil + } else if len(eArgs) == 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "add" || eArgs[0] == "del") { + if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY, eArgs, nil); err != nil { + return err + } + return nil + } + parser := flags.NewParser(nil, flags.Default) + parser.Usage = "policy routepolicy [OPTIONS]\n gobgp policy routepolicy" + //parser.AddCommand(CMD_ADD, "subcommand for add policy of routepolicy", "", &PolicyRoutePolicyAddCommand{}) + //parser.AddCommand(CMD_DEL, "subcommand for delete policy of routepolicy", "", &PolicyRoutePolicyDelCommand{}) parser.ParseArgs(eArgs) return nil } @@ -1543,9 +1698,9 @@ var neighborsOpts struct { } func main() { - cmds = []string{CMD_GLOBAL, CMD_NEIGHBOR, CMD_POLICY, CMD_RIB, CMD_ADD, CMD_DEL, CMD_LOCAL, CMD_ADJ_IN, CMD_ADJ_OUT, - CMD_RESET, CMD_SOFT_RESET, CMD_SOFT_RESET_IN, CMD_SOFT_RESET_OUT, CMD_SHUTDOWN, CMD_ENABLE, CMD_DISABLE, - CMD_PREFIX, CMD_ALL} + cmds = []string{CMD_GLOBAL, CMD_NEIGHBOR, CMD_POLICY, CMD_RIB, CMD_ADD, CMD_DEL, CMD_ALL, CMD_LOCAL, CMD_ADJ_IN, + CMD_ADJ_OUT, CMD_RESET, CMD_SOFT_RESET, CMD_SOFT_RESET_IN, CMD_SOFT_RESET_OUT, CMD_SHUTDOWN, CMD_ENABLE, + CMD_DISABLE, CMD_PREFIX, CMD_ROUTEPOLICY} eArgs := extractArgs("") parser := flags.NewParser(&globalOpts, flags.Default) diff --git a/server/grpc_server.go b/server/grpc_server.go index 2965d647..3fd45b83 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -50,6 +50,8 @@ const ( REQ_POLICY_PREFIXES_DELETE REQ_POLICY_NEIGHBOR REQ_POLICY_NEIGHBORS + REQ_POLICY_ROUTEPOLICIES + REQ_POLICY_ROUTEPOLICY ) const GRPC_PORT = 8080 @@ -281,6 +283,8 @@ func (s *Server) getPolicies(reqType int, arg *api.PolicyArguments, stream inter err = stream.(api.Grpc_GetPolicyPrefixesServer).Send(res.Data.(*api.PrefixSet)) case api.Resource_POLICY_NEIGHBOR: err = stream.(api.Grpc_GetPolicyNeighborsServer).Send(res.Data.(*api.NeighborSet)) + case api.Resource_POLICY_ROUTEPOLICY: + err = stream.(api.Grpc_GetPolicyRoutePoliciesServer).Send(res.Data.(*api.PolicyDefinition)) default: return fmt.Errorf("unsupported resource type: %v", arg.Resource) } @@ -299,6 +303,8 @@ func (s *Server) getPolicy(arg *api.PolicyArguments) (interface{}, error) { reqType = REQ_POLICY_PREFIX case api.Resource_POLICY_NEIGHBOR: reqType = REQ_POLICY_NEIGHBOR + case api.Resource_POLICY_ROUTEPOLICY: + reqType = REQ_POLICY_ROUTEPOLICY default: return nil, fmt.Errorf("unsupported resource type: %v", arg.Resource) } @@ -396,6 +402,21 @@ func (s *Server) GetPolicyNeighbor(ctx context.Context, arg *api.PolicyArguments return data.(*api.NeighborSet), nil } +func (s *Server) GetPolicyRoutePolicies(arg *api.PolicyArguments, stream api.Grpc_GetPolicyRoutePoliciesServer) error { + if err := s.getPolicies(REQ_POLICY_ROUTEPOLICIES, arg, stream); err != nil { + return err + } + return nil +} + +func (s *Server) GetPolicyRoutePolicy(ctx context.Context, arg *api.PolicyArguments) (*api.PolicyDefinition, error) { + data, err := s.getPolicy(arg) + if err != nil { + return nil, err + } + return data.(*api.PolicyDefinition), nil +} + type GrpcRequest struct { RequestType int RemoteAddr string diff --git a/server/server.go b/server/server.go index 5a847045..d2a82a85 100644 --- a/server/server.go +++ b/server/server.go @@ -338,7 +338,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { grpcReq.ResponseCh <- result } } else { - result.ResponseErr = fmt.Errorf("Policy Prefix is not exist.") + result.ResponseErr = fmt.Errorf("Prefix is not exist.") grpcReq.ResponseCh <- result } close(grpcReq.ResponseCh) @@ -359,7 +359,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { } grpcReq.ResponseCh <- result } else { - result.ResponseErr = fmt.Errorf("Policy Prefix that has %v does not exist.", name) + result.ResponseErr = fmt.Errorf("Prefix that has %v does not exist.", name) grpcReq.ResponseCh <- result } close(grpcReq.ResponseCh) @@ -373,7 +373,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) } - idxPrefixSet, idxPrefix := findPrefixSet(conPrefixSetList, reqPrefixSet, prefixSet) + idxPrefixSet, idxPrefix := findPrefixSet(conPrefixSetList, prefixSet) if idxPrefixSet == -1 { conPrefixSetList = append(conPrefixSetList, prefixSet) } else { @@ -391,13 +391,13 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { result := &GrpcResponse{} isReqPrefixSet, prefixSet := prefixToConfigStruct(reqPrefixSet) if isReqPrefixSet { - idxPrefixSet, idxPrefix := findPrefixSet(conPrefixSetList, reqPrefixSet, prefixSet) + idxPrefixSet, idxPrefix := findPrefixSet(conPrefixSetList, prefixSet) if idxPrefixSet == -1 { - result.ResponseErr = fmt.Errorf("Policy Prefix %v %v/%v %v does not exist.", prefixSet.PrefixSetName, + result.ResponseErr = fmt.Errorf("Prefix %v %v/%v %v does not exist.", prefixSet.PrefixSetName, prefixSet.PrefixList[0].Address, prefixSet.PrefixList[0].Masklength, prefixSet.PrefixList[0].MasklengthRange) } else { if idxPrefix == -1 { - result.ResponseErr = fmt.Errorf("Policy Prefix %v %v/%v %v does not exist.", prefixSet.PrefixSetName, + result.ResponseErr = fmt.Errorf("Prefix %v %v/%v %v does not exist.", prefixSet.PrefixSetName, prefixSet.PrefixList[0].Address, prefixSet.PrefixList[0].Masklength, prefixSet.PrefixList[0].MasklengthRange) } else { copy(conPrefixSetList[idxPrefixSet].PrefixList[idxPrefix:], conPrefixSetList[idxPrefixSet].PrefixList[idxPrefix+1:]) @@ -413,7 +413,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { } } if idxPrefixSet == -1 { - result.ResponseErr = fmt.Errorf("Policy Prefix %v does not exist.", prefixSet.PrefixSetName) + result.ResponseErr = fmt.Errorf("Prefix %v does not exist.", prefixSet.PrefixSetName) } else { copy(conPrefixSetList[idxPrefixSet:], conPrefixSetList[idxPrefixSet+1:]) conPrefixSetList = conPrefixSetList[:len(conPrefixSetList)-1] @@ -441,7 +441,7 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { grpcReq.ResponseCh <- result } } else { - result.ResponseErr = fmt.Errorf("Policy Neighbor is not exist.") + result.ResponseErr = fmt.Errorf("Neighbor is not exist.") grpcReq.ResponseCh <- result } close(grpcReq.ResponseCh) @@ -462,24 +462,66 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { } grpcReq.ResponseCh <- result } else { - result.ResponseErr = fmt.Errorf("Policy Neighbor that has %v does not exist.", name) + result.ResponseErr = fmt.Errorf("Neighbor that has %v does not exist.", name) + grpcReq.ResponseCh <- result + } + close(grpcReq.ResponseCh) + case REQ_POLICY_ROUTEPOLICIES: + info := server.routingPolicy.PolicyDefinitionList + df := server.routingPolicy.DefinedSets + result := &GrpcResponse{} + if len(info) > 0 { + for _, pd := range info { + resPolicyDefinition := policyDefinitionToApiStruct(pd, df) + result = &GrpcResponse{ + Data: resPolicyDefinition, + } + grpcReq.ResponseCh <- result + } + } else { + result.ResponseErr = fmt.Errorf("Route Policy is not exist.") + grpcReq.ResponseCh <- result + } + close(grpcReq.ResponseCh) + case REQ_POLICY_ROUTEPOLICY: + name := grpcReq.Data.(string) + info := server.routingPolicy.PolicyDefinitionList + df := server.routingPolicy.DefinedSets + result := &GrpcResponse{} + resPolicyDefinition := &api.PolicyDefinition{} + for _, pd := range info { + if pd.Name == name { + resPolicyDefinition = policyDefinitionToApiStruct(pd, df) + break + } + } + if len(resPolicyDefinition.StatementList) > 0 { + result = &GrpcResponse{ + Data: resPolicyDefinition, + } + grpcReq.ResponseCh <- result + } else { + result.ResponseErr = fmt.Errorf("Route Policy that has %v does not exist.", name) grpcReq.ResponseCh <- result } close(grpcReq.ResponseCh) } } -func findPrefixSet(conPrefixSetList []config.PrefixSet, reqPrefixSet *api.PrefixSet, prefixSet config.PrefixSet) (int, int) { +func findPrefixSet(conPrefixSetList []config.PrefixSet, reqPrefixSet config.PrefixSet) (int, int) { idxPrefixSet := -1 idxPrefix := -1 for i, conPrefixSet := range conPrefixSetList { if conPrefixSet.PrefixSetName == reqPrefixSet.PrefixSetName { idxPrefixSet = i + if reqPrefixSet.PrefixList == nil { + return idxPrefixSet, idxPrefix + } for j, conPrefix := range conPrefixSet.PrefixList { - if reflect.DeepEqual(conPrefix.Address, prefixSet.PrefixList[0].Address) && conPrefix.Masklength == prefixSet.PrefixList[0].Masklength && - conPrefix.MasklengthRange == prefixSet.PrefixList[0].MasklengthRange { + if reflect.DeepEqual(conPrefix.Address, reqPrefixSet.PrefixList[0].Address) && conPrefix.Masklength == reqPrefixSet.PrefixList[0].Masklength && + conPrefix.MasklengthRange == reqPrefixSet.PrefixList[0].MasklengthRange { idxPrefix = j - break + return idxPrefixSet, idxPrefix } } } @@ -487,6 +529,26 @@ func findPrefixSet(conPrefixSetList []config.PrefixSet, reqPrefixSet *api.Prefix return idxPrefixSet, idxPrefix } +func findNeighborSet(conNeighborSetList []config.NeighborSet, reqNeighborSet config.NeighborSet) (int, int) { + idxNeighborSet := -1 + idxNeighbor := -1 + for i, conNeighborSet := range conNeighborSetList { + if conNeighborSet.NeighborSetName == reqNeighborSet.NeighborSetName { + idxNeighborSet = i + if reqNeighborSet.NeighborInfoList == nil { + return idxNeighborSet, idxNeighbor + } + for j, conNeighbor := range conNeighborSet.NeighborInfoList { + if reflect.DeepEqual(conNeighbor.Address, reqNeighborSet.NeighborInfoList[0].Address) { + idxNeighbor = j + return idxNeighborSet, idxNeighbor + } + } + } + } + return idxNeighborSet, idxNeighbor +} + func prefixToApiStruct(ps config.PrefixSet) *api.PrefixSet { resPrefixList := make([]*api.Prefix, 0) for _, p := range ps.PrefixList { @@ -544,3 +606,76 @@ func neighborToApiStruct(ns config.NeighborSet) *api.NeighborSet { } return resNeighborSet } + +func neighborToConfigStruct(reqNeighborSet *api.NeighborSet) (bool, config.NeighborSet) { + var neighbor config.NeighborInfo + var neighborSet config.NeighborSet + isReqNeighborSet := true + if reqNeighborSet.NeighborList != nil { + neighbor = config.NeighborInfo{ + Address: net.ParseIP(reqNeighborSet.NeighborList[0].Address), + } + neighborList := []config.NeighborInfo{neighbor} + + neighborSet = config.NeighborSet{ + NeighborSetName: reqNeighborSet.NeighborSetName, + NeighborInfoList: neighborList, + } + } else { + isReqNeighborSet = false + neighborSet = config.NeighborSet{ + NeighborSetName: reqNeighborSet.NeighborSetName, + NeighborInfoList: nil, + } + } + return isReqNeighborSet, neighborSet +} + +func policyDefinitionToApiStruct(pd config.PolicyDefinition, df config.DefinedSets) *api.PolicyDefinition { + conPrefixSetList := df.PrefixSetList + conNeighborSetList := df.NeighborSetList + resStatementList := make([]*api.Statement, 0) + for _, st := range pd.StatementList { + conditions := st.Conditions + actions := st.Actions + + prefixSet := &api.PrefixSet{ + PrefixSetName: conditions.MatchPrefixSet, + } + neighborSet := &api.NeighborSet{ + NeighborSetName: conditions.MatchNeighborSet, + } + _, conPrefixSet := prefixToConfigStruct(prefixSet) + _, conNeighborSet := neighborToConfigStruct(neighborSet) + idxPrefixSet, _ := findPrefixSet(conPrefixSetList, conPrefixSet) + idxNeighborSet, _ := findNeighborSet(conNeighborSetList, conNeighborSet) + + if idxPrefixSet != -1 { + prefixSet = prefixToApiStruct(conPrefixSetList[idxPrefixSet]) + } + if idxNeighborSet != -1 { + neighborSet = neighborToApiStruct(conNeighborSetList[idxNeighborSet]) + } + + resConditions := &api.Conditions{ + MatchPrefixSet: prefixSet, + MatchNeighborSet: neighborSet, + MatchSetOptions: int64(conditions.MatchSetOptions), + } + resActions := &api.Actions{ + AcceptRoute: actions.AcceptRoute, + RejectRoute: actions.RejectRoute, + } + resStatement := &api.Statement{ + StatementNeme: st.Name, + Conditions: resConditions, + Actions: resActions, + } + resStatementList = append(resStatementList, resStatement) + } + resPolicyDefinition := &api.PolicyDefinition{ + PolicyDefinitionName: pd.Name, + StatementList: resStatementList, + } + return resPolicyDefinition +} |