diff options
author | Ondrej Fabry <ofabry@cisco.com> | 2018-08-15 12:59:25 +0200 |
---|---|---|
committer | Ondrej Fabry <ofabry@cisco.com> | 2018-08-16 15:03:29 +0200 |
commit | a3bb834db727a3ac9a1ffcfeae9265e5dead851f (patch) | |
tree | 6ffe64d2dd78a4c3434c2889dd7582b74619fe2b /adapter | |
parent | da815585c3f75c4ac073b0766dd668abf83844d8 (diff) |
Refactor GoVPP
Squashed commit of the following:
commit 348930db31575e9f59b3834d9fec07411f011e05
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 15 11:30:13 2018 +0200
Use debug level for log about different context
commit 9fc963c559cea67a41b85c6cdadc322fb3b1fc7c
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 15 11:22:03 2018 +0200
Remove annoying logs and add env vars for debugging
commit fdc9fd624d13feadb602e0d03d58f8a44b7a565f
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 15 11:18:47 2018 +0200
Fix printing unknown VPPApiError
commit 8f968be36a91de4d4a8ea17593ba314f82aa9583
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Tue Aug 14 17:25:10 2018 +0200
Refactor entire GoVPP
- fix some cases with inconsistent VPP messages, causing messages
to be incorrectly identified as event or request
- simplify API, remove direct access to internal Go channels
- add module name with message to registration of messages
- start watching filesystem only when vpe-api file does not exist
- simplify code in message codec and remove unneeded parts
- retrieve IDs of all registered messages after connect to VPP
- define fallback for control ping in core to avoid duplicate registration
- add SetLogLevel function to set logger level more easily
- remove lot of unused code
commit 34dd1b7e10ef0324aa8c4e4cc42375bd6021c6cb
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Mon Aug 13 11:29:54 2018 +0200
Rename VnetError to VPPApiError
commit c6549d6f77847a1367a12ff47fb716e2955e973a
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Mon Aug 13 10:23:43 2018 +0200
Fix examples and regenerate binapi
commit 4612e36b416779771f5efab4fc654c2766d2cb1c
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Mon Aug 13 09:51:22 2018 +0200
Add parsing and generation for services
commit ac9c5280c5aa27e325f327609e2364cc66f3723f
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Fri Aug 10 14:30:15 2018 +0200
Fix exit status on error and add continue-onerror flag
commit 9b3f4ef9fc7c8c62037fa107085eae18a8725314
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 15:20:56 2018 +0200
Return VnetError when Retval != 0
commit 8fd21a907b5e628ec4d2026215b83d15da96c297
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 14:59:05 2018 +0200
Add all missing errors from api_errno.h
commit 08450f288d3046ebaecf40203174ae342a07f1eb
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 14:29:27 2018 +0200
Update README
commit d8dced0728dd62243539be741868fb7d9b8de4cc
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:59:59 2018 +0200
Regenerate vpe in core
commit 254da7592cdbf634cf7aa46ae36ce7bb6d4ee555
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:37:00 2018 +0200
Add VnetError type for Retvals
commit 4475c1087fb53ab4c788e530bc7fef7cfc89d2cd
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:36:07 2018 +0200
Add registration API
commit 892a3ea5a2c703e2f7c29331663f6a6fa706bff5
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:30:43 2018 +0200
Generate registration for messages and check all IDs on connect
commit 389ed03b6e7082260281866c3449d72d72347c99
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:32:41 2018 +0200
Show error for empty adapter (on Darwin/Windows)
commit ef1ea040d656ade64242432dc5f06810ed8dcde6
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:31:37 2018 +0200
Improve logged info
commit d4adae3b14ed54c8d693060dd857fa9ba5ec8e06
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:27:48 2018 +0200
Update examples
commit 63921e1346014701a22639a2611129563bb1eb78
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:02:56 2018 +0200
Generate unions and fix some issues
- add comments between sections
- define structs on single line if it has no fields
- generate unions with setters/getters for each field
- fix detection of message type
commit 6ab3e3fa590b245898306a6ffaf32c7721eab60c
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 8 15:37:10 2018 +0200
Refactor binapi-generator
- split JSON parsing from code generation
- parse and generate enums
- parse unions (no generation yet)
- change output file suffix to '.ba.go'
- cleanup and simplify code
- split code into files
- add flag for debug mode
Change-Id: I58f685e0d4c7a38e9a7b6ea0a1f47792d95d7399
Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
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) +} |