diff options
-rw-r--r-- | api/gobgp.pb.go | 152 | ||||
-rw-r--r-- | api/gobgp.proto | 14 | ||||
-rw-r--r-- | gobgp/main.go | 139 | ||||
-rw-r--r-- | server/grpc_server.go | 21 | ||||
-rw-r--r-- | server/server.go | 52 |
5 files changed, 364 insertions, 14 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index a67af8f7..809e8d50 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -33,6 +33,8 @@ It has these top-level messages: Peer Prefix PrefixSet + Neighbor + NeighborSet */ package api @@ -53,11 +55,12 @@ 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_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 ) var Resource_name = map[int32]string{ @@ -66,13 +69,15 @@ var Resource_name = map[int32]string{ 2: "ADJ_IN", 3: "ADJ_OUT", 4: "POLICY_PREFIX", + 5: "POLICY_NEIGHBOR", } var Resource_value = map[string]int32{ - "GLOBAL": 0, - "LOCAL": 1, - "ADJ_IN": 2, - "ADJ_OUT": 3, - "POLICY_PREFIX": 4, + "GLOBAL": 0, + "LOCAL": 1, + "ADJ_IN": 2, + "ADJ_OUT": 3, + "POLICY_PREFIX": 4, + "POLICY_NEIGHBOR": 5, } func (x Resource) String() string { @@ -506,10 +511,11 @@ 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"` + 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"` } func (m *PolicyArguments) Reset() { *m = PolicyArguments{} } @@ -523,6 +529,13 @@ func (m *PolicyArguments) GetPrefixSet() *PrefixSet { return nil } +func (m *PolicyArguments) GetNeighborSet() *NeighborSet { + if m != nil { + return m.NeighborSet + } + 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"` @@ -921,6 +934,30 @@ func (m *PrefixSet) GetPrefixList() []*Prefix { return nil } +type Neighbor struct { + Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` +} + +func (m *Neighbor) Reset() { *m = Neighbor{} } +func (m *Neighbor) String() string { return proto.CompactTextString(m) } +func (*Neighbor) ProtoMessage() {} + +type NeighborSet struct { + NeighborSetName string `protobuf:"bytes,1,opt,name=neighbor_set_name" json:"neighbor_set_name,omitempty"` + NeighborList []*Neighbor `protobuf:"bytes,2,rep,name=neighbor_list" json:"neighbor_list,omitempty"` +} + +func (m *NeighborSet) Reset() { *m = NeighborSet{} } +func (m *NeighborSet) String() string { return proto.CompactTextString(m) } +func (*NeighborSet) ProtoMessage() {} + +func (m *NeighborSet) GetNeighborList() []*Neighbor { + if m != nil { + return m.NeighborList + } + return nil +} + func init() { proto.RegisterEnum("api.Resource", Resource_name, Resource_value) proto.RegisterEnum("api.Operation", Operation_name, Operation_value) @@ -955,6 +992,8 @@ type GrpcClient interface { GetPolicyPrefixes(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (Grpc_GetPolicyPrefixesClient, error) GetPolicyPrefix(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (*PrefixSet, error) 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) } type grpcClient struct { @@ -1236,6 +1275,47 @@ func (x *grpcModPolicyPrefixClient) Recv() (*Error, error) { return m, nil } +func (c *grpcClient) GetPolicyNeighbors(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (Grpc_GetPolicyNeighborsClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[6], c.cc, "/api.Grpc/GetPolicyNeighbors", opts...) + if err != nil { + return nil, err + } + x := &grpcGetPolicyNeighborsClient{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_GetPolicyNeighborsClient interface { + Recv() (*NeighborSet, error) + grpc.ClientStream +} + +type grpcGetPolicyNeighborsClient struct { + grpc.ClientStream +} + +func (x *grpcGetPolicyNeighborsClient) Recv() (*NeighborSet, error) { + m := new(NeighborSet) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *grpcClient) GetPolicyNeighbor(ctx context.Context, in *PolicyArguments, opts ...grpc.CallOption) (*NeighborSet, error) { + out := new(NeighborSet) + err := grpc.Invoke(ctx, "/api.Grpc/GetPolicyNeighbor", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Grpc service type GrpcServer interface { @@ -1254,6 +1334,8 @@ type GrpcServer interface { GetPolicyPrefixes(*PolicyArguments, Grpc_GetPolicyPrefixesServer) error GetPolicyPrefix(context.Context, *PolicyArguments) (*PrefixSet, error) ModPolicyPrefix(Grpc_ModPolicyPrefixServer) error + GetPolicyNeighbors(*PolicyArguments, Grpc_GetPolicyNeighborsServer) error + GetPolicyNeighbor(context.Context, *PolicyArguments) (*NeighborSet, error) } func RegisterGrpcServer(s *grpc.Server, srv GrpcServer) { @@ -1504,6 +1586,39 @@ func (x *grpcModPolicyPrefixServer) Recv() (*PolicyArguments, error) { return m, nil } +func _Grpc_GetPolicyNeighbors_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PolicyArguments) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GrpcServer).GetPolicyNeighbors(m, &grpcGetPolicyNeighborsServer{stream}) +} + +type Grpc_GetPolicyNeighborsServer interface { + Send(*NeighborSet) error + grpc.ServerStream +} + +type grpcGetPolicyNeighborsServer struct { + grpc.ServerStream +} + +func (x *grpcGetPolicyNeighborsServer) Send(m *NeighborSet) error { + return x.ServerStream.SendMsg(m) +} + +func _Grpc_GetPolicyNeighbor_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).GetPolicyNeighbor(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + var _Grpc_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Grpc", HandlerType: (*GrpcServer)(nil), @@ -1544,6 +1659,10 @@ var _Grpc_serviceDesc = grpc.ServiceDesc{ MethodName: "GetPolicyPrefix", Handler: _Grpc_GetPolicyPrefix_Handler, }, + { + MethodName: "GetPolicyNeighbor", + Handler: _Grpc_GetPolicyNeighbor_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -1578,5 +1697,10 @@ var _Grpc_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, ClientStreams: true, }, + { + StreamName: "GetPolicyNeighbors", + Handler: _Grpc_GetPolicyNeighbors_Handler, + ServerStreams: true, + }, }, } diff --git a/api/gobgp.proto b/api/gobgp.proto index 6a2e3844..7ee47965 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -35,6 +35,8 @@ service Grpc { rpc GetPolicyPrefixes(PolicyArguments) returns (stream PrefixSet) {} rpc GetPolicyPrefix(PolicyArguments) returns (PrefixSet) {} rpc ModPolicyPrefix(stream PolicyArguments) returns (stream Error) {} + rpc GetPolicyNeighbors(PolicyArguments) returns (stream NeighborSet) {} + rpc GetPolicyNeighbor(PolicyArguments) returns (NeighborSet) {} } message Error { @@ -62,6 +64,7 @@ message PolicyArguments { Operation operation = 2; string name = 3; PrefixSet prefix_set = 4; + NeighborSet neighbor_set = 5; } enum Resource { @@ -70,6 +73,7 @@ enum Resource { ADJ_IN = 2; ADJ_OUT = 3; POLICY_PREFIX = 4; + POLICY_NEIGHBOR = 5; } enum Operation { @@ -347,3 +351,13 @@ message PrefixSet { string prefix_set_name = 1; repeated Prefix prefix_list = 2; } + +message Neighbor { + string address = 1; +} + +message NeighborSet { + string neighbor_set_name = 1; + repeated Neighbor neighbor_list = 2; +} + diff --git a/gobgp/main.go b/gobgp/main.go index 4f5a3052..434cd68f 100644 --- a/gobgp/main.go +++ b/gobgp/main.go @@ -151,6 +151,20 @@ func (p prefixes) Less(i, j int) bool { return p[i].PrefixSetName < p[j].PrefixSetName } +type neighbors []*api.NeighborSet + +func (n neighbors) Len() int { + return len(n) +} + +func (n neighbors) Swap(i, j int) { + n[i], n[j] = n[j], n[i] +} + +func (n neighbors) Less(i, j int) bool { + return n[i].NeighborSetName < n[j].NeighborSetName +} + func connGrpc() *grpc.ClientConn { timeout := grpc.WithTimeout(time.Second) @@ -217,6 +231,12 @@ func requestGrpc(cmd string, eArgs []string, remoteIP net.IP) error { return modPolicyPrefix(CMD_ADD, eArgs) case CMD_POLICY + "_" + CMD_PREFIX + "_" + CMD_DEL: return modPolicyPrefix(CMD_DEL, eArgs) + case CMD_POLICY + "_" + CMD_NEIGHBOR: + if len(eArgs) == 0 { + return showPolicyNeighbors() + } else { + return showPolicyNeighbor(eArgs) + } } return nil } @@ -1091,6 +1111,7 @@ func (x *PolicyCommand) Execute(args []string) error { parser := flags.NewParser(nil, flags.Default) parser.Usage = "policy" parser.AddCommand(CMD_PREFIX, "subcommand for prefix of policy", "", &PolicyPrefixCommand{}) + parser.AddCommand(CMD_NEIGHBOR, "subcommand for prefix of neighbor", "", &PolicyNeighborCommand{}) if _, err := parser.ParseArgs(eArgs); err != nil { os.Exit(1) } @@ -1387,6 +1408,124 @@ func (x *PolicyPrefixDelAllCommand) Execute(args []string) error { return nil } +type PolicyNeighborCommand struct{} + +func showPolicyNeighbors() error { + arg := &api.PolicyArguments{ + Resource: api.Resource_POLICY_NEIGHBOR, + } + stream, e := client.GetPolicyNeighbors(context.Background(), arg) + if e != nil { + fmt.Println(e) + return e + } + m := neighbors{} + 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 _, n := range m { + fmt.Println(n.NeighborSetName) + } + 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" + fmt.Printf(format, "Name", "Address") + for _, ns := range m { + for i, n := range ns.NeighborList { + if i == 0 { + fmt.Printf(format, ns.NeighborSetName, n.Address) + } else { + fmt.Printf(format, "", n.Address) + } + } + } + return nil +} + +func showPolicyNeighbor(args []string) error { + arg := &api.PolicyArguments{ + Resource: api.Resource_POLICY_NEIGHBOR, + Name: args[0], + } + ns, e := client.GetPolicyNeighbor(context.Background(), arg) + if e != nil { + return e + } + + if globalOpts.Json { + j, _ := json.Marshal(ns) + fmt.Println(string(j)) + return nil + } + + maxaddresslen := len("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 +} + +func (x *PolicyNeighborCommand) Execute(args []string) error { + eArgs := extractArgs(CMD_NEIGHBOR) + if len(eArgs) == 0 { + if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR, 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_NEIGHBOR, eArgs, nil); err != nil { + return err + } + return nil + } + 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.ParseArgs(eArgs) + return nil +} + var globalOpts struct { Host string `short:"u" long:"url" description:"specifying an url" default:"127.0.0.1"` Port int `short:"p" long:"port" description:"specifying a port" default:"8080"` diff --git a/server/grpc_server.go b/server/grpc_server.go index cc0a0e16..2965d647 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -48,6 +48,8 @@ const ( REQ_POLICY_PREFIX_ADD REQ_POLICY_PREFIX_DELETE REQ_POLICY_PREFIXES_DELETE + REQ_POLICY_NEIGHBOR + REQ_POLICY_NEIGHBORS ) const GRPC_PORT = 8080 @@ -277,6 +279,8 @@ func (s *Server) getPolicies(reqType int, arg *api.PolicyArguments, stream inter switch arg.Resource { case api.Resource_POLICY_PREFIX: 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)) default: return fmt.Errorf("unsupported resource type: %v", arg.Resource) } @@ -293,6 +297,8 @@ func (s *Server) getPolicy(arg *api.PolicyArguments) (interface{}, error) { switch arg.Resource { case api.Resource_POLICY_PREFIX: reqType = REQ_POLICY_PREFIX + case api.Resource_POLICY_NEIGHBOR: + reqType = REQ_POLICY_NEIGHBOR default: return nil, fmt.Errorf("unsupported resource type: %v", arg.Resource) } @@ -375,6 +381,21 @@ func (s *Server) ModPolicyPrefix(stream api.Grpc_ModPolicyPrefixServer) error { } } +func (s *Server) GetPolicyNeighbors(arg *api.PolicyArguments, stream api.Grpc_GetPolicyNeighborsServer) error { + if err := s.getPolicies(REQ_POLICY_NEIGHBORS, arg, stream); err != nil { + return err + } + return nil +} + +func (s *Server) GetPolicyNeighbor(ctx context.Context, arg *api.PolicyArguments) (*api.NeighborSet, error) { + data, err := s.getPolicy(arg) + if err != nil { + return nil, err + } + return data.(*api.NeighborSet), nil +} + type GrpcRequest struct { RequestType int RemoteAddr string diff --git a/server/server.go b/server/server.go index 443a4ba2..5a847045 100644 --- a/server/server.go +++ b/server/server.go @@ -429,6 +429,43 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { server.handlePolicy(pl) grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) + case REQ_POLICY_NEIGHBORS: + info := server.routingPolicy.DefinedSets.NeighborSetList + result := &GrpcResponse{} + if len(info) > 0 { + for _, ns := range info { + resNeighborSet := neighborToApiStruct(ns) + result = &GrpcResponse{ + Data: resNeighborSet, + } + grpcReq.ResponseCh <- result + } + } else { + result.ResponseErr = fmt.Errorf("Policy Neighbor is not exist.") + grpcReq.ResponseCh <- result + } + close(grpcReq.ResponseCh) + case REQ_POLICY_NEIGHBOR: + name := grpcReq.Data.(string) + info := server.routingPolicy.DefinedSets.NeighborSetList + result := &GrpcResponse{} + resNeighborSet := &api.NeighborSet{} + for _, ns := range info { + if ns.NeighborSetName == name { + resNeighborSet = neighborToApiStruct(ns) + break + } + } + if len(resNeighborSet.NeighborList) > 0 { + result = &GrpcResponse{ + Data: resNeighborSet, + } + grpcReq.ResponseCh <- result + } else { + result.ResponseErr = fmt.Errorf("Policy Neighbor that has %v does not exist.", name) + grpcReq.ResponseCh <- result + } + close(grpcReq.ResponseCh) } } @@ -492,3 +529,18 @@ func prefixToConfigStruct(reqPrefixSet *api.PrefixSet) (bool, config.PrefixSet) } return isReqPrefixSet, prefixSet } + +func neighborToApiStruct(ns config.NeighborSet) *api.NeighborSet { + resNeighborList := make([]*api.Neighbor, 0) + for _, n := range ns.NeighborInfoList { + resNeighbor := &api.Neighbor{ + Address: n.Address.String(), + } + resNeighborList = append(resNeighborList, resNeighbor) + } + resNeighborSet := &api.NeighborSet{ + NeighborSetName: ns.NeighborSetName, + NeighborList: resNeighborList, + } + return resNeighborSet +} |