diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-12-01 14:57:51 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-12-02 08:53:04 +0900 |
commit | ff26d4e93bf728b4fb312a2f66b1becbd2675c9f (patch) | |
tree | c0128bcba14072fbd41885ff437252d4d008a23d | |
parent | 3dfb941b336dc72bcd6fcadfd7b55f7c67ffcc4e (diff) |
api/server: refine GetRib API
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | api/gobgp.pb.go | 110 | ||||
-rw-r--r-- | api/gobgp.proto | 9 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 18 | ||||
-rw-r--r-- | server/grpc_server.go | 18 | ||||
-rw-r--r-- | server/server.go | 175 |
5 files changed, 159 insertions, 171 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index d992a43b..c3956e92 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -22,6 +22,7 @@ It has these top-level messages: ModPolicyArguments ModPolicyAssignmentArguments ModGlobalConfigArguments + Table Path Destination Peer @@ -517,6 +518,24 @@ func (m *ModGlobalConfigArguments) GetGlobal() *Global { return nil } +type Table struct { + Type Resource `protobuf:"varint,1,opt,name=type,enum=gobgpapi.Resource" json:"type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + Family uint32 `protobuf:"varint,3,opt,name=family" json:"family,omitempty"` + Destinations []*Destination `protobuf:"bytes,4,rep,name=destinations" json:"destinations,omitempty"` +} + +func (m *Table) Reset() { *m = Table{} } +func (m *Table) String() string { return proto.CompactTextString(m) } +func (*Table) ProtoMessage() {} + +func (m *Table) GetDestinations() []*Destination { + if m != nil { + return m.Destinations + } + return nil +} + type Path struct { Nlri []byte `protobuf:"bytes,1,opt,name=nlri,proto3" json:"nlri,omitempty"` Pattrs [][]byte `protobuf:"bytes,2,rep,name=pattrs,proto3" json:"pattrs,omitempty"` @@ -1527,7 +1546,7 @@ type GobgpApiClient interface { GetNeighbors(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetNeighborsClient, error) GetNeighbor(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Peer, error) ModNeighbor(ctx context.Context, in *ModNeighborArguments, opts ...grpc.CallOption) (*Error, error) - GetRib(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetRibClient, error) + GetRib(ctx context.Context, in *Table, opts ...grpc.CallOption) (*Table, 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) @@ -1634,36 +1653,13 @@ func (c *gobgpApiClient) ModNeighbor(ctx context.Context, in *ModNeighborArgumen return out, nil } -func (c *gobgpApiClient) GetRib(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetRibClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[1], c.cc, "/gobgpapi.GobgpApi/GetRib", opts...) +func (c *gobgpApiClient) GetRib(ctx context.Context, in *Table, opts ...grpc.CallOption) (*Table, error) { + out := new(Table) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/GetRib", in, out, c.cc, opts...) if err != nil { return nil, err } - x := &gobgpApiGetRibClient{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 GobgpApi_GetRibClient interface { - Recv() (*Destination, error) - grpc.ClientStream -} - -type gobgpApiGetRibClient struct { - grpc.ClientStream -} - -func (x *gobgpApiGetRibClient) Recv() (*Destination, error) { - m := new(Destination) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil + return out, nil } func (c *gobgpApiClient) Reset(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error) { @@ -1730,7 +1726,7 @@ func (c *gobgpApiClient) Disable(ctx context.Context, in *Arguments, opts ...grp } func (c *gobgpApiClient) ModPath(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModPathClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[2], c.cc, "/gobgpapi.GobgpApi/ModPath", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[1], c.cc, "/gobgpapi.GobgpApi/ModPath", opts...) if err != nil { return nil, err } @@ -1764,7 +1760,7 @@ func (x *gobgpApiModPathClient) CloseAndRecv() (*Error, error) { } func (c *gobgpApiClient) MonitorBestChanged(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorBestChangedClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[3], c.cc, "/gobgpapi.GobgpApi/MonitorBestChanged", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[2], c.cc, "/gobgpapi.GobgpApi/MonitorBestChanged", opts...) if err != nil { return nil, err } @@ -1796,7 +1792,7 @@ func (x *gobgpApiMonitorBestChangedClient) Recv() (*Destination, error) { } func (c *gobgpApiClient) MonitorPeerState(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorPeerStateClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[4], c.cc, "/gobgpapi.GobgpApi/MonitorPeerState", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[3], c.cc, "/gobgpapi.GobgpApi/MonitorPeerState", opts...) if err != nil { return nil, err } @@ -1828,7 +1824,7 @@ func (x *gobgpApiMonitorPeerStateClient) Recv() (*Peer, error) { } func (c *gobgpApiClient) GetMrt(ctx context.Context, in *MrtArguments, opts ...grpc.CallOption) (GobgpApi_GetMrtClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[5], c.cc, "/gobgpapi.GobgpApi/GetMrt", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[4], c.cc, "/gobgpapi.GobgpApi/GetMrt", opts...) if err != nil { return nil, err } @@ -1869,7 +1865,7 @@ func (c *gobgpApiClient) ModMrt(ctx context.Context, in *ModMrtArguments, opts . } func (c *gobgpApiClient) GetRPKI(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetRPKIClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[6], c.cc, "/gobgpapi.GobgpApi/GetRPKI", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[5], c.cc, "/gobgpapi.GobgpApi/GetRPKI", opts...) if err != nil { return nil, err } @@ -1910,7 +1906,7 @@ func (c *gobgpApiClient) ModRPKI(ctx context.Context, in *ModRpkiArguments, opts } func (c *gobgpApiClient) GetROA(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetROAClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[7], c.cc, "/gobgpapi.GobgpApi/GetROA", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[6], c.cc, "/gobgpapi.GobgpApi/GetROA", opts...) if err != nil { return nil, err } @@ -1942,7 +1938,7 @@ func (x *gobgpApiGetROAClient) Recv() (*ROA, error) { } func (c *gobgpApiClient) GetVrfs(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_GetVrfsClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[8], c.cc, "/gobgpapi.GobgpApi/GetVrfs", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[7], c.cc, "/gobgpapi.GobgpApi/GetVrfs", opts...) if err != nil { return nil, err } @@ -1992,7 +1988,7 @@ func (c *gobgpApiClient) GetDefinedSet(ctx context.Context, in *DefinedSet, opts } func (c *gobgpApiClient) GetDefinedSets(ctx context.Context, in *DefinedSet, opts ...grpc.CallOption) (GobgpApi_GetDefinedSetsClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[9], c.cc, "/gobgpapi.GobgpApi/GetDefinedSets", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[8], c.cc, "/gobgpapi.GobgpApi/GetDefinedSets", opts...) if err != nil { return nil, err } @@ -2042,7 +2038,7 @@ func (c *gobgpApiClient) GetStatement(ctx context.Context, in *Statement, opts . } func (c *gobgpApiClient) GetStatements(ctx context.Context, in *Statement, opts ...grpc.CallOption) (GobgpApi_GetStatementsClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[10], c.cc, "/gobgpapi.GobgpApi/GetStatements", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[9], c.cc, "/gobgpapi.GobgpApi/GetStatements", opts...) if err != nil { return nil, err } @@ -2092,7 +2088,7 @@ func (c *gobgpApiClient) GetPolicy(ctx context.Context, in *Policy, opts ...grpc } func (c *gobgpApiClient) GetPolicies(ctx context.Context, in *Policy, opts ...grpc.CallOption) (GobgpApi_GetPoliciesClient, error) { - stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[11], c.cc, "/gobgpapi.GobgpApi/GetPolicies", opts...) + stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[10], c.cc, "/gobgpapi.GobgpApi/GetPolicies", opts...) if err != nil { return nil, err } @@ -2158,7 +2154,7 @@ type GobgpApiServer interface { GetNeighbors(*Arguments, GobgpApi_GetNeighborsServer) error GetNeighbor(context.Context, *Arguments) (*Peer, error) ModNeighbor(context.Context, *ModNeighborArguments) (*Error, error) - GetRib(*Arguments, GobgpApi_GetRibServer) error + GetRib(context.Context, *Table) (*Table, error) Reset(context.Context, *Arguments) (*Error, error) SoftReset(context.Context, *Arguments) (*Error, error) SoftResetIn(context.Context, *Arguments) (*Error, error) @@ -2262,25 +2258,16 @@ func _GobgpApi_ModNeighbor_Handler(srv interface{}, ctx context.Context, dec fun return out, nil } -func _GobgpApi_GetRib_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(Arguments) - if err := stream.RecvMsg(m); err != nil { - return err +func _GobgpApi_GetRib_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { + in := new(Table) + if err := dec(in); err != nil { + return nil, err } - return srv.(GobgpApiServer).GetRib(m, &gobgpApiGetRibServer{stream}) -} - -type GobgpApi_GetRibServer interface { - Send(*Destination) error - grpc.ServerStream -} - -type gobgpApiGetRibServer struct { - grpc.ServerStream -} - -func (x *gobgpApiGetRibServer) Send(m *Destination) error { - return x.ServerStream.SendMsg(m) + out, err := srv.(GobgpApiServer).GetRib(ctx, in) + if err != nil { + return nil, err + } + return out, nil } func _GobgpApi_Reset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { @@ -2735,6 +2722,10 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{ Handler: _GobgpApi_ModNeighbor_Handler, }, { + MethodName: "GetRib", + Handler: _GobgpApi_GetRib_Handler, + }, + { MethodName: "Reset", Handler: _GobgpApi_Reset_Handler, }, @@ -2814,11 +2805,6 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, }, { - StreamName: "GetRib", - Handler: _GobgpApi_GetRib_Handler, - ServerStreams: true, - }, - { StreamName: "ModPath", Handler: _GobgpApi_ModPath_Handler, ClientStreams: true, diff --git a/api/gobgp.proto b/api/gobgp.proto index 2857cf45..ab9e0d2d 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -25,7 +25,7 @@ service GobgpApi { rpc GetNeighbors(Arguments) returns (stream Peer) {} rpc GetNeighbor(Arguments) returns (Peer) {} rpc ModNeighbor(ModNeighborArguments) returns(Error) {} - rpc GetRib(Arguments) returns (stream Destination) {} + rpc GetRib(Table) returns (Table) {} rpc Reset(Arguments) returns (Error) {} rpc SoftReset(Arguments) returns (Error) {} rpc SoftResetIn(Arguments) returns (Error) {} @@ -172,6 +172,13 @@ message Destination { repeated Path paths = 2; } +message Table { + Resource type = 1; + string name = 2; + uint32 family = 3; + repeated Destination destinations = 4; +} + message Peer { AddPaths addpaths = 1; AfiSafis afisafis = 2; diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index a3181ba0..d8079449 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -415,13 +415,13 @@ func showNeighborRib(r string, name string, args []string) error { } } - arg := &api.Arguments{ - Resource: resource, - Rf: uint32(rf), - Name: name, + arg := &api.Table{ + Type: resource, + Family: uint32(rf), + Name: name, } - stream, err := client.GetRib(context.Background(), arg) + rib, err := client.GetRib(context.Background(), arg) if err != nil { return err } @@ -437,13 +437,7 @@ func showNeighborRib(r string, name string, args []string) error { dsts := []*Destination{} maxOnes := 0 counter := 0 - for { - d, e := stream.Recv() - if e == io.EOF { - break - } else if e != nil { - return e - } + for _, d := range rib.Destinations { if prefix != "" && prefix != d.Prefix { continue } diff --git a/server/grpc_server.go b/server/grpc_server.go index 68d0e72b..07ff4e94 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -121,9 +121,9 @@ func (s *Server) GetNeighbors(_ *api.Arguments, stream api.GobgpApi_GetNeighbors }) } -func (s *Server) GetRib(arg *api.Arguments, stream api.GobgpApi_GetRibServer) error { +func (s *Server) GetRib(ctx context.Context, arg *api.Table) (*api.Table, error) { var reqType int - switch arg.Resource { + switch arg.Type { case api.Resource_LOCAL: reqType = REQ_LOCAL_RIB case api.Resource_GLOBAL: @@ -135,15 +135,13 @@ func (s *Server) GetRib(arg *api.Arguments, stream api.GobgpApi_GetRibServer) er case api.Resource_VRF: reqType = REQ_VRF default: - return fmt.Errorf("unsupported resource type: %v", arg.Resource) + return nil, fmt.Errorf("unsupported resource type: %v", arg.Type) } - - req := NewGrpcRequest(reqType, arg.Name, bgp.RouteFamily(arg.Rf), nil) - s.bgpServerCh <- req - - return handleMultipleResponses(req, func(res *GrpcResponse) error { - return stream.Send(res.Data.(*api.Destination)) - }) + d, err := s.get(reqType, arg) + if err != nil { + return nil, err + } + return d.(*api.Table), nil } func (s *Server) MonitorBestChanged(arg *api.Arguments, stream api.GobgpApi_MonitorBestChangedServer) error { diff --git a/server/server.go b/server/server.go index e3ff1a3b..7b6ffb3b 100644 --- a/server/server.go +++ b/server/server.go @@ -1237,7 +1237,8 @@ func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path { switch req.RequestType { case REQ_VRF: - name := req.Name + arg := req.Data.(*api.Table) + name := arg.Name rib := server.globalRib vrfs := rib.Vrfs if _, ok := vrfs[name]; !ok { @@ -1245,7 +1246,7 @@ func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path { break } var rf bgp.RouteFamily - switch req.RouteFamily { + switch bgp.RouteFamily(arg.Family) { case bgp.RF_IPv4_UC: rf = bgp.RF_IPv4_VPN case bgp.RF_IPv6_UC: @@ -1253,20 +1254,27 @@ func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path { case bgp.RF_EVPN: rf = bgp.RF_EVPN default: - result.ResponseErr = fmt.Errorf("unsupported route family: %s", req.RouteFamily) + result.ResponseErr = fmt.Errorf("unsupported route family: %s", bgp.RouteFamily(arg.Family)) break } - for _, path := range rib.GetPathList(rf) { + paths := rib.GetPathList(rf) + dsts := make([]*api.Destination, 0, len(paths)) + for _, path := range paths { ok := table.CanImportToVrf(vrfs[name], path) if !ok { continue } - req.ResponseCh <- &GrpcResponse{ - Data: &api.Destination{ - Prefix: path.GetNlri().String(), - Paths: []*api.Path{path.ToApiStruct()}, - }, - } + dsts = append(dsts, &api.Destination{ + Prefix: path.GetNlri().String(), + Paths: []*api.Path{path.ToApiStruct()}, + }) + } + req.ResponseCh <- &GrpcResponse{ + Data: &api.Table{ + Type: arg.Type, + Family: arg.Family, + Destinations: dsts, + }, } goto END case REQ_VRFS: @@ -1350,20 +1358,15 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { return []*Peer{peer}, err } - sortedDsts := func(t *table.Table) []*GrpcResponse { - results := make([]*GrpcResponse, len(t.GetDestinations())) + sortedDsts := func(t *table.Table) []*api.Destination { + results := make([]*api.Destination, 0, len(t.GetDestinations())) r := radix.New() for _, dst := range t.GetDestinations() { - result := &GrpcResponse{} - result.Data = dst.ToApiStruct() - r.Insert(dst.RadixKey, result) + r.Insert(dst.RadixKey, dst.ToApiStruct()) } - i := 0 r.Walk(func(s string, v interface{}) bool { - r, _ := v.(*GrpcResponse) - results[i] = r - i++ + results = append(results, v.(*api.Destination)) return false }) @@ -1378,6 +1381,8 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { return nil } + var err error + switch grpcReq.RequestType { case REQ_GLOBAL_CONFIG: result := &GrpcResponse{ @@ -1394,25 +1399,41 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { ResponseErr: err, } close(grpcReq.ResponseCh) - case REQ_GLOBAL_RIB: - var results []*GrpcResponse - if t, ok := server.globalRib.Tables[grpcReq.RouteFamily]; ok { - results = make([]*GrpcResponse, len(t.GetDestinations())) - switch grpcReq.RouteFamily { + case REQ_GLOBAL_RIB, REQ_LOCAL_RIB: + arg := grpcReq.Data.(*api.Table) + d := &api.Table{ + Type: arg.Type, + Family: arg.Family, + } + rib := server.globalRib + if grpcReq.RequestType == REQ_LOCAL_RIB { + peer, ok := server.neighborMap[arg.Name] + if !ok { + err = fmt.Errorf("Neighbor that has %v doesn't exist.", arg.Name) + goto ERROR + } + if !peer.isRouteServerClient() { + err = fmt.Errorf("Neighbor %v doesn't have local rib", arg.Name) + goto ERROR + } + rib = peer.localRib + } + rf := bgp.RouteFamily(arg.Family) + if t, ok := rib.Tables[rf]; ok { + switch rf { case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: - results = sortedDsts(server.globalRib.Tables[grpcReq.RouteFamily]) + d.Destinations = sortedDsts(rib.Tables[rf]) default: - i := 0 + d.Destinations = make([]*api.Destination, 0, len(t.GetDestinations())) for _, dst := range t.GetDestinations() { - result := &GrpcResponse{} - result.Data = dst.ToApiStruct() - results[i] = result - i++ + d.Destinations = append(d.Destinations, dst.ToApiStruct()) } } } - go sendMultipleResponses(grpcReq, results) - + grpcReq.ResponseCh <- &GrpcResponse{ + Data: d, + } + close(grpcReq.ResponseCh) case REQ_MOD_PATH: pathList := server.handleModPathRequest(grpcReq) if len(pathList) > 0 { @@ -1444,39 +1465,21 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) - case REQ_LOCAL_RIB: - peer, err := server.checkNeighborRequest(grpcReq) - if err != nil { - break - } - var results []*GrpcResponse - if peer.isRouteServerClient() && peer.fsm.adminState != ADMIN_STATE_DOWN { - if t, ok := peer.localRib.Tables[grpcReq.RouteFamily]; ok { - results = make([]*GrpcResponse, len(t.GetDestinations())) - switch grpcReq.RouteFamily { - case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: - results = sortedDsts(peer.localRib.Tables[grpcReq.RouteFamily]) - default: - i := 0 - for _, dst := range t.GetDestinations() { - result := &GrpcResponse{} - result.Data = dst.ToApiStruct() - results[i] = result - i++ - } - } - } + case REQ_ADJ_RIB_IN, REQ_ADJ_RIB_OUT: + arg := grpcReq.Data.(*api.Table) + d := &api.Table{ + Type: arg.Type, + Family: arg.Family, } - go sendMultipleResponses(grpcReq, results) - case REQ_ADJ_RIB_IN, REQ_ADJ_RIB_OUT: - peer, err := server.checkNeighborRequest(grpcReq) - if err != nil { - break + peer, ok := server.neighborMap[arg.Name] + if !ok { + err = fmt.Errorf("Neighbor that has %v doesn't exist.", arg.Name) + goto ERROR } - rf := grpcReq.RouteFamily - var paths []*table.Path + rf := bgp.RouteFamily(arg.Family) + var paths []*table.Path if grpcReq.RequestType == REQ_ADJ_RIB_IN { paths = peer.adjRib.GetInPathList([]bgp.RouteFamily{rf}) log.Debugf("RouteFamily=%v adj-rib-in found : %d", rf.String(), len(paths)) @@ -1485,36 +1488,34 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { log.Debugf("RouteFamily=%v adj-rib-out found : %d", rf.String(), len(paths)) } - toResult := func(p *table.Path) *GrpcResponse { - return &GrpcResponse{ - Data: &api.Destination{ - Prefix: p.GetNlri().String(), - Paths: []*api.Path{p.ToApiStruct()}, - }, - } - } - - results := make([]*GrpcResponse, len(paths)) + results := make([]*api.Destination, 0, len(paths)) switch rf { case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: r := radix.New() for _, p := range paths { - r.Insert(table.CidrToRadixkey(p.GetNlri().String()), toResult(p)) + key := p.GetNlri().String() + r.Insert(table.CidrToRadixkey(key), &api.Destination{ + Prefix: key, + Paths: []*api.Path{p.ToApiStruct()}, + }) } - i := 0 r.Walk(func(s string, v interface{}) bool { - r, _ := v.(*GrpcResponse) - results[i] = r - i++ + results = append(results, v.(*api.Destination)) return false }) default: - for i, p := range paths { - results[i] = toResult(p) + for _, p := range paths { + results = append(results, &api.Destination{ + Prefix: p.GetNlri().String(), + Paths: []*api.Path{p.ToApiStruct()}, + }) } } - go sendMultipleResponses(grpcReq, results) - + d.Destinations = results + grpcReq.ResponseCh <- &GrpcResponse{ + Data: d, + } + close(grpcReq.ResponseCh) case REQ_NEIGHBOR_SHUTDOWN: peers, err := reqToPeers(grpcReq) if err != nil { @@ -1709,14 +1710,16 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { msgs = server.propagateUpdate(nil, pathList) } default: - errmsg := fmt.Errorf("Unknown request type: %v", grpcReq.RequestType) - result := &GrpcResponse{ - ResponseErr: errmsg, - } - grpcReq.ResponseCh <- result - close(grpcReq.ResponseCh) + err = fmt.Errorf("Unknown request type: %v", grpcReq.RequestType) + goto ERROR } return msgs +ERROR: + grpcReq.ResponseCh <- &GrpcResponse{ + ResponseErr: err, + } + close(grpcReq.ResponseCh) + return msgs } func (server *BgpServer) handleGrpcGetDefinedSet(grpcReq *GrpcRequest) error { |