#cgo CFLAGS: -DPNG_DEBUG=1
#cgo LDFLAGS: -lvppapiclient
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <arpa/inet.h>
-#include <vpp-api/client/vppapiclient.h>
-
-extern void go_msg_callback(uint16_t msg_id, void* data, size_t size);
-
-typedef struct __attribute__((__packed__)) _req_header {
- uint16_t msg_id;
- uint32_t client_index;
- uint32_t context;
-} req_header_t;
-
-typedef struct __attribute__((__packed__)) _reply_header {
- uint16_t msg_id;
-} reply_header_t;
-
-static void
-govpp_msg_callback(unsigned char *data, int size)
-{
- reply_header_t *header = ((reply_header_t *)data);
- go_msg_callback(ntohs(header->msg_id), data, size);
-}
-
-static int
-govpp_send(uint32_t context, void *data, size_t size)
-{
- req_header_t *header = ((req_header_t *)data);
- header->context = htonl(context);
- return vac_write(data, size);
-}
-
-static int
-govpp_connect(char *shm)
-{
- return vac_connect("govpp", shm, govpp_msg_callback, 32);
-}
-
-static int
-govpp_disconnect()
-{
- return vac_disconnect();
-}
-
-static uint32_t
-govpp_get_msg_index(char *name_and_crc)
-{
- return vac_get_msg_index(name_and_crc);
-}
+#include "vppapiclient_wrapper.h"
*/
import "C"
"os"
"path/filepath"
"reflect"
+ "time"
"unsafe"
- "git.fd.io/govpp.git/adapter"
"github.com/fsnotify/fsnotify"
+
+ "git.fd.io/govpp.git/adapter"
+)
+
+var (
+ // MaxWaitReady defines maximum duration before waiting for shared memory
+ // segment times out
+ MaxWaitReady = time.Second * 15
)
const (
// stubVppClient is the default implementation of the VppAPI.
type vppClient struct {
- shmPrefix string
- msgCallback adapter.MsgCallback
+ shmPrefix string
+ msgCallback adapter.MsgCallback
+ inputQueueSize uint16
}
// NewVppClient returns a new VPP binary API client.
func NewVppClient(shmPrefix string) adapter.VppAPI {
+ return NewVppClientWithInputQueueSize(shmPrefix, 32)
+}
+
+// NewVppClientWithInputQueueSize returns a new VPP binary API client with a custom input queue size.
+func NewVppClientWithInputQueueSize(shmPrefix string, inputQueueSize uint16) adapter.VppAPI {
return &vppClient{
- shmPrefix: shmPrefix,
+ shmPrefix: shmPrefix,
+ inputQueueSize: inputQueueSize,
}
}
return fmt.Errorf("already connected to binary API, disconnect first")
}
+ rxQlen := C.int(a.inputQueueSize)
var rc C.int
if a.shmPrefix == "" {
- rc = C.govpp_connect(nil)
+ rc = C.govpp_connect(nil, rxQlen)
} else {
shm := C.CString(a.shmPrefix)
- rc = C.govpp_connect(shm)
+ rc = C.govpp_connect(shm, rxQlen)
}
if rc != 0 {
return fmt.Errorf("connecting to VPP binary API failed (rc=%v)", rc)
// WaitReady blocks until shared memory for sending
// binary api calls is present on the file system.
func (a *vppClient) WaitReady() error {
- var path string
-
// join the path to the shared memory segment
+ var path string
if a.shmPrefix == "" {
path = filepath.Join(shmDir, vppShmFile)
} else {
path = filepath.Join(shmDir, a.shmPrefix+"-"+vppShmFile)
}
- // check if file at the path exists
+ // check if file at the path already exists
if _, err := os.Stat(path); err == nil {
// file exists, we are ready
return nil
}
defer watcher.Close()
+ // start watching directory
if err := watcher.Add(shmDir); err != nil {
return err
}
for {
- ev := <-watcher.Events
- if ev.Name == path {
- if (ev.Op & fsnotify.Create) == fsnotify.Create {
- // file was created, we are ready
- break
+ select {
+ case <-time.After(MaxWaitReady):
+ return fmt.Errorf("waiting for shared memory segment timed out (%s)", MaxWaitReady)
+ case e := <-watcher.Errors:
+ return e
+ case ev := <-watcher.Events:
+ if ev.Name == path {
+ if (ev.Op & fsnotify.Create) == fsnotify.Create {
+ // file was created, we are ready
+ return nil
+ }
}
}
}
-
- return nil
}
//export go_msg_callback