From 4b0cfc7539ec6fdbc462f60269656fee761bafaf Mon Sep 17 00:00:00 2001 From: Rastislav Szabo Date: Wed, 17 May 2017 16:19:30 +0200 Subject: multiple small fixes Change-Id: I9e822ce7e9b9f44f7d074b0294d6eda37c2a0f12 Signed-off-by: Rastislav Szabo --- .gitignore | 1 + adapter/mock/mock_adapter.go | 15 +++++++++++---- api/api.go | 6 ++++-- binapi_generator/generator.go | 5 ++--- core/core.go | 11 +++++++---- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 0d0d750..0f9e2cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.idea binapi_generator/binapi_generator examples/examples diff --git a/adapter/mock/mock_adapter.go b/adapter/mock/mock_adapter.go index ab49cef..796b96e 100644 --- a/adapter/mock/mock_adapter.go +++ b/adapter/mock/mock_adapter.go @@ -37,7 +37,7 @@ type VppAdapter struct { msgIdsToName *map[uint16]string msgIdSeq uint16 binApiTypes map[string]reflect.Type - //TODO lock + access sync.RWMutex } // replyHeader represents a common header of each VPP request message. @@ -104,8 +104,6 @@ func (a *VppAdapter) Disconnect() { } func (a *VppAdapter) GetMsgNameByID(msgId uint16) (string, bool) { - a.initMaps() - switch msgId { case 100: return "control_ping", true @@ -117,12 +115,17 @@ func (a *VppAdapter) GetMsgNameByID(msgId uint16) (string, bool) { return "sw_interface_details", true } + a.access.Lock() + defer a.access.Unlock() + a.initMaps() msgName, found := (*a.msgIdsToName)[msgId] return msgName, found } func (a *VppAdapter) RegisterBinApiTypes(binApiTypes map[string]reflect.Type) { + a.access.Lock() + defer a.access.Unlock() a.initMaps() for _, v := range binApiTypes { if msg, ok := reflect.New(v).Interface().(api.Message); ok { @@ -187,6 +190,8 @@ func (a *VppAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) { return 201, nil } + a.access.Lock() + defer a.access.Unlock() a.initMaps() if msgId, found := (*a.msgNameToIds)[msgName]; found { @@ -219,6 +224,7 @@ func (a *VppAdapter) initMaps() { func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { switch mode { case useReplyHandlers: + a.initMaps() for i := len(replyHandlers) - 1; i >= 0; i-- { replyHandler := replyHandlers[i] @@ -226,8 +232,9 @@ func (a *VppAdapter) SendMsg(clientID uint32, data []byte) error { reqHeader := requestHeader{} struc.Unpack(buf, &reqHeader) - a.initMaps() + a.access.Lock() reqMsgName, _ := (*a.msgIdsToName)[reqHeader.VlMsgID] + a.access.Unlock() reply, msgID, finished := replyHandler(MessageDTO{reqHeader.VlMsgID, reqMsgName, clientID, data}) diff --git a/api/api.go b/api/api.go index 783f97a..f478bf1 100644 --- a/api/api.go +++ b/api/api.go @@ -78,7 +78,8 @@ type MessageIdentifier interface { // Channel is the main communication interface with govpp core. It contains two Go channels, one for sending the requests // to VPP and one for receiving the replies from it. The user can access the Go channels directly, or use the helper -// methods provided inside of this package. +// methods provided inside of this package. Do not use the same channel from multiple goroutines concurrently, +// otherwise the responses could mix! Use multiple channels instead. type Channel struct { ReqChan chan *VppRequest // channel for sending the requests to VPP, closing this channel releases all resources in the ChannelProvider ReplyChan chan *VppReply // channel where VPP replies are delivered to @@ -230,7 +231,8 @@ func (ch *Channel) receiveReplyInternal(msg Message) (LastReplyReceived bool, er return false, err } if vppReply.MessageID != expMsgID { - err = fmt.Errorf("invalid message ID %d, expected %d", vppReply.MessageID, expMsgID) + err = fmt.Errorf("invalid message ID %d, expected %d "+ + "(also check if multiple goroutines are not sharing one GoVPP channel)", vppReply.MessageID, expMsgID) return false, err } // decode the message diff --git a/binapi_generator/generator.go b/binapi_generator/generator.go index 43f9ede..22fe3e1 100644 --- a/binapi_generator/generator.go +++ b/binapi_generator/generator.go @@ -27,7 +27,6 @@ import ( "os/exec" "path/filepath" "strings" - "time" "unicode" "github.com/bennyscetbun/jsongo" @@ -44,7 +43,7 @@ const ( const ( apiImportPath = "git.fd.io/govpp.git/api" // import path of the govpp API - inputFileExt = ".json" // filename extension of files that should be processed as the input + inputFileExt = ".json" // filename extension of files that should be processed as the input ) // context is a structure storing details of a particular code generation task @@ -386,7 +385,7 @@ func processMessageField(ctx *context, fields *[]string, fld *jsongo.JSONNode) e // generatePackageHeader generates package header into provider writer func generatePackageHeader(ctx *context, w io.Writer, rootNode *jsongo.JSONNode) { fmt.Fprintln(w, "// Package "+ctx.packageName+" represents the VPP binary API of the '"+ctx.packageName+"' VPP module.") - fmt.Fprintln(w, "// DO NOT EDIT. Generated from '"+ctx.inputFile+"' on "+time.Now().Format(time.RFC1123)+".") + fmt.Fprintln(w, "// DO NOT EDIT. Generated from '"+ctx.inputFile+"'") fmt.Fprintln(w, "package "+ctx.packageName) diff --git a/core/core.go b/core/core.go index 7dc45de..550b6a7 100644 --- a/core/core.go +++ b/core/core.go @@ -207,13 +207,16 @@ func (c *Connection) processRequest(ch *api.Channel, chMeta *channelMetadata, re "msg_size": len(data), }).Debug("Sending a message to VPP.") - c.vpp.SendMsg(chMeta.id, data) - if req.Multipart { - // multipart request + // expect multipart response atomic.StoreUint32(&chMeta.multipart, 1) + } - // send a control ping + // send the request to VPP + c.vpp.SendMsg(chMeta.id, data) + + if req.Multipart { + // send a control ping to determine end of the multipart response ping := &vpe.ControlPing{} pingData, _ := c.codec.EncodeMsg(ping, c.pingReqID) -- cgit 1.2.3-korg