diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-04-04 23:46:01 +0000 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-04-14 08:10:28 +0900 |
commit | 75f835725deb42b00d5f746828f2738d15e3bc4f (patch) | |
tree | 5294cc59377f51896fd75a57cdb776f5e2f8bf54 /api | |
parent | 18bbb843d2e025af8e1ffd33b7c9a09d1a19c565 (diff) |
api: use gRPC instead of REST
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'api')
-rw-r--r-- | api/gobgp.pb.go | 853 | ||||
-rw-r--r-- | api/gobgp.proto | 145 | ||||
-rw-r--r-- | api/grpc.go | 318 | ||||
-rw-r--r-- | api/rest.go | 293 |
4 files changed, 1316 insertions, 293 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go new file mode 100644 index 00000000..3b91d6ea --- /dev/null +++ b/api/gobgp.pb.go @@ -0,0 +1,853 @@ +// Code generated by protoc-gen-go. +// source: gobgp.proto +// DO NOT EDIT! + +/* +Package api is a generated protocol buffer package. + +It is generated from these files: + gobgp.proto + +It has these top-level messages: + Error + Arguments + PathAttr + Path + Destination + PeerConf + PeerInfo + Peer +*/ +package api + +import proto "github.com/golang/protobuf/proto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// Reference imports to suppress errors if they are not otherwise used. +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 +) + +var Resource_name = map[int32]string{ + 0: "GLOBAL", + 1: "LOCAL", + 2: "ADJ_IN", + 3: "ADJ_OUT", +} +var Resource_value = map[string]int32{ + "GLOBAL": 0, + "LOCAL": 1, + "ADJ_IN": 2, + "ADJ_OUT": 3, +} + +func (x Resource) String() string { + return proto.EnumName(Resource_name, int32(x)) +} + +type AddressFamily int32 + +const ( + AddressFamily_IPV4 AddressFamily = 0 + AddressFamily_IPV6 AddressFamily = 1 + AddressFamily_EVPN AddressFamily = 2 +) + +var AddressFamily_name = map[int32]string{ + 0: "IPV4", + 1: "IPV6", + 2: "EVPN", +} +var AddressFamily_value = map[string]int32{ + "IPV4": 0, + "IPV6": 1, + "EVPN": 2, +} + +func (x AddressFamily) String() string { + return proto.EnumName(AddressFamily_name, int32(x)) +} + +type Error_ErrorCode int32 + +const ( + Error_SUCCESS Error_ErrorCode = 0 + Error_FAIL Error_ErrorCode = 1 +) + +var Error_ErrorCode_name = map[int32]string{ + 0: "SUCCESS", + 1: "FAIL", +} +var Error_ErrorCode_value = map[string]int32{ + "SUCCESS": 0, + "FAIL": 1, +} + +func (x Error_ErrorCode) String() string { + return proto.EnumName(Error_ErrorCode_name, int32(x)) +} + +type PathAttr_Origin int32 + +const ( + PathAttr_IGP PathAttr_Origin = 0 + PathAttr_EGP PathAttr_Origin = 1 + PathAttr_INCOMPLETE PathAttr_Origin = 2 +) + +var PathAttr_Origin_name = map[int32]string{ + 0: "IGP", + 1: "EGP", + 2: "INCOMPLETE", +} +var PathAttr_Origin_value = map[string]int32{ + "IGP": 0, + "EGP": 1, + "INCOMPLETE": 2, +} + +func (x PathAttr_Origin) String() string { + return proto.EnumName(PathAttr_Origin_name, int32(x)) +} + +type Error struct { + Code Error_ErrorCode `protobuf:"varint,1,opt,name=code,enum=api.Error_ErrorCode" json:"code,omitempty"` + Msg string `protobuf:"bytes,2,opt,name=msg" json:"msg,omitempty"` +} + +func (m *Error) Reset() { *m = Error{} } +func (m *Error) String() string { return proto.CompactTextString(m) } +func (*Error) ProtoMessage() {} + +type Arguments struct { + Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"` + Af AddressFamily `protobuf:"varint,2,opt,name=af,enum=api.AddressFamily" json:"af,omitempty"` + RouterId string `protobuf:"bytes,3,opt,name=router_id" json:"router_id,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=prefix" json:"prefix,omitempty"` +} + +func (m *Arguments) Reset() { *m = Arguments{} } +func (m *Arguments) String() string { return proto.CompactTextString(m) } +func (*Arguments) ProtoMessage() {} + +type PathAttr struct { + Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"` + Origin PathAttr_Origin `protobuf:"varint,2,opt,name=origin,enum=api.PathAttr_Origin" json:"origin,omitempty"` + AsPath []uint32 `protobuf:"varint,3,rep,name=as_path" json:"as_path,omitempty"` + Metric uint32 `protobuf:"varint,4,opt,name=metric" json:"metric,omitempty"` + Pref uint32 `protobuf:"varint,5,opt,name=pref" json:"pref,omitempty"` + Aggregator *PathAttr_Aggregator `protobuf:"bytes,6,opt,name=aggregator" json:"aggregator,omitempty"` + Communites []uint32 `protobuf:"varint,7,rep,name=communites" json:"communites,omitempty"` + Originator string `protobuf:"bytes,8,opt,name=originator" json:"originator,omitempty"` + Cluster string `protobuf:"bytes,9,opt,name=cluster" json:"cluster,omitempty"` + Value uint32 `protobuf:"varint,10,opt,name=value" json:"value,omitempty"` +} + +func (m *PathAttr) Reset() { *m = PathAttr{} } +func (m *PathAttr) String() string { return proto.CompactTextString(m) } +func (*PathAttr) ProtoMessage() {} + +func (m *PathAttr) GetAggregator() *PathAttr_Aggregator { + if m != nil { + return m.Aggregator + } + return nil +} + +type PathAttr_Aggregator struct { + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"` +} + +func (m *PathAttr_Aggregator) Reset() { *m = PathAttr_Aggregator{} } +func (m *PathAttr_Aggregator) String() string { return proto.CompactTextString(m) } +func (*PathAttr_Aggregator) ProtoMessage() {} + +type Path struct { + Network string `protobuf:"bytes,1,opt,name=network" json:"network,omitempty"` + Nexthop string `protobuf:"bytes,2,opt,name=nexthop" json:"nexthop,omitempty"` + Age int64 `protobuf:"varint,3,opt,name=age" json:"age,omitempty"` + Attrs []*PathAttr `protobuf:"bytes,4,rep,name=attrs" json:"attrs,omitempty"` + Best bool `protobuf:"varint,5,opt,name=best" json:"best,omitempty"` +} + +func (m *Path) Reset() { *m = Path{} } +func (m *Path) String() string { return proto.CompactTextString(m) } +func (*Path) ProtoMessage() {} + +func (m *Path) GetAttrs() []*PathAttr { + if m != nil { + return m.Attrs + } + return nil +} + +type Destination struct { + Prefix string `protobuf:"bytes,1,opt,name=prefix" json:"prefix,omitempty"` + Paths []*Path `protobuf:"bytes,2,rep,name=paths" json:"paths,omitempty"` + BestPathIdx int32 `protobuf:"varint,3,opt,name=best_path_idx" json:"best_path_idx,omitempty"` +} + +func (m *Destination) Reset() { *m = Destination{} } +func (m *Destination) String() string { return proto.CompactTextString(m) } +func (*Destination) ProtoMessage() {} + +func (m *Destination) GetPaths() []*Path { + if m != nil { + return m.Paths + } + return nil +} + +type PeerConf struct { + RemoteIp string `protobuf:"bytes,1,opt,name=remote_ip" json:"remote_ip,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"` + RemoteAs uint32 `protobuf:"varint,3,opt,name=remote_as" json:"remote_as,omitempty"` + CapRefresh bool `protobuf:"varint,4,opt,name=cap_refresh" json:"cap_refresh,omitempty"` + CapEnhancedRefresh bool `protobuf:"varint,5,opt,name=cap_enhanced_refresh" json:"cap_enhanced_refresh,omitempty"` + RemoteCap []int32 `protobuf:"varint,6,rep,name=remote_cap" json:"remote_cap,omitempty"` + LocalCap []int32 `protobuf:"varint,7,rep,name=local_cap" json:"local_cap,omitempty"` +} + +func (m *PeerConf) Reset() { *m = PeerConf{} } +func (m *PeerConf) String() string { return proto.CompactTextString(m) } +func (*PeerConf) ProtoMessage() {} + +type PeerInfo struct { + BgpState string `protobuf:"bytes,1,opt,name=bgp_state" json:"bgp_state,omitempty"` + AdminState string `protobuf:"bytes,2,opt,name=admin_state" json:"admin_state,omitempty"` + FsmEstablishedTransitions uint32 `protobuf:"varint,3,opt,name=fsm_established_transitions" json:"fsm_established_transitions,omitempty"` + TotalMessageOut uint32 `protobuf:"varint,4,opt,name=total_message_out" json:"total_message_out,omitempty"` + TotalMessageIn uint32 `protobuf:"varint,5,opt,name=total_message_in" json:"total_message_in,omitempty"` + UpdateMessageOut uint32 `protobuf:"varint,6,opt,name=update_message_out" json:"update_message_out,omitempty"` + UpdateMessageIn uint32 `protobuf:"varint,7,opt,name=update_message_in" json:"update_message_in,omitempty"` + KeepAliveMessageOut uint32 `protobuf:"varint,8,opt,name=keep_alive_message_out" json:"keep_alive_message_out,omitempty"` + KeepAliveMessageIn uint32 `protobuf:"varint,9,opt,name=keep_alive_message_in" json:"keep_alive_message_in,omitempty"` + OpenMessageOut uint32 `protobuf:"varint,10,opt,name=open_message_out" json:"open_message_out,omitempty"` + OpenMessageIn uint32 `protobuf:"varint,11,opt,name=open_message_in" json:"open_message_in,omitempty"` + NotificationOut uint32 `protobuf:"varint,12,opt,name=notification_out" json:"notification_out,omitempty"` + NotificationIn uint32 `protobuf:"varint,13,opt,name=notification_in" json:"notification_in,omitempty"` + RefreshMessageOut uint32 `protobuf:"varint,14,opt,name=refresh_message_out" json:"refresh_message_out,omitempty"` + RefreshMessageIn uint32 `protobuf:"varint,15,opt,name=refresh_message_in" json:"refresh_message_in,omitempty"` + DiscardedOut uint32 `protobuf:"varint,16,opt,name=discarded_out" json:"discarded_out,omitempty"` + DiscardedIn uint32 `protobuf:"varint,17,opt,name=discarded_in" json:"discarded_in,omitempty"` + Uptime int64 `protobuf:"varint,18,opt,name=uptime" json:"uptime,omitempty"` + Downtime int64 `protobuf:"varint,19,opt,name=downtime" json:"downtime,omitempty"` + LastError string `protobuf:"bytes,20,opt,name=last_error" json:"last_error,omitempty"` + Received uint32 `protobuf:"varint,21,opt,name=received" json:"received,omitempty"` + Accepted uint32 `protobuf:"varint,22,opt,name=accepted" json:"accepted,omitempty"` + Advertized uint32 `protobuf:"varint,23,opt,name=advertized" json:"advertized,omitempty"` + OutQ uint32 `protobuf:"varint,24,opt,name=out_q" json:"out_q,omitempty"` + Flops uint32 `protobuf:"varint,25,opt,name=flops" json:"flops,omitempty"` +} + +func (m *PeerInfo) Reset() { *m = PeerInfo{} } +func (m *PeerInfo) String() string { return proto.CompactTextString(m) } +func (*PeerInfo) ProtoMessage() {} + +type Peer struct { + Conf *PeerConf `protobuf:"bytes,1,opt,name=conf" json:"conf,omitempty"` + Info *PeerInfo `protobuf:"bytes,2,opt,name=info" json:"info,omitempty"` +} + +func (m *Peer) Reset() { *m = Peer{} } +func (m *Peer) String() string { return proto.CompactTextString(m) } +func (*Peer) ProtoMessage() {} + +func (m *Peer) GetConf() *PeerConf { + if m != nil { + return m.Conf + } + return nil +} + +func (m *Peer) GetInfo() *PeerInfo { + if m != nil { + return m.Info + } + return nil +} + +func init() { + proto.RegisterEnum("api.Resource", Resource_name, Resource_value) + proto.RegisterEnum("api.AddressFamily", AddressFamily_name, AddressFamily_value) + proto.RegisterEnum("api.Error_ErrorCode", Error_ErrorCode_name, Error_ErrorCode_value) + proto.RegisterEnum("api.PathAttr_Origin", PathAttr_Origin_name, PathAttr_Origin_value) +} + +// Client API for Grpc service + +type GrpcClient interface { + GetNeighbors(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (Grpc_GetNeighborsClient, error) + GetNeighbor(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Peer, error) + GetRib(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (Grpc_GetRibClient, error) + GetAdjRib(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (Grpc_GetAdjRibClient, error) + Reset(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + SoftReset(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + SoftResetIn(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + SoftResetOut(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + Shutdown(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + Enable(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + Disable(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) + AddPath(ctx context.Context, opts ...grpc.CallOption) (Grpc_AddPathClient, error) + DeletePath(ctx context.Context, opts ...grpc.CallOption) (Grpc_DeletePathClient, error) +} + +type grpcClient struct { + cc *grpc.ClientConn +} + +func NewGrpcClient(cc *grpc.ClientConn) GrpcClient { + return &grpcClient{cc} +} + +func (c *grpcClient) GetNeighbors(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (Grpc_GetNeighborsClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[0], c.cc, "/api.Grpc/GetNeighbors", opts...) + if err != nil { + return nil, err + } + x := &grpcGetNeighborsClient{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_GetNeighborsClient interface { + Recv() (*Peer, error) + grpc.ClientStream +} + +type grpcGetNeighborsClient struct { + grpc.ClientStream +} + +func (x *grpcGetNeighborsClient) Recv() (*Peer, error) { + m := new(Peer) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *grpcClient) GetNeighbor(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Peer, error) { + out := new(Peer) + err := grpc.Invoke(ctx, "/api.Grpc/GetNeighbor", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) GetRib(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (Grpc_GetRibClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[1], c.cc, "/api.Grpc/GetRib", opts...) + if err != nil { + return nil, err + } + x := &grpcGetRibClient{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_GetRibClient interface { + Recv() (*Destination, error) + grpc.ClientStream +} + +type grpcGetRibClient struct { + grpc.ClientStream +} + +func (x *grpcGetRibClient) Recv() (*Destination, error) { + m := new(Destination) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *grpcClient) GetAdjRib(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (Grpc_GetAdjRibClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[2], c.cc, "/api.Grpc/GetAdjRib", opts...) + if err != nil { + return nil, err + } + x := &grpcGetAdjRibClient{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_GetAdjRibClient interface { + Recv() (*Path, error) + grpc.ClientStream +} + +type grpcGetAdjRibClient struct { + grpc.ClientStream +} + +func (x *grpcGetAdjRibClient) Recv() (*Path, error) { + m := new(Path) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *grpcClient) Reset(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/Reset", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) SoftReset(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/SoftReset", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) SoftResetIn(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/SoftResetIn", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) SoftResetOut(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/SoftResetOut", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) Shutdown(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/Shutdown", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) Enable(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/Enable", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) Disable(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { + out := new(Error) + err := grpc.Invoke(ctx, "/api.Grpc/Disable", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *grpcClient) AddPath(ctx context.Context, opts ...grpc.CallOption) (Grpc_AddPathClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[3], c.cc, "/api.Grpc/AddPath", opts...) + if err != nil { + return nil, err + } + x := &grpcAddPathClient{stream} + return x, nil +} + +type Grpc_AddPathClient interface { + Send(*Arguments) error + CloseAndRecv() (*Error, error) + grpc.ClientStream +} + +type grpcAddPathClient struct { + grpc.ClientStream +} + +func (x *grpcAddPathClient) Send(m *Arguments) error { + return x.ClientStream.SendMsg(m) +} + +func (x *grpcAddPathClient) CloseAndRecv() (*Error, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(Error) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *grpcClient) DeletePath(ctx context.Context, opts ...grpc.CallOption) (Grpc_DeletePathClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[4], c.cc, "/api.Grpc/DeletePath", opts...) + if err != nil { + return nil, err + } + x := &grpcDeletePathClient{stream} + return x, nil +} + +type Grpc_DeletePathClient interface { + Send(*Arguments) error + CloseAndRecv() (*Error, error) + grpc.ClientStream +} + +type grpcDeletePathClient struct { + grpc.ClientStream +} + +func (x *grpcDeletePathClient) Send(m *Arguments) error { + return x.ClientStream.SendMsg(m) +} + +func (x *grpcDeletePathClient) CloseAndRecv() (*Error, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(Error) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for Grpc service + +type GrpcServer interface { + GetNeighbors(*Arguments, Grpc_GetNeighborsServer) error + GetNeighbor(context.Context, *Arguments) (*Peer, error) + GetRib(*Arguments, Grpc_GetRibServer) error + GetAdjRib(*Arguments, Grpc_GetAdjRibServer) error + Reset(context.Context, *Arguments) (*Error, error) + SoftReset(context.Context, *Arguments) (*Error, error) + SoftResetIn(context.Context, *Arguments) (*Error, error) + SoftResetOut(context.Context, *Arguments) (*Error, error) + Shutdown(context.Context, *Arguments) (*Error, error) + Enable(context.Context, *Arguments) (*Error, error) + Disable(context.Context, *Arguments) (*Error, error) + AddPath(Grpc_AddPathServer) error + DeletePath(Grpc_DeletePathServer) error +} + +func RegisterGrpcServer(s *grpc.Server, srv GrpcServer) { + s.RegisterService(&_Grpc_serviceDesc, srv) +} + +func _Grpc_GetNeighbors_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Arguments) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GrpcServer).GetNeighbors(m, &grpcGetNeighborsServer{stream}) +} + +type Grpc_GetNeighborsServer interface { + Send(*Peer) error + grpc.ServerStream +} + +type grpcGetNeighborsServer struct { + grpc.ServerStream +} + +func (x *grpcGetNeighborsServer) Send(m *Peer) error { + return x.ServerStream.SendMsg(m) +} + +func _Grpc_GetNeighbor_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).GetNeighbor(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_GetRib_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Arguments) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GrpcServer).GetRib(m, &grpcGetRibServer{stream}) +} + +type Grpc_GetRibServer interface { + Send(*Destination) error + grpc.ServerStream +} + +type grpcGetRibServer struct { + grpc.ServerStream +} + +func (x *grpcGetRibServer) Send(m *Destination) error { + return x.ServerStream.SendMsg(m) +} + +func _Grpc_GetAdjRib_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Arguments) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GrpcServer).GetAdjRib(m, &grpcGetAdjRibServer{stream}) +} + +type Grpc_GetAdjRibServer interface { + Send(*Path) error + grpc.ServerStream +} + +type grpcGetAdjRibServer struct { + grpc.ServerStream +} + +func (x *grpcGetAdjRibServer) Send(m *Path) error { + return x.ServerStream.SendMsg(m) +} + +func _Grpc_Reset_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).Reset(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_SoftReset_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).SoftReset(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_SoftResetIn_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).SoftResetIn(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_SoftResetOut_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).SoftResetOut(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_Shutdown_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).Shutdown(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_Enable_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).Enable(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_Disable_Handler(srv interface{}, ctx context.Context, buf []byte) (interface{}, error) { + in := new(Arguments) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(GrpcServer).Disable(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _Grpc_AddPath_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GrpcServer).AddPath(&grpcAddPathServer{stream}) +} + +type Grpc_AddPathServer interface { + SendAndClose(*Error) error + Recv() (*Arguments, error) + grpc.ServerStream +} + +type grpcAddPathServer struct { + grpc.ServerStream +} + +func (x *grpcAddPathServer) SendAndClose(m *Error) error { + return x.ServerStream.SendMsg(m) +} + +func (x *grpcAddPathServer) Recv() (*Arguments, error) { + m := new(Arguments) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _Grpc_DeletePath_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GrpcServer).DeletePath(&grpcDeletePathServer{stream}) +} + +type Grpc_DeletePathServer interface { + SendAndClose(*Error) error + Recv() (*Arguments, error) + grpc.ServerStream +} + +type grpcDeletePathServer struct { + grpc.ServerStream +} + +func (x *grpcDeletePathServer) SendAndClose(m *Error) error { + return x.ServerStream.SendMsg(m) +} + +func (x *grpcDeletePathServer) Recv() (*Arguments, error) { + m := new(Arguments) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _Grpc_serviceDesc = grpc.ServiceDesc{ + ServiceName: "api.Grpc", + HandlerType: (*GrpcServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetNeighbor", + Handler: _Grpc_GetNeighbor_Handler, + }, + { + MethodName: "Reset", + Handler: _Grpc_Reset_Handler, + }, + { + MethodName: "SoftReset", + Handler: _Grpc_SoftReset_Handler, + }, + { + MethodName: "SoftResetIn", + Handler: _Grpc_SoftResetIn_Handler, + }, + { + MethodName: "SoftResetOut", + Handler: _Grpc_SoftResetOut_Handler, + }, + { + MethodName: "Shutdown", + Handler: _Grpc_Shutdown_Handler, + }, + { + MethodName: "Enable", + Handler: _Grpc_Enable_Handler, + }, + { + MethodName: "Disable", + Handler: _Grpc_Disable_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetNeighbors", + Handler: _Grpc_GetNeighbors_Handler, + ServerStreams: true, + }, + { + StreamName: "GetRib", + Handler: _Grpc_GetRib_Handler, + ServerStreams: true, + }, + { + StreamName: "GetAdjRib", + Handler: _Grpc_GetAdjRib_Handler, + ServerStreams: true, + }, + { + StreamName: "AddPath", + Handler: _Grpc_AddPath_Handler, + ClientStreams: true, + }, + { + StreamName: "DeletePath", + Handler: _Grpc_DeletePath_Handler, + ClientStreams: true, + }, + }, +} diff --git a/api/gobgp.proto b/api/gobgp.proto new file mode 100644 index 00000000..41832653 --- /dev/null +++ b/api/gobgp.proto @@ -0,0 +1,145 @@ +// Copyright (C) 2015 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package api; + +// Interface exported by the server. + +service Grpc { + rpc GetNeighbors(Arguments) returns (stream Peer) {} + rpc GetNeighbor(Arguments) returns (Peer) {} + rpc GetRib(Arguments) returns (stream Destination) {} + rpc GetAdjRib(Arguments) returns (stream Path) {} + rpc Reset(Arguments) returns (Error) {} + rpc SoftReset(Arguments) returns (Error) {} + rpc SoftResetIn(Arguments) returns (Error) {} + rpc SoftResetOut(Arguments) returns (Error) {} + rpc Shutdown(Arguments) returns (Error) {} + rpc Enable(Arguments) returns (Error) {} + rpc Disable(Arguments) returns (Error) {} + rpc AddPath(stream Arguments) returns (Error) {} + rpc DeletePath(stream Arguments) returns (Error) {} +} + +message Error { + enum ErrorCode { + SUCCESS = 0; + FAIL = 1; + } + ErrorCode code = 1; + string msg = 2; +} + +message Arguments { + Resource resource = 1; + AddressFamily af = 2; + string router_id = 3; + string prefix = 4; +} + +enum Resource { + GLOBAL = 0; + LOCAL = 1; + ADJ_IN = 2; + ADJ_OUT = 3; +} + +enum AddressFamily { + IPV4 = 0; + IPV6 = 1; + EVPN = 2; +} + +message PathAttr { + + string type = 1; + enum Origin { + IGP = 0; + EGP = 1; + INCOMPLETE = 2; + } + message Aggregator { + uint32 as = 1; + string address = 2; + } + Origin origin = 2; + repeated uint32 as_path = 3; + uint32 metric = 4; + uint32 pref = 5; + Aggregator aggregator = 6; + repeated uint32 communites = 7; + string originator = 8; + string cluster = 9; + uint32 value = 10; +} + +message Path { + string network = 1; + string nexthop = 2; + int64 age = 3; + repeated PathAttr attrs = 4; + bool best = 5; +} + +message Destination { + string prefix = 1; + repeated Path paths = 2; + int32 best_path_idx = 3; +} + +message PeerConf { + string remote_ip = 1; + string id = 2; + uint32 remote_as = 3; + bool cap_refresh = 4; + bool cap_enhanced_refresh = 5; + repeated int32 remote_cap = 6; + repeated int32 local_cap = 7; +} + +message PeerInfo { + string bgp_state = 1; + string admin_state = 2; + uint32 fsm_established_transitions = 3; + uint32 total_message_out = 4; + uint32 total_message_in = 5; + uint32 update_message_out = 6; + uint32 update_message_in = 7; + uint32 keep_alive_message_out = 8; + uint32 keep_alive_message_in = 9; + uint32 open_message_out = 10; + uint32 open_message_in = 11; + uint32 notification_out = 12; + uint32 notification_in = 13; + uint32 refresh_message_out = 14; + uint32 refresh_message_in = 15; + uint32 discarded_out = 16; + uint32 discarded_in = 17; + int64 uptime = 18; + int64 downtime = 19; + string last_error = 20; + uint32 received = 21; + uint32 accepted = 22; + uint32 advertized = 23; + uint32 out_q = 24; + uint32 flops = 25; +} + +message Peer { + PeerConf conf = 1; + PeerInfo info = 2; +} diff --git a/api/grpc.go b/api/grpc.go new file mode 100644 index 00000000..69e8d159 --- /dev/null +++ b/api/grpc.go @@ -0,0 +1,318 @@ +// Copyright (C) 2014,2015 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +import ( + "fmt" + log "github.com/Sirupsen/logrus" + "github.com/osrg/gobgp/packet" + "golang.org/x/net/context" + "google.golang.org/grpc" + "io" + "net" +) + +const ( + _ = iota + REQ_NEIGHBOR + REQ_NEIGHBORS + REQ_ADJ_RIB_IN + REQ_ADJ_RIB_OUT + REQ_LOCAL_RIB + REQ_NEIGHBOR_SHUTDOWN + REQ_NEIGHBOR_RESET + REQ_NEIGHBOR_SOFT_RESET + REQ_NEIGHBOR_SOFT_RESET_IN + REQ_NEIGHBOR_SOFT_RESET_OUT + REQ_NEIGHBOR_ENABLE + REQ_NEIGHBOR_DISABLE + REQ_GLOBAL_RIB + REQ_GLOBAL_ADD + REQ_GLOBAL_DELETE +) + +const GRPC_PORT = 8080 + +type Server struct { + grpcServer *grpc.Server + bgpServerCh chan *GrpcRequest +} + +func (s *Server) Serve() error { + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", GRPC_PORT)) + if err != nil { + return fmt.Errorf("failed to listen: %v", err) + } + s.grpcServer.Serve(lis) + return nil +} + +func (s *Server) GetNeighbor(ctx context.Context, arg *Arguments) (*Peer, error) { + var rf bgp.RouteFamily + req := NewGrpcRequest(REQ_NEIGHBOR, arg.RouterId, rf, nil) + s.bgpServerCh <- req + + res := <-req.ResponseCh + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return nil, err + } + + return res.Data.(*Peer), nil +} + +func (s *Server) GetNeighbors(_ *Arguments, stream Grpc_GetNeighborsServer) error { + var rf bgp.RouteFamily + req := NewGrpcRequest(REQ_NEIGHBORS, "", rf, nil) + s.bgpServerCh <- req + + for res := range req.ResponseCh { + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return err + } + if err := stream.Send(res.Data.(*Peer)); err != nil { + return err + } + } + + return nil +} + +func (s *Server) GetAdjRib(arg *Arguments, stream Grpc_GetAdjRibServer) error { + var reqType int + switch arg.Resource { + case Resource_ADJ_IN: + reqType = REQ_ADJ_RIB_IN + case Resource_ADJ_OUT: + reqType = REQ_ADJ_RIB_OUT + default: + return fmt.Errorf("unsupported resource type: %v", arg.Resource) + } + + var rf bgp.RouteFamily + switch arg.Af { + case AddressFamily_IPV4: + rf = bgp.RF_IPv4_UC + case AddressFamily_IPV6: + rf = bgp.RF_IPv6_UC + case AddressFamily_EVPN: + rf = bgp.RF_EVPN + default: + return fmt.Errorf("unsupported resource type: %v", arg.Af) + } + + req := NewGrpcRequest(reqType, arg.RouterId, rf, nil) + s.bgpServerCh <- req + + for res := range req.ResponseCh { + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return err + } + if err := stream.Send(res.Data.(*Path)); err != nil { + return err + } + } + + return nil +} + +func (s *Server) GetRib(arg *Arguments, stream Grpc_GetRibServer) error { + var reqType int + switch arg.Resource { + case Resource_LOCAL: + reqType = REQ_LOCAL_RIB + case Resource_GLOBAL: + reqType = REQ_GLOBAL_RIB + default: + return fmt.Errorf("unsupported resource type: %v", arg.Resource) + } + + var rf bgp.RouteFamily + switch arg.Af { + case AddressFamily_IPV4: + rf = bgp.RF_IPv4_UC + case AddressFamily_IPV6: + rf = bgp.RF_IPv6_UC + case AddressFamily_EVPN: + rf = bgp.RF_EVPN + default: + return fmt.Errorf("unsupported resource type: %v", arg.Af) + } + + req := NewGrpcRequest(reqType, arg.RouterId, rf, nil) + s.bgpServerCh <- req + + for res := range req.ResponseCh { + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return err + } + if err := stream.Send(res.Data.(*Destination)); err != nil { + return err + } + } + return nil +} + +func (s *Server) neighbor(reqType int, arg *Arguments) (*Error, error) { + var rf bgp.RouteFamily + switch arg.Af { + case AddressFamily_IPV4: + rf = bgp.RF_IPv4_UC + case AddressFamily_IPV6: + rf = bgp.RF_IPv6_UC + case AddressFamily_EVPN: + rf = bgp.RF_EVPN + default: + return nil, fmt.Errorf("unsupported resource type: %v", arg.Af) + } + + none := &Error{} + req := NewGrpcRequest(reqType, arg.RouterId, rf, nil) + s.bgpServerCh <- req + + res := <-req.ResponseCh + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return nil, err + } + return none, nil +} + +func (s *Server) Reset(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_RESET, arg) +} + +func (s *Server) SoftReset(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_SOFT_RESET, arg) +} + +func (s *Server) SoftResetIn(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_SOFT_RESET_IN, arg) +} + +func (s *Server) SoftResetOut(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_SOFT_RESET_OUT, arg) +} + +func (s *Server) Shutdown(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_SHUTDOWN, arg) +} + +func (s *Server) Enable(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_ENABLE, arg) +} + +func (s *Server) Disable(ctx context.Context, arg *Arguments) (*Error, error) { + return s.neighbor(REQ_NEIGHBOR_DISABLE, arg) +} + +func (s *Server) modPath(reqType int, stream grpc.ServerStream) error { + for { + var err error + var arg *Arguments + + if reqType == REQ_GLOBAL_ADD { + arg, err = stream.(Grpc_AddPathServer).Recv() + } else if reqType == REQ_GLOBAL_DELETE { + arg, err = stream.(Grpc_DeletePathServer).Recv() + } else { + return fmt.Errorf("unsupportd req: %d", reqType) + } + + if err == io.EOF { + return nil + } else if err != nil { + return err + } + + if arg.Resource != Resource_GLOBAL { + return fmt.Errorf("unsupported resource: %s", arg.Resource) + } + prefix := make(map[string]interface{}, 1) + prefix["prefix"] = arg.Prefix + + var rf bgp.RouteFamily + switch arg.Af { + case AddressFamily_IPV4: + rf = bgp.RF_IPv4_UC + case AddressFamily_IPV6: + rf = bgp.RF_IPv6_UC + case AddressFamily_EVPN: + rf = bgp.RF_EVPN + default: + return fmt.Errorf("unsupported resource type: %v", arg.Af) + } + + req := NewGrpcRequest(reqType, arg.RouterId, rf, prefix) + s.bgpServerCh <- req + + res := <-req.ResponseCh + if err := res.Err(); err != nil { + log.Debug(err.Error()) + return err + } + } +} + +func (s *Server) AddPath(stream Grpc_AddPathServer) error { + return s.modPath(REQ_GLOBAL_ADD, stream) +} + +func (s *Server) DeletePath(stream Grpc_DeletePathServer) error { + return s.modPath(REQ_GLOBAL_DELETE, stream) +} + +type GrpcRequest struct { + RequestType int + RemoteAddr string + RouteFamily bgp.RouteFamily + ResponseCh chan *GrpcResponse + Err error + Data map[string]interface{} +} + +func NewGrpcRequest(reqType int, remoteAddr string, rf bgp.RouteFamily, d map[string]interface{}) *GrpcRequest { + r := &GrpcRequest{ + RequestType: reqType, + RouteFamily: rf, + RemoteAddr: remoteAddr, + ResponseCh: make(chan *GrpcResponse), + Data: d, + } + return r +} + +type GrpcResponse struct { + ResponseErr error + Data interface{} +} + +func (r *GrpcResponse) Err() error { + return r.ResponseErr +} + +func NewGrpcServer(port int, bgpServerCh chan *GrpcRequest) *Server { + grpcServer := grpc.NewServer() + server := &Server{ + grpcServer: grpcServer, + bgpServerCh: bgpServerCh, + } + RegisterGrpcServer(grpcServer, server) + return server +} diff --git a/api/rest.go b/api/rest.go deleted file mode 100644 index fd57253d..00000000 --- a/api/rest.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (C) 2014,2015 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. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package api - -import ( - "bytes" - log "github.com/Sirupsen/logrus" - "github.com/fukata/golang-stats-api-handler" - "github.com/gorilla/mux" - "github.com/osrg/gobgp/packet" - "net/http" - "net/url" - "strconv" -) - -const ( - _ = iota - REQ_NEIGHBOR - REQ_NEIGHBORS - REQ_ADJ_RIB_IN - REQ_ADJ_RIB_OUT - REQ_LOCAL_RIB - REQ_NEIGHBOR_SHUTDOWN - REQ_NEIGHBOR_RESET - REQ_NEIGHBOR_SOFT_RESET - REQ_NEIGHBOR_SOFT_RESET_IN - REQ_NEIGHBOR_SOFT_RESET_OUT - REQ_NEIGHBOR_ENABLE - REQ_NEIGHBOR_DISABLE - REQ_GLOBAL_RIB - REQ_GLOBAL_ADD - REQ_GLOBAL_DELETE -) - -const ( - BASE_VERSION = "/v1" - GLOBAL = "/bgp/global" - NEIGHBOR = "/bgp/neighbor" - NEIGHBORS = "/bgp/neighbors" - - PARAM_REMOTE_PEER_ADDR = "remotePeerAddr" - PARAM_SHOW_OBJECT = "showObject" - PARAM_OPERATION = "operation" - PARAM_ROUTE_FAMILY = "routeFamily" - - STATS = "/stats" -) - -const REST_PORT = 8080 - -// trigger struct for exchanging information in the rest and peer. -// rest and peer operated at different thread. - -type RestRequest struct { - RequestType int - RemoteAddr string - RouteFamily bgp.RouteFamily - ResponseCh chan *RestResponse - Err error - Data map[string]interface{} -} - -func NewRestRequest(reqType int, remoteAddr string, rf bgp.RouteFamily, d map[string]interface{}) *RestRequest { - r := &RestRequest{ - RequestType: reqType, - RouteFamily: rf, - RemoteAddr: remoteAddr, - ResponseCh: make(chan *RestResponse), - Data: d, - } - return r -} - -type RestResponse struct { - ResponseErr error - Data []byte -} - -func (r *RestResponse) Err() error { - return r.ResponseErr -} - -type RestServer struct { - port int - bgpServerCh chan *RestRequest -} - -func NewRestServer(port int, bgpServerCh chan *RestRequest) *RestServer { - rs := &RestServer{ - port: port, - bgpServerCh: bgpServerCh} - return rs -} - -// Main thread of rest service. -// URL than can receive. -// get state of neighbors. -// -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbors -// get state of neighbor. -// -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor> -// get adj-rib-in of each neighbor. -// -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/adj-rib-in/<rf> -// get adj-rib-out of each neighbor. -// -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/adj-rib-out/<rf> -// get local-rib of each neighbor. -// -- curl -i -X GET http://<ownIP>:8080/v1/bgp/neighbor/<remote address of target neighbor>/local-rib/<rf> -func (rs *RestServer) Serve() { - global := BASE_VERSION + GLOBAL - neighbor := BASE_VERSION + NEIGHBOR - neighbors := BASE_VERSION + NEIGHBORS - - r := mux.NewRouter() - perPeerURL := "/{" + PARAM_REMOTE_PEER_ADDR + "}" - showObjectURL := "/{" + PARAM_SHOW_OBJECT + "}" - operationURL := "/{" + PARAM_OPERATION + "}" - routeFamilyURL := "/{" + PARAM_ROUTE_FAMILY + "}" - r.HandleFunc(global+showObjectURL+routeFamilyURL, rs.GlobalGET).Methods("GET") - r.HandleFunc(global+routeFamilyURL, rs.GlobalPOST).Methods("POST") - r.HandleFunc(global+routeFamilyURL, rs.GlobalDELETE).Methods("DELETE") - r.HandleFunc(neighbors, rs.NeighborGET).Methods("GET") - r.HandleFunc(neighbor+perPeerURL, rs.NeighborGET).Methods("GET") - r.HandleFunc(neighbor+perPeerURL+showObjectURL+routeFamilyURL, rs.NeighborGET).Methods("GET") - r.HandleFunc(neighbor+perPeerURL+operationURL, rs.NeighborPOST).Methods("POST") - r.HandleFunc(neighbor+perPeerURL+operationURL+routeFamilyURL, rs.NeighborPOST).Methods("POST") - - // stats - r.HandleFunc(STATS, stats_api.Handler).Methods("GET") - - // Handler when not found url - r.NotFoundHandler = http.HandlerFunc(NotFoundHandler) - http.Handle("/", r) - - http.ListenAndServe(":"+strconv.Itoa(rs.port), nil) - -} - -func (rs *RestServer) neighbor(w http.ResponseWriter, r *http.Request, reqType int) { - params := mux.Vars(r) - remoteAddr, _ := params[PARAM_REMOTE_PEER_ADDR] - log.Debugf("Look up neighbor with the remote address : %v", remoteAddr) - var rf bgp.RouteFamily - routeFamily, ok := params[PARAM_ROUTE_FAMILY] - if ok { - switch routeFamily { - case "ipv4": - rf = bgp.RF_IPv4_UC - case "ipv6": - rf = bgp.RF_IPv6_UC - case "evpn": - rf = bgp.RF_EVPN - default: - NotFoundHandler(w, r) - return - } - } - - //Send channel of request parameter. - req := NewRestRequest(reqType, remoteAddr, rf, nil) - rs.bgpServerCh <- req - - //Wait response - res := <-req.ResponseCh - if e := res.Err(); e != nil { - log.Debug(e.Error()) - http.Error(w, e.Error(), http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Write(res.Data) -} - -func (rs *RestServer) NeighborPOST(w http.ResponseWriter, r *http.Request) { - params := mux.Vars(r) - switch params[PARAM_OPERATION] { - case "shutdown": - rs.neighbor(w, r, REQ_NEIGHBOR_SHUTDOWN) - case "reset": - rs.neighbor(w, r, REQ_NEIGHBOR_RESET) - case "softreset": - rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET) - case "softresetin": - rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_IN) - case "softresetout": - rs.neighbor(w, r, REQ_NEIGHBOR_SOFT_RESET_OUT) - case "enable": - rs.neighbor(w, r, REQ_NEIGHBOR_ENABLE) - case "disable": - rs.neighbor(w, r, REQ_NEIGHBOR_DISABLE) - default: - NotFoundHandler(w, r) - } -} - -func (rs *RestServer) NeighborGET(w http.ResponseWriter, r *http.Request) { - params := mux.Vars(r) - if _, ok := params[PARAM_REMOTE_PEER_ADDR]; !ok { - rs.neighbor(w, r, REQ_NEIGHBORS) - return - } - - if showObject, ok := params[PARAM_SHOW_OBJECT]; ok { - switch showObject { - case "local-rib": - rs.neighbor(w, r, REQ_LOCAL_RIB) - case "adj-rib-in": - rs.neighbor(w, r, REQ_ADJ_RIB_IN) - case "adj-rib-out": - rs.neighbor(w, r, REQ_ADJ_RIB_OUT) - default: - NotFoundHandler(w, r) - } - } else { - rs.neighbor(w, r, REQ_NEIGHBOR) - } -} - -func (rs *RestServer) GlobalGET(w http.ResponseWriter, r *http.Request) { - params := mux.Vars(r) - if showObject, ok := params[PARAM_SHOW_OBJECT]; ok { - switch showObject { - case "rib": - rs.neighbor(w, r, REQ_GLOBAL_RIB) - default: - NotFoundHandler(w, r) - } - } - -} - -func (rs *RestServer) global(w http.ResponseWriter, r *http.Request, reqType int) { - params := mux.Vars(r) - var rf bgp.RouteFamily - routeFamily, ok := params[PARAM_ROUTE_FAMILY] - if ok { - switch routeFamily { - case "ipv4": - rf = bgp.RF_IPv4_UC - case "ipv6": - rf = bgp.RF_IPv6_UC - case "evpn": - rf = bgp.RF_EVPN - default: - NotFoundHandler(w, r) - return - } - } - var buf bytes.Buffer - buf.ReadFrom(r.Body) - query, _ := url.ParseQuery(buf.String()) - d := make(map[string]interface{}) - for k, v := range query { - d[k] = v - } - req := NewRestRequest(reqType, "", rf, d) - rs.bgpServerCh <- req - - //Wait response - res := <-req.ResponseCh - if e := res.Err(); e != nil { - log.Debug(e.Error()) - http.Error(w, e.Error(), http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Write(res.Data) -} - -func (rs *RestServer) GlobalPOST(w http.ResponseWriter, r *http.Request) { - rs.global(w, r, REQ_GLOBAL_ADD) -} - -func (rs *RestServer) GlobalDELETE(w http.ResponseWriter, r *http.Request) { - rs.global(w, r, REQ_GLOBAL_DELETE) -} - -func NotFoundHandler(w http.ResponseWriter, r *http.Request) { - http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) -} |