diff options
Diffstat (limited to 'adapter')
-rw-r--r-- | adapter/adapter.go | 12 | ||||
-rw-r--r-- | adapter/mock/mock_adapter.go | 30 | ||||
-rw-r--r-- | adapter/vppapiclient/empty_adapter.go | 4 | ||||
-rw-r--r-- | adapter/vppapiclient/vppapiclient_adapter.go | 71 |
4 files changed, 64 insertions, 53 deletions
diff --git a/adapter/adapter.go b/adapter/adapter.go index bc3a573..7d3d1e4 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -14,6 +14,16 @@ package adapter +import ( + "errors" +) + +// ErrNotImplemented is an error returned when missing implementation. +var ErrNotImplemented = errors.New("not implemented for this OS") + +// MsgCallback defines func signature for message callback. +type MsgCallback func(msgID uint16, context uint32, data []byte) + // VppAdapter provides connection to VPP. It is responsible for sending and receiving of binary-encoded messages to/from VPP. type VppAdapter interface { // Connect connects the process to VPP. @@ -29,7 +39,7 @@ type VppAdapter interface { SendMsg(context uint32, data []byte) error // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from VPP. - SetMsgCallback(func(context uint32, msgId uint16, data []byte)) + SetMsgCallback(cb MsgCallback) // WaitReady waits until adapter is ready. WaitReady() error diff --git a/adapter/mock/mock_adapter.go b/adapter/mock/mock_adapter.go index a5cb62d..3f5686f 100644 --- a/adapter/mock/mock_adapter.go +++ b/adapter/mock/mock_adapter.go @@ -25,7 +25,6 @@ import ( "git.fd.io/govpp.git/adapter" "git.fd.io/govpp.git/adapter/mock/binapi" "git.fd.io/govpp.git/api" - "git.fd.io/govpp.git/codec" "github.com/lunixbochs/struc" ) @@ -33,24 +32,24 @@ import ( type replyMode int const ( - _ replyMode = 0 - useRepliesQueue = 1 // use replies in the queue - useReplyHandlers = 2 // use reply handler + _ replyMode = iota + useRepliesQueue // use replies in the queue + useReplyHandlers // use reply handler ) // VppAdapter represents a mock VPP adapter that can be used for unit/integration testing instead of the vppapiclient adapter. type VppAdapter struct { - callback func(context uint32, msgId uint16, data []byte) + callback adapter.MsgCallback + msgIDSeq uint16 + access sync.RWMutex msgNameToIds map[string]uint16 msgIDsToName map[uint16]string - msgIDSeq uint16 binAPITypes map[string]reflect.Type - access sync.RWMutex + repliesLock sync.Mutex // mutex for the queue replies []reply // FIFO queue of messages replyHandlers []ReplyHandler // callbacks that are able to calculate mock responses - repliesLock sync.Mutex // mutex for the queue mode replyMode // mode in which the mock operates } @@ -211,8 +210,6 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) { a.msgNameToIds[msgName] = msgID a.msgIDsToName[msgID] = msgName - log.Println("VPP GetMessageId ", msgID, " name:", msgName, " crc:", msgCrc) - return msgID, nil } @@ -252,11 +249,12 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { Data: data, }) if finished { - a.callback(clientID, msgID, reply) + a.callback(msgID, clientID, reply) return nil } } fallthrough + case useRepliesQueue: a.repliesLock.Lock() defer a.repliesLock.Unlock() @@ -274,15 +272,15 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { } if msg.Msg.GetMessageType() == api.ReplyMessage { struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: msgID, Context: context}) - } else if msg.Msg.GetMessageType() == api.EventMessage { - struc.Pack(buf, &codec.VppEventHeader{VlMsgID: msgID, Context: context}) } else if msg.Msg.GetMessageType() == api.RequestMessage { struc.Pack(buf, &codec.VppRequestHeader{VlMsgID: msgID, Context: context}) + } else if msg.Msg.GetMessageType() == api.EventMessage { + struc.Pack(buf, &codec.VppEventHeader{VlMsgID: msgID}) } else { struc.Pack(buf, &codec.VppOtherHeader{VlMsgID: msgID}) } struc.Pack(buf, msg.Msg) - a.callback(context, msgID, buf.Bytes()) + a.callback(msgID, context, buf.Bytes()) } a.replies = a.replies[1:] @@ -301,13 +299,13 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { msgID := uint16(defaultReplyMsgID) struc.Pack(buf, &codec.VppReplyHeader{VlMsgID: msgID, Context: clientID}) struc.Pack(buf, &defaultReply{}) - a.callback(clientID, msgID, buf.Bytes()) + a.callback(msgID, clientID, buf.Bytes()) } return nil } // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from the mock. -func (a *VppAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { +func (a *VppAdapter) SetMsgCallback(cb adapter.MsgCallback) { a.callback = cb } diff --git a/adapter/vppapiclient/empty_adapter.go b/adapter/vppapiclient/empty_adapter.go index c3010a0..7514048 100644 --- a/adapter/vppapiclient/empty_adapter.go +++ b/adapter/vppapiclient/empty_adapter.go @@ -32,7 +32,7 @@ func NewVppAdapter(string) adapter.VppAdapter { } func (a *vppAPIClientAdapter) Connect() error { - return nil + return adapter.ErrNotImplemented } func (a *vppAPIClientAdapter) Disconnect() { @@ -47,7 +47,7 @@ func (a *vppAPIClientAdapter) SendMsg(clientID uint32, data []byte) error { return nil } -func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { +func (a *vppAPIClientAdapter) SetMsgCallback(cb adapter.MsgCallback) { // no op } diff --git a/adapter/vppapiclient/vppapiclient_adapter.go b/adapter/vppapiclient/vppapiclient_adapter.go index c77d7f1..7aafa55 100644 --- a/adapter/vppapiclient/vppapiclient_adapter.go +++ b/adapter/vppapiclient/vppapiclient_adapter.go @@ -28,7 +28,7 @@ package vppapiclient #include <arpa/inet.h> #include <vpp-api/client/vppapiclient.h> -extern void go_msg_callback(uint16_t, uint32_t, void*, size_t); +extern void go_msg_callback(uint16_t msg_id, uint32_t context, void* data, size_t size); typedef struct __attribute__((__packed__)) _req_header { uint16_t msg_id; @@ -38,7 +38,7 @@ typedef struct __attribute__((__packed__)) _req_header { typedef struct __attribute__((__packed__)) _reply_header { uint16_t msg_id; - uint32_t context; + uint32_t context; // currently not all reply messages contain context field } reply_header_t; static void @@ -49,23 +49,23 @@ govpp_msg_callback (unsigned char *data, int size) } static int -govpp_connect (char *shm) +govpp_send(uint32_t context, void *data, size_t size) { - return vac_connect("govpp", shm, govpp_msg_callback, 32); + req_header_t *header = ((req_header_t *)data); + header->context = htonl(context); + return vac_write(data, size); } static int -govvp_disconnect() +govpp_connect (char *shm) { - return vac_disconnect(); + return vac_connect("govpp", shm, govpp_msg_callback, 32); } static int -govpp_send(uint32_t context, void *data, size_t size) +govvp_disconnect() { - req_header_t *header = ((req_header_t *)data); - header->context = htonl(context); - return vac_write(data, size); + return vac_disconnect(); } static uint32_t @@ -79,6 +79,7 @@ import "C" import ( "fmt" "os" + "path/filepath" "reflect" "unsafe" @@ -98,7 +99,7 @@ const ( // vppAPIClientAdapter is the opaque context of the adapter. type vppAPIClientAdapter struct { shmPrefix string - callback func(context uint32, msgId uint16, data []byte) + callback adapter.MsgCallback } var vppClient *vppAPIClientAdapter // global vpp API client adapter context @@ -138,6 +139,7 @@ func (a *vppAPIClientAdapter) GetMsgID(msgName string, msgCrc string) (uint16, e msgID := uint16(C.govpp_get_msg_index(nameAndCrc)) if msgID == ^uint16(0) { + // VPP does not know this message return msgID, fmt.Errorf("unknown message: %v (crc: %v)", msgName, msgCrc) } @@ -154,40 +156,41 @@ func (a *vppAPIClientAdapter) SendMsg(context uint32, data []byte) error { } // SetMsgCallback sets a callback function that will be called by the adapter whenever a message comes from VPP. -func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { +func (a *vppAPIClientAdapter) SetMsgCallback(cb adapter.MsgCallback) { a.callback = cb } // WaitReady blocks until shared memory for sending // binary api calls is present on the file system. func (a *vppAPIClientAdapter) WaitReady() error { - watcher, err := fsnotify.NewWatcher() - if err != nil { - return err - } - defer watcher.Close() - - err = watcher.Add(watchedFolder) - if err != nil { - return err - } - // Path to the shared memory segment with prefix, if set + // Path to the shared memory segment var path string if a.shmPrefix == "" { - path = watchedFolder + watchedFile + path = filepath.Join(watchedFolder, watchedFile) } else { - path = watchedFolder + a.shmPrefix + "-" + watchedFile - } - if fileExists(path) { - return nil + path = filepath.Join(watchedFolder, a.shmPrefix+"-"+watchedFile) } - for { - ev := <-watcher.Events - if ev.Name == path && (ev.Op&fsnotify.Create) == fsnotify.Create { - break + // Watch folder if file does not exist yet + if !fileExists(path) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return err + } + defer watcher.Close() + + if err := watcher.Add(watchedFolder); err != nil { + return err + } + + for { + ev := <-watcher.Events + if ev.Name == path && (ev.Op&fsnotify.Create) == fsnotify.Create { + break + } } } + return nil } @@ -206,5 +209,5 @@ func go_msg_callback(msgID C.uint16_t, context C.uint32_t, data unsafe.Pointer, slice := &reflect.SliceHeader{Data: uintptr(data), Len: int(size), Cap: int(size)} byteArr := *(*[]byte)(unsafe.Pointer(slice)) - vppClient.callback(uint32(context), uint16(msgID), byteArr) -}
\ No newline at end of file + vppClient.callback(uint16(msgID), uint32(context), byteArr) +} |