@@ -9,6 +9,7 @@ package layers
99import (
1010 "encoding/binary"
1111 "errors"
12+ "fmt"
1213
1314 "github.com/google/gopacket"
1415)
@@ -119,3 +120,59 @@ func decodeGeneve(data []byte, p gopacket.PacketBuilder) error {
119120 gn := & Geneve {}
120121 return decodingLayerDecoder (gn , data , p )
121122}
123+
124+ // SerializeTo writes the serialized form of this layer into the
125+ // SerializationBuffer, implementing gopacket.SerializableLayer.
126+ // See the docs for gopacket.SerializableLayer for more info.
127+ func (gn * Geneve ) SerializeTo (b gopacket.SerializeBuffer , opts gopacket.SerializeOptions ) error {
128+ plen := int (gn .OptionsLength + 8 )
129+ bytes , err := b .PrependBytes (plen )
130+ if err != nil {
131+ return err
132+ }
133+
134+ // PrependBytes does not guarantee that bytes are zeroed. Setting flags via OR requires that they start off at zero
135+ bytes [0 ] = 0
136+ bytes [1 ] = 0
137+
138+ // Construct Geneve
139+
140+ bytes [0 ] |= gn .Version << 6
141+ bytes [0 ] |= ((gn .OptionsLength >> 2 ) & 0x3f )
142+
143+ if gn .OAMPacket {
144+ bytes [1 ] |= 0x80
145+ }
146+
147+ if gn .CriticalOption {
148+ bytes [1 ] |= 0x40
149+ }
150+
151+ binary .BigEndian .PutUint16 (bytes [2 :4 ], uint16 (gn .Protocol ))
152+
153+ if gn .VNI >= 1 << 24 {
154+ return fmt .Errorf ("Virtual Network Identifier = %x exceeds max for 24-bit uint" , gn .VNI )
155+ }
156+ binary .BigEndian .PutUint32 (bytes [4 :8 ], gn .VNI << 8 )
157+
158+ // Construct Options
159+
160+ offset , _ := uint8 (8 ), int32 (gn .OptionsLength )
161+ for _ , o := range gn .Options {
162+ binary .BigEndian .PutUint16 (bytes [offset :(offset + 2 )], uint16 (o .Class ))
163+
164+ offset += 2
165+ bytes [offset ] = o .Type
166+
167+ offset += 1
168+ bytes [offset ] |= o .Flags << 5
169+ bytes [offset ] |= ((o .Length - 4 ) >> 2 ) & 0x1f
170+
171+ offset += 1
172+ copy (bytes [offset :(offset + o .Length - 4 )], o .Data )
173+
174+ offset += o .Length - 4
175+ }
176+
177+ return nil
178+ }
0 commit comments