aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRastislav Szabo <raszabo@cisco.com>2017-05-17 16:19:30 +0200
committerRastislav Szabo <raszabo@cisco.com>2017-05-17 16:19:30 +0200
commit4b0cfc7539ec6fdbc462f60269656fee761bafaf (patch)
tree27a9f634d5201dea49207a50fa8e1ba9639bdc58
parent51f628282c65f754152a346074f2ae286121138e (diff)
multiple small fixes
Change-Id: I9e822ce7e9b9f44f7d074b0294d6eda37c2a0f12 Signed-off-by: Rastislav Szabo <raszabo@cisco.com>
-rw-r--r--.gitignore1
-rw-r--r--adapter/mock/mock_adapter.go15
-rw-r--r--api/api.go6
-rw-r--r--binapi_generator/generator.go5
-rw-r--r--core/core.go11
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)