1 // Copyright (c) 2017 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
23 logger "github.com/Sirupsen/logrus"
24 "github.com/lunixbochs/struc"
26 "git.fd.io/govpp.git/api"
29 // MsgCodec provides encoding and decoding functionality of `api.Message` structs into/from
30 // binary format as accepted by VPP.
31 type MsgCodec struct{}
33 // vppRequestHeader struct contains header fields implemented by all VPP requests.
34 type vppRequestHeader struct {
40 // vppReplyHeader struct contains header fields implemented by all VPP replies.
41 type vppReplyHeader struct {
46 // vppOtherHeader struct contains header fields implemented by other VPP messages (not requests nor replies).
47 type vppOtherHeader struct {
52 vppRequestHeaderSize = 10 // size of a VPP request header
53 vppReplyHeaderSize = 6 // size of a VPP reply header
54 vppOtherHeaderSize = 2 // size of the header of other VPP messages
57 // EncodeMsg encodes provided `Message` structure into its binary-encoded data representation.
58 func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
60 return nil, errors.New("nil message passed in")
63 buf := new(bytes.Buffer)
65 // encode message header
66 var header interface{}
67 if msg.GetMessageType() == api.RequestMessage {
68 header = &vppRequestHeader{VlMsgID: msgID}
69 } else if msg.GetMessageType() == api.ReplyMessage {
70 header = &vppReplyHeader{VlMsgID: msgID}
72 header = &vppOtherHeader{VlMsgID: msgID}
74 err := struc.Pack(buf, header)
76 log.WithFields(logger.Fields{
79 }).Error("Unable to encode the message header: ", err)
80 return nil, fmt.Errorf("unable to encode the message header: %v", err)
83 // encode message content
84 if reflect.Indirect(reflect.ValueOf(msg)).NumField() > 0 {
85 err := struc.Pack(buf, msg)
87 log.WithFields(logger.Fields{
90 }).Error("Unable to encode the message: ", err)
91 return nil, fmt.Errorf("unable to encode the message: %v", err)
95 return buf.Bytes(), nil
98 // DecodeMsg decodes binary-encoded data of a message into provided `Message` structure.
99 func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error {
101 return errors.New("nil message passed in")
104 buf := bytes.NewReader(data)
106 // check which header is expected
107 var header interface{}
108 if msg.GetMessageType() == api.RequestMessage {
109 header = &vppRequestHeader{}
110 } else if msg.GetMessageType() == api.ReplyMessage {
111 header = &vppReplyHeader{}
113 header = &vppOtherHeader{}
116 // decode message header
117 err := struc.Unpack(buf, header)
119 log.WithFields(logger.Fields{
122 }).Error("Unable to decode header of the message.")
123 return fmt.Errorf("unable to decode the message header: %v", err)
126 // get rid of the message header
127 if msg.GetMessageType() == api.RequestMessage {
128 buf = bytes.NewReader(data[vppRequestHeaderSize:])
129 } else if msg.GetMessageType() == api.ReplyMessage {
130 buf = bytes.NewReader(data[vppReplyHeaderSize:])
132 buf = bytes.NewReader(data[vppOtherHeaderSize:])
135 // decode message content
136 err = struc.Unpack(buf, msg)
138 log.WithFields(logger.Fields{
141 }).Error("Unable to decode the message.")
142 return fmt.Errorf("unable to decode the message: %v", err)