diff options
Diffstat (limited to 'adapter')
-rw-r--r-- | adapter/adapter.go | 3 | ||||
-rw-r--r-- | adapter/mock/mock_adapter.go | 56 | ||||
-rw-r--r-- | adapter/vppapiclient/empty_adapter.go | 4 | ||||
-rw-r--r-- | adapter/vppapiclient/vppapiclient_adapter.go | 47 |
4 files changed, 78 insertions, 32 deletions
diff --git a/adapter/adapter.go b/adapter/adapter.go index 2843d2c..a5b3352 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -30,4 +30,7 @@ type VppAdapter interface { // 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)) + + // WaitReady waits until adapter is ready. + WaitReady() error } diff --git a/adapter/mock/mock_adapter.go b/adapter/mock/mock_adapter.go index e6b4bc4..d8a80d6 100644 --- a/adapter/mock/mock_adapter.go +++ b/adapter/mock/mock_adapter.go @@ -22,6 +22,7 @@ import ( "reflect" "sync" + "git.fd.io/govpp.git/core" "github.com/lunixbochs/struc" "git.fd.io/govpp.git/adapter" @@ -33,31 +34,13 @@ import ( type VppAdapter struct { callback func(context uint32, msgId uint16, data []byte) - msgNameToIds *map[string]uint16 - msgIDsToName *map[uint16]string + msgNameToIds map[string]uint16 + msgIDsToName map[uint16]string msgIDSeq uint16 binAPITypes map[string]reflect.Type access sync.RWMutex } -// replyHeader represents a common header of each VPP request message. -type requestHeader struct { - VlMsgID uint16 - ClientIndex uint32 - Context uint32 -} - -// replyHeader represents a common header of each VPP reply message. -type replyHeader struct { - VlMsgID uint16 - Context uint32 -} - -// otherHeader represents a common header of each VPP reply message. -type otherHeader struct { - VlMsgID uint16 -} - // defaultReply is a default reply message that mock adapter returns for a request. type defaultReply struct { Retval int32 @@ -118,7 +101,7 @@ func (a *VppAdapter) GetMsgNameByID(msgID uint16) (string, bool) { a.access.Lock() defer a.access.Unlock() a.initMaps() - msgName, found := (*a.msgIDsToName)[msgID] + msgName, found := a.msgIDsToName[msgID] return msgName, found } @@ -175,7 +158,7 @@ func (a *VppAdapter) ReplyBytes(request MessageDTO, reply api.Message) ([]byte, log.Println("ReplyBytes ", replyMsgID, " ", reply.GetMessageName(), " clientId: ", request.ClientID) buf := new(bytes.Buffer) - struc.Pack(buf, &replyHeader{VlMsgID: replyMsgID, Context: request.ClientID}) + struc.Pack(buf, &core.VppReplyHeader{VlMsgID: replyMsgID, Context: request.ClientID}) struc.Pack(buf, reply) return buf.Bytes(), nil @@ -198,15 +181,15 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) { defer a.access.Unlock() a.initMaps() - msgID, found := (*a.msgNameToIds)[msgName] + msgID, found := a.msgNameToIds[msgName] if found { return msgID, nil } a.msgIDSeq++ msgID = a.msgIDSeq - (*a.msgNameToIds)[msgName] = msgID - (*a.msgIDsToName)[msgID] = msgName + a.msgNameToIds[msgName] = msgID + a.msgIDsToName[msgID] = msgName log.Println("VPP GetMessageId ", msgID, " name:", msgName, " crc:", msgCrc) @@ -216,8 +199,8 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) { // initMaps initializes internal maps (if not already initialized). func (a *VppAdapter) initMaps() { if a.msgIDsToName == nil { - a.msgIDsToName = &map[uint16]string{} - a.msgNameToIds = &map[string]uint16{} + a.msgIDsToName = map[uint16]string{} + a.msgNameToIds = map[string]uint16{} a.msgIDSeq = 1000 } @@ -235,11 +218,11 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { replyHandler := replyHandlers[i] buf := bytes.NewReader(data) - reqHeader := requestHeader{} + reqHeader := core.VppRequestHeader{} struc.Unpack(buf, &reqHeader) a.access.Lock() - reqMsgName, _ := (*a.msgIDsToName)[reqHeader.VlMsgID] + reqMsgName, _ := a.msgIDsToName[reqHeader.VlMsgID] a.access.Unlock() reply, msgID, finished := replyHandler(MessageDTO{reqHeader.VlMsgID, reqMsgName, @@ -265,9 +248,13 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { msgID, _ := a.GetMsgID(reply.GetMessageName(), reply.GetCrcString()) buf := new(bytes.Buffer) if reply.GetMessageType() == api.ReplyMessage { - struc.Pack(buf, &replyHeader{VlMsgID: msgID, Context: clientID}) + struc.Pack(buf, &core.VppReplyHeader{VlMsgID: msgID, Context: clientID}) + } else if reply.GetMessageType() == api.EventMessage { + struc.Pack(buf, &core.VppEventHeader{VlMsgID: msgID, Context: clientID}) + } else if reply.GetMessageType() == api.RequestMessage { + struc.Pack(buf, &core.VppRequestHeader{VlMsgID: msgID, Context: clientID}) } else { - struc.Pack(buf, &requestHeader{VlMsgID: msgID, Context: clientID}) + struc.Pack(buf, &core.VppOtherHeader{VlMsgID: msgID}) } struc.Pack(buf, reply) a.callback(clientID, msgID, buf.Bytes()) @@ -287,7 +274,7 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { // return default reply buf := new(bytes.Buffer) msgID := uint16(defaultReplyMsgID) - struc.Pack(buf, &replyHeader{VlMsgID: msgID, Context: clientID}) + struc.Pack(buf, &core.VppReplyHeader{VlMsgID: msgID, Context: clientID}) struc.Pack(buf, &defaultReply{}) a.callback(clientID, msgID, buf.Bytes()) } @@ -299,6 +286,11 @@ func (a *VppAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data [ a.callback = cb } +// WaitReady mocks waiting for VPP +func (a *VppAdapter) WaitReady() error { + return nil +} + // MockReply stores a message to be returned when the next request comes. It is a FIFO queue - multiple replies // can be pushed into it, the first one will be popped when some request comes. // Using of this method automatically switches the mock into th useRepliesQueue mode. diff --git a/adapter/vppapiclient/empty_adapter.go b/adapter/vppapiclient/empty_adapter.go index 14f804d..7249864 100644 --- a/adapter/vppapiclient/empty_adapter.go +++ b/adapter/vppapiclient/empty_adapter.go @@ -50,3 +50,7 @@ func (a *vppAPIClientAdapter) SendMsg(clientID uint32, data []byte) error { func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint16, data []byte)) { // no op } + +func (a *vppAPIClientAdapter) WaitReady() func() error { + return func() error { return nil } +} diff --git a/adapter/vppapiclient/vppapiclient_adapter.go b/adapter/vppapiclient/vppapiclient_adapter.go index 74f0118..1cdaf72 100644 --- a/adapter/vppapiclient/vppapiclient_adapter.go +++ b/adapter/vppapiclient/vppapiclient_adapter.go @@ -79,10 +79,21 @@ import "C" import ( "errors" "fmt" + "os" "reflect" "unsafe" "git.fd.io/govpp.git/adapter" + "github.com/fsnotify/fsnotify" +) + +const ( + // watchedFolder is a folder where vpp's shared memory is supposed to be created. + // File system events are monitored in this folder. + watchedFolder = "/dev/shm/" + // watchedFile is a name of the file in the watchedFolder. Once the file is present + // the vpp is ready to accept a new connection. + watchedFile = watchedFolder + "vpe-api" ) // vppAPIClientAdapter is the opaque context of the adapter. @@ -139,6 +150,42 @@ func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint1 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 + } + + if fileExists(watchedFile) { + return nil + } + + for { + ev := <-watcher.Events + if ev.Name == watchedFile && (ev.Op&fsnotify.Create) == fsnotify.Create { + break + } + } + return nil +} + +func fileExists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } + } + return true +} + //export go_msg_callback func go_msg_callback(msgID C.uint16_t, context C.uint32_t, data unsafe.Pointer, size C.size_t) { // convert unsafe.Pointer to byte slice |