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 // VppEventHeader struct contains header fields implemented by all VPP events.
47 type VppEventHeader struct {
52 // VppOtherHeader struct contains header fields implemented by other VPP messages (not requests nor replies).
53 type VppOtherHeader struct {
58 vppRequestHeaderSize = 10 // size of a VPP request header
59 vppReplyHeaderSize = 6 // size of a VPP reply header
60 vppEventHeaderSize = 6 // size of a VPP event header
61 vppOtherHeaderSize = 2 // size of the header of other VPP messages
64 // EncodeMsg encodes provided `Message` structure into its binary-encoded data representation.
65 func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
67 return nil, errors.New("nil message passed in")
70 buf := new(bytes.Buffer)
72 // encode message header
73 var header interface{}
74 if msg.GetMessageType() == api.RequestMessage {
75 header = &VppRequestHeader{VlMsgID: msgID}
76 } else if msg.GetMessageType() == api.ReplyMessage {
77 header = &VppReplyHeader{VlMsgID: msgID}
78 } else if msg.GetMessageType() == api.EventMessage {
79 header = &VppEventHeader{VlMsgID: msgID}
81 header = &VppOtherHeader{VlMsgID: msgID}
83 err := struc.Pack(buf, header)
85 log.WithFields(logger.Fields{
88 }).Error("Unable to encode the message header: ", err)
89 return nil, fmt.Errorf("unable to encode the message header: %v", err)
92 // encode message content
93 if reflect.Indirect(reflect.ValueOf(msg)).NumField() > 0 {
94 err := struc.Pack(buf, msg)
96 log.WithFields(logger.Fields{
99 }).Error("Unable to encode the message: ", err)
100 return nil, fmt.Errorf("unable to encode the message: %v", err)
104 return buf.Bytes(), nil
107 // DecodeMsg decodes binary-encoded data of a message into provided `Message` structure.
108 func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error {
110 return errors.New("nil message passed in")
113 buf := bytes.NewReader(data)
115 // check which header is expected
116 var header interface{}
117 if msg.GetMessageType() == api.RequestMessage {
118 header = &VppRequestHeader{}
119 } else if msg.GetMessageType() == api.ReplyMessage {
120 header = &VppReplyHeader{}
121 } else if msg.GetMessageType() == api.EventMessage {
122 header = &VppEventHeader{}
124 header = &VppOtherHeader{}
127 // decode message header
128 err := struc.Unpack(buf, header)
130 log.WithFields(logger.Fields{
133 }).Error("Unable to decode header of the message.")
134 return fmt.Errorf("unable to decode the message header: %v", err)
137 // get rid of the message header
138 if msg.GetMessageType() == api.RequestMessage {
139 buf = bytes.NewReader(data[vppRequestHeaderSize:])
140 } else if msg.GetMessageType() == api.ReplyMessage {
141 buf = bytes.NewReader(data[vppReplyHeaderSize:])
142 } else if msg.GetMessageType() == api.EventMessage {
143 buf = bytes.NewReader(data[vppEventHeaderSize:])
145 buf = bytes.NewReader(data[vppOtherHeaderSize:])
148 // decode message content
149 err = struc.Unpack(buf, msg)
151 log.WithFields(logger.Fields{
154 }).Error("Unable to decode the message.")
155 return fmt.Errorf("unable to decode the message: %v", err)