summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-04-04 23:46:01 +0000
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-04-14 08:10:28 +0900
commit75f835725deb42b00d5f746828f2738d15e3bc4f (patch)
tree5294cc59377f51896fd75a57cdb776f5e2f8bf54
parent18bbb843d2e025af8e1ffd33b7c9a09d1a19c565 (diff)
api: use gRPC instead of REST
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go853
-rw-r--r--api/gobgp.proto145
-rw-r--r--api/grpc.go318
-rw-r--r--api/rest.go293
-rw-r--r--gobgp/main.go713
-rw-r--r--gobgpd/main.go6
-rw-r--r--packet/bgp.go2
-rw-r--r--server/peer.go243
-rw-r--r--server/peer_test.go101
-rw-r--r--server/server.go60
-rw-r--r--table/destination.go8
-rw-r--r--table/path.go16
-rw-r--r--test/scenario_test/bgp_router_test.py22
-rw-r--r--test/scenario_test/constant.py27
-rw-r--r--test/scenario_test/docker_control.py70
-rw-r--r--test/scenario_test/gobgp_test.py140
-rw-r--r--test/scenario_test/peer_info.py19
-rw-r--r--test/scenario_test/route_server_ipv4_v6_test.py13
-rw-r--r--test/scenario_test/route_server_malformed_test.py12
-rw-r--r--test/scenario_test/route_server_policy_test.py133
-rw-r--r--test/scenario_test/route_server_test.py34
-rw-r--r--test/scenario_test/scenario_test_util.py201
22 files changed, 2221 insertions, 1208 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)
-}
diff --git a/gobgp/main.go b/gobgp/main.go
index fd761da2..3f6f4e81 100644
--- a/gobgp/main.go
+++ b/gobgp/main.go
@@ -16,58 +16,21 @@
package main
import (
+ "bytes"
"encoding/json"
"fmt"
"github.com/jessevdk/go-flags"
- "github.com/parnurzeal/gorequest"
+ "github.com/osrg/gobgp/api"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "io"
"net"
- "net/http"
"os"
"sort"
+ "strings"
+ "time"
)
-func isError(resp *http.Response) bool {
- return resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated
-}
-
-func execute(resource string, callback func(url string, r *gorequest.SuperAgent) *gorequest.SuperAgent) []byte {
- r := gorequest.New()
- url := globalOpts.URL + ":" + fmt.Sprint(globalOpts.Port) + "/v1/bgp/" + resource
- if globalOpts.Debug {
- fmt.Println(url)
- }
- r = callback(url, r)
- resp, body, err := r.End()
- if err != nil {
- fmt.Print("Failed to connect to gobgpd. It runs?\n")
- if globalOpts.Debug {
- fmt.Println(err)
- }
- os.Exit(1)
- }
- if globalOpts.Debug || isError(resp) {
- fmt.Println(body)
- if isError(resp) {
- os.Exit(1)
- }
- }
- return []byte(body)
-}
-
-func post(resource string) []byte {
- f := func(url string, r *gorequest.SuperAgent) *gorequest.SuperAgent {
- return r.Post(url)
- }
- return execute(resource, f)
-}
-
-func get(resource string) []byte {
- f := func(url string, r *gorequest.SuperAgent) *gorequest.SuperAgent {
- return r.Get(url)
- }
- return execute(resource, f)
-}
-
func formatTimedelta(d int64) string {
u := uint64(d)
neg := d < 0
@@ -89,115 +52,92 @@ func formatTimedelta(d int64) string {
}
}
-type PeerConf struct {
- RemoteIP string `json:"remote_ip"`
- Id string `json:"id"`
- RemoteAS uint32 `json:"remote_as"`
- CapRefresh bool `json:"cap_refresh"`
- CapEnhancedRefresh bool `json:"cap_enhanced_refresh"`
- RemoteCap []int
- LocalCap []int
-}
-
-type PeerInfo struct {
- BgpState string `json:"bgp_state"`
- AdminState string
- FsmEstablishedTransitions uint32 `json:"fsm_established_transitions"`
- TotalMessageOut uint32 `json:"total_message_out"`
- TotalMessageIn uint32 `json:"total_message_in"`
- UpdateMessageOut uint32 `json:"update_message_out"`
- UpdateMessageIn uint32 `json:"update_message_in"`
- KeepAliveMessageOut uint32 `json:"keepalive_message_out"`
- KeepAliveMessageIn uint32 `json:"keepalive_message_in"`
- OpenMessageOut uint32 `json:"open_message_out"`
- OpenMessageIn uint32 `json:"open_message_in"`
- NotificationOut uint32 `json:"notification_out"`
- NotificationIn uint32 `json:"notification_in"`
- RefreshMessageOut uint32 `json:"refresh_message_out"`
- RefreshMessageIn uint32 `json:"refresh_message_in"`
- DiscardedOut uint32
- DiscardedIn uint32
- Uptime int64 `json:"uptime"`
- Downtime int64 `json:"downtime"`
- LastError string `json:"last_error"`
- Received uint32
- Accepted uint32
- Advertized uint32
- OutQ int
- Flops uint32
-}
-
-type peer struct {
- Conf PeerConf
- Info PeerInfo
-}
+var client api.GrpcClient
type ShowNeighborCommand struct {
}
-func showNeighbor(args []string) {
- p := peer{}
- b := get("neighbor/" + args[0])
- e := json.Unmarshal(b, &p)
+func showNeighbor(args []string) error {
+ id := &api.Arguments{
+ RouterId: args[0],
+ }
+ p, e := client.GetNeighbor(context.Background(), id)
if e != nil {
fmt.Println(e)
- } else {
- fmt.Printf("BGP neighbor is %s, remote AS %d\n", p.Conf.RemoteIP, p.Conf.RemoteAS)
- fmt.Printf(" BGP version 4, remote router ID %s\n", p.Conf.Id)
- fmt.Printf(" BGP state = %s, up for %s\n", p.Info.BgpState, formatTimedelta(p.Info.Uptime))
- fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.Info.OutQ, p.Info.Flops)
- fmt.Printf(" Neighbor capabilities:\n")
- caps := []int{}
- lookup := func(val int, l []int) bool {
- for _, v := range l {
- if v == val {
- return true
- }
+ return e
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(p)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ fmt.Printf("BGP neighbor is %s, remote AS %d\n", p.Conf.RemoteIp, p.Conf.RemoteAs)
+ fmt.Printf(" BGP version 4, remote router ID %s\n", p.Conf.Id)
+ fmt.Printf(" BGP state = %s, up for %s\n", p.Info.BgpState, formatTimedelta(p.Info.Uptime))
+ fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.Info.OutQ, p.Info.Flops)
+ fmt.Printf(" Neighbor capabilities:\n")
+ caps := []int32{}
+ lookup := func(val int32, l []int32) bool {
+ for _, v := range l {
+ if v == val {
+ return true
}
- return false
}
- caps = append(caps, p.Conf.LocalCap...)
- for _, v := range p.Conf.RemoteCap {
- if !lookup(v, caps) {
- caps = append(caps, v)
- }
+ return false
+ }
+ caps = append(caps, p.Conf.LocalCap...)
+ for _, v := range p.Conf.RemoteCap {
+ if !lookup(v, caps) {
+ caps = append(caps, v)
}
+ }
- sort.Sort(sort.IntSlice(caps))
- capdict := map[int]string{1: "MULTIPROTOCOL",
- 2: "ROUTE_REFRESH",
- 4: "CARRYING_LABEL_INFO",
- 64: "GRACEFUL_RESTART",
- 65: "FOUR_OCTET_AS_NUMBER",
- 70: "ENHANCED_ROUTE_REFRESH",
- 128: "ROUTE_REFRESH_CISCO"}
- for _, c := range caps {
- k, found := capdict[c]
- if !found {
- k = "UNKNOWN (" + fmt.Sprint(c) + ")"
- }
- support := ""
- if lookup(c, p.Conf.LocalCap) {
- support += "advertised"
- }
- if lookup(c, p.Conf.RemoteCap) {
- if len(support) != 0 {
- support += " and "
- }
- support += "received"
+ toInt := func(arg []int32) []int {
+ ret := make([]int, 0, len(arg))
+ for _, v := range arg {
+ ret = append(ret, int(v))
+ }
+ return ret
+ }
+
+ sort.Sort(sort.IntSlice(toInt(caps)))
+ capdict := map[int]string{1: "MULTIPROTOCOL",
+ 2: "ROUTE_REFRESH",
+ 4: "CARRYING_LABEL_INFO",
+ 64: "GRACEFUL_RESTART",
+ 65: "FOUR_OCTET_AS_NUMBER",
+ 70: "ENHANCED_ROUTE_REFRESH",
+ 128: "ROUTE_REFRESH_CISCO"}
+ for _, c := range caps {
+ k, found := capdict[int(c)]
+ if !found {
+ k = "UNKNOWN (" + fmt.Sprint(c) + ")"
+ }
+ support := ""
+ if lookup(c, p.Conf.LocalCap) {
+ support += "advertised"
+ }
+ if lookup(c, p.Conf.RemoteCap) {
+ if len(support) != 0 {
+ support += " and "
}
- fmt.Printf(" %s: %s\n", k, support)
- }
- fmt.Print(" Message statistics:\n")
- fmt.Print(" Sent Rcvd\n")
- fmt.Printf(" Opens: %10d %10d\n", p.Info.OpenMessageOut, p.Info.OpenMessageIn)
- fmt.Printf(" Notifications: %10d %10d\n", p.Info.NotificationOut, p.Info.NotificationIn)
- fmt.Printf(" Updates: %10d %10d\n", p.Info.UpdateMessageOut, p.Info.UpdateMessageIn)
- fmt.Printf(" Keepalives: %10d %10d\n", p.Info.KeepAliveMessageOut, p.Info.KeepAliveMessageIn)
- fmt.Printf(" Route Refesh: %10d %10d\n", p.Info.RefreshMessageOut, p.Info.RefreshMessageIn)
- fmt.Printf(" Discarded: %10d %10d\n", p.Info.DiscardedOut, p.Info.DiscardedIn)
- fmt.Printf(" Total: %10d %10d\n", p.Info.TotalMessageOut, p.Info.TotalMessageIn)
+ support += "received"
+ }
+ fmt.Printf(" %s: %s\n", k, support)
}
+ fmt.Print(" Message statistics:\n")
+ fmt.Print(" Sent Rcvd\n")
+ fmt.Printf(" Opens: %10d %10d\n", p.Info.OpenMessageOut, p.Info.OpenMessageIn)
+ fmt.Printf(" Notifications: %10d %10d\n", p.Info.NotificationOut, p.Info.NotificationIn)
+ fmt.Printf(" Updates: %10d %10d\n", p.Info.UpdateMessageOut, p.Info.UpdateMessageIn)
+ fmt.Printf(" Keepalives: %10d %10d\n", p.Info.KeepAliveMessageOut, p.Info.KeepAliveMessageIn)
+ fmt.Printf(" Route Refesh: %10d %10d\n", p.Info.RefreshMessageOut, p.Info.RefreshMessageIn)
+ fmt.Printf(" Discarded: %10d %10d\n", p.Info.DiscardedOut, p.Info.DiscardedIn)
+ fmt.Printf(" Total: %10d %10d\n", p.Info.TotalMessageOut, p.Info.TotalMessageIn)
+
+ return nil
}
func (x *ShowNeighborCommand) Execute(args []string) error {
@@ -211,9 +151,9 @@ func (x *ShowNeighborCommand) Execute(args []string) error {
showNeighbor(args)
} else {
parser := flags.NewParser(nil, flags.Default)
- parser.AddCommand("local", "", "", NewShowNeighborRibCommand(args[0], "local-rib"))
- parser.AddCommand("adj-in", "", "", NewShowNeighborRibCommand(args[0], "adj-rib-in"))
- parser.AddCommand("adj-out", "", "", NewShowNeighborRibCommand(args[0], "adj-rib-out"))
+ parser.AddCommand("local", "", "", NewShowNeighborRibCommand(args[0], api.Resource_LOCAL))
+ parser.AddCommand("adj-in", "", "", NewShowNeighborRibCommand(args[0], api.Resource_ADJ_IN))
+ parser.AddCommand("adj-out", "", "", NewShowNeighborRibCommand(args[0], api.Resource_ADJ_OUT))
if _, err := parser.ParseArgs(args[1:]); err != nil {
os.Exit(1)
}
@@ -223,18 +163,10 @@ func (x *ShowNeighborCommand) Execute(args []string) error {
type ShowNeighborRibCommand struct {
remoteIP net.IP
- resource string
+ resource api.Resource
}
-type path struct {
- Network string
- Nexthop string
- Age float64
- Attrs []map[string]interface{}
- best bool
-}
-
-func showRoute(pathList []path, showAge bool, showBest bool) {
+func showRoute(pathList []*api.Path, showAge bool, showBest bool) {
var format string
if showAge {
format = "%-2s %-18s %-15s %-10s %-10s %-s\n"
@@ -245,28 +177,35 @@ func showRoute(pathList []path, showAge bool, showBest bool) {
}
for _, p := range pathList {
- aspath := func(attrs []map[string]interface{}) string {
+ aspath := func(attrs []*api.PathAttr) string {
+ s := bytes.NewBuffer(make([]byte, 0, 64))
+ s.WriteString("[")
for _, a := range attrs {
- if a["Type"] == "BGP_ATTR_TYPE_AS_PATH" {
- return fmt.Sprint(a["AsPath"])
+ if a.Type == "BGP_ATTR_TYPE_AS_PATH" {
+ var ss []string
+ for _, as := range a.AsPath {
+ ss = append(ss, fmt.Sprintf("%d", as))
+ }
+ s.WriteString(strings.Join(ss, " "))
}
}
- return ""
+ s.WriteString("]")
+ return s.String()
}
- formatAttrs := func(attrs []map[string]interface{}) string {
+ formatAttrs := func(attrs []*api.PathAttr) string {
s := []string{}
for _, a := range attrs {
- switch a["Type"] {
+ switch a.Type {
case "BGP_ATTR_TYPE_ORIGIN":
- s = append(s, fmt.Sprintf("{Origin: %v}", a["Value"]))
+ s = append(s, fmt.Sprintf("{Origin: %s}", a.Origin))
case "BGP_ATTR_TYPE_MULTI_EXIT_DISC":
- s = append(s, fmt.Sprintf("{Med: %v}", a["Metric"]))
+ s = append(s, fmt.Sprintf("{Med: %d}", a.Metric))
case "BGP_ATTR_TYPE_LOCAL_PREF":
- s = append(s, fmt.Sprintf("{LocalPref: %v}", a["Pref"]))
+ s = append(s, fmt.Sprintf("{LocalPref: %v}", a.Pref))
case "BGP_ATTR_TYPE_ATOMIC_AGGREGATE":
s = append(s, "AtomicAggregate")
- case "BGP_ATTR_TYPE_AGGREGATE":
- s = append(s, fmt.Sprintf("{Aggregate: {AS: %v, Address: %v}", a["AS"], a["Address"]))
+ case "BGP_ATTR_TYPE_AGGREGATOR":
+ s = append(s, fmt.Sprintf("{Aggregate: {AS: %d, Address: %s}", a.GetAggregator().As, a.GetAggregator().Address))
case "BGP_ATTR_TYPE_COMMUNITIES":
l := []string{}
known := map[uint32]string{
@@ -283,8 +222,7 @@ func showRoute(pathList []path, showAge bool, showBest bool) {
0xFFFFFF03: "NO_EXPORT_SUBCONFED",
0xFFFFFF04: "NOPEER"}
- for _, vv := range a["Value"].([]interface{}) {
- v := uint32(vv.(float64))
+ for _, v := range a.Communites {
k, found := known[v]
if found {
l = append(l, fmt.Sprint(k))
@@ -294,96 +232,123 @@ func showRoute(pathList []path, showAge bool, showBest bool) {
}
s = append(s, fmt.Sprintf("{Cummunity: %v}", l))
case "BGP_ATTR_TYPE_ORIGINATOR_ID":
- s = append(s, fmt.Sprintf("{Originator: %v|", a["Address"]))
+ s = append(s, fmt.Sprintf("{Originator: %v|", a.Originator))
case "BGP_ATTR_TYPE_CLUSTER_LIST":
- s = append(s, fmt.Sprintf("{Cluster: %v|", a["Address"]))
+ s = append(s, fmt.Sprintf("{Cluster: %v|", a.Cluster))
case "BGP_ATTR_TYPE_AS4_PATH", "BGP_ATTR_TYPE_MP_UNREACH_NLRI", "BGP_ATTR_TYPE_MP_REACH_NLRI", "BGP_ATTR_TYPE_NEXT_HOP", "BGP_ATTR_TYPE_AS_PATH":
default:
- s = append(s, fmt.Sprintf("{%v: %v}", a["Type"], a["Value"]))
+ s = append(s, fmt.Sprintf("{%v: %v}", a.Type, a.Value))
}
}
return fmt.Sprint(s)
}
best := ""
if showBest {
- if p.best {
+ if p.Best {
best = "*>"
} else {
best = "* "
}
}
if showAge {
- fmt.Printf(format, best, p.Network, p.Nexthop, aspath(p.Attrs), formatTimedelta(int64(p.Age)), formatAttrs(p.Attrs))
+ fmt.Printf(format, best, p.Network, p.Nexthop, aspath(p.Attrs), formatTimedelta(p.Age), formatAttrs(p.Attrs))
} else {
fmt.Printf(format, best, p.Network, p.Nexthop, aspath(p.Attrs), formatAttrs(p.Attrs))
}
}
}
-func showRibCommand(isAdj, showAge, showBest bool, b []byte) {
- type dest struct {
- Prefix string
- Paths []path
- BestPathIdx int
- }
- type local struct {
- Destinations []dest
- }
-
- m := []path{}
- var e error
- if isAdj == false {
- l := local{}
- e = json.Unmarshal(b, &l)
- if e == nil {
- for _, d := range l.Destinations {
- for i, p := range d.Paths {
- if i == d.BestPathIdx {
- p.best = true
- }
- m = append(m, p)
- }
- }
- }
- } else {
- e = json.Unmarshal(b, &m)
- }
- if e != nil {
- return
- }
- showRoute(m, showAge, showBest)
-}
-
func (x *ShowNeighborRibCommand) Execute(args []string) error {
- var rt string
+ var rt api.AddressFamily
if len(args) == 0 {
if x.remoteIP.To4() != nil {
- rt = "ipv4"
+ rt = api.AddressFamily_IPV4
} else {
- rt = "ipv6"
+ rt = api.AddressFamily_IPV6
}
} else {
- rt = args[0]
+ switch args[0] {
+ case "ipv4":
+ rt = api.AddressFamily_IPV4
+ case "ipv6":
+ rt = api.AddressFamily_IPV6
+ case "evpn":
+ rt = api.AddressFamily_EVPN
+ }
+ }
+
+ arg := &api.Arguments{
+ Resource: x.resource,
+ Af: rt,
+ RouterId: x.remoteIP.String(),
}
- b := get("neighbor/" + x.remoteIP.String() + "/" + x.resource + "/" + rt)
- isAdj := false
+ ps := []*api.Path{}
showBest := false
showAge := true
- if x.resource == "adj-rib-out" || x.resource == "adj-rib-in" {
- isAdj = true
- if x.resource == "adj-rib-out" {
- showAge = false
- }
- }
- if x.resource == "local-rib" {
+
+ switch x.resource {
+ case api.Resource_LOCAL:
showBest = true
+ stream, e := client.GetRib(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+
+ ds := []*api.Destination{}
+ for {
+ d, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ ds = append(ds, d)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ds)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ for _, d := range ds {
+ for idx, p := range d.Paths {
+ if idx == int(d.BestPathIdx) {
+ p.Best = true
+ }
+ ps = append(ps, p)
+ }
+ }
+ case api.Resource_ADJ_OUT:
+ showAge = false
+ fallthrough
+ case api.Resource_ADJ_IN:
+ stream, e := client.GetAdjRib(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+ for {
+ p, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ ps = append(ps, p)
+ }
+ if globalOpts.Json {
+ j, _ := json.Marshal(ps)
+ fmt.Println(string(j))
+ return nil
+ }
}
- showRibCommand(isAdj, showAge, showBest, b)
+
+ showRoute(ps, showAge, showBest)
return nil
}
-func NewShowNeighborRibCommand(addr, resource string) *ShowNeighborRibCommand {
+func NewShowNeighborRibCommand(addr string, resource api.Resource) *ShowNeighborRibCommand {
return &ShowNeighborRibCommand{
remoteIP: net.ParseIP(addr),
resource: resource,
@@ -394,70 +359,86 @@ type ShowNeighborsCommand struct {
}
func (x *ShowNeighborsCommand) Execute(args []string) error {
- m := []peer{}
- b := get("neighbors")
- e := json.Unmarshal(b, &m)
+ arg := &api.Arguments{}
+ stream, e := client.GetNeighbors(context.Background(), arg)
if e != nil {
fmt.Println(e)
- } else {
- if globalOpts.Quiet {
- for _, p := range m {
- fmt.Println(p.Conf.RemoteIP)
- }
- return nil
+ return e
+ }
+ m := []*api.Peer{}
+ for {
+ p, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
}
- maxaddrlen := 0
- maxaslen := 0
- maxtimelen := len("Up/Down")
- timedelta := []string{}
- for _, p := range m {
- if len(p.Conf.RemoteIP) > maxaddrlen {
- maxaddrlen = len(p.Conf.RemoteIP)
- }
+ m = append(m, p)
+ }
- if len(fmt.Sprint(p.Conf.RemoteAS)) > maxaslen {
- maxaslen = len(fmt.Sprint(p.Conf.RemoteAS))
- }
- var t string
- if p.Info.Uptime == 0 {
- t = "never"
- } else if p.Info.BgpState == "BGP_FSM_ESTABLISHED" {
- t = formatTimedelta(p.Info.Uptime)
- } else {
- t = formatTimedelta(p.Info.Downtime)
- }
- if len(t) > maxtimelen {
- maxtimelen = len(t)
- }
- timedelta = append(timedelta, t)
- }
- var format string
- format = "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s"
- format += " %-11s |%11s %8s %8s\n"
- fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Advertised", "Received", "Accepted")
- format_fsm := func(admin, fsm string) string {
- if admin == "ADMIN_STATE_DOWN" {
- return "Idle(Admin)"
- }
+ if globalOpts.Json {
+ j, _ := json.Marshal(m)
+ fmt.Println(string(j))
+ return nil
+ }
- if fsm == "BGP_FSM_IDLE" {
- return "Idle"
- } else if fsm == "BGP_FSM_CONNECT" {
- return "Connect"
- } else if fsm == "BGP_FSM_ACTIVE" {
- return "Active"
- } else if fsm == "BGP_FSM_OPENSENT" {
- return "Sent"
- } else if fsm == "BGP_FSM_OPENCONFIRM" {
- return "Confirm"
- } else {
- return "Establ"
- }
+ if globalOpts.Quiet {
+ for _, p := range m {
+ fmt.Println(p.Conf.RemoteIp)
+ }
+ return nil
+ }
+ maxaddrlen := 0
+ maxaslen := 0
+ maxtimelen := len("Up/Down")
+ timedelta := []string{}
+ for _, p := range m {
+ if len(p.Conf.RemoteIp) > maxaddrlen {
+ maxaddrlen = len(p.Conf.RemoteIp)
}
- for i, p := range m {
- fmt.Printf(format, p.Conf.RemoteIP, fmt.Sprint(p.Conf.RemoteAS), timedelta[i], format_fsm(p.Info.AdminState, p.Info.BgpState), fmt.Sprint(p.Info.Advertized), fmt.Sprint(p.Info.Received), fmt.Sprint(p.Info.Accepted))
+ if len(fmt.Sprint(p.Conf.RemoteAs)) > maxaslen {
+ maxaslen = len(fmt.Sprint(p.Conf.RemoteAs))
}
+ var t string
+ if p.Info.Uptime == 0 {
+ t = "never"
+ } else if p.Info.BgpState == "BGP_FSM_ESTABLISHED" {
+ t = formatTimedelta(p.Info.Uptime)
+ } else {
+ t = formatTimedelta(p.Info.Downtime)
+ }
+ if len(t) > maxtimelen {
+ maxtimelen = len(t)
+ }
+ timedelta = append(timedelta, t)
+ }
+ var format string
+ format = "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s"
+ format += " %-11s |%11s %8s %8s\n"
+ fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Advertised", "Received", "Accepted")
+ format_fsm := func(admin, fsm string) string {
+ if admin == "ADMIN_STATE_DOWN" {
+ return "Idle(Admin)"
+ }
+
+ if fsm == "BGP_FSM_IDLE" {
+ return "Idle"
+ } else if fsm == "BGP_FSM_CONNECT" {
+ return "Connect"
+ } else if fsm == "BGP_FSM_ACTIVE" {
+ return "Active"
+ } else if fsm == "BGP_FSM_OPENSENT" {
+ return "Sent"
+ } else if fsm == "BGP_FSM_OPENCONFIRM" {
+ return "Confirm"
+ } else {
+ return "Establ"
+ }
+ }
+
+ for i, p := range m {
+ fmt.Printf(format, p.Conf.RemoteIp, fmt.Sprint(p.Conf.RemoteAs), timedelta[i], format_fsm(p.Info.AdminState, p.Info.BgpState), fmt.Sprint(p.Info.Advertized), fmt.Sprint(p.Info.Received), fmt.Sprint(p.Info.Accepted))
}
return nil
@@ -467,14 +448,56 @@ type ShowGlobalCommand struct {
}
func (x *ShowGlobalCommand) Execute(args []string) error {
- var rt string
+ var rt api.AddressFamily
if len(args) == 0 {
- rt = "ipv4"
+ rt = api.AddressFamily_IPV4
} else {
- rt = args[0]
+ switch args[0] {
+ case "ipv4":
+ rt = api.AddressFamily_IPV4
+ case "ipv6":
+ rt = api.AddressFamily_IPV6
+ case "evpn":
+ rt = api.AddressFamily_EVPN
+ }
+ }
+
+ arg := &api.Arguments{
+ Resource: api.Resource_GLOBAL,
+ Af: rt,
+ }
+ stream, e := client.GetRib(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+ ds := []*api.Destination{}
+ for {
+ d, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ ds = append(ds, d)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ds)
+ fmt.Println(string(j))
+ return nil
}
- b := get("global/rib/" + rt)
- showRibCommand(false, true, true, b)
+
+ ps := []*api.Path{}
+ for _, d := range ds {
+ for idx, p := range d.Paths {
+ if idx == int(d.BestPathIdx) {
+ p.Best = true
+ }
+ ps = append(ps, p)
+ }
+ }
+
+ showRoute(ps, true, true)
return nil
}
@@ -497,10 +520,54 @@ type ResetCommand struct {
}
func (x *ResetCommand) Execute(args []string) error {
- if len(args) != 2 {
- return nil
+ if len(args) < 2 {
+ return fmt.Errorf("usage: %s neighbor <router_id> [ipv4|ipv6]", x.resource)
+ }
+
+ var rt api.AddressFamily
+ switch x.resource {
+ case "softreset", "softresetin", "softresetout":
+ if len(args) == 2 {
+ rt = api.AddressFamily_IPV4
+ } else {
+ switch args[2] {
+ case "ipv4":
+ rt = api.AddressFamily_IPV4
+ case "ipv6":
+ rt = api.AddressFamily_IPV6
+ case "evpn":
+ rt = api.AddressFamily_EVPN
+ default:
+ return fmt.Errorf("unsupported rf: %s", args[2])
+ }
+ }
+ }
+
+ arg := &api.Arguments{
+ RouterId: args[1],
+ Af: rt,
+ }
+
+ fmt.Println(arg)
+
+ switch x.resource {
+ case "reset":
+ client.Reset(context.Background(), arg)
+ case "softreset":
+ client.SoftReset(context.Background(), arg)
+ case "softresetin":
+ client.SoftResetIn(context.Background(), arg)
+ case "softresetout":
+ client.SoftResetOut(context.Background(), arg)
+ case "shutdown":
+ client.Shutdown(context.Background(), arg)
+ case "enable":
+ client.Enable(context.Background(), arg)
+ case "disable":
+ client.Disable(context.Background(), arg)
+ default:
+ return fmt.Errorf("unsupported command: %s", x.resource)
}
- post("neighbor/" + args[1] + "/" + x.resource)
return nil
}
@@ -510,15 +577,87 @@ func NewResetCommand(resource string) *ResetCommand {
}
}
+type PathCommand struct {
+ modtype string
+}
+
+func (x *PathCommand) Execute(args []string) error {
+ if len(args) != 3 {
+ return fmt.Errorf("usage: %s global <af> <prefix>", x.modtype)
+ }
+ var rt api.AddressFamily
+ switch args[1] {
+ case "ipv4":
+ rt = api.AddressFamily_IPV4
+ case "ipv6":
+ rt = api.AddressFamily_IPV6
+ case "evpn":
+ rt = api.AddressFamily_EVPN
+ }
+
+ arg := &api.Arguments{
+ Resource: api.Resource_GLOBAL,
+ Af: rt,
+ Prefix: args[2],
+ }
+
+ switch x.modtype {
+ case "add":
+ stream, err := client.AddPath(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ _, err = stream.CloseAndRecv()
+ if err != nil {
+ return err
+ }
+ case "delete":
+ stream, err := client.DeletePath(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ _, err = stream.CloseAndRecv()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func NewPathCommand(modtype string) *PathCommand {
+ return &PathCommand{
+ modtype: modtype,
+ }
+}
+
var globalOpts struct {
- URL string `short:"u" long:"url" description:"specifying an url" default:"http://127.0.0.1"`
+ 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"`
Debug bool `short:"d" long:"debug"`
Quiet bool `short:"q" long:"quiet"`
+ Json bool `short:"j" long:"json"`
}
func main() {
parser := flags.NewParser(&globalOpts, flags.Default)
+ parser.Parse()
+ timeout := grpc.WithTimeout(time.Second)
+ conn, err := grpc.Dial(fmt.Sprintf("%s:%d", globalOpts.Host, globalOpts.Port), timeout)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ defer conn.Close()
+ client = api.NewGrpcClient(conn)
+
parser.AddCommand("show", "show stuff", "get information", &ShowCommand{})
parser.AddCommand("reset", "show stuff", "get information", NewResetCommand("reset"))
parser.AddCommand("softreset", "show stuff", "get information", NewResetCommand("softreset"))
@@ -527,6 +666,8 @@ func main() {
parser.AddCommand("shutdown", "show stuff", "get information", NewResetCommand("shutdown"))
parser.AddCommand("enable", "show stuff", "get information", NewResetCommand("enable"))
parser.AddCommand("disable", "show stuff", "get information", NewResetCommand("disable"))
+ parser.AddCommand("add", "show stuff", "get information", NewPathCommand("add"))
+ parser.AddCommand("delete", "show stuff", "get information", NewPathCommand("delete"))
if _, err := parser.Parse(); err != nil {
fmt.Println(err)
diff --git a/gobgpd/main.go b/gobgpd/main.go
index 090828eb..e8922226 100644
--- a/gobgpd/main.go
+++ b/gobgpd/main.go
@@ -143,9 +143,9 @@ func main() {
bgpServer := server.NewBgpServer(bgp.BGP_PORT)
go bgpServer.Serve()
- // start Rest Server
- restServer := api.NewRestServer(api.REST_PORT, bgpServer.RestReqCh)
- go restServer.Serve()
+ // start grpc Server
+ grpcServer := api.NewGrpcServer(api.GRPC_PORT, bgpServer.GrpcReqCh)
+ go grpcServer.Serve()
var bgpConfig *config.Bgp = nil
var policyConfig *config.RoutingPolicy = nil
diff --git a/packet/bgp.go b/packet/bgp.go
index 464ec018..84169bcc 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -1894,7 +1894,7 @@ func (p *PathAttributeAsPath) MarshalJSON() ([]byte, error) {
}
return json.Marshal(struct {
Type string
- AsPath []uint32
+ AsPath []uint32 `json:"as_path,omitempty"`
}{
Type: p.Type.String(),
AsPath: aslist,
diff --git a/server/peer.go b/server/peer.go
index 8c62d105..194998fb 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -288,79 +288,93 @@ func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) {
}
}
-func (peer *Peer) handleREST(restReq *api.RestRequest) {
- result := &api.RestResponse{}
- switch restReq.RequestType {
+func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) {
+ result := &api.GrpcResponse{}
+ switch grpcReq.RequestType {
case api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE:
- rf := restReq.RouteFamily
- prefixes := restReq.Data["prefix"].([]string)
+ rf := grpcReq.RouteFamily
+ prefix := grpcReq.Data["prefix"].(string)
var isWithdraw bool
- if restReq.RequestType == api.REQ_GLOBAL_DELETE {
+ if grpcReq.RequestType == api.REQ_GLOBAL_DELETE {
isWithdraw = true
}
- pList := make([]table.Path, 0, len(prefixes))
- for _, prefix := range prefixes {
- var nlri bgp.AddrPrefixInterface
- pattr := make([]bgp.PathAttributeInterface, 0)
- pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
- asparam := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{peer.peerInfo.AS})
- pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam}))
-
- if rf == bgp.RF_IPv4_UC {
- ip, net, _ := net.ParseCIDR(prefix)
- if ip.To4() == nil {
- result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", prefix)
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
- return
- }
- ones, _ := net.Mask.Size()
- nlri = &bgp.NLRInfo{
- IPAddrPrefix: *bgp.NewIPAddrPrefix(uint8(ones), ip.String()),
- }
+ var nlri bgp.AddrPrefixInterface
+ pattr := make([]bgp.PathAttributeInterface, 0)
+ pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
+ asparam := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{peer.peerInfo.AS})
+ pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam}))
- pattr = append(pattr, bgp.NewPathAttributeNextHop("0.0.0.0"))
-
- } else if rf == bgp.RF_IPv6_UC {
- ip, net, _ := net.ParseCIDR(prefix)
- if ip.To16() == nil {
- result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", prefix)
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
- return
- }
- ones, _ := net.Mask.Size()
- nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String())
+ if rf == bgp.RF_IPv4_UC {
+ ip, net, _ := net.ParseCIDR(prefix)
+ if ip.To4() == nil {
+ result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", prefix)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return
+ }
+ ones, _ := net.Mask.Size()
+ nlri = &bgp.NLRInfo{
+ IPAddrPrefix: *bgp.NewIPAddrPrefix(uint8(ones), ip.String()),
+ }
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
+ pattr = append(pattr, bgp.NewPathAttributeNextHop("0.0.0.0"))
- } else {
- result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf)
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
+ } else if rf == bgp.RF_IPv6_UC {
+ ip, net, _ := net.ParseCIDR(prefix)
+ if ip.To16() == nil {
+ result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", prefix)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
return
}
+ ones, _ := net.Mask.Size()
+ nlri = bgp.NewIPv6AddrPrefix(uint8(ones), ip.String())
- p := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now())
- pList = append(pList, p)
+ pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
+
+ } else {
+ result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return
}
+ p := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now())
+
pm := &peerMsg{
msgType: PEER_MSG_PATH,
- msgData: pList,
+ msgData: []table.Path{p},
}
peer.peerMsgCh <- pm
case api.REQ_LOCAL_RIB, api.REQ_GLOBAL_RIB:
- // just empty so we use ipv4 for any route family
- j, _ := json.Marshal(table.NewIPv4Table(0))
- if peer.fsm.adminState != ADMIN_STATE_DOWN {
- if t, ok := peer.rib.Tables[restReq.RouteFamily]; ok {
- j, _ = json.Marshal(t)
+ if peer.fsm.adminState == ADMIN_STATE_DOWN {
+ close(grpcReq.ResponseCh)
+ return
+ }
+ if t, ok := peer.rib.Tables[grpcReq.RouteFamily]; ok {
+ type table struct {
+ Destinations []*api.Destination
+ }
+ var tt table
+ j, _ := json.Marshal(t)
+ err := json.Unmarshal(j, &tt)
+ if err != nil {
+ result := &api.GrpcResponse{}
+ result.ResponseErr = err
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return
+ }
+ for _, dst := range tt.Destinations {
+ result := &api.GrpcResponse{}
+ result.Data = dst
+ grpcReq.ResponseCh <- result
}
+ close(grpcReq.ResponseCh)
+ return
}
- result.Data = j
case api.REQ_NEIGHBOR_SHUTDOWN:
peer.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, nil)
case api.REQ_NEIGHBOR_RESET:
@@ -368,40 +382,55 @@ func (peer *Peer) handleREST(restReq *api.RestRequest) {
peer.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, nil)
case api.REQ_NEIGHBOR_SOFT_RESET, api.REQ_NEIGHBOR_SOFT_RESET_IN:
// soft-reconfiguration inbound
- peer.sendPathsToSiblings(peer.adjRib.GetInPathList(restReq.RouteFamily))
- if restReq.RequestType == api.REQ_NEIGHBOR_SOFT_RESET_IN {
+ peer.sendPathsToSiblings(peer.adjRib.GetInPathList(grpcReq.RouteFamily))
+ if grpcReq.RequestType == api.REQ_NEIGHBOR_SOFT_RESET_IN {
break
}
fallthrough
case api.REQ_NEIGHBOR_SOFT_RESET_OUT:
- pathList := peer.adjRib.GetOutPathList(restReq.RouteFamily)
+ pathList := peer.adjRib.GetOutPathList(grpcReq.RouteFamily)
peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList))
case api.REQ_ADJ_RIB_IN, api.REQ_ADJ_RIB_OUT:
- rf := restReq.RouteFamily
- if restReq.RequestType == api.REQ_ADJ_RIB_IN {
- paths := peer.adjRib.GetInPathList(rf)
- j, _ := json.Marshal(paths)
- result.Data = j
+ rf := grpcReq.RouteFamily
+ var paths []table.Path
+
+ if grpcReq.RequestType == api.REQ_ADJ_RIB_IN {
+ paths = peer.adjRib.GetInPathList(rf)
log.Debugf("RouteFamily=%v adj-rib-in found : %d", rf.String(), len(paths))
} else {
- paths := peer.adjRib.GetOutPathList(rf)
- j, _ := json.Marshal(paths)
- result.Data = j
+ paths = peer.adjRib.GetOutPathList(rf)
log.Debugf("RouteFamily=%v adj-rib-out found : %d", rf.String(), len(paths))
}
+
+ for _, p := range paths {
+ result := &api.GrpcResponse{}
+ path := &api.Path{}
+ j, _ := json.Marshal(p)
+ err := json.Unmarshal(j, path)
+ if err != nil {
+ result.ResponseErr = err
+ } else {
+ result.Data = path
+ }
+ grpcReq.ResponseCh <- result
+ }
+ close(grpcReq.ResponseCh)
+ return
case api.REQ_NEIGHBOR_ENABLE, api.REQ_NEIGHBOR_DISABLE:
- r := make(map[string]string)
- if restReq.RequestType == api.REQ_NEIGHBOR_ENABLE {
+ var err api.Error
+ if grpcReq.RequestType == api.REQ_NEIGHBOR_ENABLE {
select {
case peer.fsm.adminStateCh <- ADMIN_STATE_UP:
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": peer.peerConfig.NeighborAddress,
}).Debug("ADMIN_STATE_UP requested")
- r["result"] = "ADMIN_STATE_UP"
+ err.Code = api.Error_SUCCESS
+ err.Msg = "ADMIN_STATE_UP"
default:
log.Warning("previous request is still remaining. : ", peer.peerConfig.NeighborAddress)
- r["result"] = "previous request is still remaining"
+ err.Code = api.Error_FAIL
+ err.Msg = "previous request is still remaining"
}
} else {
select {
@@ -410,17 +439,18 @@ func (peer *Peer) handleREST(restReq *api.RestRequest) {
"Topic": "Peer",
"Key": peer.peerConfig.NeighborAddress,
}).Debug("ADMIN_STATE_DOWN requested")
- r["result"] = "ADMIN_STATE_DOWN"
+ err.Code = api.Error_SUCCESS
+ err.Msg = "ADMIN_STATE_DOWN"
default:
log.Warning("previous request is still remaining. : ", peer.peerConfig.NeighborAddress)
- r["result"] = "previous request is still remaining"
+ err.Code = api.Error_FAIL
+ err.Msg = "previous request is still remaining"
}
}
- j, _ := json.Marshal(r)
- result.Data = j
+ result.Data = err
}
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
}
func (peer *Peer) sendUpdateMsgFromPaths(pList []table.Path) {
@@ -626,7 +656,7 @@ func (peer *Peer) handleServerMsg(m *serverMsg) {
log.Warning("can not find peer: ", d.Address.String())
}
case SRV_MSG_API:
- peer.handleREST(m.msgData.(*api.RestRequest))
+ peer.handleGrpc(m.msgData.(*api.GrpcRequest))
case SRV_MSG_POLICY_UPDATED:
log.Debug("policy updated")
d := m.msgData.(map[string]*policy.Policy)
@@ -797,30 +827,29 @@ func (peer *Peer) PassConn(conn *net.TCPConn) {
}
func (peer *Peer) MarshalJSON() ([]byte, error) {
+ p, err := peer.ToGrpc()
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(p)
+}
+
+func (peer *Peer) ToGrpc() (*api.Peer, error) {
f := peer.fsm
c := f.peerConfig
- p := make(map[string]interface{})
- capList := make([]int, 0)
+ capList := make([]int32, 0, len(peer.capMap))
for k, _ := range peer.capMap {
- capList = append(capList, int(k))
+ capList = append(capList, int32(k))
}
- p["conf"] = struct {
- RemoteIP string `json:"remote_ip"`
- Id string `json:"id"`
- RemoteAS uint32 `json:"remote_as"`
- CapRefresh bool `json:"cap_refresh"`
- CapEnhancedRefresh bool `json:"cap_enhanced_refresh"`
- RemoteCap []int
- LocalCap []int
- }{
- RemoteIP: c.NeighborAddress.String(),
+ conf := &api.PeerConf{
+ RemoteIp: c.NeighborAddress.String(),
Id: peer.peerInfo.ID.To4().String(),
- RemoteAS: c.PeerAs,
+ RemoteAs: c.PeerAs,
RemoteCap: capList,
- LocalCap: []int{int(bgp.BGP_CAP_MULTIPROTOCOL), int(bgp.BGP_CAP_ROUTE_REFRESH), int(bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER)},
+ LocalCap: []int32{int32(bgp.BGP_CAP_MULTIPROTOCOL), int32(bgp.BGP_CAP_ROUTE_REFRESH), int32(bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER)},
}
s := c.BgpNeighborCommonState
@@ -845,34 +874,7 @@ func (peer *Peer) MarshalJSON() ([]byte, error) {
}
}
- p["info"] = struct {
- BgpState string `json:"bgp_state"`
- AdminState string
- FsmEstablishedTransitions uint32 `json:"fsm_established_transitions"`
- TotalMessageOut uint32 `json:"total_message_out"`
- TotalMessageIn uint32 `json:"total_message_in"`
- UpdateMessageOut uint32 `json:"update_message_out"`
- UpdateMessageIn uint32 `json:"update_message_in"`
- KeepAliveMessageOut uint32 `json:"keepalive_message_out"`
- KeepAliveMessageIn uint32 `json:"keepalive_message_in"`
- OpenMessageOut uint32 `json:"open_message_out"`
- OpenMessageIn uint32 `json:"open_message_in"`
- NotificationOut uint32 `json:"notification_out"`
- NotificationIn uint32 `json:"notification_in"`
- RefreshMessageOut uint32 `json:"refresh_message_out"`
- RefreshMessageIn uint32 `json:"refresh_message_in"`
- DiscardedOut uint32
- DiscardedIn uint32
- Uptime int64 `json:"uptime"`
- Downtime int64 `json:"downtime"`
- LastError string `json:"last_error"`
- Received uint32
- Accepted uint32
- Advertized uint32
- OutQ int
- Flops uint32
- }{
-
+ info := &api.PeerInfo{
BgpState: f.state.String(),
AdminState: f.adminState.String(),
FsmEstablishedTransitions: s.EstablishedCount,
@@ -895,9 +897,12 @@ func (peer *Peer) MarshalJSON() ([]byte, error) {
Received: received,
Accepted: accepted,
Advertized: advertized,
- OutQ: len(peer.outgoing),
+ OutQ: uint32(len(peer.outgoing)),
Flops: s.Flops,
}
- return json.Marshal(p)
+ return &api.Peer{
+ Conf: conf,
+ Info: info,
+ }, nil
}
diff --git a/server/peer_test.go b/server/peer_test.go
index 90c64960..cae3b0c7 100644
--- a/server/peer_test.go
+++ b/server/peer_test.go
@@ -17,8 +17,6 @@ package server
import (
"fmt"
- //"encoding/json"
- "encoding/json"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
@@ -123,17 +121,16 @@ func TestPeerAdminShutdownWhileEstablished(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_ESTABLISHED, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_DOWN", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 1000)
@@ -166,17 +163,16 @@ func TestPeerAdminShutdownWhileIdle(t *testing.T) {
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_DOWN", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 100)
assert.Equal(bgp.BGP_FSM_IDLE, peer.fsm.state)
@@ -201,17 +197,16 @@ func TestPeerAdminShutdownWhileActive(t *testing.T) {
waitUntil(assert, bgp.BGP_FSM_ACTIVE, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_DOWN", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 100)
assert.Equal(bgp.BGP_FSM_IDLE, peer.fsm.state)
@@ -238,17 +233,16 @@ func TestPeerAdminShutdownWhileOpensent(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_OPENSENT, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_DOWN", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 100)
assert.Equal(bgp.BGP_FSM_IDLE, peer.fsm.state)
@@ -283,17 +277,16 @@ func TestPeerAdminShutdownWhileOpenconfirm(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_OPENCONFIRM, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_DOWN", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 1000)
assert.Equal(bgp.BGP_FSM_IDLE, peer.fsm.state)
@@ -334,32 +327,30 @@ func TestPeerAdminEnable(t *testing.T) {
waitUntil(assert, bgp.BGP_FSM_ESTABLISHED, peer, 1000)
// shutdown peer at first
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_DOWN", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 100)
assert.Equal(bgp.BGP_FSM_IDLE, peer.fsm.state)
assert.Equal(ADMIN_STATE_DOWN, peer.fsm.adminState)
// enable peer
- restReq = api.NewRestRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq = api.NewGrpcRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg = &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result = <-restReq.ResponseCh
- res = make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("ADMIN_STATE_UP", res["result"])
+ result = <-grpcReq.ResponseCh
+ err = result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_SUCCESS)
waitUntil(assert, bgp.BGP_FSM_ACTIVE, peer, (HOLDTIME_IDLE+1)*1000)
assert.Equal(bgp.BGP_FSM_ACTIVE, peer.fsm.state)
@@ -397,31 +388,29 @@ func TestPeerAdminShutdownReject(t *testing.T) {
peer.connCh <- m
waitUntil(assert, bgp.BGP_FSM_OPENSENT, peer, 1000)
- restReq := api.NewRestRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.fsm.adminStateCh <- ADMIN_STATE_DOWN
peer.serverMsgCh <- msg
- result := <-restReq.ResponseCh
- res := make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("previous request is still remaining", res["result"])
+ result := <-grpcReq.ResponseCh
+ err := result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_FAIL)
- restReq = api.NewRestRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
+ grpcReq = api.NewGrpcRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil)
msg = &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
peer.serverMsgCh <- msg
- result = <-restReq.ResponseCh
- res = make(map[string]string)
- json.Unmarshal(result.Data, &res)
- assert.Equal("previous request is still remaining", res["result"])
+ result = <-grpcReq.ResponseCh
+ err = result.Data.(api.Error)
+ assert.Equal(err.Code, api.Error_FAIL)
waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 1000)
assert.Equal(bgp.BGP_FSM_IDLE, peer.fsm.state)
diff --git a/server/server.go b/server/server.go
index a47f9177..8212a1a0 100644
--- a/server/server.go
+++ b/server/server.go
@@ -16,7 +16,6 @@
package server
import (
- "encoding/json"
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/api"
@@ -61,7 +60,7 @@ type BgpServer struct {
globalTypeCh chan config.Global
addedPeerCh chan config.Neighbor
deletedPeerCh chan config.Neighbor
- RestReqCh chan *api.RestRequest
+ GrpcReqCh chan *api.GrpcRequest
listenPort int
peerMap map[string]peerMapInfo
globalRib *Peer
@@ -74,7 +73,7 @@ func NewBgpServer(port int) *BgpServer {
b.globalTypeCh = make(chan config.Global)
b.addedPeerCh = make(chan config.Neighbor)
b.deletedPeerCh = make(chan config.Neighbor)
- b.RestReqCh = make(chan *api.RestRequest, 1)
+ b.GrpcReqCh = make(chan *api.GrpcRequest, 1)
b.policyUpdateCh = make(chan config.RoutingPolicy)
b.listenPort = port
return &b
@@ -217,8 +216,8 @@ func (server *BgpServer) Serve() {
} else {
log.Info("Can't delete a peer configuration for ", addr)
}
- case restReq := <-server.RestReqCh:
- server.handleRest(restReq)
+ case grpcReq := <-server.GrpcReqCh:
+ server.handleGrpc(grpcReq)
case pl := <-server.policyUpdateCh:
server.SetPolicy(pl)
msg := &serverMsg{
@@ -294,37 +293,44 @@ func (p peers) Less(i, j int) bool {
return strings.Less(0, 1)
}
-func (server *BgpServer) handleRest(restReq *api.RestRequest) {
- switch restReq.RequestType {
+func (server *BgpServer) handleGrpc(grpcReq *api.GrpcRequest) {
+ switch grpcReq.RequestType {
case api.REQ_NEIGHBORS:
- result := &api.RestResponse{}
peerList := peers{}
for _, info := range server.peerMap {
peerList = append(peerList, info.peer)
}
sort.Sort(peerList)
- j, _ := json.Marshal(peerList)
- result.Data = j
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
-
+ for _, peer := range peerList {
+ data, err := peer.ToGrpc()
+ result := &api.GrpcResponse{
+ ResponseErr: err,
+ Data: data,
+ }
+ grpcReq.ResponseCh <- result
+ }
+ close(grpcReq.ResponseCh)
case api.REQ_NEIGHBOR:
-
- remoteAddr := restReq.RemoteAddr
- result := &api.RestResponse{}
+ remoteAddr := grpcReq.RemoteAddr
+ var result *api.GrpcResponse
info, found := server.peerMap[remoteAddr]
if found {
- j, _ := json.Marshal(info.peer)
- result.Data = j
+ data, err := info.peer.ToGrpc()
+ result = &api.GrpcResponse{
+ ResponseErr: err,
+ Data: data,
+ }
} else {
- result.ResponseErr = fmt.Errorf("Neighbor that has %v does not exist.", remoteAddr)
+ result = &api.GrpcResponse{
+ ResponseErr: fmt.Errorf("Neighbor that has %v does not exist.", remoteAddr),
+ }
}
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
case api.REQ_GLOBAL_RIB, api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE:
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
server.globalRib.serverMsgCh <- msg
case api.REQ_LOCAL_RIB, api.REQ_NEIGHBOR_SHUTDOWN, api.REQ_NEIGHBOR_RESET,
@@ -332,19 +338,19 @@ func (server *BgpServer) handleRest(restReq *api.RestRequest) {
api.REQ_ADJ_RIB_IN, api.REQ_ADJ_RIB_OUT,
api.REQ_NEIGHBOR_ENABLE, api.REQ_NEIGHBOR_DISABLE:
- remoteAddr := restReq.RemoteAddr
- result := &api.RestResponse{}
+ remoteAddr := grpcReq.RemoteAddr
+ result := &api.GrpcResponse{}
info, found := server.peerMap[remoteAddr]
if found {
msg := &serverMsg{
msgType: SRV_MSG_API,
- msgData: restReq,
+ msgData: grpcReq,
}
info.peer.serverMsgCh <- msg
} else {
result.ResponseErr = fmt.Errorf("Neighbor that has %v does not exist.", remoteAddr)
- restReq.ResponseCh <- result
- close(restReq.ResponseCh)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
}
}
}
diff --git a/table/destination.go b/table/destination.go
index 72350d8a..aae02822 100644
--- a/table/destination.go
+++ b/table/destination.go
@@ -111,7 +111,7 @@ func (dd *DestinationDefault) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Prefix string
Paths []Path
- BestPathIdx int
+ BestPathIdx int `json:"best_path_idx"`
}{
Prefix: prefix.String(),
Paths: dd.knownPathList,
@@ -929,7 +929,7 @@ func (ipv6d *IPv6Destination) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Prefix string
Paths []Path
- BestPathIdx int
+ BestPathIdx int `json:"best_path_idx"`
}{
Prefix: prefix.String(),
Paths: ipv6d.knownPathList,
@@ -985,7 +985,7 @@ func (ipv4vpnd *IPv4VPNDestination) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Prefix string
Paths []Path
- BestPathIdx int
+ BestPathIdx int `json:"best_path_idx"`
}{
Prefix: prefix.String(),
Paths: ipv4vpnd.knownPathList,
@@ -1023,7 +1023,7 @@ func (evpnd *EVPNDestination) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Prefix string
Paths []Path
- BestPathIdx int
+ BestPathIdx int `json:"best_path_idx"`
}{
Prefix: nlri.String(),
Paths: evpnd.knownPathList,
diff --git a/table/path.go b/table/path.go
index c7329587..fddde7d3 100644
--- a/table/path.go
+++ b/table/path.go
@@ -175,12 +175,12 @@ func (pd *PathDefault) MarshalJSON() ([]byte, error) {
Network string
Nexthop string
Attrs []bgp.PathAttributeInterface
- Age float64
+ Age int64
}{
Network: pd.getPrefix(),
Nexthop: pd.GetNexthop().String(),
Attrs: pd.getPathAttrs(),
- Age: time.Now().Sub(pd.timestamp).Seconds(),
+ Age: int64(time.Now().Sub(pd.timestamp).Seconds()),
})
}
@@ -399,12 +399,12 @@ func (ipv6p *IPv6Path) MarshalJSON() ([]byte, error) {
Network string
Nexthop string
Attrs []bgp.PathAttributeInterface
- Age float64
+ Age int64
}{
Network: ipv6p.getPrefix(),
Nexthop: ipv6p.PathDefault.GetNexthop().String(),
Attrs: ipv6p.PathDefault.getPathAttrs(),
- Age: time.Now().Sub(ipv6p.PathDefault.timestamp).Seconds(),
+ Age: int64(time.Now().Sub(ipv6p.PathDefault.timestamp).Seconds()),
})
}
@@ -451,12 +451,12 @@ func (ipv4vpnp *IPv4VPNPath) MarshalJSON() ([]byte, error) {
Network string
Nexthop string
Attrs []bgp.PathAttributeInterface
- Age float64
+ Age int64
}{
Network: ipv4vpnp.getPrefix(),
Nexthop: ipv4vpnp.PathDefault.GetNexthop().String(),
Attrs: ipv4vpnp.PathDefault.getPathAttrs(),
- Age: time.Now().Sub(ipv4vpnp.PathDefault.timestamp).Seconds(),
+ Age: int64(time.Now().Sub(ipv4vpnp.PathDefault.timestamp).Seconds()),
})
}
@@ -503,11 +503,11 @@ func (evpnp *EVPNPath) MarshalJSON() ([]byte, error) {
Network string
Nexthop string
Attrs []bgp.PathAttributeInterface
- Age float64
+ Age int64
}{
Network: evpnp.getPrefix(),
Nexthop: evpnp.PathDefault.GetNexthop().String(),
Attrs: evpnp.PathDefault.getPathAttrs(),
- Age: time.Now().Sub(evpnp.PathDefault.timestamp).Seconds(),
+ Age: int64(time.Now().Sub(evpnp.PathDefault.timestamp).Seconds()),
})
}
diff --git a/test/scenario_test/bgp_router_test.py b/test/scenario_test/bgp_router_test.py
index f2d3ce16..62ff9b5f 100644
--- a/test/scenario_test/bgp_router_test.py
+++ b/test/scenario_test/bgp_router_test.py
@@ -73,12 +73,12 @@ class GoBGPTest(GoBGPTestBase):
for p in d.paths:
print "check of %s's route %s existance in gobgp global rib" % (peer_ip, p.network)
exist = False
- for dst in rib['Destinations']:
- for path in dst['Paths']:
- if path['Network'] == p.network:
+ for dst in rib:
+ for path in dst['paths']:
+ if path['network'] == p.network:
exist = True
if exist:
- self.assertEqual(path['Nexthop'] == p.nexthop, True)
+ self.assertEqual(path['nexthop'] == p.nexthop, True)
self.assertEqual(exist, True)
# Test of advertising route to each quagga form gobgp
@@ -150,12 +150,12 @@ class GoBGPTest(GoBGPTestBase):
for p in d.paths:
print "check of %s's route %s existance in gobgp global rib" % (peer_ip, p.network)
exist = False
- for dst in rib['Destinations']:
- for path in dst['Paths']:
- if path['Network'] == p.network:
+ for dst in rib:
+ for path in dst['paths']:
+ if path['network'] == p.network:
exist = True
if exist:
- self.assertEqual(path['Nexthop'] == p.nexthop, True)
+ self.assertEqual(path['nexthop'] == p.nexthop, True)
self.assertEqual(exist, True)
# Test of advertising route to each quagga form gobgp when append quagga container
@@ -215,9 +215,9 @@ class GoBGPTest(GoBGPTestBase):
removed_prefix = "10.0.0.%d/24" % self.remove_quagga
still_exists = False
- for dst in rib['Destinations']:
- for path in dst['Paths']:
- if path['Network'] == removed_prefix:
+ for dst in rib:
+ for path in dst['paths']:
+ if path['network'] == removed_prefix:
still_exists = True
self.assertEqual(still_exists, False)
diff --git a/test/scenario_test/constant.py b/test/scenario_test/constant.py
index 5e672a79..131cfd04 100644
--- a/test/scenario_test/constant.py
+++ b/test/scenario_test/constant.py
@@ -1,3 +1,19 @@
+# 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.
+
+
IPv4 = 'ipv4'
IPv6 = 'ipv6'
GOBGP_IP = "10.0.255.1"
@@ -12,12 +28,15 @@ GOBGP_CONFIG_FILE = "gobgpd.conf"
CONFIG_DIR = "/tmp/gobgp"
CONFIG_DIRR = "/tmp/gobgp/"
SHARE_VOLUME = "/root/share_volume"
+CLI_CMD = "gobgpcli"
EXABGP_CONTAINER_NAME = "exabgp"
EXABGP_ADDRESS = "10.0.0.100/16"
EXABGP_CONFDIR = SHARE_VOLUME + "/exabgp_test_conf"
EXABGP_LOG_FILE = "exabgpd.log"
STARTUP_FILE_NAME = "gobgp_startup.sh"
STARTUP_FILE = SHARE_VOLUME + "/" + STARTUP_FILE_NAME
+INSTALL_FILE_NAME = "gobgp_install.sh"
+INSTALL_FILE = SHARE_VOLUME + "/" + INSTALL_FILE_NAME
IP_VERSION = IPv4
IF_CONFIG_OPTION = {IPv4: "inet", IPv6: "inet6"}
@@ -40,8 +59,8 @@ BASE_MASK = {IPv4: "/16", IPv6: "/64"}
A_PART_OF_CURRENT_DIR = "/test/scenario_test"
-ADJ_RIB_IN = "adj-rib-in"
-ADJ_RIB_OUT = "adj-rib-out"
-LOCAL_RIB = "local-rib"
-GLOBAL_RIB = "global/rib"
+ADJ_RIB_IN = "adj-in"
+ADJ_RIB_OUT = "adj-out"
+LOCAL_RIB = "local"
+GLOBAL_RIB = "global"
NEIGHBOR = "neighbor"
diff --git a/test/scenario_test/docker_control.py b/test/scenario_test/docker_control.py
index 64446111..008b346d 100644
--- a/test/scenario_test/docker_control.py
+++ b/test/scenario_test/docker_control.py
@@ -154,35 +154,38 @@ def create_config_dir():
cmd = "mkdir " + CONFIG_DIR
local(cmd, capture=True)
-
def make_startup_file(log_opt=""):
-
file_buff = '#!/bin/bash' + '\n'
- file_buff += 'cd /go/src/github.com/osrg/gobgp' + '\n'
- file_buff += 'git pull origin master' + '\n'
- file_buff += 'cd gobgpd' + '\n'
- file_buff += 'go get -v' + '\n'
- file_buff += 'go build' + '\n'
- file_buff += './gobgpd -f ' + SHARE_VOLUME + '/gobgpd.conf ' + log_opt + ' > ' + SHARE_VOLUME + '/gobgpd.log'
+ file_buff += "cd /go/src/github.com/osrg/gobgp/gobgpd" + '\n'
+ file_buff += "./gobgpd -f " + SHARE_VOLUME + "/gobgpd.conf " + log_opt + " > " + SHARE_VOLUME + "/gobgpd.log"
+
cmd = "echo \"" + file_buff + "\" > " + CONFIG_DIR + "/" + STARTUP_FILE_NAME
local(cmd, capture=True)
cmd = "chmod 755 " + CONFIG_DIRR + STARTUP_FILE_NAME
local(cmd, capture=True)
-def make_startup_file_use_local_gobgp(log_opt=""):
-
+def make_install_file(use_local=False):
file_buff = '#!/bin/bash' + '\n'
- file_buff += 'rm -rf /go/src/github.com/osrg/gobgp' + '\n'
- file_buff += 'cp -r ' + SHARE_VOLUME + '/gobgp /go/src/github.com/osrg/' + '\n'
- file_buff += 'cd /go/src/github.com/osrg/gobgp' + '\n'
- file_buff += 'cd gobgpd' + '\n'
+
+ if use_local:
+ file_buff += 'rm -rf /go/src/github.com/osrg/gobgp' + '\n'
+ file_buff += 'cp -r ' + SHARE_VOLUME + '/gobgp /go/src/github.com/osrg/' + '\n'
+ file_buff += 'cd /go/src/github.com/osrg/gobgp' + '\n'
+ else:
+ file_buff += 'cd /go/src/github.com/osrg/gobgp' + '\n'
+ file_buff += 'git pull origin master' + '\n'
+
+ file_buff += 'cd gobgp' + '\n'
file_buff += 'go get -v' + '\n'
file_buff += 'go build' + '\n'
- file_buff += './gobgpd -f ' + SHARE_VOLUME + '/gobgpd.conf ' + log_opt + ' > ' + SHARE_VOLUME + '/gobgpd.log'
- cmd = "echo \"" + file_buff + "\" > " + CONFIG_DIR + "/" + STARTUP_FILE_NAME
+ file_buff += 'cp gobgp ' + SHARE_VOLUME + '/' + CLI_CMD + '\n'
+ file_buff += 'cd ../gobgpd' + '\n'
+ file_buff += 'go get -v' + '\n'
+ file_buff += 'go build'
+ cmd = "echo \"" + file_buff + "\" > " + CONFIG_DIR + "/" + INSTALL_FILE_NAME
local(cmd, capture=True)
- cmd = "chmod 755 " + CONFIG_DIRR + STARTUP_FILE_NAME
+ cmd = "chmod 755 " + CONFIG_DIRR + INSTALL_FILE_NAME
local(cmd, capture=True)
@@ -255,7 +258,9 @@ def bridge_unsetting_for_docker_connection():
def start_gobgp():
- cmd = "docker exec gobgp " + STARTUP_FILE + " > /dev/null 2>&1 &"
+ cmd = "docker exec -it gobgp " + INSTALL_FILE
+ local(cmd, capture=True)
+ cmd = "docker exec -it gobgp " + STARTUP_FILE + "&"
local(cmd, capture=True)
@@ -334,7 +339,7 @@ def change_exabgp_version():
def reload_config():
- cmd = "docker exec gobgp /usr/bin/pkill gobgp -SIGHUP"
+ cmd = "docker exec gobgp /usr/bin/pkill gobgpd -SIGHUP"
local(cmd, capture=True)
print "complete append docker container."
@@ -359,6 +364,7 @@ def init_test_env_executor(quagga_num, use_local, go_path, log_debug=False, is_r
opt = "-l debug" if log_debug else ""
# execute local gobgp program in the docker container if the input option is local
+ make_startup_file(log_opt=opt)
if use_local:
print "execute gobgp program in local machine."
pwd = local("pwd", capture=True)
@@ -366,14 +372,14 @@ def init_test_env_executor(quagga_num, use_local, go_path, log_debug=False, is_r
gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd)
cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR
local(cmd, capture=True)
- make_startup_file_use_local_gobgp(log_opt=opt)
+ make_install_file(use_local=True)
else:
print "scenario_test directory is not."
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
else:
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
change_owner_to_root(CONFIG_DIR)
start_gobgp()
@@ -405,6 +411,7 @@ def init_policy_test_env_executor(quagga_num, use_local, go_path, log_debug=Fals
opt = "-l debug" if log_debug else ""
# execute local gobgp program in the docker container if the input option is local
+ make_startup_file(log_opt=opt)
if use_local:
print "execute gobgp program in local machine."
pwd = local("pwd", capture=True)
@@ -412,14 +419,14 @@ def init_policy_test_env_executor(quagga_num, use_local, go_path, log_debug=Fals
gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd)
cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR
local(cmd, capture=True)
- make_startup_file_use_local_gobgp(log_opt=opt)
+ make_install_file(use_local=True)
else:
print "scenario_test directory is not."
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
else:
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
change_owner_to_root(CONFIG_DIR)
start_gobgp()
@@ -451,6 +458,7 @@ def init_ipv6_test_env_executor(quagga_num, use_local, go_path, log_debug=False)
opt = "-l debug" if log_debug else ""
# execute local gobgp program in the docker container if the input option is local
+ make_startup_file(log_opt=opt)
if use_local:
print "execute gobgp program in local machine."
pwd = local("pwd", capture=True)
@@ -458,14 +466,14 @@ def init_ipv6_test_env_executor(quagga_num, use_local, go_path, log_debug=False)
gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd)
cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR
local(cmd, capture=True)
- make_startup_file_use_local_gobgp(log_opt=opt)
+ make_install_file(use_local=True)
else:
print "scenario_test directory is not."
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
else:
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
change_owner_to_root(CONFIG_DIR)
start_gobgp()
@@ -508,14 +516,14 @@ def init_malformed_test_env_executor(conf_file, use_local, go_path, exabgp_path
gobgp_path = re.sub(A_PART_OF_CURRENT_DIR, "", pwd)
cmd = "cp -r " + gobgp_path + " " + CONFIG_DIRR
local(cmd, capture=True)
- make_startup_file_use_local_gobgp(log_opt=opt)
+ make_install_file(use_local=True)
else:
print "scenario_test directory is not."
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
else:
print "execute gobgp program of osrg/master in github."
- make_startup_file(log_opt=opt)
+ make_install_file()
change_owner_to_root(CONFIG_DIR)
diff --git a/test/scenario_test/gobgp_test.py b/test/scenario_test/gobgp_test.py
index 0cf42199..aafc41ed 100644
--- a/test/scenario_test/gobgp_test.py
+++ b/test/scenario_test/gobgp_test.py
@@ -14,7 +14,7 @@
# limitations under the License.
import unittest
-import requests
+from fabric.api import local
import json
import toml
import os
@@ -24,6 +24,7 @@ from peer_info import Peer
from peer_info import Destination
from peer_info import Path
from constant import *
+import quagga_access as qaccess
class GoBGPTestBase(unittest.TestCase):
@@ -42,6 +43,19 @@ class GoBGPTestBase(unittest.TestCase):
def setUp(self):
self.quagga_configs = []
+ def get_neighbor_state(self, neighbor_address):
+ print "check neighbor state for %s" % (neighbor_address)
+ state = None
+ try:
+ neighbor = self.ask_gobgp(NEIGHBOR, neighbor_address)
+ state = neighbor['info']['bgp_state']
+ remote_ip = neighbor['conf']['remote_ip']
+ assert remote_ip == neighbor_address
+ return state
+ except Exception as e:
+ print e
+ return state
+
def retry_routine_for_state(self, addresses, allow_state):
in_prepare_quagga = True
retry_count = 0
@@ -56,15 +70,8 @@ class GoBGPTestBase(unittest.TestCase):
success_count = 0
for address in addresses:
# get neighbor state and remote ip from gobgp connections
- try:
- neighbor = self.ask_gobgp(NEIGHBOR, address)
- except Exception:
- continue
- if neighbor is None:
- continue
- state = neighbor['info']['bgp_state']
- remote_ip = neighbor['conf']['remote_ip']
- if address == remote_ip and state == allow_state:
+ state = self.get_neighbor_state(address)
+ if state == allow_state:
success_count += 1
if success_count == len(addresses):
in_prepare_quagga = False
@@ -77,12 +84,11 @@ class GoBGPTestBase(unittest.TestCase):
rib = self.ask_gobgp(LOCAL_RIB, check_address)
target_exist = False
- g_dests = rib['Destinations']
- for g_dest in g_dests:
- best_path_idx = g_dest['BestPathIdx']
- if target_network == g_dest['Prefix']:
+ for g_dest in rib:
+ best_path_idx = g_dest['best_path_idx'] if 'best_path_idx' in g_dest else 0
+ if target_network == g_dest['prefix']:
target_exist = True
- g_paths = g_dest['Paths']
+ g_paths = g_dest['paths']
idx = 0
if len(g_paths) < 2:
print "target path has not been bestpath selected yet."
@@ -91,10 +97,11 @@ class GoBGPTestBase(unittest.TestCase):
self.retry_routine_for_bestpath(check_address, target_network, ans_nexthop)
return
for g_path in g_paths:
- print "best_path_Idx: " + str(best_path_idx) + "idx: " + str(idx)
- print "pre: ", g_dest['Prefix'], "net: ", g_path['Network'], "next: ", g_path['Nexthop']
+ print "best_path_Idx: " + str(best_path_idx) + ", idx: " + str(idx)
+ print g_dest
+ print "pre: ", g_dest['prefix'], "net: ", g_path['network'], "next: ", g_path['nexthop']
if str(best_path_idx) == str(idx):
- rep_nexthop = g_path['Nexthop']
+ rep_nexthop = g_path['nexthop']
idx += 1
if target_exist is False:
print "target path has not been receive yet."
@@ -179,13 +186,98 @@ class GoBGPTestBase(unittest.TestCase):
return True
def ask_gobgp(self, what, who="", af="ipv4"):
- url = "http://" + self.gobgp_ip + ":" + self.gobgp_port + "/v1/bgp/"
+ cmd = "%s/%s -j -u %s -p %s show " % (CONFIG_DIR, CLI_CMD, self.gobgp_ip, self.gobgp_port)
if what == GLOBAL_RIB:
- url += "/".join([what, af])
+ cmd += " ".join([what, af])
elif what == NEIGHBOR:
- url += "/".join([NEIGHBOR, who])
+ cmd += " ".join([NEIGHBOR, who])
else:
- url += "/".join([NEIGHBOR, who, what, af])
- r = requests.get(url)
- result = json.loads(r.text)
+ cmd += " ".join([NEIGHBOR, who, what, af])
+ j = local(cmd, capture=True)
+ result = json.loads(j)
return result
+
+ def soft_reset(self, neighbor_address, route_family, type="in"):
+ cmd = "%s/%s -j -u %s -p %s softreset%s " % (CONFIG_DIR, CLI_CMD, self.gobgp_ip, self.gobgp_port, type)
+ cmd += "neighbor %s %s" % (neighbor_address, route_family)
+ local(cmd)
+
+ def get_paths_in_localrib(self, neighbor_address, target_prefix, retry=3, interval=5):
+ retry_count = 0
+ while True:
+ local_rib = self.ask_gobgp(LOCAL_RIB, neighbor_address)
+ g_dest = [dest for dest in local_rib if dest['prefix'] == target_prefix]
+ if len(g_dest) > 0:
+ assert len(g_dest) == 1
+ d = g_dest[0]
+ return d['paths']
+ else:
+ retry_count += 1
+ if retry_count > retry:
+ break
+ else:
+ print "destination is none : %s" % neighbor_address
+ print "please wait more (" + str(interval) + " second)"
+ time.sleep(interval)
+
+ print "destination is none"
+ return None
+
+ def get_adj_rib_in(self, neighbor_address, target_prefix, retry=3, interval=-1):
+ if interval < 0:
+ interval = self.wait_per_retry
+ return self.get_adj_rib(neighbor_address, target_prefix, retry, interval, type=ADJ_RIB_IN)
+
+
+ def get_adj_rib_out(self, neighbor_address, target_prefix, retry=3, interval=-1):
+ if interval < 0:
+ interval = self.wait_per_retry
+ return self.get_adj_rib(neighbor_address, target_prefix, retry, interval, type=ADJ_RIB_OUT)
+
+
+ def get_adj_rib(self, neighbor_address, target_prefix, retry, interval, type=ADJ_RIB_IN):
+ retry_count = 0
+ while True:
+ rib = self.ask_gobgp(type, neighbor_address)
+ paths = [p for p in rib if p['network'] == target_prefix]
+
+ if len(paths) > 0:
+ assert len(paths) == 1
+ return paths[0]
+ else:
+ retry_count += 1
+ if retry_count > retry:
+ break
+ else:
+ print "adj_rib_%s is none" % type
+ print "wait (" + str(interval) + " seconds)"
+ time.sleep(interval)
+
+ print "adj_rib_%s is none" % type
+ return None
+
+
+ # get route information on quagga
+ def get_routing_table(self, neighbor_address, target_prefix, retry=3, interval=-1):
+ if interval < 0:
+ interval = self.wait_per_retry
+ print "check route %s on quagga : %s" % (target_prefix, neighbor_address)
+ retry_count = 0
+ while True:
+ tn = qaccess.login(neighbor_address)
+ q_rib = qaccess.show_rib(tn)
+ qaccess.logout(tn)
+ for q_path in q_rib:
+ if target_prefix == q_path['Network']:
+ return q_path
+
+ retry_count += 1
+ if retry_count > retry:
+ break
+ else:
+ print "target_prefix %s is none" % target_prefix
+ print "wait (" + str(interval) + " seconds)"
+ time.sleep(interval)
+
+ print "route : %s is none" % target_prefix
+ return None
diff --git a/test/scenario_test/peer_info.py b/test/scenario_test/peer_info.py
index 00490d09..5a965f7b 100644
--- a/test/scenario_test/peer_info.py
+++ b/test/scenario_test/peer_info.py
@@ -1,6 +1,21 @@
+# 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.
+
+
class Peer:
def __init__(self, peer_ip, peer_id, peer_as, ip_version):
- # def __init__(self, peer_ip, peer_id, peer_as):
self.peer_ip = peer_ip
self.peer_id = peer_id
self.peer_as = peer_as
@@ -21,4 +36,4 @@ class Path:
self.nexthop = nexthop
self.origin = None
self.as_path = []
- self.metric = None \ No newline at end of file
+ self.metric = None
diff --git a/test/scenario_test/route_server_ipv4_v6_test.py b/test/scenario_test/route_server_ipv4_v6_test.py
index a171536b..4233988f 100644
--- a/test/scenario_test/route_server_ipv4_v6_test.py
+++ b/test/scenario_test/route_server_ipv4_v6_test.py
@@ -76,21 +76,16 @@ class GoBGPIPv6Test(GoBGPTestBase):
if quagga_config.peer_ip == address or quagga_config.ip_version != af:
for c_dest in quagga_config.destinations.itervalues():
# print "config : ", c_dest.prefix, "my ip or different ip version!!!"
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- # print "gobgp : ", g_dest['Prefix']
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 0)
else:
for c_dest in quagga_config.destinations.itervalues():
- # print "config : ", c_dest.prefix"
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- # print "gobgp : ", g_dest['Prefix']
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 1)
diff --git a/test/scenario_test/route_server_malformed_test.py b/test/scenario_test/route_server_malformed_test.py
index 4c45a9f7..ab8993ae 100644
--- a/test/scenario_test/route_server_malformed_test.py
+++ b/test/scenario_test/route_server_malformed_test.py
@@ -20,12 +20,13 @@ import sys
import nose
import collections
import docker_control as fab
+from fabric.api import local
import requests
import json
import toml
from noseplugin import OptionParser
from noseplugin import parser_option
-
+from constant import CONFIG_DIR, CLI_CMD
initial_wait_time = 10
wait_per_retry = 5
@@ -98,13 +99,13 @@ def check_func(exabgp_conf, result):
retry_count = 0
# get neighbor addresses from gobgpd.conf
addresses = get_neighbor_address()
- url = "http://" + gobgp_ip + ":" + gobgp_port + "/v1/bgp/neighbors"
neighbors = None
q_address = ""
e_address = ""
q_transitions = 0
q_state = ""
notification = ""
+
while in_prepare_quagga or in_prepare_exabgp:
if retry_count != 0:
print "please wait more (" + str(wait_per_retry) + " second)"
@@ -115,8 +116,9 @@ def check_func(exabgp_conf, result):
retry_count += 1
# check whether the service of gobgp is normally
try:
- r = requests.get(url)
- neighbors = json.loads(r.text)
+ cmd = "%s/%s -j -u %s -p %s show neighbors" % (CONFIG_DIR, CLI_CMD, gobgp_ip, gobgp_port)
+ j = local(cmd, capture=True)
+ neighbors = json.loads(j)
except Exception:
continue
if neighbors is None:
@@ -173,4 +175,4 @@ if __name__ == '__main__':
if fab.docker_pkg_check() is False:
print "not install docker package."
sys.exit(1)
- nose.main(argv=sys.argv, addplugins=[OptionParser()], defaultTest=sys.argv[0]) \ No newline at end of file
+ nose.main(argv=sys.argv, addplugins=[OptionParser()], defaultTest=sys.argv[0])
diff --git a/test/scenario_test/route_server_policy_test.py b/test/scenario_test/route_server_policy_test.py
index 42d74d9e..9ae29a2b 100644
--- a/test/scenario_test/route_server_policy_test.py
+++ b/test/scenario_test/route_server_policy_test.py
@@ -14,42 +14,25 @@
# limitations under the License.
import unittest
-import requests
-import json
-import toml
import os
import time
import sys
import nose
import quagga_access as qaccess
-from peer_info import Peer
-from peer_info import Destination
-from peer_info import Path
-from ciscoconfparse import CiscoConfParse
import docker_control as fab
from noseplugin import OptionParser
from noseplugin import parser_option
-import scenario_test_util as util
+from gobgp_test import GoBGPTestBase
+from constant import *
-class GoBGPTest(unittest.TestCase):
+class GoBGPTest(GoBGPTestBase):
- gobgp_ip = "10.0.255.1"
- gobgp_port = "8080"
- rest_url_neighbor = "http://" + gobgp_ip + ":" + gobgp_port + "/v1/bgp/neighbor/"
- base_dir = "/tmp/gobgp/"
- gobgp_config_file = "/tmp/gobgp/gobgpd.conf"
- gobgp_config = None
quagga_num = 3
- initial_wait_time = 10
- wait_per_retry = 5
def __init__(self, *args, **kwargs):
super(GoBGPTest, self).__init__(*args, **kwargs)
- def setUp(self):
- self.quagga_configs = []
-
def initialize(self, policy_pattern=None):
use_local = parser_option.use_local
go_path = parser_option.go_path
@@ -60,12 +43,6 @@ class GoBGPTest(unittest.TestCase):
self.assertTrue(self.check_load_config())
- def check_established(self, addresses):
- for address in addresses:
- result = self.retry_until(address, target_state="BGP_FSM_ESTABLISHED",retry=10)
- self.assertEqual(result, True)
-
-
"""
import-policy test
---------------------------------------
@@ -80,33 +57,32 @@ class GoBGPTest(unittest.TestCase):
# policy_pattern:p1 attaches a policy to reject route 192.168.0.0/16 (16...24)
# coming from peer2(10.0.0.2) to peer3(10.0.0.3)'s import-policy.
self.initialize(policy_pattern="p1")
- self.check_established(util.get_neighbor_address(self.gobgp_config))
+ addresses = self.get_neighbor_address(self.gobgp_config)
+ self.retry_routine_for_state(addresses, "BGP_FSM_ESTABLISHED")
peer1 = "10.0.0.1"
peer2 = "10.0.0.2"
peer3 = "10.0.0.3"
- base_url = self.rest_url_neighbor
- w = self.wait_per_retry
- path = util.get_paths_in_localrib(base_url, peer1, "192.168.2.0", retry=3, interval=w)
+ path = self.get_paths_in_localrib(peer1, "192.168.2.0", retry=3)
self.assertIsNotNone(path)
# check show ip bgp on peer1(quagga1)
- qpath = util.get_routing_table(peer1,"192.168.2.0", retry=3, interval=w)
+ qpath = self.get_routing_table(peer1,"192.168.2.0", retry=3)
print qpath
self.assertIsNotNone(qpath)
# check adj-rib-out in peer2
- path = util.get_adj_rib_in(base_url, peer2, "192.168.2.0/24", retry=3, interval=w)
+ path = self.get_adj_rib_in(peer2, "192.168.2.0/24", retry=3)
# print path
self.assertIsNotNone(path)
- path = util.get_paths_in_localrib(base_url, peer3, "192.168.2.0",retry=0, interval=w)
+ path = self.get_paths_in_localrib(peer3, "192.168.2.0",retry=0)
# print path
self.assertIsNone(path)
# check show ip bgp on peer1(quagga3)
- qpath = util.get_routing_table(peer3,"192.168.2.0", retry=3, interval=w)
+ qpath = self.get_routing_table(peer3,"192.168.2.0", retry=3)
# print qpath
self.assertIsNone(qpath)
@@ -125,38 +101,37 @@ class GoBGPTest(unittest.TestCase):
# policy_pattern:p1 attaches a policy to reject route 192.168.0.0/16 (16...24)
# coming from peer2(10.0.0.2) to peer3(10.0.0.3)'s export-policy.
self.initialize(policy_pattern="p2")
- self.check_established(util.get_neighbor_address(self.gobgp_config))
+ addresses = self.get_neighbor_address(self.gobgp_config)
+ self.retry_routine_for_state(addresses, "BGP_FSM_ESTABLISHED")
peer1 = "10.0.0.1"
peer2 = "10.0.0.2"
peer3 = "10.0.0.3"
- base_url = self.rest_url_neighbor
- w = self.wait_per_retry
- paths = util.get_paths_in_localrib(base_url, peer1, "192.168.2.0", retry=3, interval=w)
+ paths = self.get_paths_in_localrib(peer1, "192.168.2.0", retry=3)
# print paths
self.assertIsNotNone(paths)
# check show ip bgp on peer1(quagga1)
- qpath = util.get_routing_table(peer1, "192.168.2.0", retry=3, interval=w)
+ qpath = self.get_routing_table(peer1, "192.168.2.0", retry=3)
# print qpath
self.assertIsNotNone(qpath)
# check adj-rib-out in peer2
- path = util.get_adj_rib_in(base_url, peer2, "192.168.2.0/24", retry=1, interval=w)
+ path = self.get_adj_rib_in(peer2, "192.168.2.0/24", retry=1)
# print path
self.assertIsNotNone(path)
- path = util.get_paths_in_localrib(base_url, peer3, "192.168.2.0")
+ path = self.get_paths_in_localrib(peer3, "192.168.2.0")
# print path
self.assertIsNotNone(path)
- path = util.get_adj_rib_out(base_url, peer3, "192.168.2.0", retry=1, interval=w)
+ path = self.get_adj_rib_out(peer3, "192.168.2.0", retry=1)
# print path
self.assertIsNone(path)
# check show ip bgp on peer1(quagga3)
- qpath = util.get_routing_table(peer3,"192.168.2.0", retry=3, interval=w)
+ qpath = self.get_routing_table(peer3,"192.168.2.0", retry=3)
# print qpath
self.assertIsNone(qpath)
@@ -195,8 +170,6 @@ class GoBGPTest(unittest.TestCase):
peer1 = "10.0.0.1"
peer2 = "10.0.0.2"
peer3 = "10.0.0.3"
- base_url = self.rest_url_neighbor
- w = self.wait_per_retry
# add other network
tn = qaccess.login(peer2)
@@ -206,20 +179,21 @@ class GoBGPTest(unittest.TestCase):
qaccess.add_network(tn, 65002, "192.168.200.0/24")
qaccess.logout(tn)
- self.check_established(util.get_neighbor_address(self.gobgp_config))
+ addresses = self.get_neighbor_address(self.gobgp_config)
+ self.retry_routine_for_state(addresses, "BGP_FSM_ESTABLISHED")
time.sleep(self.initial_wait_time)
def path_exists_in_localrib(peer, prefix,r=10):
- paths = util.get_paths_in_localrib(base_url, peer, prefix, retry=r, interval=w)
+ paths = self.get_paths_in_localrib(peer, prefix, retry=r)
return paths is not None
def path_exists_in_routing_table(peer, prefix,r=10):
- qpath = util.get_routing_table(peer, prefix, retry=r, interval=w)
+ qpath = self.get_routing_table(peer, prefix, retry=r)
return qpath is not None
def path_exists_in_adj_rib_in(peer, prefix,r=10):
- path = util.get_adj_rib_in(base_url, peer, prefix, retry=r, interval=w)
+ path = self.get_adj_rib_in(peer, prefix, retry=r)
return path is not None
@@ -253,7 +227,7 @@ class GoBGPTest(unittest.TestCase):
# soft reset
print "soft_reset"
- self.soft_reset(peer2, "ipv4")
+ self.soft_reset(peer2, IPv4)
# check local-rib
self.assertTrue(path_exists_in_localrib(peer3,"192.168.2.0"))
@@ -301,8 +275,6 @@ class GoBGPTest(unittest.TestCase):
peer1 = "10.0.0.1"
peer2 = "10.0.0.2"
peer3 = "10.0.0.3"
- base_url = self.rest_url_neighbor
- w = self.wait_per_retry
# add other network
tn = qaccess.login(peer2)
@@ -312,25 +284,25 @@ class GoBGPTest(unittest.TestCase):
qaccess.add_network(tn, 65002, "192.168.200.0/24")
qaccess.logout(tn)
- self.check_established(self.get_neighbor_address(self.gobgp_config))
+ addresses = self.get_neighbor_address(self.gobgp_config)
+ self.retry_routine_for_state(addresses, "BGP_FSM_ESTABLISHED")
time.sleep(self.initial_wait_time)
-
def path_exists_in_localrib(peer, prefix,r=10):
- paths = util.get_paths_in_localrib(base_url, peer, prefix, retry=r, interval=w)
+ paths = self.get_paths_in_localrib(peer, prefix, retry=r)
return paths is not None
def path_exists_in_routing_table(peer, prefix,r=10):
- qpath = util.get_routing_table(peer, prefix, retry=r, interval=w)
+ qpath = self.get_routing_table(peer, prefix, retry=r)
return qpath is not None
def path_exists_in_adj_rib_in(peer, prefix,r=10):
- path = util.get_adj_rib_in(base_url, peer, prefix, retry=r, interval=w)
+ path = self.get_adj_rib_in(peer, prefix, retry=r)
return path is not None
def path_exists_in_adj_rib_out(peer, prefix,r=10):
- path = util.get_adj_rib_out(base_url, peer, prefix, retry=r, interval=w)
+ path = self.get_adj_rib_out(peer, prefix, retry=r)
return path is not None
@@ -371,7 +343,7 @@ class GoBGPTest(unittest.TestCase):
# soft reset
print "soft_reset"
- self.soft_reset(peer2, "ipv4")
+ self.soft_reset(peer2, IPv4)
# check local-rib
self.assertTrue(path_exists_in_localrib(peer3,"192.168.2.0"))
@@ -389,49 +361,6 @@ class GoBGPTest(unittest.TestCase):
self.assertTrue(path_exists_in_routing_table(peer3, "192.168.200.0"))
- def retry_until(self, neighbor_address, target_state="BGP_FSM_ESTABLISHED", retry=3):
- retry_count = 0
-
- while True:
-
- current_state = util.get_neighbor_state(self.rest_url_neighbor, neighbor_address)
- if current_state == target_state:
- print "state changed to %s : %s" % (current_state, neighbor_address)
- return True
- else:
- retry_count += 1
- if retry_count > retry:
- break
- else:
- print "current state is %s" % current_state
- print "please wait more (" + str(self.wait_per_retry) + " second)"
- time.sleep(self.wait_per_retry)
-
- print "exceeded retry count : %s" % neighbor_address
- return False
-
-
- def soft_reset(self, neighbor_address, route_family, type="in"):
- url = self.rest_url_neighbor + neighbor_address + "/softreset"+type+"/" + route_family
- r = requests.post(url)
- if r.status_code == requests.codes.ok:
- print "Succeed"
- else:
- print "Failed"
-
-
- def check_load_config(self):
- self.gobgp_config = util.load_gobgp_config(self.gobgp_config_file)
- self.quagga_configs = util.load_quagga_config(self.base_dir)
- if self.gobgp_config is None:
- print "Failed to read the gobgp configuration file"
- return False
- if len(self.quagga_configs) == 0:
- print "Failed to read the quagga configuration file"
- return False
- return True
-
-
if __name__ == '__main__':
if fab.test_user_check() is False:
print "you are not root."
diff --git a/test/scenario_test/route_server_test.py b/test/scenario_test/route_server_test.py
index 7621d628..36ea0b20 100644
--- a/test/scenario_test/route_server_test.py
+++ b/test/scenario_test/route_server_test.py
@@ -73,18 +73,16 @@ class GoBGPTest(GoBGPTestBase):
for quagga_config in self.quagga_configs:
if quagga_config.peer_ip == address:
for c_dest in quagga_config.destinations.itervalues():
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 0)
else:
for c_dest in quagga_config.destinations.itervalues():
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 1)
@@ -152,22 +150,17 @@ class GoBGPTest(GoBGPTestBase):
for quagga_config in self.quagga_configs:
if quagga_config.peer_ip == address:
for c_dest in quagga_config.destinations.itervalues():
- # print "config : ", c_dest.prefix, "my ip !!!"
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- # print "gobgp : ", g_dest['Prefix']
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 0)
else:
for c_dest in quagga_config.destinations.itervalues():
# print "config : ", c_dest.prefix,"
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- # print "gobgp : ", g_dest['Prefix']
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 1)
@@ -241,21 +234,18 @@ class GoBGPTest(GoBGPTestBase):
if quagga_config.peer_ip == address:
for c_dest in quagga_config.destinations.itervalues():
# print "config : ", c_dest.prefix, "my ip !!!"
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
- # print "gobgp : ", g_dest['Prefix']
- if c_dest.prefix == g_dest['Prefix']:
+ for g_dest in local_rib:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 0)
else:
for c_dest in quagga_config.destinations.itervalues():
# print "config : ", c_dest.prefix
- g_dests = local_rib['Destinations']
exist_n = 0
- for g_dest in g_dests:
+ for g_dest in local_rib:
# print "gobgp : ", g_dest['Prefix']
- if c_dest.prefix == g_dest['Prefix']:
+ if c_dest.prefix == g_dest['prefix']:
exist_n += 1
self.assertEqual(exist_n, 1)
diff --git a/test/scenario_test/scenario_test_util.py b/test/scenario_test/scenario_test_util.py
deleted file mode 100644
index a889c2db..00000000
--- a/test/scenario_test/scenario_test_util.py
+++ /dev/null
@@ -1,201 +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.
-
-import os
-import time
-import json
-import requests
-import quagga_access as qaccess
-import toml
-from peer_info import Peer
-from peer_info import Destination
-from peer_info import Path
-from ciscoconfparse import CiscoConfParse
-
-
-# get address of each neighbor from gobpg configration
-def get_neighbor_address(config):
- address = []
- neighbors_config = config['NeighborList']
- for neighbor_config in neighbors_config:
- neighbor_ip = neighbor_config['NeighborAddress']
- address.append(neighbor_ip)
- return address
-
-
-# get route information on quagga
-def get_routing_table(neighbor_address, target_prefix, retry=3, interval=5):
- print "check route %s on quagga : %s" % (target_prefix, neighbor_address)
- retry_count = 0
- while True:
-
- tn = qaccess.login(neighbor_address)
- q_rib = qaccess.show_rib(tn)
- qaccess.logout(tn)
- for q_path in q_rib:
- if target_prefix == q_path['Network']:
- return q_path
-
- retry_count += 1
- if retry_count > retry:
- break
- else:
- print "target_prefix %s is none" % target_prefix
- print "wait (" + str(interval) + " seconds)"
- time.sleep(interval)
-
- print "route : %s is none" % target_prefix
- return None
-
-
-def get_adj_rib_in(url, neighbor_address, target_prefix, retry=3, interval=5):
- return get_adj_rib(url, neighbor_address, target_prefix, retry, interval, type="in")
-
-
-def get_adj_rib_out(url, neighbor_address, target_prefix, retry=3, interval=5):
- return get_adj_rib(url, neighbor_address, target_prefix, retry, interval, type="out")
-
-
-def get_adj_rib(base_url, neighbor_address, target_prefix, retry, interval, type="in"):
- url = base_url + neighbor_address + "/adj-rib-" +type +"/ipv4"
-
- retry_count = 0
- while True:
-
- r = requests.get(url)
- in_rib = json.loads(r.text)
- print in_rib
- paths = [p for p in in_rib if p['Network'] == target_prefix]
-
- if len(paths) > 0:
- assert len(paths) == 1
- return paths[0]
- else:
- retry_count += 1
- if retry_count > retry:
- break
- else:
- print "adj_rib_%s is none" % type
- print "wait (" + str(interval) + " seconds)"
- time.sleep(interval)
-
- print "adj_rib_%s is none" % type
- return None
-
-
-def get_neighbor_state(base_url, neighbor_address):
- print "check neighbor state for %s" % (neighbor_address)
- state = None
- url = base_url + neighbor_address
- try:
- r = requests.get(url)
- neighbor = json.loads(r.text)
- state = neighbor['info']['bgp_state']
- remote_ip = neighbor['conf']['remote_ip']
- assert remote_ip == neighbor_address
- return state
- except Exception as e:
- print e
- return state
-
-
-def get_paths_in_localrib(base_url, neighbor_address, target_prefix, retry=3, interval=5):
- url = base_url + neighbor_address + "/local-rib" + "/ipv4"
-
- retry_count = 0
- while True:
-
- r = requests.get(url)
- local_rib = json.loads(r.text)
- g_dests = local_rib['Destinations']
- g_dest = [dest for dest in g_dests if dest['Prefix'] == target_prefix]
- if len(g_dest) > 0:
- assert len(g_dest) == 1
- d = g_dest[0]
- return d['Paths']
- else:
- retry_count += 1
- if retry_count > retry:
- break
- else:
- print "destination is none : %s" % neighbor_address
- print "please wait more (" + str(interval) + " second)"
- time.sleep(interval)
-
- print "destination is none"
- return None
-
-
-def load_gobgp_config(gobgp_config_file):
-
- config = None
- try:
- config = toml.loads(open(gobgp_config_file).read())
- except IOError, (errno, strerror):
- print "I/O error(%s): %s" % (errno, strerror)
-
- return config
-
-
-# load configration from quagga(bgpd.conf)
-def load_quagga_config(base_dir):
- configs = []
- dirs = []
- try:
- content = os.listdir(base_dir)
- for item in content:
- if "q" != item[0]:
- continue
- if os.path.isdir(os.path.join(base_dir, item)):
- dirs.append(item)
- except OSError, (errno, strerror):
- print "I/O error(%s): %s" % (errno, strerror)
-
- for dir in dirs:
- config_path = base_dir + dir + "/bgpd.conf"
- config = CiscoConfParse(config_path)
-
- peer_ip = config.find_objects(r"^!\smy\saddress")[0].text.split(" ")[3]
- peer_ip_version = config.find_objects(r"^!\smy\sip_version")[0].text.split(" ")[3]
- peer_id = config.find_objects(r"^bgp\srouter-id")[0].text.split(" ")[2]
- peer_as = config.find_objects(r"^router\sbgp")[0].text.split(" ")[2]
- quagga_config = Peer(peer_ip, peer_id, peer_as, peer_ip_version)
-
- networks = config.find_objects(r"^network")
- if len(networks) == 0:
- continue
- for network in networks:
- elems = network.text.split(" ")
- prefix = elems[1].split("/")[0]
- network = elems[1]
- nexthop = peer_ip
- path = Path(network, nexthop)
- dest = Destination(prefix)
- dest.paths.append(path)
- quagga_config.destinations[prefix] = dest
- # print "prefix: " + prefix
- # print "network: " + network
- # print "nexthop: " + nexthop
-
- neighbors = config.find_objects(r"^neighbor\s.*\sremote-as")
- if len(neighbors) == 0:
- continue
- for neighbor in neighbors:
- elems = neighbor.text.split(" ")
- neighbor = Peer(elems[1], None, elems[3], None)
- quagga_config.neighbors.append(neighbor)
- configs.append(quagga_config)
-
- return configs \ No newline at end of file