Skip to content

Commit

Permalink
Add Geneve SerializeTo support
Browse files Browse the repository at this point in the history
Added missing SerializeTo functionality to Geneve.

Fixes: google#1043
  • Loading branch information
retr0h authored and gconnell committed Aug 10, 2022
1 parent 3eaba08 commit 4e29164
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
57 changes: 57 additions & 0 deletions layers/geneve.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package layers
import (
"encoding/binary"
"errors"
"fmt"

"github.com/google/gopacket"
)
Expand Down Expand Up @@ -119,3 +120,59 @@ func decodeGeneve(data []byte, p gopacket.PacketBuilder) error {
gn := &Geneve{}
return decodingLayerDecoder(gn, data, p)
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (gn *Geneve) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
plen := int(gn.OptionsLength + 8)
bytes, err := b.PrependBytes(plen)
if err != nil {
return err
}

// PrependBytes does not guarantee that bytes are zeroed. Setting flags via OR requires that they start off at zero
bytes[0] = 0
bytes[1] = 0

// Construct Geneve

bytes[0] |= gn.Version << 6
bytes[0] |= ((gn.OptionsLength >> 2) & 0x3f)

if gn.OAMPacket {
bytes[1] |= 0x80
}

if gn.CriticalOption {
bytes[1] |= 0x40
}

binary.BigEndian.PutUint16(bytes[2:4], uint16(gn.Protocol))

if gn.VNI >= 1<<24 {
return fmt.Errorf("Virtual Network Identifier = %x exceeds max for 24-bit uint", gn.VNI)
}
binary.BigEndian.PutUint32(bytes[4:8], gn.VNI<<8)

// Construct Options

offset, _ := uint8(8), int32(gn.OptionsLength)
for _, o := range gn.Options {
binary.BigEndian.PutUint16(bytes[offset:(offset+2)], uint16(o.Class))

offset += 2
bytes[offset] = o.Type

offset += 1
bytes[offset] |= o.Flags << 5
bytes[offset] |= ((o.Length - 4) >> 2) & 0x1f

offset += 1
copy(bytes[offset:(offset+o.Length-4)], o.Data)

offset += o.Length - 4
}

return nil
}
38 changes: 37 additions & 1 deletion layers/geneve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func TestDecodeGeneve3(t *testing.T) {
Protocol: EthernetTypeTransparentEthernetBridging,
VNI: 0xa,
Options: []*GeneveOption{
&GeneveOption{
{
Class: 0x0,
Type: 0x80,
Length: 8,
Expand All @@ -155,3 +155,39 @@ func BenchmarkDecodeGeneve1(b *testing.B) {
gopacket.NewPacket(testPacketGeneve1, LinkTypeEthernet, gopacket.NoCopy)
}
}

func TestIsomorphicPacketGeneve(t *testing.T) {
gn := &Geneve{
Version: 0x0,
OptionsLength: 0x14,
OAMPacket: false,
CriticalOption: true,
Protocol: EthernetTypeTransparentEthernetBridging,
VNI: 0xa,
Options: []*GeneveOption{
{
Class: 0x0,
Type: 0x80,
Length: 12,
Data: []byte{0, 0, 0, 0, 0, 0, 0, 0xc},
},
{
Class: 0x0,
Type: 0x80,
Length: 8,
Data: []byte{0, 0, 0, 0xc},
},
},
}

b := gopacket.NewSerializeBuffer()
gn.SerializeTo(b, gopacket.SerializeOptions{})

p := gopacket.NewPacket(b.Bytes(), gopacket.DecodeFunc(decodeGeneve), gopacket.Default)
gnTranslated := p.Layer(LayerTypeGeneve).(*Geneve)
gnTranslated.BaseLayer = BaseLayer{}

if !reflect.DeepEqual(gn, gnTranslated) {
t.Errorf("VXLAN isomorph mismatch, \nwant %#v\ngot %#v\n", gn, gnTranslated)
}
}

0 comments on commit 4e29164

Please sign in to comment.