diff options
-rw-r--r-- | api/gobgp.pb.go | 490 | ||||
-rw-r--r-- | api/gobgp.proto | 134 | ||||
-rw-r--r-- | api/util.go | 24 | ||||
-rw-r--r-- | gobgp/main.go | 147 | ||||
-rw-r--r-- | gobgpd/main.go | 3 | ||||
-rw-r--r-- | packet/bgp.go | 288 | ||||
-rw-r--r-- | server/grpc_server.go (renamed from api/grpc.go) | 154 | ||||
-rw-r--r-- | server/peer.go | 77 | ||||
-rw-r--r-- | server/peer_test.go | 18 | ||||
-rw-r--r-- | server/server.go | 39 | ||||
-rw-r--r-- | table/destination.go | 33 | ||||
-rw-r--r-- | table/path.go | 31 | ||||
-rw-r--r-- | table/table.go | 8 | ||||
-rw-r--r-- | table/table_manager.go | 2 | ||||
-rw-r--r-- | table/table_manager_test.go | 4 | ||||
-rw-r--r-- | table/table_test.go | 4 | ||||
-rw-r--r-- | test/scenario_test/bgp_router_test.py | 5 | ||||
-rw-r--r-- | test/scenario_test/gobgp_test.py | 16 | ||||
-rw-r--r-- | test/scenario_test/route_server_policy_test.py | 149 | ||||
-rw-r--r-- | test/scenario_test/route_server_test.py | 2 |
20 files changed, 1004 insertions, 624 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index 3b91d6ea..f69432a0 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -11,6 +11,12 @@ It is generated from these files: It has these top-level messages: Error Arguments + ModPathArguments + AddressFamily + Aggregator + EVPNNlri + EvpnMacIpAdvertisement + Nlri PathAttr Path Destination @@ -60,70 +66,205 @@ func (x Resource) String() string { return proto.EnumName(Resource_name, int32(x)) } -type AddressFamily int32 +type AFI int32 const ( - AddressFamily_IPV4 AddressFamily = 0 - AddressFamily_IPV6 AddressFamily = 1 - AddressFamily_EVPN AddressFamily = 2 + AFI_UNKNOWN_AFI AFI = 0 + AFI_IP AFI = 1 + AFI_IP6 AFI = 2 + AFI_L2VPN AFI = 25 ) -var AddressFamily_name = map[int32]string{ - 0: "IPV4", - 1: "IPV6", - 2: "EVPN", +var AFI_name = map[int32]string{ + 0: "UNKNOWN_AFI", + 1: "IP", + 2: "IP6", + 25: "L2VPN", } -var AddressFamily_value = map[string]int32{ - "IPV4": 0, - "IPV6": 1, - "EVPN": 2, +var AFI_value = map[string]int32{ + "UNKNOWN_AFI": 0, + "IP": 1, + "IP6": 2, + "L2VPN": 25, } -func (x AddressFamily) String() string { - return proto.EnumName(AddressFamily_name, int32(x)) +func (x AFI) String() string { + return proto.EnumName(AFI_name, int32(x)) } -type Error_ErrorCode int32 +type SAFI int32 const ( - Error_SUCCESS Error_ErrorCode = 0 - Error_FAIL Error_ErrorCode = 1 + SAFI_UNKNOWN_SAFI SAFI = 0 + SAFI_UNICAST SAFI = 1 + SAFI_MULTICAST SAFI = 2 + SAFI_MPLS_LABEL SAFI = 4 + SAFI_VPLS SAFI = 65 + SAFI_EVPN SAFI = 70 + SAFI_MPLS_VPN SAFI = 128 + SAFI_MPLS_VPN_MULTICAST SAFI = 129 + SAFI_ROUTE_TARGET_CONSTRTAINS SAFI = 132 ) -var Error_ErrorCode_name = map[int32]string{ - 0: "SUCCESS", - 1: "FAIL", +var SAFI_name = map[int32]string{ + 0: "UNKNOWN_SAFI", + 1: "UNICAST", + 2: "MULTICAST", + 4: "MPLS_LABEL", + 65: "VPLS", + 70: "EVPN", + 128: "MPLS_VPN", + 129: "MPLS_VPN_MULTICAST", + 132: "ROUTE_TARGET_CONSTRTAINS", } -var Error_ErrorCode_value = map[string]int32{ - "SUCCESS": 0, - "FAIL": 1, +var SAFI_value = map[string]int32{ + "UNKNOWN_SAFI": 0, + "UNICAST": 1, + "MULTICAST": 2, + "MPLS_LABEL": 4, + "VPLS": 65, + "EVPN": 70, + "MPLS_VPN": 128, + "MPLS_VPN_MULTICAST": 129, + "ROUTE_TARGET_CONSTRTAINS": 132, } -func (x Error_ErrorCode) String() string { - return proto.EnumName(Error_ErrorCode_name, int32(x)) +func (x SAFI) String() string { + return proto.EnumName(SAFI_name, int32(x)) } -type PathAttr_Origin int32 +type Origin int32 const ( - PathAttr_IGP PathAttr_Origin = 0 - PathAttr_EGP PathAttr_Origin = 1 - PathAttr_INCOMPLETE PathAttr_Origin = 2 + Origin_IGP Origin = 0 + Origin_EGP Origin = 1 + Origin_INCOMPLETE Origin = 2 ) -var PathAttr_Origin_name = map[int32]string{ +var Origin_name = map[int32]string{ 0: "IGP", 1: "EGP", 2: "INCOMPLETE", } -var PathAttr_Origin_value = map[string]int32{ +var 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)) +func (x Origin) String() string { + return proto.EnumName(Origin_name, int32(x)) +} + +type EVPN_TYPE int32 + +const ( + EVPN_TYPE__ EVPN_TYPE = 0 + EVPN_TYPE_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY EVPN_TYPE = 1 + EVPN_TYPE_ROUTE_TYPE_MAC_IP_ADVERTISEMENT EVPN_TYPE = 2 + EVPN_TYPE_INCLUSIVE_MULTICAST_ETHERNET_TAG EVPN_TYPE = 3 + EVPN_TYPE_ETHERNET_SEGMENT_ROUTE EVPN_TYPE = 4 +) + +var EVPN_TYPE_name = map[int32]string{ + 0: "_", + 1: "ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY", + 2: "ROUTE_TYPE_MAC_IP_ADVERTISEMENT", + 3: "INCLUSIVE_MULTICAST_ETHERNET_TAG", + 4: "ETHERNET_SEGMENT_ROUTE", +} +var EVPN_TYPE_value = map[string]int32{ + "_": 0, + "ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY": 1, + "ROUTE_TYPE_MAC_IP_ADVERTISEMENT": 2, + "INCLUSIVE_MULTICAST_ETHERNET_TAG": 3, + "ETHERNET_SEGMENT_ROUTE": 4, +} + +func (x EVPN_TYPE) String() string { + return proto.EnumName(EVPN_TYPE_name, int32(x)) +} + +type BGP_ATTR_TYPE int32 + +const ( + BGP_ATTR_TYPE_UNKNOWN_ATTR BGP_ATTR_TYPE = 0 + BGP_ATTR_TYPE_ORIGIN BGP_ATTR_TYPE = 1 + BGP_ATTR_TYPE_AS_PATH BGP_ATTR_TYPE = 2 + BGP_ATTR_TYPE_NEXT_HOP BGP_ATTR_TYPE = 3 + BGP_ATTR_TYPE_MULTI_EXIT_DISC BGP_ATTR_TYPE = 4 + BGP_ATTR_TYPE_LOCAL_PREF BGP_ATTR_TYPE = 5 + BGP_ATTR_TYPE_ATOMIC_AGGREGATE BGP_ATTR_TYPE = 6 + BGP_ATTR_TYPE_AGGREGATOR BGP_ATTR_TYPE = 7 + BGP_ATTR_TYPE_COMMUNITIES BGP_ATTR_TYPE = 8 + BGP_ATTR_TYPE_ORIGINATOR_ID BGP_ATTR_TYPE = 9 + BGP_ATTR_TYPE_CLUSTER_LIST BGP_ATTR_TYPE = 10 + BGP_ATTR_TYPE_MP_REACH_NLRI BGP_ATTR_TYPE = 14 + BGP_ATTR_TYPE_MP_UNREACH_NLRI BGP_ATTR_TYPE = 15 + BGP_ATTR_TYPE_EXTENDED_COMMUNITIES BGP_ATTR_TYPE = 16 + BGP_ATTR_TYPE_AS4_PATH BGP_ATTR_TYPE = 17 + BGP_ATTR_TYPE_AS4_AGGREGATOR BGP_ATTR_TYPE = 18 +) + +var BGP_ATTR_TYPE_name = map[int32]string{ + 0: "UNKNOWN_ATTR", + 1: "ORIGIN", + 2: "AS_PATH", + 3: "NEXT_HOP", + 4: "MULTI_EXIT_DISC", + 5: "LOCAL_PREF", + 6: "ATOMIC_AGGREGATE", + 7: "AGGREGATOR", + 8: "COMMUNITIES", + 9: "ORIGINATOR_ID", + 10: "CLUSTER_LIST", + 14: "MP_REACH_NLRI", + 15: "MP_UNREACH_NLRI", + 16: "EXTENDED_COMMUNITIES", + 17: "AS4_PATH", + 18: "AS4_AGGREGATOR", +} +var BGP_ATTR_TYPE_value = map[string]int32{ + "UNKNOWN_ATTR": 0, + "ORIGIN": 1, + "AS_PATH": 2, + "NEXT_HOP": 3, + "MULTI_EXIT_DISC": 4, + "LOCAL_PREF": 5, + "ATOMIC_AGGREGATE": 6, + "AGGREGATOR": 7, + "COMMUNITIES": 8, + "ORIGINATOR_ID": 9, + "CLUSTER_LIST": 10, + "MP_REACH_NLRI": 14, + "MP_UNREACH_NLRI": 15, + "EXTENDED_COMMUNITIES": 16, + "AS4_PATH": 17, + "AS4_AGGREGATOR": 18, +} + +func (x BGP_ATTR_TYPE) String() string { + return proto.EnumName(BGP_ATTR_TYPE_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 Error struct { @@ -136,61 +277,166 @@ 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"` + Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"` + Af *AddressFamily `protobuf:"bytes,2,opt,name=af" json:"af,omitempty"` + RouterId string `protobuf:"bytes,3,opt,name=router_id" json:"router_id,omitempty"` } func (m *Arguments) Reset() { *m = Arguments{} } func (m *Arguments) String() string { return proto.CompactTextString(m) } func (*Arguments) ProtoMessage() {} +func (m *Arguments) GetAf() *AddressFamily { + if m != nil { + return m.Af + } + return nil +} + +type ModPathArguments struct { + Resource Resource `protobuf:"varint,1,opt,name=resource,enum=api.Resource" json:"resource,omitempty"` + Path *Path `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` +} + +func (m *ModPathArguments) Reset() { *m = ModPathArguments{} } +func (m *ModPathArguments) String() string { return proto.CompactTextString(m) } +func (*ModPathArguments) ProtoMessage() {} + +func (m *ModPathArguments) GetPath() *Path { + if m != nil { + return m.Path + } + return nil +} + +type AddressFamily struct { + Afi AFI `protobuf:"varint,1,opt,enum=api.AFI" json:"Afi,omitempty"` + Safi SAFI `protobuf:"varint,2,opt,enum=api.SAFI" json:"Safi,omitempty"` +} + +func (m *AddressFamily) Reset() { *m = AddressFamily{} } +func (m *AddressFamily) String() string { return proto.CompactTextString(m) } +func (*AddressFamily) ProtoMessage() {} + +type 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 *Aggregator) Reset() { *m = Aggregator{} } +func (m *Aggregator) String() string { return proto.CompactTextString(m) } +func (*Aggregator) ProtoMessage() {} + +type EVPNNlri struct { + Type EVPN_TYPE `protobuf:"varint,1,opt,name=type,enum=api.EVPN_TYPE" json:"type,omitempty"` + // EvpnAutoDiscoveryRoute = 2; + MacIpAdv *EvpnMacIpAdvertisement `protobuf:"bytes,3,opt,name=mac_ip_adv" json:"mac_ip_adv,omitempty"` +} + +func (m *EVPNNlri) Reset() { *m = EVPNNlri{} } +func (m *EVPNNlri) String() string { return proto.CompactTextString(m) } +func (*EVPNNlri) ProtoMessage() {} + +func (m *EVPNNlri) GetMacIpAdv() *EvpnMacIpAdvertisement { + if m != nil { + return m.MacIpAdv + } + return nil +} + +type EvpnMacIpAdvertisement struct { + MacAddr string `protobuf:"bytes,1,opt,name=mac_addr" json:"mac_addr,omitempty"` + MacAddrLen uint32 `protobuf:"varint,2,opt,name=mac_addr_len" json:"mac_addr_len,omitempty"` + IpAddr string `protobuf:"bytes,3,opt,name=ip_addr" json:"ip_addr,omitempty"` + IpAddrLen uint32 `protobuf:"varint,4,opt,name=ip_addr_len" json:"ip_addr_len,omitempty"` + Rd string `protobuf:"bytes,5,opt,name=rd" json:"rd,omitempty"` + Esi string `protobuf:"bytes,6,opt,name=esi" json:"esi,omitempty"` + Etag uint32 `protobuf:"varint,7,opt,name=etag" json:"etag,omitempty"` + Labels []uint32 `protobuf:"varint,8,rep,name=labels" json:"labels,omitempty"` +} + +func (m *EvpnMacIpAdvertisement) Reset() { *m = EvpnMacIpAdvertisement{} } +func (m *EvpnMacIpAdvertisement) String() string { return proto.CompactTextString(m) } +func (*EvpnMacIpAdvertisement) ProtoMessage() {} + +type Nlri struct { + Af *AddressFamily `protobuf:"bytes,1,opt,name=af" json:"af,omitempty"` + Prefix string `protobuf:"bytes,2,opt,name=prefix" json:"prefix,omitempty"` + EvpnNlri *EVPNNlri `protobuf:"bytes,3,opt,name=evpn_nlri" json:"evpn_nlri,omitempty"` + Nexthop string `protobuf:"bytes,4,opt,name=nexthop" json:"nexthop,omitempty"` +} + +func (m *Nlri) Reset() { *m = Nlri{} } +func (m *Nlri) String() string { return proto.CompactTextString(m) } +func (*Nlri) ProtoMessage() {} + +func (m *Nlri) GetAf() *AddressFamily { + if m != nil { + return m.Af + } + return nil +} + +func (m *Nlri) GetEvpnNlri() *EVPNNlri { + if m != nil { + return m.EvpnNlri + } + return nil +} + 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"` + Type BGP_ATTR_TYPE `protobuf:"varint,1,opt,name=type,enum=api.BGP_ATTR_TYPE" json:"type,omitempty"` + Value []string `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` + Origin Origin `protobuf:"varint,3,opt,name=origin,enum=api.Origin" json:"origin,omitempty"` + AsPath []uint32 `protobuf:"varint,4,rep,name=as_path" json:"as_path,omitempty"` + Nexthop string `protobuf:"bytes,5,opt,name=nexthop" json:"nexthop,omitempty"` + Metric uint32 `protobuf:"varint,6,opt,name=metric" json:"metric,omitempty"` + Pref uint32 `protobuf:"varint,7,opt,name=pref" json:"pref,omitempty"` + Aggregator *Aggregator `protobuf:"bytes,8,opt,name=aggregator" json:"aggregator,omitempty"` + Communites []uint32 `protobuf:"varint,9,rep,name=communites" json:"communites,omitempty"` + Originator string `protobuf:"bytes,10,opt,name=originator" json:"originator,omitempty"` + Cluster []string `protobuf:"bytes,11,rep,name=cluster" json:"cluster,omitempty"` + Nlri *Nlri `protobuf:"bytes,12,opt,name=nlri" json:"nlri,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 { +func (m *PathAttr) GetAggregator() *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) GetNlri() *Nlri { + if m != nil { + return m.Nlri + } + return nil } -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"` + Nlri *Nlri `protobuf:"bytes,1,opt,name=nlri" json:"nlri,omitempty"` + Attrs []*PathAttr `protobuf:"bytes,2,rep,name=attrs" json:"attrs,omitempty"` + Nexthop string `protobuf:"bytes,3,opt,name=nexthop" json:"nexthop,omitempty"` + Age int64 `protobuf:"varint,4,opt,name=age" json:"age,omitempty"` + Best bool `protobuf:"varint,5,opt,name=best" json:"best,omitempty"` + IsWithdraw bool `protobuf:"varint,6,opt,name=is_withdraw" json:"is_withdraw,omitempty"` } func (m *Path) Reset() { *m = Path{} } func (m *Path) String() string { return proto.CompactTextString(m) } func (*Path) ProtoMessage() {} +func (m *Path) GetNlri() *Nlri { + if m != nil { + return m.Nlri + } + return nil +} + func (m *Path) GetAttrs() []*PathAttr { if m != nil { return m.Attrs @@ -201,7 +447,7 @@ func (m *Path) GetAttrs() []*PathAttr { 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"` + BestPathIdx uint32 `protobuf:"varint,3,opt,name=best_path_idx" json:"best_path_idx,omitempty"` } func (m *Destination) Reset() { *m = Destination{} } @@ -286,9 +532,12 @@ func (m *Peer) GetInfo() *PeerInfo { func init() { proto.RegisterEnum("api.Resource", Resource_name, Resource_value) - proto.RegisterEnum("api.AddressFamily", AddressFamily_name, AddressFamily_value) + proto.RegisterEnum("api.AFI", AFI_name, AFI_value) + proto.RegisterEnum("api.SAFI", SAFI_name, SAFI_value) + proto.RegisterEnum("api.Origin", Origin_name, Origin_value) + proto.RegisterEnum("api.EVPN_TYPE", EVPN_TYPE_name, EVPN_TYPE_value) + proto.RegisterEnum("api.BGP_ATTR_TYPE", BGP_ATTR_TYPE_name, BGP_ATTR_TYPE_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 @@ -305,8 +554,7 @@ type GrpcClient interface { 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) + ModPath(ctx context.Context, opts ...grpc.CallOption) (Grpc_ModPathClient, error) } type grpcClient struct { @@ -485,67 +733,30 @@ func (c *grpcClient) Disable(ctx context.Context, in *Arguments, opts ...grpc.Ca 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...) +func (c *grpcClient) ModPath(ctx context.Context, opts ...grpc.CallOption) (Grpc_ModPathClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Grpc_serviceDesc.Streams[3], c.cc, "/api.Grpc/ModPath", opts...) if err != nil { return nil, err } - x := &grpcDeletePathClient{stream} + x := &grpcModPathClient{stream} return x, nil } -type Grpc_DeletePathClient interface { - Send(*Arguments) error - CloseAndRecv() (*Error, error) +type Grpc_ModPathClient interface { + Send(*ModPathArguments) error + Recv() (*Error, error) grpc.ClientStream } -type grpcDeletePathClient struct { +type grpcModPathClient struct { grpc.ClientStream } -func (x *grpcDeletePathClient) Send(m *Arguments) error { +func (x *grpcModPathClient) Send(m *ModPathArguments) error { return x.ClientStream.SendMsg(m) } -func (x *grpcDeletePathClient) CloseAndRecv() (*Error, error) { - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } +func (x *grpcModPathClient) Recv() (*Error, error) { m := new(Error) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err @@ -567,8 +778,7 @@ type GrpcServer interface { 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 + ModPath(Grpc_ModPathServer) error } func RegisterGrpcServer(s *grpc.Server, srv GrpcServer) { @@ -734,52 +944,26 @@ func _Grpc_Disable_Handler(srv interface{}, ctx context.Context, buf []byte) (in 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 _Grpc_ModPath_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GrpcServer).ModPath(&grpcModPathServer{stream}) } -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) +type Grpc_ModPathServer interface { + Send(*Error) error + Recv() (*ModPathArguments, error) grpc.ServerStream } -type grpcDeletePathServer struct { +type grpcModPathServer struct { grpc.ServerStream } -func (x *grpcDeletePathServer) SendAndClose(m *Error) error { +func (x *grpcModPathServer) Send(m *Error) error { return x.ServerStream.SendMsg(m) } -func (x *grpcDeletePathServer) Recv() (*Arguments, error) { - m := new(Arguments) +func (x *grpcModPathServer) Recv() (*ModPathArguments, error) { + m := new(ModPathArguments) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } @@ -840,13 +1024,9 @@ var _Grpc_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, }, { - StreamName: "AddPath", - Handler: _Grpc_AddPath_Handler, - ClientStreams: true, - }, - { - StreamName: "DeletePath", - Handler: _Grpc_DeletePath_Handler, + StreamName: "ModPath", + Handler: _Grpc_ModPath_Handler, + ServerStreams: true, ClientStreams: true, }, }, diff --git a/api/gobgp.proto b/api/gobgp.proto index 41832653..7c796463 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -31,8 +31,7 @@ service Grpc { 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) {} + rpc ModPath(stream ModPathArguments) returns (stream Error) {} } message Error { @@ -48,7 +47,11 @@ message Arguments { Resource resource = 1; AddressFamily af = 2; string router_id = 3; - string prefix = 4; +} + +message ModPathArguments { + Resource resource = 1; + Path path = 2; } enum Resource { @@ -58,41 +61,116 @@ enum Resource { ADJ_OUT = 3; } -enum AddressFamily { - IPV4 = 0; - IPV6 = 1; - EVPN = 2; +enum AFI { + UNKNOWN_AFI = 0; + IP = 1; + IP6 = 2; + L2VPN = 25; } -message PathAttr { +enum SAFI { + UNKNOWN_SAFI = 0; + UNICAST = 1; + MULTICAST = 2; + MPLS_LABEL = 4; + VPLS = 65; + EVPN = 70; + MPLS_VPN = 128; + MPLS_VPN_MULTICAST = 129; + ROUTE_TARGET_CONSTRTAINS = 132; +} - 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 AddressFamily { + AFI Afi = 1; + SAFI Safi = 2; +} + +enum Origin { + IGP = 0; + EGP = 1; + INCOMPLETE = 2; +} + +message Aggregator { + uint32 as = 1; + string address = 2; +} + +enum EVPN_TYPE { + UNKNOWN_EVPN_TYPE = 0; + ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY = 1; + ROUTE_TYPE_MAC_IP_ADVERTISEMENT = 2; + INCLUSIVE_MULTICAST_ETHERNET_TAG = 3; + ETHERNET_SEGMENT_ROUTE = 4; +} + +message EVPNNlri { + EVPN_TYPE type = 1; +// EvpnAutoDiscoveryRoute = 2; + EvpnMacIpAdvertisement mac_ip_adv = 3; +// EvpnInclusiveMulticastEthernetTag = 4; +// EvpnEthernetSegmentRoute = 5; +} + +message EvpnMacIpAdvertisement { + string mac_addr = 1; + uint32 mac_addr_len = 2; + string ip_addr = 3; + uint32 ip_addr_len = 4; + string rd = 5; + string esi = 6; + uint32 etag = 7; + repeated uint32 labels = 8; +} + +message Nlri { + AddressFamily af = 1; + string prefix = 2; + EVPNNlri evpn_nlri = 3; + string nexthop = 4; +} + +enum BGP_ATTR_TYPE { + UNKNOWN_ATTR = 0; + ORIGIN = 1; + AS_PATH = 2; + NEXT_HOP = 3; + MULTI_EXIT_DISC = 4; + LOCAL_PREF = 5; + ATOMIC_AGGREGATE = 6; + AGGREGATOR = 7; + COMMUNITIES = 8; + ORIGINATOR_ID = 9; + CLUSTER_LIST = 10; + MP_REACH_NLRI = 14; + MP_UNREACH_NLRI = 15; + EXTENDED_COMMUNITIES = 16; + AS4_PATH = 17; + AS4_AGGREGATOR = 18; +} + +message PathAttr { + BGP_ATTR_TYPE type = 1; + repeated string value = 2; + Origin origin = 3; + repeated uint32 as_path = 4; + string nexthop = 5; + uint32 metric = 6; + uint32 pref = 7; + Aggregator aggregator = 8; + repeated uint32 communites = 9; + string originator = 10; + repeated string cluster = 11; + Nlri nlri = 12; } message Path { - string network = 1; + Nlri nlri = 1; string nexthop = 2; int64 age = 3; repeated PathAttr attrs = 4; bool best = 5; + bool is_withdraw = 6; } message Destination { diff --git a/api/util.go b/api/util.go new file mode 100644 index 00000000..aa27e3d3 --- /dev/null +++ b/api/util.go @@ -0,0 +1,24 @@ +// 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. + +package api + +var AF_IPV4_UC *AddressFamily = &AddressFamily{AFI_IP, SAFI_UNICAST} +var AF_IPV6_UC *AddressFamily = &AddressFamily{AFI_IP6, SAFI_UNICAST} +var AF_EVPN *AddressFamily = &AddressFamily{AFI_L2VPN, SAFI_EVPN} + +func (lhs *AddressFamily) Equal(rhs *AddressFamily) bool { + return lhs.Afi == rhs.Afi && lhs.Safi == rhs.Safi +} diff --git a/gobgp/main.go b/gobgp/main.go index 3f6f4e81..a433d181 100644 --- a/gobgp/main.go +++ b/gobgp/main.go @@ -181,7 +181,7 @@ func showRoute(pathList []*api.Path, showAge bool, showBest bool) { s := bytes.NewBuffer(make([]byte, 0, 64)) s.WriteString("[") for _, a := range attrs { - if a.Type == "BGP_ATTR_TYPE_AS_PATH" { + if a.Type == api.BGP_ATTR_TYPE_AS_PATH { var ss []string for _, as := range a.AsPath { ss = append(ss, fmt.Sprintf("%d", as)) @@ -196,17 +196,17 @@ func showRoute(pathList []*api.Path, showAge bool, showBest bool) { s := []string{} for _, a := range attrs { switch a.Type { - case "BGP_ATTR_TYPE_ORIGIN": + case api.BGP_ATTR_TYPE_ORIGIN: s = append(s, fmt.Sprintf("{Origin: %s}", a.Origin)) - case "BGP_ATTR_TYPE_MULTI_EXIT_DISC": + case api.BGP_ATTR_TYPE_MULTI_EXIT_DISC: s = append(s, fmt.Sprintf("{Med: %d}", a.Metric)) - case "BGP_ATTR_TYPE_LOCAL_PREF": + case api.BGP_ATTR_TYPE_LOCAL_PREF: s = append(s, fmt.Sprintf("{LocalPref: %v}", a.Pref)) - case "BGP_ATTR_TYPE_ATOMIC_AGGREGATE": + case api.BGP_ATTR_TYPE_ATOMIC_AGGREGATE: s = append(s, "AtomicAggregate") - case "BGP_ATTR_TYPE_AGGREGATOR": + case api.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": + case api.BGP_ATTR_TYPE_COMMUNITIES: l := []string{} known := map[uint32]string{ 0xffff0000: "planned-shut", @@ -231,11 +231,11 @@ func showRoute(pathList []*api.Path, showAge bool, showBest bool) { } } s = append(s, fmt.Sprintf("{Cummunity: %v}", l)) - case "BGP_ATTR_TYPE_ORIGINATOR_ID": + case api.BGP_ATTR_TYPE_ORIGINATOR_ID: s = append(s, fmt.Sprintf("{Originator: %v|", a.Originator)) - case "BGP_ATTR_TYPE_CLUSTER_LIST": + case api.BGP_ATTR_TYPE_CLUSTER_LIST: 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": + case api.BGP_ATTR_TYPE_AS4_PATH, api.BGP_ATTR_TYPE_MP_REACH_NLRI, api.BGP_ATTR_TYPE_MP_UNREACH_NLRI, api.BGP_ATTR_TYPE_NEXT_HOP, api.BGP_ATTR_TYPE_AS_PATH: default: s = append(s, fmt.Sprintf("{%v: %v}", a.Type, a.Value)) } @@ -251,29 +251,29 @@ func showRoute(pathList []*api.Path, showAge bool, showBest bool) { } } if showAge { - fmt.Printf(format, best, p.Network, p.Nexthop, aspath(p.Attrs), formatTimedelta(p.Age), formatAttrs(p.Attrs)) + fmt.Printf(format, best, p.Nlri.Prefix, 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)) + fmt.Printf(format, best, p.Nlri.Prefix, p.Nexthop, aspath(p.Attrs), formatAttrs(p.Attrs)) } } } func (x *ShowNeighborRibCommand) Execute(args []string) error { - var rt api.AddressFamily + var rt *api.AddressFamily if len(args) == 0 { if x.remoteIP.To4() != nil { - rt = api.AddressFamily_IPV4 + rt = api.AF_IPV4_UC } else { - rt = api.AddressFamily_IPV6 + rt = api.AF_IPV6_UC } } else { switch args[0] { case "ipv4": - rt = api.AddressFamily_IPV4 + rt = api.AF_IPV4_UC case "ipv6": - rt = api.AddressFamily_IPV6 + rt = api.AF_IPV6_UC case "evpn": - rt = api.AddressFamily_EVPN + rt = api.AF_EVPN } } @@ -441,6 +441,10 @@ func (x *ShowNeighborsCommand) Execute(args []string) error { 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)) } + 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 } @@ -448,17 +452,17 @@ type ShowGlobalCommand struct { } func (x *ShowGlobalCommand) Execute(args []string) error { - var rt api.AddressFamily + var rt *api.AddressFamily if len(args) == 0 { - rt = api.AddressFamily_IPV4 + rt = api.AF_IPV4_UC } else { switch args[0] { case "ipv4": - rt = api.AddressFamily_IPV4 + rt = api.AF_IPV4_UC case "ipv6": - rt = api.AddressFamily_IPV6 + rt = api.AF_IPV6_UC case "evpn": - rt = api.AddressFamily_EVPN + rt = api.AF_EVPN } } @@ -524,19 +528,19 @@ func (x *ResetCommand) Execute(args []string) error { return fmt.Errorf("usage: %s neighbor <router_id> [ipv4|ipv6]", x.resource) } - var rt api.AddressFamily + var rt *api.AddressFamily switch x.resource { case "softreset", "softresetin", "softresetout": if len(args) == 2 { - rt = api.AddressFamily_IPV4 + rt = api.AF_IPV4_UC } else { switch args[2] { case "ipv4": - rt = api.AddressFamily_IPV4 + rt = api.AF_IPV4_UC case "ipv6": - rt = api.AddressFamily_IPV6 + rt = api.AF_IPV6_UC case "evpn": - rt = api.AddressFamily_EVPN + rt = api.AF_EVPN default: return fmt.Errorf("unsupported rf: %s", args[2]) } @@ -548,8 +552,6 @@ func (x *ResetCommand) Execute(args []string) error { Af: rt, } - fmt.Println(arg) - switch x.resource { case "reset": client.Reset(context.Background(), arg) @@ -582,53 +584,66 @@ type PathCommand struct { } func (x *PathCommand) Execute(args []string) error { - if len(args) != 3 { + if len(args) < 3 { return fmt.Errorf("usage: %s global <af> <prefix>", x.modtype) } - var rt api.AddressFamily + + if args[0] != "global" { + return fmt.Errorf("unsupported resource (currently only 'global' is supported): %s", args[0]) + } + + 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 + case "ipv4", "v4", "4": + rt = api.AF_IPV4_UC + case "ipv6", "v6", "6": + rt = api.AF_IPV6_UC + default: + return fmt.Errorf("unsupported address family: %s", args[1]) } - arg := &api.Arguments{ - Resource: api.Resource_GLOBAL, - Af: rt, - Prefix: args[2], + path := &api.Path{} + + switch rt { + case api.AF_IPV4_UC, api.AF_IPV6_UC: + path.Nlri = &api.Nlri{ + 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 - } + path.IsWithdraw = false 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 - } + path.IsWithdraw = true + } + + arg := &api.ModPathArguments{ + Resource: api.Resource_GLOBAL, + Path: path, + } + + stream, err := client.ModPath(context.Background()) + if err != nil { + return err + } + + err = stream.Send(arg) + if err != nil { + return err } + + stream.CloseSend() + + res, e := stream.Recv() + if e != nil { + return e + } + if res.Code != api.Error_SUCCESS { + return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg) + } + return nil } diff --git a/gobgpd/main.go b/gobgpd/main.go index e8922226..d2aee38a 100644 --- a/gobgpd/main.go +++ b/gobgpd/main.go @@ -19,7 +19,6 @@ import ( log "github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus/hooks/syslog" "github.com/jessevdk/go-flags" - "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet" "github.com/osrg/gobgp/server" @@ -144,7 +143,7 @@ func main() { go bgpServer.Serve() // start grpc Server - grpcServer := api.NewGrpcServer(api.GRPC_PORT, bgpServer.GrpcReqCh) + grpcServer := server.NewGrpcServer(server.GRPC_PORT, bgpServer.GrpcReqCh) go grpcServer.Serve() var bgpConfig *config.Bgp = nil diff --git a/packet/bgp.go b/packet/bgp.go index 84169bcc..8e468ec4 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -21,9 +21,11 @@ import ( "encoding/json" "errors" "fmt" + "github.com/osrg/gobgp/api" "math" "net" "reflect" + "strings" ) const ( @@ -452,6 +454,7 @@ type AddrPrefixInterface interface { SAFI() uint8 Len() int String() string + ToApiStruct() *api.Nlri } type IPAddrPrefixDefault struct { @@ -530,6 +533,13 @@ func (r *IPAddrPrefix) SAFI() uint8 { return SAFI_UNICAST } +func (r *IPAddrPrefix) ToApiStruct() *api.Nlri { + return &api.Nlri{ + Af: &api.AddressFamily{api.AFI(r.AFI()), api.SAFI(r.SAFI())}, + Prefix: r.String(), + } +} + type IPv6AddrPrefix struct { IPAddrPrefix } @@ -815,6 +825,13 @@ func (l *LabelledVPNIPAddrPrefix) SAFI() uint8 { return SAFI_MPLS_VPN } +func (l *LabelledVPNIPAddrPrefix) ToApiStruct() *api.Nlri { + return &api.Nlri{ + Af: &api.AddressFamily{api.AFI(l.AFI()), api.SAFI(l.SAFI())}, + Prefix: l.String(), + } +} + func NewLabelledVPNIPAddrPrefix(length uint8, prefix string, label Label, rd RouteDistinguisherInterface) *LabelledVPNIPAddrPrefix { rdlen := 0 if rd != nil { @@ -865,6 +882,13 @@ func (r *LabelledIPAddrPrefix) SAFI() uint8 { return SAFI_MPLS_LABEL } +func (r *LabelledIPAddrPrefix) ToApiStruct() *api.Nlri { + return &api.Nlri{ + Af: &api.AddressFamily{api.AFI(r.AFI()), api.SAFI(r.SAFI())}, + Prefix: r.String(), + } +} + func (r *IPAddrPrefix) decodeNextHop(data []byte) net.IP { if r.addrlen == 0 { r.addrlen = 4 @@ -971,6 +995,13 @@ func (n *RouteTargetMembershipNLRI) String() string { return fmt.Sprintf("%d:%s/%d", n.AS, n.RouteTarget.String(), n.Len()*8) } +func (n *RouteTargetMembershipNLRI) ToApiStruct() *api.Nlri { + return &api.Nlri{ + Af: &api.AddressFamily{api.AFI(n.AFI()), api.SAFI(n.SAFI())}, + Prefix: n.String(), + } +} + type ESIType uint8 const ( @@ -1327,10 +1358,13 @@ func (n *EVPNNLRI) String() string { case EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: m := n.RouteTypeData.(*EVPNMacIPAdvertisementRoute) + var ss []string switch m.RD.(type) { case *RouteDistinguisherIPAddressAS: - return fmt.Sprintf("%s", m.IPAddress.String()) + ss = append(ss, fmt.Sprintf("%s", m.IPAddress.String())) } + ss = append(ss, m.MacAddress.String()) + return strings.Join(ss, ".") case EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: m := n.RouteTypeData.(*EVPNMulticastEthernetTagRoute) @@ -1346,6 +1380,13 @@ func (n *EVPNNLRI) String() string { return fmt.Sprintf("%d:%d", n.RouteType, n.Length) } +func (n *EVPNNLRI) ToApiStruct() *api.Nlri { + return &api.Nlri{ + Af: &api.AddressFamily{api.AFI(n.AFI()), api.SAFI(n.SAFI())}, + Prefix: n.String(), + } +} + func NewEVPNNLRI(routetype uint8, length uint8, routetypedata EVPNRouteTypeInterface) *EVPNNLRI { return &EVPNNLRI{ routetype, @@ -1559,6 +1600,7 @@ type PathAttributeInterface interface { Len() int getFlags() uint8 getType() BGPAttrType + ToApiStruct() *api.PathAttr } type PathAttribute struct { @@ -1645,14 +1687,15 @@ type PathAttributeOrigin struct { PathAttribute } +func (p *PathAttributeOrigin) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_ORIGIN, + Origin: api.Origin(uint8(p.Value[0])), + } +} + func (p *PathAttributeOrigin) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - Value uint8 - }{ - Type: p.Type.String(), - Value: uint8(p.Value[0]), - }) + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeOrigin(value uint8) *PathAttributeOrigin { @@ -1879,7 +1922,7 @@ func (p *PathAttributeAsPath) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeAsPath) MarshalJSON() ([]byte, error) { +func (p *PathAttributeAsPath) ToApiStruct() *api.PathAttr { aslist := make([]uint32, 0) for _, a := range p.Value { path, y := a.(*As4PathParam) @@ -1892,13 +1935,14 @@ func (p *PathAttributeAsPath) MarshalJSON() ([]byte, error) { } } } - return json.Marshal(struct { - Type string - AsPath []uint32 `json:"as_path,omitempty"` - }{ - Type: p.Type.String(), + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_AS_PATH, AsPath: aslist, - }) + } +} + +func (p *PathAttributeAsPath) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeAsPath(value []AsPathParamInterface) *PathAttributeAsPath { @@ -1936,14 +1980,15 @@ func (p *PathAttributeNextHop) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeNextHop) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - Nexthop string - }{ - Type: p.Type.String(), +func (p *PathAttributeNextHop) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_NEXT_HOP, Nexthop: p.Value.String(), - }) + } +} + +func (p *PathAttributeNextHop) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeNextHop(value string) *PathAttributeNextHop { @@ -1983,14 +2028,15 @@ func (p *PathAttributeMultiExitDisc) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeMultiExitDisc) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - Metric uint32 - }{ - Type: p.Type.String(), +func (p *PathAttributeMultiExitDisc) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_MULTI_EXIT_DISC, Metric: p.Value, - }) + } +} + +func (p *PathAttributeMultiExitDisc) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeMultiExitDisc(value uint32) *PathAttributeMultiExitDisc { @@ -2030,14 +2076,15 @@ func (p *PathAttributeLocalPref) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeLocalPref) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - Pref uint32 - }{ - Type: p.Type.String(), +func (p *PathAttributeLocalPref) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_LOCAL_PREF, Pref: p.Value, - }) + } +} + +func (p *PathAttributeLocalPref) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeLocalPref(value uint32) *PathAttributeLocalPref { @@ -2055,12 +2102,14 @@ type PathAttributeAtomicAggregate struct { PathAttribute } +func (p *PathAttributeAtomicAggregate) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_ATOMIC_AGGREGATE, + } +} + func (p *PathAttributeAtomicAggregate) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - }{ - Type: p.Type.String(), - }) + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeAtomicAggregate() *PathAttributeAtomicAggregate { @@ -2123,16 +2172,18 @@ func (p *PathAttributeAggregator) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } +func (p *PathAttributeAggregator) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_AGGREGATOR, + Aggregator: &api.Aggregator{ + As: p.Value.AS, + Address: p.Value.Address.String(), + }, + } +} + func (p *PathAttributeAggregator) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - AS uint32 - Address net.IP - }{ - Type: p.Type.String(), - AS: p.Value.AS, - Address: p.Value.Address, - }) + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeAggregator(as interface{}, address string) *PathAttributeAggregator { @@ -2183,14 +2234,15 @@ func (p *PathAttributeCommunities) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } +func (p *PathAttributeCommunities) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_COMMUNITIES, + Communites: p.Value, + } +} + func (p *PathAttributeCommunities) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - Value []uint32 - }{ - Type: p.Type.String(), - Value: p.Value, - }) + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeCommunities(value []uint32) *PathAttributeCommunities { @@ -2231,14 +2283,15 @@ func (p *PathAttributeOriginatorId) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } +func (p *PathAttributeOriginatorId) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_ORIGINATOR_ID, + Originator: p.Value.String(), + } +} + func (p *PathAttributeOriginatorId) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Type string - Address string - }{ - Type: p.Type.String(), - Address: p.Value.String(), - }) + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeOriginatorId(value string) *PathAttributeOriginatorId { @@ -2285,19 +2338,19 @@ func (p *PathAttributeClusterList) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeClusterList) MarshalJSON() ([]byte, error) { +func (p *PathAttributeClusterList) ToApiStruct() *api.PathAttr { l := make([]string, 0) for _, addr := range p.Value { l = append(l, addr.String()) } + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_CLUSTER_LIST, + Cluster: l, + } +} - return json.Marshal(struct { - Type string - Address []string - }{ - Type: p.Type.String(), - Address: l, - }) +func (p *PathAttributeClusterList) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeClusterList(value []string) *PathAttributeClusterList { @@ -2426,26 +2479,29 @@ func (p *PathAttributeMpReachNLRI) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeMpReachNLRI) MarshalJSON() ([]byte, error) { - // TODO: fix address printing - return json.Marshal(struct { - Type string - Nexthop string - Address []string - }{ - Type: p.Type.String(), +func (p *PathAttributeMpReachNLRI) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_MP_REACH_NLRI, Nexthop: p.Nexthop.String(), - }) + } +} + +func (p *PathAttributeMpReachNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeMpReachNLRI(nexthop string, nlri []AddrPrefixInterface) *PathAttributeMpReachNLRI { t := BGP_ATTR_TYPE_MP_REACH_NLRI + ip := net.ParseIP(nexthop) + if ip.To4() != nil { + ip = ip.To4() + } p := &PathAttributeMpReachNLRI{ PathAttribute: PathAttribute{ Flags: pathAttrFlags[t], Type: t, }, - Nexthop: net.ParseIP(nexthop), + Nexthop: ip, Value: nlri, } if len(nlri) > 0 { @@ -2516,6 +2572,16 @@ func (p *PathAttributeMpUnreachNLRI) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } +func (p *PathAttributeMpUnreachNLRI) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_MP_UNREACH_NLRI, + } +} + +func (p *PathAttributeMpUnreachNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) +} + func NewPathAttributeMpUnreachNLRI(nlri []AddrPrefixInterface) *PathAttributeMpUnreachNLRI { t := BGP_ATTR_TYPE_MP_UNREACH_NLRI p := &PathAttributeMpUnreachNLRI{ @@ -2705,6 +2771,24 @@ func (p *PathAttributeExtendedCommunities) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } +func (p *PathAttributeExtendedCommunities) ToApiStruct() *api.PathAttr { + value := func(arg []ExtendedCommunityInterface) []string { + ret := make([]string, 0, len(arg)) + for _, v := range p.Value { + ret = append(ret, v.String()) + } + return ret + }(p.Value) + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES, + Value: value, + } +} + +func (p *PathAttributeExtendedCommunities) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) +} + func NewPathAttributeExtendedCommunities(value []ExtendedCommunityInterface) *PathAttributeExtendedCommunities { t := BGP_ATTR_TYPE_EXTENDED_COMMUNITIES return &PathAttributeExtendedCommunities{ @@ -2762,18 +2846,19 @@ func (p *PathAttributeAs4Path) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } -func (p *PathAttributeAs4Path) MarshalJSON() ([]byte, error) { +func (p *PathAttributeAs4Path) ToApiStruct() *api.PathAttr { aslist := make([]uint32, 0) for _, a := range p.Value { aslist = append(aslist, a.AS...) } - return json.Marshal(struct { - Type string - AsPath []uint32 - }{ - Type: p.Type.String(), + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_AS4_PATH, AsPath: aslist, - }) + } +} + +func (p *PathAttributeAs4Path) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) } func NewPathAttributeAs4Path(value []*As4PathParam) *PathAttributeAs4Path { @@ -2815,6 +2900,20 @@ func (p *PathAttributeAs4Aggregator) Serialize() ([]byte, error) { return p.PathAttribute.Serialize() } +func (p *PathAttributeAs4Aggregator) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_AS4_AGGREGATOR, + Aggregator: &api.Aggregator{ + As: p.Value.AS, + Address: p.Value.Address.String(), + }, + } +} + +func (p *PathAttributeAs4Aggregator) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) +} + func NewPathAttributeAs4Aggregator(as uint32, address string) *PathAttributeAs4Aggregator { t := BGP_ATTR_TYPE_AS4_AGGREGATOR return &PathAttributeAs4Aggregator{ @@ -2833,6 +2932,17 @@ type PathAttributeUnknown struct { PathAttribute } +func (p *PathAttributeUnknown) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_UNKNOWN_ATTR, + Value: []string{string(p.Value)}, + } +} + +func (p *PathAttributeUnknown) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToApiStruct()) +} + func getPathAttribute(data []byte) (PathAttributeInterface, error) { if len(data) < 1 { eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) diff --git a/api/grpc.go b/server/grpc_server.go index 69e8d159..76e79943 100644 --- a/api/grpc.go +++ b/server/grpc_server.go @@ -13,11 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package api +package server import ( "fmt" log "github.com/Sirupsen/logrus" + "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/packet" "golang.org/x/net/context" "google.golang.org/grpc" @@ -46,6 +47,18 @@ const ( const GRPC_PORT = 8080 +func convertAf2Rf(af *api.AddressFamily) (bgp.RouteFamily, error) { + if af.Equal(api.AF_IPV4_UC) { + return bgp.RF_IPv4_UC, nil + } else if af.Equal(api.AF_IPV6_UC) { + return bgp.RF_IPv6_UC, nil + } else if af.Equal(api.AF_EVPN) { + return bgp.RF_EVPN, nil + } + + return bgp.RouteFamily(0), fmt.Errorf("unsupported address family: %v", af) +} + type Server struct { grpcServer *grpc.Server bgpServerCh chan *GrpcRequest @@ -60,7 +73,7 @@ func (s *Server) Serve() error { return nil } -func (s *Server) GetNeighbor(ctx context.Context, arg *Arguments) (*Peer, error) { +func (s *Server) GetNeighbor(ctx context.Context, arg *api.Arguments) (*api.Peer, error) { var rf bgp.RouteFamily req := NewGrpcRequest(REQ_NEIGHBOR, arg.RouterId, rf, nil) s.bgpServerCh <- req @@ -71,10 +84,10 @@ func (s *Server) GetNeighbor(ctx context.Context, arg *Arguments) (*Peer, error) return nil, err } - return res.Data.(*Peer), nil + return res.Data.(*api.Peer), nil } -func (s *Server) GetNeighbors(_ *Arguments, stream Grpc_GetNeighborsServer) error { +func (s *Server) GetNeighbors(_ *api.Arguments, stream api.Grpc_GetNeighborsServer) error { var rf bgp.RouteFamily req := NewGrpcRequest(REQ_NEIGHBORS, "", rf, nil) s.bgpServerCh <- req @@ -84,7 +97,7 @@ func (s *Server) GetNeighbors(_ *Arguments, stream Grpc_GetNeighborsServer) erro log.Debug(err.Error()) return err } - if err := stream.Send(res.Data.(*Peer)); err != nil { + if err := stream.Send(res.Data.(*api.Peer)); err != nil { return err } } @@ -92,27 +105,20 @@ func (s *Server) GetNeighbors(_ *Arguments, stream Grpc_GetNeighborsServer) erro return nil } -func (s *Server) GetAdjRib(arg *Arguments, stream Grpc_GetAdjRibServer) error { +func (s *Server) GetAdjRib(arg *api.Arguments, stream api.Grpc_GetAdjRibServer) error { var reqType int switch arg.Resource { - case Resource_ADJ_IN: + case api.Resource_ADJ_IN: reqType = REQ_ADJ_RIB_IN - case Resource_ADJ_OUT: + case api.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) + rf, err := convertAf2Rf(arg.Af) + if err != nil { + return err } req := NewGrpcRequest(reqType, arg.RouterId, rf, nil) @@ -123,7 +129,7 @@ func (s *Server) GetAdjRib(arg *Arguments, stream Grpc_GetAdjRibServer) error { log.Debug(err.Error()) return err } - if err := stream.Send(res.Data.(*Path)); err != nil { + if err := stream.Send(res.Data.(*api.Path)); err != nil { return err } } @@ -131,27 +137,20 @@ func (s *Server) GetAdjRib(arg *Arguments, stream Grpc_GetAdjRibServer) error { return nil } -func (s *Server) GetRib(arg *Arguments, stream Grpc_GetRibServer) error { +func (s *Server) GetRib(arg *api.Arguments, stream api.Grpc_GetRibServer) error { var reqType int switch arg.Resource { - case Resource_LOCAL: + case api.Resource_LOCAL: reqType = REQ_LOCAL_RIB - case Resource_GLOBAL: + case api.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) + rf, err := convertAf2Rf(arg.Af) + if err != nil { + return err } req := NewGrpcRequest(reqType, arg.RouterId, rf, nil) @@ -162,27 +161,20 @@ func (s *Server) GetRib(arg *Arguments, stream Grpc_GetRibServer) error { log.Debug(err.Error()) return err } - if err := stream.Send(res.Data.(*Destination)); err != nil { + if err := stream.Send(res.Data.(*api.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) +func (s *Server) neighbor(reqType int, arg *api.Arguments) (*api.Error, error) { + rf, err := convertAf2Rf(arg.Af) + if err != nil { + return nil, err } - none := &Error{} + none := &api.Error{} req := NewGrpcRequest(reqType, arg.RouterId, rf, nil) s.bgpServerCh <- req @@ -194,46 +186,37 @@ func (s *Server) neighbor(reqType int, arg *Arguments) (*Error, error) { return none, nil } -func (s *Server) Reset(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) Reset(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_RESET, arg) } -func (s *Server) SoftReset(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) SoftReset(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_SOFT_RESET, arg) } -func (s *Server) SoftResetIn(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) SoftResetIn(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_SOFT_RESET_IN, arg) } -func (s *Server) SoftResetOut(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) SoftResetOut(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_SOFT_RESET_OUT, arg) } -func (s *Server) Shutdown(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) Shutdown(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_SHUTDOWN, arg) } -func (s *Server) Enable(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) Enable(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_ENABLE, arg) } -func (s *Server) Disable(ctx context.Context, arg *Arguments) (*Error, error) { +func (s *Server) Disable(ctx context.Context, arg *api.Arguments) (*api.Error, error) { return s.neighbor(REQ_NEIGHBOR_DISABLE, arg) } -func (s *Server) modPath(reqType int, stream grpc.ServerStream) error { +func (s *Server) ModPath(stream api.Grpc_ModPathServer) 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) - } + arg, err := stream.Recv() if err == io.EOF { return nil @@ -241,25 +224,20 @@ func (s *Server) modPath(reqType int, stream grpc.ServerStream) error { return err } - if arg.Resource != Resource_GLOBAL { + if arg.Resource != api.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) + + reqType := REQ_GLOBAL_ADD + if arg.Path.IsWithdraw { + reqType = REQ_GLOBAL_DELETE } - req := NewGrpcRequest(reqType, arg.RouterId, rf, prefix) + rf, err := convertAf2Rf(arg.Path.Nlri.Af) + if err != nil { + return nil + } + req := NewGrpcRequest(reqType, "", rf, arg.Path) s.bgpServerCh <- req res := <-req.ResponseCh @@ -267,15 +245,15 @@ func (s *Server) modPath(reqType int, stream grpc.ServerStream) error { log.Debug(err.Error()) return err } - } -} -func (s *Server) AddPath(stream Grpc_AddPathServer) error { - return s.modPath(REQ_GLOBAL_ADD, stream) -} + err = stream.Send(&api.Error{ + Code: api.Error_SUCCESS, + }) -func (s *Server) DeletePath(stream Grpc_DeletePathServer) error { - return s.modPath(REQ_GLOBAL_DELETE, stream) + if err != nil { + return err + } + } } type GrpcRequest struct { @@ -284,10 +262,10 @@ type GrpcRequest struct { RouteFamily bgp.RouteFamily ResponseCh chan *GrpcResponse Err error - Data map[string]interface{} + Data interface{} } -func NewGrpcRequest(reqType int, remoteAddr string, rf bgp.RouteFamily, d map[string]interface{}) *GrpcRequest { +func NewGrpcRequest(reqType int, remoteAddr string, rf bgp.RouteFamily, d interface{}) *GrpcRequest { r := &GrpcRequest{ RequestType: reqType, RouteFamily: rf, @@ -313,6 +291,6 @@ func NewGrpcServer(port int, bgpServerCh chan *GrpcRequest) *Server { grpcServer: grpcServer, bgpServerCh: bgpServerCh, } - RegisterGrpcServer(grpcServer, server) + api.RegisterGrpcServer(grpcServer, server) return server } diff --git a/server/peer.go b/server/peer.go index 194998fb..2570019f 100644 --- a/server/peer.go +++ b/server/peer.go @@ -288,14 +288,20 @@ func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) { } } -func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { - result := &api.GrpcResponse{} +func (peer *Peer) handleGrpc(grpcReq *GrpcRequest) { + result := &GrpcResponse{} switch grpcReq.RequestType { - case api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE: + case REQ_GLOBAL_ADD, REQ_GLOBAL_DELETE: rf := grpcReq.RouteFamily - prefix := grpcReq.Data["prefix"].(string) + path, ok := grpcReq.Data.(*api.Path) + if !ok { + result.ResponseErr = fmt.Errorf("type assertion failed") + grpcReq.ResponseCh <- result + close(grpcReq.ResponseCh) + return + } var isWithdraw bool - if grpcReq.RequestType == api.REQ_GLOBAL_DELETE { + if grpcReq.RequestType == REQ_GLOBAL_DELETE { isWithdraw = true } @@ -306,9 +312,9 @@ func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { pattr = append(pattr, bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{asparam})) if rf == bgp.RF_IPv4_UC { - ip, net, _ := net.ParseCIDR(prefix) + ip, net, _ := net.ParseCIDR(path.Nlri.Prefix) if ip.To4() == nil { - result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", prefix) + result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", path.Nlri.Prefix) grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) return @@ -321,9 +327,9 @@ func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { pattr = append(pattr, bgp.NewPathAttributeNextHop("0.0.0.0")) } else if rf == bgp.RF_IPv6_UC { - ip, net, _ := net.ParseCIDR(prefix) + ip, net, _ := net.ParseCIDR(path.Nlri.Prefix) if ip.To16() == nil { - result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", prefix) + result.ResponseErr = fmt.Errorf("Invalid ipv6 prefix: %s", path.Nlri.Prefix) grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) return @@ -348,53 +354,40 @@ func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { } peer.peerMsgCh <- pm - case api.REQ_LOCAL_RIB, api.REQ_GLOBAL_RIB: + case REQ_LOCAL_RIB, REQ_GLOBAL_RIB: 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 + for _, dst := range t.GetDestinations() { + result := &GrpcResponse{} + result.Data = dst.ToApiStruct() grpcReq.ResponseCh <- result } close(grpcReq.ResponseCh) return } - case api.REQ_NEIGHBOR_SHUTDOWN: + case REQ_NEIGHBOR_SHUTDOWN: peer.outgoing <- bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, nil) - case api.REQ_NEIGHBOR_RESET: + case REQ_NEIGHBOR_RESET: peer.fsm.idleHoldTime = peer.peerConfig.Timers.IdleHoldTimeAfterReset 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: + case REQ_NEIGHBOR_SOFT_RESET, REQ_NEIGHBOR_SOFT_RESET_IN: // soft-reconfiguration inbound peer.sendPathsToSiblings(peer.adjRib.GetInPathList(grpcReq.RouteFamily)) - if grpcReq.RequestType == api.REQ_NEIGHBOR_SOFT_RESET_IN { + if grpcReq.RequestType == REQ_NEIGHBOR_SOFT_RESET_IN { break } fallthrough - case api.REQ_NEIGHBOR_SOFT_RESET_OUT: + case REQ_NEIGHBOR_SOFT_RESET_OUT: pathList := peer.adjRib.GetOutPathList(grpcReq.RouteFamily) peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList)) - case api.REQ_ADJ_RIB_IN, api.REQ_ADJ_RIB_OUT: + case REQ_ADJ_RIB_IN, REQ_ADJ_RIB_OUT: rf := grpcReq.RouteFamily var paths []table.Path - if grpcReq.RequestType == api.REQ_ADJ_RIB_IN { + if grpcReq.RequestType == REQ_ADJ_RIB_IN { paths = peer.adjRib.GetInPathList(rf) log.Debugf("RouteFamily=%v adj-rib-in found : %d", rf.String(), len(paths)) } else { @@ -403,7 +396,7 @@ func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { } for _, p := range paths { - result := &api.GrpcResponse{} + result := &GrpcResponse{} path := &api.Path{} j, _ := json.Marshal(p) err := json.Unmarshal(j, path) @@ -416,9 +409,9 @@ func (peer *Peer) handleGrpc(grpcReq *api.GrpcRequest) { } close(grpcReq.ResponseCh) return - case api.REQ_NEIGHBOR_ENABLE, api.REQ_NEIGHBOR_DISABLE: + case REQ_NEIGHBOR_ENABLE, REQ_NEIGHBOR_DISABLE: var err api.Error - if grpcReq.RequestType == api.REQ_NEIGHBOR_ENABLE { + if grpcReq.RequestType == REQ_NEIGHBOR_ENABLE { select { case peer.fsm.adminStateCh <- ADMIN_STATE_UP: log.WithFields(log.Fields{ @@ -656,7 +649,7 @@ func (peer *Peer) handleServerMsg(m *serverMsg) { log.Warning("can not find peer: ", d.Address.String()) } case SRV_MSG_API: - peer.handleGrpc(m.msgData.(*api.GrpcRequest)) + peer.handleGrpc(m.msgData.(*GrpcRequest)) case SRV_MSG_POLICY_UPDATED: log.Debug("policy updated") d := m.msgData.(map[string]*policy.Policy) @@ -827,14 +820,10 @@ 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) + return json.Marshal(peer.ToApiStruct()) } -func (peer *Peer) ToGrpc() (*api.Peer, error) { +func (peer *Peer) ToApiStruct() *api.Peer { f := peer.fsm c := f.peerConfig @@ -904,5 +893,5 @@ func (peer *Peer) ToGrpc() (*api.Peer, error) { return &api.Peer{ Conf: conf, Info: info, - }, nil + } } diff --git a/server/peer_test.go b/server/peer_test.go index cae3b0c7..ab3bfa54 100644 --- a/server/peer_test.go +++ b/server/peer_test.go @@ -121,7 +121,7 @@ func TestPeerAdminShutdownWhileEstablished(t *testing.T) { peer.connCh <- m waitUntil(assert, bgp.BGP_FSM_ESTABLISHED, peer, 1000) - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -163,7 +163,7 @@ func TestPeerAdminShutdownWhileIdle(t *testing.T) { waitUntil(assert, bgp.BGP_FSM_IDLE, peer, 1000) - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -197,7 +197,7 @@ func TestPeerAdminShutdownWhileActive(t *testing.T) { waitUntil(assert, bgp.BGP_FSM_ACTIVE, peer, 1000) - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -233,7 +233,7 @@ func TestPeerAdminShutdownWhileOpensent(t *testing.T) { peer.connCh <- m waitUntil(assert, bgp.BGP_FSM_OPENSENT, peer, 1000) - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -277,7 +277,7 @@ func TestPeerAdminShutdownWhileOpenconfirm(t *testing.T) { peer.connCh <- m waitUntil(assert, bgp.BGP_FSM_OPENCONFIRM, peer, 1000) - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -327,7 +327,7 @@ func TestPeerAdminEnable(t *testing.T) { waitUntil(assert, bgp.BGP_FSM_ESTABLISHED, peer, 1000) // shutdown peer at first - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -342,7 +342,7 @@ func TestPeerAdminEnable(t *testing.T) { assert.Equal(ADMIN_STATE_DOWN, peer.fsm.adminState) // enable peer - grpcReq = api.NewGrpcRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq = NewGrpcRequest(REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg = &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -388,7 +388,7 @@ func TestPeerAdminShutdownReject(t *testing.T) { peer.connCh <- m waitUntil(assert, bgp.BGP_FSM_OPENSENT, peer, 1000) - grpcReq := api.NewGrpcRequest(api.REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq := NewGrpcRequest(REQ_NEIGHBOR_DISABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, @@ -401,7 +401,7 @@ func TestPeerAdminShutdownReject(t *testing.T) { err := result.Data.(api.Error) assert.Equal(err.Code, api.Error_FAIL) - grpcReq = api.NewGrpcRequest(api.REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) + grpcReq = NewGrpcRequest(REQ_NEIGHBOR_ENABLE, "0.0.0.0", bgp.RF_IPv4_UC, nil) msg = &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, diff --git a/server/server.go b/server/server.go index 8212a1a0..c83c48df 100644 --- a/server/server.go +++ b/server/server.go @@ -18,7 +18,6 @@ package server import ( "fmt" log "github.com/Sirupsen/logrus" - "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/policy" "net" @@ -60,7 +59,7 @@ type BgpServer struct { globalTypeCh chan config.Global addedPeerCh chan config.Neighbor deletedPeerCh chan config.Neighbor - GrpcReqCh chan *api.GrpcRequest + GrpcReqCh chan *GrpcRequest listenPort int peerMap map[string]peerMapInfo globalRib *Peer @@ -73,7 +72,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.GrpcReqCh = make(chan *api.GrpcRequest, 1) + b.GrpcReqCh = make(chan *GrpcRequest, 1) b.policyUpdateCh = make(chan config.RoutingPolicy) b.listenPort = port return &b @@ -293,53 +292,49 @@ func (p peers) Less(i, j int) bool { return strings.Less(0, 1) } -func (server *BgpServer) handleGrpc(grpcReq *api.GrpcRequest) { +func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { switch grpcReq.RequestType { - case api.REQ_NEIGHBORS: + case REQ_NEIGHBORS: peerList := peers{} for _, info := range server.peerMap { peerList = append(peerList, info.peer) } sort.Sort(peerList) for _, peer := range peerList { - data, err := peer.ToGrpc() - result := &api.GrpcResponse{ - ResponseErr: err, - Data: data, + result := &GrpcResponse{ + Data: peer.ToApiStruct(), } grpcReq.ResponseCh <- result } close(grpcReq.ResponseCh) - case api.REQ_NEIGHBOR: + case REQ_NEIGHBOR: remoteAddr := grpcReq.RemoteAddr - var result *api.GrpcResponse + var result *GrpcResponse info, found := server.peerMap[remoteAddr] if found { - data, err := info.peer.ToGrpc() - result = &api.GrpcResponse{ - ResponseErr: err, - Data: data, + result = &GrpcResponse{ + Data: info.peer.ToApiStruct(), } } else { - result = &api.GrpcResponse{ + result = &GrpcResponse{ ResponseErr: fmt.Errorf("Neighbor that has %v does not exist.", remoteAddr), } } grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) - case api.REQ_GLOBAL_RIB, api.REQ_GLOBAL_ADD, api.REQ_GLOBAL_DELETE: + case REQ_GLOBAL_RIB, REQ_GLOBAL_ADD, REQ_GLOBAL_DELETE: msg := &serverMsg{ msgType: SRV_MSG_API, msgData: grpcReq, } server.globalRib.serverMsgCh <- msg - case api.REQ_LOCAL_RIB, api.REQ_NEIGHBOR_SHUTDOWN, api.REQ_NEIGHBOR_RESET, - api.REQ_NEIGHBOR_SOFT_RESET, api.REQ_NEIGHBOR_SOFT_RESET_IN, api.REQ_NEIGHBOR_SOFT_RESET_OUT, - api.REQ_ADJ_RIB_IN, api.REQ_ADJ_RIB_OUT, - api.REQ_NEIGHBOR_ENABLE, api.REQ_NEIGHBOR_DISABLE: + case REQ_LOCAL_RIB, REQ_NEIGHBOR_SHUTDOWN, REQ_NEIGHBOR_RESET, + REQ_NEIGHBOR_SOFT_RESET, REQ_NEIGHBOR_SOFT_RESET_IN, REQ_NEIGHBOR_SOFT_RESET_OUT, + REQ_ADJ_RIB_IN, REQ_ADJ_RIB_OUT, + REQ_NEIGHBOR_ENABLE, REQ_NEIGHBOR_DISABLE: remoteAddr := grpcReq.RemoteAddr - result := &api.GrpcResponse{} + result := &GrpcResponse{} info, found := server.peerMap[remoteAddr] if found { msg := &serverMsg{ diff --git a/table/destination.go b/table/destination.go index aae02822..cfd411ce 100644 --- a/table/destination.go +++ b/table/destination.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" log "github.com/Sirupsen/logrus" + "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/packet" "net" "reflect" @@ -66,6 +67,7 @@ type Destination interface { addNewPath(newPath Path) constructWithdrawPath() Path removeOldPathsFromSource(source *PeerInfo) []Path + ToApiStruct() *api.Destination MarshalJSON() ([]byte, error) } @@ -94,7 +96,11 @@ func NewDestinationDefault(nlri bgp.AddrPrefixInterface) *DestinationDefault { } func (dd *DestinationDefault) MarshalJSON() ([]byte, error) { - prefix := dd.getNlri().(*bgp.NLRInfo).Prefix + return json.Marshal(dd.ToApiStruct()) +} + +func (dd *DestinationDefault) ToApiStruct() *api.Destination { + prefix := dd.getNlri().String() idx := func() int { for i, p := range dd.knownPathList { @@ -104,19 +110,24 @@ func (dd *DestinationDefault) MarshalJSON() ([]byte, error) { } log.WithFields(log.Fields{ "Topic": "Table", - "Key": prefix.String(), + "Key": prefix, }).Panic("no best path") return 0 }() - return json.Marshal(struct { - Prefix string - Paths []Path - BestPathIdx int `json:"best_path_idx"` - }{ - Prefix: prefix.String(), - Paths: dd.knownPathList, - BestPathIdx: idx, - }) + + paths := func(arg []Path) []*api.Path { + ret := make([]*api.Path, 0, len(arg)) + for _, p := range arg { + ret = append(ret, p.ToApiStruct()) + } + return ret + }(dd.knownPathList) + + return &api.Destination{ + Prefix: prefix, + Paths: paths, + BestPathIdx: uint32(idx), + } } func (dd *DestinationDefault) getRouteFamily() bgp.RouteFamily { diff --git a/table/path.go b/table/path.go index fddde7d3..5abd1f10 100644 --- a/table/path.go +++ b/table/path.go @@ -19,6 +19,7 @@ import ( "encoding/json" "fmt" log "github.com/Sirupsen/logrus" + "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet" "net" @@ -45,6 +46,7 @@ type Path interface { Clone(IsWithdraw bool) Path getTimestamp() time.Time setTimestamp(t time.Time) + ToApiStruct() *api.Path MarshalJSON() ([]byte, error) } @@ -170,18 +172,25 @@ func (pd *PathDefault) setTimestamp(t time.Time) { pd.timestamp = t } +func (pd *PathDefault) ToApiStruct() *api.Path { + pathAttrs := func(arg []bgp.PathAttributeInterface) []*api.PathAttr { + ret := make([]*api.PathAttr, 0, len(arg)) + for _, a := range arg { + ret = append(ret, a.ToApiStruct()) + } + return ret + }(pd.getPathAttrs()) + return &api.Path{ + Nlri: pd.GetNlri().ToApiStruct(), + Nexthop: pd.GetNexthop().String(), + Attrs: pathAttrs, + Age: int64(time.Now().Sub(pd.timestamp).Seconds()), + IsWithdraw: pd.IsWithdraw(), + } +} + func (pd *PathDefault) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Network string - Nexthop string - Attrs []bgp.PathAttributeInterface - Age int64 - }{ - Network: pd.getPrefix(), - Nexthop: pd.GetNexthop().String(), - Attrs: pd.getPathAttrs(), - Age: int64(time.Now().Sub(pd.timestamp).Seconds()), - }) + return json.Marshal(pd.ToApiStruct()) } // create new PathAttributes diff --git a/table/table.go b/table/table.go index 28799a24..d9c14144 100644 --- a/table/table.go +++ b/table/table.go @@ -30,7 +30,7 @@ import ( type Table interface { createDest(nlri bgp.AddrPrefixInterface) Destination - getDestinations() map[string]Destination + GetDestinations() map[string]Destination setDestinations(destinations map[string]Destination) getDestination(key string) Destination setDestination(key string, dest Destination) @@ -153,7 +153,7 @@ func (td *TableDefault) DeleteDestByPeer(peerInfo *PeerInfo) []Destination { func deleteDestByNlri(table Table, nlri bgp.AddrPrefixInterface) Destination { table.validateNlri(nlri) - destinations := table.getDestinations() + destinations := table.GetDestinations() dest := destinations[table.tableKey(nlri)] if dest != nil { delete(destinations, table.tableKey(nlri)) @@ -162,7 +162,7 @@ func deleteDestByNlri(table Table, nlri bgp.AddrPrefixInterface) Destination { } func deleteDest(table Table, dest Destination) { - destinations := table.getDestinations() + destinations := table.GetDestinations() delete(destinations, table.tableKey(dest.getNlri())) } @@ -230,7 +230,7 @@ func getOrCreateDest(table Table, nlri bgp.AddrPrefixInterface) Destination { return dest } -func (td *TableDefault) getDestinations() map[string]Destination { +func (td *TableDefault) GetDestinations() map[string]Destination { return td.destinations } func (td *TableDefault) setDestinations(destinations map[string]Destination) { diff --git a/table/table_manager.go b/table/table_manager.go index abb00cf9..679b684c 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -269,7 +269,7 @@ func (manager *TableManager) GetPathList(rf bgp.RouteFamily) []Path { return []Path{} } var paths []Path - for _, dest := range manager.Tables[rf].getDestinations() { + for _, dest := range manager.Tables[rf].GetDestinations() { paths = append(paths, dest.getBestPath()) } return paths diff --git a/table/table_manager_test.go b/table/table_manager_test.go index 8e800c8c..91887cfb 100644 --- a/table/table_manager_test.go +++ b/table/table_manager_test.go @@ -2053,7 +2053,7 @@ func TestProcessBGPUpdate_multiple_nlri_ipv4(t *testing.T) { // check table table := tm.Tables[bgp.RF_IPv4_UC] - assert.Equal(t, 13, len(table.getDestinations())) + assert.Equal(t, 13, len(table.GetDestinations())) } @@ -2200,7 +2200,7 @@ func TestProcessBGPUpdate_multiple_nlri_ipv6(t *testing.T) { // check table table := tm.Tables[bgp.RF_IPv6_UC] - assert.Equal(t, 13, len(table.getDestinations())) + assert.Equal(t, 13, len(table.GetDestinations())) } diff --git a/table/table_test.go b/table/table_test.go index 81e377f6..407fbe0a 100644 --- a/table/table_test.go +++ b/table/table_test.go @@ -88,7 +88,7 @@ func TestTableSetDestinations(t *testing.T) { destinations[tableKey] = dest } ipv4t.setDestinations(destinations) - ds := ipv4t.getDestinations() + ds := ipv4t.GetDestinations() assert.Equal(t, ds, destinations) } func TestTableGetDestinations(t *testing.T) { @@ -103,7 +103,7 @@ func TestTableGetDestinations(t *testing.T) { destinations[tableKey] = dest } ipv4t.setDestinations(destinations) - ds := ipv4t.getDestinations() + ds := ipv4t.GetDestinations() assert.Equal(t, ds, destinations) } diff --git a/test/scenario_test/bgp_router_test.py b/test/scenario_test/bgp_router_test.py index 268f468d..f965d224 100644 --- a/test/scenario_test/bgp_router_test.py +++ b/test/scenario_test/bgp_router_test.py @@ -69,7 +69,6 @@ class GoBGPTest(GoBGPTestBase): self.assert_global_rib() - # Test of advertising route to each quagga form gobgp def test_03_advertising_route(self): print "test_advertising_route" @@ -157,7 +156,7 @@ class GoBGPTest(GoBGPTestBase): still_exists = False for dst in rib: for path in dst['paths']: - if path['network'] == removed_prefix: + if path['nlri']['prefix'] == removed_prefix: still_exists = True if not still_exists: @@ -236,7 +235,7 @@ class GoBGPTest(GoBGPTestBase): print "please wait " + str(self.initial_wait_time) + " second" time.sleep(self.initial_wait_time) - target_network = "192.168.20.0" + target_network = "192.168.20.0/24" ans_nexthop = "10.0.0.3" print "check whether target network %s 's nexthop is %s" % (target_network, ans_nexthop) diff --git a/test/scenario_test/gobgp_test.py b/test/scenario_test/gobgp_test.py index 2e998178..d3bcdc21 100644 --- a/test/scenario_test/gobgp_test.py +++ b/test/scenario_test/gobgp_test.py @@ -100,7 +100,7 @@ class GoBGPTestBase(unittest.TestCase): for g_path in g_paths: 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'] + print "pre: ", g_dest['prefix'], "net: ", g_path['nlri']['prefix'], "next: ", g_path['nexthop'] if str(best_path_idx) == str(idx): rep_nexthop = g_path['nexthop'] idx += 1 @@ -146,13 +146,12 @@ class GoBGPTestBase(unittest.TestCase): 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 = Destination(network) dest.paths.append(path) - quagga_config.destinations[prefix] = dest + quagga_config.destinations[network] = dest # print "prefix: " + prefix # print "network: " + network # print "nexthop: " + nexthop @@ -240,7 +239,7 @@ class GoBGPTestBase(unittest.TestCase): retry_count = 0 while True: rib = self.ask_gobgp(type, neighbor_address) - paths = [p for p in rib if p['network'] == target_prefix] + paths = [p for p in rib if p['nlri']['prefix'] == target_prefix] if len(paths) > 0: assert len(paths) == 1 @@ -264,12 +263,15 @@ class GoBGPTestBase(unittest.TestCase): interval = self.wait_per_retry print "check route %s on quagga : %s" % (target_prefix, neighbor_address) retry_count = 0 + + # quagga cli doesn't show prefix's netmask + quagga_prefix = target_prefix.split('/')[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']: + if quagga_prefix == q_path['Network']: return q_path retry_count += 1 @@ -342,7 +344,7 @@ class GoBGPTestBase(unittest.TestCase): exist = False for dst in rib: for path in dst['paths']: - if path['network'] == p.network: + if path['nlri']['prefix'] == p.network: exist = True if exist: is_nexthop_same = path['nexthop'] == p.nexthop diff --git a/test/scenario_test/route_server_policy_test.py b/test/scenario_test/route_server_policy_test.py index 9ae29a2b..7c2e0456 100644 --- a/test/scenario_test/route_server_policy_test.py +++ b/test/scenario_test/route_server_policy_test.py @@ -25,6 +25,13 @@ from noseplugin import parser_option from gobgp_test import GoBGPTestBase from constant import * +peer1 = "10.0.0.1" +peer2 = "10.0.0.2" +peer3 = "10.0.0.3" + +prefix1 = "192.168.2.0/24" +prefix2 = "192.168.20.0/24" +prefix3 = "192.168.200.0/24" class GoBGPTest(GoBGPTestBase): @@ -60,29 +67,25 @@ class GoBGPTest(GoBGPTestBase): 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" - - path = self.get_paths_in_localrib(peer1, "192.168.2.0", retry=3) + path = self.get_paths_in_localrib(peer1, prefix1, retry=3) self.assertIsNotNone(path) # check show ip bgp on peer1(quagga1) - qpath = self.get_routing_table(peer1,"192.168.2.0", retry=3) + qpath = self.get_routing_table(peer1,prefix1, retry=3) print qpath self.assertIsNotNone(qpath) # check adj-rib-out in peer2 - path = self.get_adj_rib_in(peer2, "192.168.2.0/24", retry=3) + path = self.get_adj_rib_in(peer2, prefix1, retry=3) # print path self.assertIsNotNone(path) - path = self.get_paths_in_localrib(peer3, "192.168.2.0",retry=0) + path = self.get_paths_in_localrib(peer3, prefix1,retry=0) # print path self.assertIsNone(path) # check show ip bgp on peer1(quagga3) - qpath = self.get_routing_table(peer3,"192.168.2.0", retry=3) + qpath = self.get_routing_table(peer3,prefix1, retry=3) # print qpath self.assertIsNone(qpath) @@ -104,34 +107,30 @@ class GoBGPTest(GoBGPTestBase): 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" - - paths = self.get_paths_in_localrib(peer1, "192.168.2.0", retry=3) + paths = self.get_paths_in_localrib(peer1, prefix1, retry=3) # print paths self.assertIsNotNone(paths) # check show ip bgp on peer1(quagga1) - qpath = self.get_routing_table(peer1, "192.168.2.0", retry=3) + qpath = self.get_routing_table(peer1, prefix1, retry=3) # print qpath self.assertIsNotNone(qpath) # check adj-rib-out in peer2 - path = self.get_adj_rib_in(peer2, "192.168.2.0/24", retry=1) + path = self.get_adj_rib_in(peer2, prefix1, retry=1) # print path self.assertIsNotNone(path) - path = self.get_paths_in_localrib(peer3, "192.168.2.0") + path = self.get_paths_in_localrib(peer3, prefix1) # print path self.assertIsNotNone(path) - path = self.get_adj_rib_out(peer3, "192.168.2.0", retry=1) + path = self.get_adj_rib_out(peer3, prefix1, retry=1) # print path self.assertIsNone(path) # check show ip bgp on peer1(quagga3) - qpath = self.get_routing_table(peer3,"192.168.2.0", retry=3) + qpath = self.get_routing_table(peer3,prefix1, retry=3) # print qpath self.assertIsNone(qpath) @@ -167,16 +166,12 @@ class GoBGPTest(GoBGPTestBase): # coming from peer2(10.0.0.2) to peer3(10.0.0.3)'s import-policy. self.initialize(policy_pattern="p3") - peer1 = "10.0.0.1" - peer2 = "10.0.0.2" - peer3 = "10.0.0.3" - # add other network tn = qaccess.login(peer2) print "add network 192.168.20.0/24" - qaccess.add_network(tn, 65002, "192.168.20.0/24") + qaccess.add_network(tn, 65002, prefix2) print "add network 192.168.200.0/24" - qaccess.add_network(tn, 65002, "192.168.200.0/24") + qaccess.add_network(tn, 65002, prefix3) qaccess.logout(tn) addresses = self.get_neighbor_address(self.gobgp_config) @@ -197,28 +192,28 @@ class GoBGPTest(GoBGPTestBase): return path is not None - self.assertTrue(path_exists_in_localrib(peer1,"192.168.2.0")) - self.assertTrue(path_exists_in_localrib(peer1,"192.168.20.0")) - self.assertTrue(path_exists_in_localrib(peer1,"192.168.200.0")) + self.assertTrue(path_exists_in_localrib(peer1,prefix1)) + self.assertTrue(path_exists_in_localrib(peer1,prefix2)) + self.assertTrue(path_exists_in_localrib(peer1,prefix3)) - self.assertTrue(path_exists_in_localrib(peer3,"192.168.2.0")) - self.assertFalse(path_exists_in_localrib(peer3,"192.168.20.0",r=3)) - self.assertFalse(path_exists_in_localrib(peer3,"192.168.200.0",r=0)) + self.assertTrue(path_exists_in_localrib(peer3,prefix1)) + self.assertFalse(path_exists_in_localrib(peer3,prefix2,r=3)) + self.assertFalse(path_exists_in_localrib(peer3,prefix3,r=0)) # check show ip bgp on peer1(quagga1) - self.assertTrue(path_exists_in_routing_table(peer1, "192.168.2.0")) - self.assertTrue(path_exists_in_routing_table(peer1, "192.168.20.0")) - self.assertTrue(path_exists_in_routing_table(peer1, "192.168.200.0")) + self.assertTrue(path_exists_in_routing_table(peer1, prefix1)) + self.assertTrue(path_exists_in_routing_table(peer1, prefix2)) + self.assertTrue(path_exists_in_routing_table(peer1, prefix3)) # check show ip bgp on peer3(quagga3) - self.assertTrue(path_exists_in_routing_table(peer3, "192.168.2.0")) - self.assertFalse(path_exists_in_routing_table(peer3, "192.168.20.0",r=3)) - self.assertFalse(path_exists_in_routing_table(peer3, "192.168.200.0",r=0)) + self.assertTrue(path_exists_in_routing_table(peer3, prefix1)) + self.assertFalse(path_exists_in_routing_table(peer3, prefix2,r=3)) + self.assertFalse(path_exists_in_routing_table(peer3, prefix3,r=0)) # check adj-rib-out in peer2 - self.assertTrue(path_exists_in_adj_rib_in(peer2, "192.168.2.0/24")) - self.assertTrue(path_exists_in_adj_rib_in(peer2, "192.168.20.0/24")) - self.assertTrue(path_exists_in_adj_rib_in(peer2, "192.168.200.0/24")) + self.assertTrue(path_exists_in_adj_rib_in(peer2, prefix1)) + self.assertTrue(path_exists_in_adj_rib_in(peer2, prefix2)) + self.assertTrue(path_exists_in_adj_rib_in(peer2, prefix3)) # update policy print "update_policy_config" @@ -230,14 +225,14 @@ class GoBGPTest(GoBGPTestBase): self.soft_reset(peer2, IPv4) # check local-rib - self.assertTrue(path_exists_in_localrib(peer3,"192.168.2.0")) - self.assertFalse(path_exists_in_localrib(peer3,"192.168.20.0",r=3)) - self.assertTrue(path_exists_in_localrib(peer3,"192.168.200.0")) + self.assertTrue(path_exists_in_localrib(peer3,prefix1)) + self.assertFalse(path_exists_in_localrib(peer3,prefix2,r=3)) + self.assertTrue(path_exists_in_localrib(peer3,prefix3)) # check show ip bgp on peer3(quagga3) - self.assertTrue(path_exists_in_routing_table(peer3, "192.168.2.0")) - self.assertFalse(path_exists_in_routing_table(peer3, "192.168.20.0",r=0)) - self.assertTrue(path_exists_in_routing_table(peer3, "192.168.200.0")) + self.assertTrue(path_exists_in_routing_table(peer3, prefix1)) + self.assertFalse(path_exists_in_routing_table(peer3, prefix2,r=0)) + self.assertTrue(path_exists_in_routing_table(peer3, prefix3)) """ @@ -272,16 +267,12 @@ class GoBGPTest(GoBGPTestBase): # coming from peer2(10.0.0.2) to peer3(10.0.0.3)'s export-policy. self.initialize(policy_pattern="p4") - peer1 = "10.0.0.1" - peer2 = "10.0.0.2" - peer3 = "10.0.0.3" - # add other network tn = qaccess.login(peer2) print "add network 192.168.20.0/24" - qaccess.add_network(tn, 65002, "192.168.20.0/24") + qaccess.add_network(tn, 65002, prefix2) print "add network 192.168.200.0/24" - qaccess.add_network(tn, 65002, "192.168.200.0/24") + qaccess.add_network(tn, 65002, prefix3) qaccess.logout(tn) addresses = self.get_neighbor_address(self.gobgp_config) @@ -306,35 +297,35 @@ class GoBGPTest(GoBGPTestBase): return path is not None - self.assertTrue(path_exists_in_localrib(peer1,"192.168.2.0")) - self.assertTrue(path_exists_in_localrib(peer1,"192.168.20.0")) - self.assertTrue(path_exists_in_localrib(peer1,"192.168.200.0")) + self.assertTrue(path_exists_in_localrib(peer1,prefix1)) + self.assertTrue(path_exists_in_localrib(peer1,prefix2)) + self.assertTrue(path_exists_in_localrib(peer1,prefix3)) # check peer3 local-rib - self.assertTrue(path_exists_in_localrib(peer3,"192.168.2.0")) - self.assertTrue(path_exists_in_localrib(peer3,"192.168.20.0")) - self.assertTrue(path_exists_in_localrib(peer3,"192.168.200.0")) + self.assertTrue(path_exists_in_localrib(peer3,prefix1)) + self.assertTrue(path_exists_in_localrib(peer3,prefix2)) + self.assertTrue(path_exists_in_localrib(peer3,prefix3)) # check peer3 rib-out - self.assertTrue(path_exists_in_adj_rib_out(peer3,"192.168.2.0/24")) - self.assertFalse(path_exists_in_adj_rib_out(peer3,"192.168.20.0/24",r=3)) - self.assertFalse(path_exists_in_adj_rib_out(peer3,"192.168.200.0/24",r=3)) + self.assertTrue(path_exists_in_adj_rib_out(peer3,prefix1)) + self.assertFalse(path_exists_in_adj_rib_out(peer3,prefix2,r=3)) + self.assertFalse(path_exists_in_adj_rib_out(peer3,prefix3,r=3)) # check show ip bgp on peer1(quagga1) - self.assertTrue(path_exists_in_routing_table(peer1, "192.168.2.0")) - self.assertTrue(path_exists_in_routing_table(peer1, "192.168.20.0")) - self.assertTrue(path_exists_in_routing_table(peer1, "192.168.200.0")) + self.assertTrue(path_exists_in_routing_table(peer1, prefix1)) + self.assertTrue(path_exists_in_routing_table(peer1, prefix2)) + self.assertTrue(path_exists_in_routing_table(peer1, prefix3)) # check show ip bgp on peer3(quagga3) - self.assertTrue(path_exists_in_routing_table(peer3, "192.168.2.0")) - self.assertFalse(path_exists_in_routing_table(peer3, "192.168.20.0",r=3)) - self.assertFalse(path_exists_in_routing_table(peer3, "192.168.200.0",r=0)) + self.assertTrue(path_exists_in_routing_table(peer3, prefix1)) + self.assertFalse(path_exists_in_routing_table(peer3, prefix2,r=3)) + self.assertFalse(path_exists_in_routing_table(peer3, prefix3,r=0)) # check adj-rib-out in peer2 peer2 = "10.0.0.2" - self.assertTrue(path_exists_in_adj_rib_in(peer2, "192.168.2.0/24")) - self.assertTrue(path_exists_in_adj_rib_in(peer2, "192.168.20.0/24")) - self.assertTrue(path_exists_in_adj_rib_in(peer2, "192.168.200.0/24")) + self.assertTrue(path_exists_in_adj_rib_in(peer2, prefix1)) + self.assertTrue(path_exists_in_adj_rib_in(peer2, prefix2)) + self.assertTrue(path_exists_in_adj_rib_in(peer2, prefix3)) # update policy print "update_policy_config" @@ -346,19 +337,19 @@ class GoBGPTest(GoBGPTestBase): self.soft_reset(peer2, IPv4) # check local-rib - self.assertTrue(path_exists_in_localrib(peer3,"192.168.2.0")) - self.assertTrue(path_exists_in_localrib(peer3,"192.168.20.0")) - self.assertTrue(path_exists_in_localrib(peer3,"192.168.200.0")) + self.assertTrue(path_exists_in_localrib(peer3,prefix1)) + self.assertTrue(path_exists_in_localrib(peer3,prefix2)) + self.assertTrue(path_exists_in_localrib(peer3,prefix3)) # check local-adj-out-rib - self.assertTrue(path_exists_in_adj_rib_out(peer3, "192.168.2.0/24")) - self.assertFalse(path_exists_in_adj_rib_out(peer3, "192.168.20.0/24",r=3)) - self.assertTrue(path_exists_in_adj_rib_out(peer3, "192.168.200.0/24")) + self.assertTrue(path_exists_in_adj_rib_out(peer3, prefix1)) + self.assertFalse(path_exists_in_adj_rib_out(peer3, prefix2,r=3)) + self.assertTrue(path_exists_in_adj_rib_out(peer3, prefix3)) # check show ip bgp on peer3(quagga3) - self.assertTrue(path_exists_in_routing_table(peer3, "192.168.2.0")) - self.assertFalse(path_exists_in_routing_table(peer3, "192.168.20.0",r=3)) - self.assertTrue(path_exists_in_routing_table(peer3, "192.168.200.0")) + self.assertTrue(path_exists_in_routing_table(peer3, prefix1)) + self.assertFalse(path_exists_in_routing_table(peer3, prefix2,r=3)) + self.assertTrue(path_exists_in_routing_table(peer3, prefix3)) if __name__ == '__main__': diff --git a/test/scenario_test/route_server_test.py b/test/scenario_test/route_server_test.py index 603ffecd..61c94eb0 100644 --- a/test/scenario_test/route_server_test.py +++ b/test/scenario_test/route_server_test.py @@ -188,7 +188,7 @@ class GoBGPTest(GoBGPTestBase): time.sleep(self.initial_wait_time) check_address = "10.0.0.1" - target_network = "192.168.20.0" + target_network = "192.168.20.0/24" ans_nexthop = "10.0.0.3" print "check of [ " + check_address + " ]" |