Skip to content

Commit e45d880

Browse files
committed
Improve compatibility checking
- added CompatibilityError to api package to represent error with list of incompatible messages - added UnknownMsgError to adapter package to represent error for unknown message - added list of registered message types Change-Id: I2623b45135521d52612ba91e4605fc064a7fc76e Signed-off-by: Ondrej Fabry <[email protected]>
1 parent 2f75863 commit e45d880

File tree

8 files changed

+68
-18
lines changed

8 files changed

+68
-18
lines changed

adapter/socketclient/socketclient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ func (c *vppClient) GetMsgID(msgName string, msgCrc string) (uint16, error) {
419419
msg := msgName + "_" + msgCrc
420420
msgID, ok := c.msgTable[msg]
421421
if !ok {
422-
return 0, fmt.Errorf("unknown message: %q", msg)
422+
return 0, &adapter.UnknownMsgError{msgName, msgCrc}
423423
}
424424
return msgID, nil
425425
}

adapter/vpp_api.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package adapter
1616

1717
import (
1818
"errors"
19+
"fmt"
1920
)
2021

2122
const (
@@ -52,3 +53,14 @@ type VppAPI interface {
5253
// WaitReady waits until adapter is ready.
5354
WaitReady() error
5455
}
56+
57+
// UnknownMsgError is the error type usually returned by GetMsgID
58+
// method of VppAPI. It describes the name and CRC for the unknown message.
59+
type UnknownMsgError struct {
60+
MsgName string
61+
MsgCrc string
62+
}
63+
64+
func (u *UnknownMsgError) Error() string {
65+
return fmt.Sprintf("unknown message: %s_%s", u.MsgName, u.MsgCrc)
66+
}

adapter/vppapiclient/vppapiclient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func (a *vppClient) GetMsgID(msgName string, msgCrc string) (uint16, error) {
116116
msgID := uint16(C.govpp_get_msg_index(nameAndCrc))
117117
if msgID == ^uint16(0) {
118118
// VPP does not know this message
119-
return msgID, fmt.Errorf("unknown message: %v (crc: %v)", msgName, msgCrc)
119+
return msgID, &adapter.UnknownMsgError{msgName, msgCrc}
120120
}
121121

122122
return msgID, nil

api/binapi.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package api
1616

1717
import (
18+
"fmt"
19+
"reflect"
1820
"time"
1921
)
2022

@@ -115,22 +117,44 @@ type SubscriptionCtx interface {
115117
Unsubscribe() error
116118
}
117119

118-
var registeredMessages = make(map[string]Message)
120+
// CompatibilityError is the error type usually returned by CheckCompatibility
121+
// method of Channel. It describes all of the incompatible messages.
122+
type CompatibilityError struct {
123+
// IncompatibleMessages is the list of all messages
124+
// that failed compatibility check.
125+
IncompatibleMessages []string
126+
}
127+
128+
func (c *CompatibilityError) Error() string {
129+
return fmt.Sprintf("%d incompatible messages: %v", len(c.IncompatibleMessages), c.IncompatibleMessages)
130+
}
131+
132+
var (
133+
registeredMessageTypes = make(map[reflect.Type]string)
134+
registeredMessages = make(map[string]Message)
135+
)
119136

120137
// RegisterMessage is called from generated code to register message.
121138
func RegisterMessage(x Message, name string) {
122-
name = x.GetMessageName() + "_" + x.GetCrcString()
123-
/*if _, ok := registeredMessages[name]; ok {
124-
panic(fmt.Errorf("govpp: duplicate message registered: %s (%s)", name, x.GetCrcString()))
125-
}*/
126-
registeredMessages[name] = x
139+
typ := reflect.TypeOf(x)
140+
namecrc := x.GetMessageName() + "_" + x.GetCrcString()
141+
if _, ok := registeredMessageTypes[typ]; ok {
142+
panic(fmt.Errorf("govpp: message type %v already registered as %s (%s)", typ, name, namecrc))
143+
}
144+
registeredMessages[namecrc] = x
145+
registeredMessageTypes[typ] = name
127146
}
128147

129148
// GetRegisteredMessages returns list of all registered messages.
130149
func GetRegisteredMessages() map[string]Message {
131150
return registeredMessages
132151
}
133152

153+
// GetRegisteredMessageTypes returns list of all registered message types.
154+
func GetRegisteredMessageTypes() map[reflect.Type]string {
155+
return registeredMessageTypes
156+
}
157+
134158
// GoVppAPIPackageIsVersion1 is referenced from generated binapi files
135159
// to assert that that code is compatible with this version of the GoVPP api package.
136160
const GoVppAPIPackageIsVersion1 = true

core/channel.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"github.com/sirupsen/logrus"
2525

26+
"git.fd.io/govpp.git/adapter"
2627
"git.fd.io/govpp.git/api"
2728
)
2829

@@ -144,14 +145,23 @@ func (ch *Channel) SendMultiRequest(msg api.Message) api.MultiRequestCtx {
144145
}
145146

146147
func (ch *Channel) CheckCompatiblity(msgs ...api.Message) error {
148+
var comperr api.CompatibilityError
147149
for _, msg := range msgs {
148-
// TODO: collect all incompatible messages and return summarized error
149150
_, err := ch.msgIdentifier.GetMessageID(msg)
150151
if err != nil {
152+
if uerr, ok := err.(*adapter.UnknownMsgError); ok {
153+
m := fmt.Sprintf("%s_%s", uerr.MsgName, uerr.MsgCrc)
154+
comperr.IncompatibleMessages = append(comperr.IncompatibleMessages, m)
155+
continue
156+
}
157+
// other errors return immediatelly
151158
return err
152159
}
153160
}
154-
return nil
161+
if len(comperr.IncompatibleMessages) == 0 {
162+
return nil
163+
}
164+
return &comperr
155165
}
156166

157167
func (ch *Channel) SubscribeNotification(notifChan chan api.Message, event api.Message) (api.SubscriptionCtx, error) {

core/channel_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,15 @@ func TestSetReplyTimeoutMultiRequest(t *testing.T) {
213213
ctx.mockVpp.MockReply(
214214
&interfaces.SwInterfaceDetails{
215215
SwIfIndex: 1,
216-
InterfaceName: []byte("if-name-test"),
216+
InterfaceName: "if-name-test",
217217
},
218218
&interfaces.SwInterfaceDetails{
219219
SwIfIndex: 2,
220-
InterfaceName: []byte("if-name-test"),
220+
InterfaceName: "if-name-test",
221221
},
222222
&interfaces.SwInterfaceDetails{
223223
SwIfIndex: 3,
224-
InterfaceName: []byte("if-name-test"),
224+
InterfaceName: "if-name-test",
225225
},
226226
)
227227
ctx.mockVpp.MockReply(&ControlPingReply{})
@@ -288,7 +288,7 @@ func TestMultiRequestDouble(t *testing.T) {
288288
msgs = append(msgs, mock.MsgWithContext{
289289
Msg: &interfaces.SwInterfaceDetails{
290290
SwIfIndex: uint32(i),
291-
InterfaceName: []byte("if-name-test"),
291+
InterfaceName: "if-name-test",
292292
},
293293
Multipart: true,
294294
SeqNum: 1,
@@ -301,7 +301,7 @@ func TestMultiRequestDouble(t *testing.T) {
301301
mock.MsgWithContext{
302302
Msg: &interfaces.SwInterfaceDetails{
303303
SwIfIndex: uint32(i),
304-
InterfaceName: []byte("if-name-test"),
304+
InterfaceName: "if-name-test",
305305
},
306306
Multipart: true,
307307
SeqNum: 2,
@@ -427,7 +427,7 @@ func TestReceiveReplyAfterTimeoutMultiRequest(t *testing.T) {
427427
msgs = append(msgs, mock.MsgWithContext{
428428
Msg: &interfaces.SwInterfaceDetails{
429429
SwIfIndex: uint32(i),
430-
InterfaceName: []byte("if-name-test"),
430+
InterfaceName: "if-name-test",
431431
},
432432
Multipart: true,
433433
SeqNum: 2,

examples/rpc-service/rpc_service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
package main
1818

1919
import (
20-
"bytes"
2120
"context"
2221
"flag"
2322
"fmt"
2423
"io"
2524
"log"
25+
"strings"
2626

2727
"git.fd.io/govpp.git"
2828
"git.fd.io/govpp.git/adapter/socketclient"
@@ -88,6 +88,6 @@ func interfaceDump(ch api.Channel) {
8888
if err != nil {
8989
log.Fatalln("ERROR: DumpSwInterface failed:", err)
9090
}
91-
fmt.Printf("- interface: %s\n", bytes.Trim(iface.InterfaceName, "\x00"))
91+
fmt.Printf("- interface: %s\n", strings.Trim(iface.InterfaceName, "\x00"))
9292
}
9393
}

examples/simple-client/simple_client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func main() {
6565

6666
vppVersion(ch)
6767

68+
if err := ch.CheckCompatiblity(interfaces.AllMessages()...); err != nil {
69+
log.Fatal(err)
70+
}
71+
6872
createLoopback(ch)
6973
createLoopback(ch)
7074
interfaceDump(ch)

0 commit comments

Comments
 (0)