1 // Copyright (c) 2021 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
24 "git.fd.io/govpp.git/api"
25 "git.fd.io/govpp.git/core"
33 // Connect dials remote proxy server on given address and
34 // returns new client if successful.
35 func Connect(addr string) (*Client, error) {
36 client, err := rpc.DialHTTP("tcp", addr)
38 return nil, fmt.Errorf("connection error:%v", err)
47 // NewStatsClient returns new StatsClient which implements api.StatsProvider.
48 func (c *Client) NewStatsClient() (*StatsClient, error) {
49 stats := &StatsClient{
55 // NewBinapiClient returns new BinapiClient which implements api.Channel.
56 func (c *Client) NewBinapiClient() (*BinapiClient, error) {
57 binapi := &BinapiClient{
59 timeout: core.DefaultReplyTimeout,
64 type StatsClient struct {
68 func (s *StatsClient) GetSystemStats(sysStats *api.SystemStats) error {
69 // we need to start with a clean, zeroed item before decoding
70 // 'cause if the new values are 'zero' for the type, they will be ignored
71 // by the decoder. (i.e the old values will be left unchanged).
72 req := StatsRequest{StatsType: "system"}
73 resp := StatsResponse{SysStats: new(api.SystemStats)}
74 if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
77 *sysStats = *resp.SysStats
81 func (s *StatsClient) GetNodeStats(nodeStats *api.NodeStats) error {
82 req := StatsRequest{StatsType: "node"}
83 resp := StatsResponse{NodeStats: new(api.NodeStats)}
84 if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
87 *nodeStats = *resp.NodeStats
91 func (s *StatsClient) GetInterfaceStats(ifaceStats *api.InterfaceStats) error {
92 req := StatsRequest{StatsType: "interface"}
93 resp := StatsResponse{IfaceStats: new(api.InterfaceStats)}
94 if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
97 *ifaceStats = *resp.IfaceStats
101 func (s *StatsClient) GetErrorStats(errStats *api.ErrorStats) error {
102 req := StatsRequest{StatsType: "error"}
103 resp := StatsResponse{ErrStats: new(api.ErrorStats)}
104 if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
107 *errStats = *resp.ErrStats
111 func (s *StatsClient) GetBufferStats(bufStats *api.BufferStats) error {
112 req := StatsRequest{StatsType: "buffer"}
113 resp := StatsResponse{BufStats: new(api.BufferStats)}
114 if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
117 *bufStats = *resp.BufStats
121 func (s *StatsClient) GetMemoryStats(memStats *api.MemoryStats) error {
122 req := StatsRequest{StatsType: "memory"}
123 resp := StatsResponse{MemStats: new(api.MemoryStats)}
124 if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
127 *memStats = *resp.MemStats
131 type BinapiClient struct {
133 timeout time.Duration
136 // RPCStream is a stream for forwarding requests to BinapiRPC's stream.
137 type RPCStream struct {
142 func (s *RPCStream) SendMsg(msg api.Message) error {
143 req := RPCStreamReqResp{
147 resp := RPCStreamReqResp{}
148 err := s.rpc.Call("BinapiRPC.SendMessage", req, &resp)
150 return fmt.Errorf("RPC SendMessage call failed: %v", err)
155 func (s *RPCStream) RecvMsg() (api.Message, error) {
156 req := RPCStreamReqResp{
159 resp := RPCStreamReqResp{}
160 err := s.rpc.Call("BinapiRPC.ReceiveMessage", req, &resp)
162 return nil, fmt.Errorf("RPC ReceiveMessage call failed: %v", err)
167 func (s *RPCStream) Close() error {
168 req := RPCStreamReqResp{
171 resp := RPCStreamReqResp{}
172 err := s.rpc.Call("BinapiRPC.CloseStream", req, &resp)
174 return fmt.Errorf("RPC CloseStream call failed: %v", err)
179 func (b *BinapiClient) NewStream(_ context.Context, _ ...api.StreamOption) (api.Stream, error) {
180 stream := &RPCStream{
183 req := RPCStreamReqResp{}
184 resp := RPCStreamReqResp{}
185 err := stream.rpc.Call("BinapiRPC.NewAPIStream", req, &resp)
187 return nil, fmt.Errorf("RPC NewAPIStream call failed: %v", err)
193 func (b *BinapiClient) Invoke(_ context.Context, request api.Message, reply api.Message) error {
194 return invokeInternal(b.rpc, request, reply, b.timeout)
197 func (b *BinapiClient) SendRequest(msg api.Message) api.RequestCtx {
203 log.Debugf("SendRequest: %T %+v", msg, msg)
207 type requestCtx struct {
210 timeout time.Duration
213 func (r *requestCtx) ReceiveReply(msg api.Message) error {
214 return invokeInternal(r.rpc, r.req, msg, r.timeout)
217 func invokeInternal(rpc *rpc.Client, msgIn, msgOut api.Message, timeout time.Duration) error {
218 req := BinapiRequest{
223 resp := BinapiResponse{}
225 err := rpc.Call("BinapiRPC.Invoke", req, &resp)
227 return fmt.Errorf("RPC call failed: %v", err)
230 // we set the value of msg to the value from response
231 reflect.ValueOf(msgOut).Elem().Set(reflect.ValueOf(resp.Msg).Elem())
236 func (b *BinapiClient) SendMultiRequest(msg api.Message) api.MultiRequestCtx {
237 req := &multiRequestCtx{
242 log.Debugf("SendMultiRequest: %T %+v", msg, msg)
246 type multiRequestCtx struct {
249 timeout time.Duration
252 replies []api.Message
255 func (r *multiRequestCtx) ReceiveReply(msg api.Message) (stop bool, err error) {
256 // we call Invoke only on first ReceiveReply
258 req := BinapiRequest{
264 resp := BinapiResponse{}
266 err := r.rpc.Call("BinapiRPC.Invoke", req, &resp)
268 return false, fmt.Errorf("RPC call failed: %v", err)
271 r.replies = resp.Msgs
274 if r.index >= len(r.replies) {
278 // we set the value of msg to the value from response
279 reflect.ValueOf(msg).Elem().Set(reflect.ValueOf(r.replies[r.index]).Elem())
285 func (b *BinapiClient) SubscribeNotification(notifChan chan api.Message, event api.Message) (api.SubscriptionCtx, error) {
286 panic("implement me")
289 func (b *BinapiClient) SetReplyTimeout(timeout time.Duration) {
293 func (b *BinapiClient) CheckCompatiblity(msgs ...api.Message) error {
294 msgNamesCrscs := make([]string, 0, len(msgs))
296 for _, msg := range msgs {
297 msgNamesCrscs = append(msgNamesCrscs, msg.GetMessageName()+"_"+msg.GetCrcString())
300 req := BinapiCompatibilityRequest{MsgNameCrcs: msgNamesCrscs}
301 resp := BinapiCompatibilityResponse{}
303 if err := b.rpc.Call("BinapiRPC.Compatibility", req, &resp); err != nil {
310 func (b *BinapiClient) Close() {