1// Copyright 2016 Google, Inc. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style license 4// that can be found in the LICENSE file in the root of the source 5// tree. 6 7package layers 8 9import ( 10 "encoding/binary" 11 "fmt" 12 "github.com/google/gopacket" 13) 14 15// VXLAN is specifed in RFC 7348 https://tools.ietf.org/html/rfc7348 16// G, D, A, Group Policy ID from https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 17// 0 1 2 3 18// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 19// 0 8 16 24 32 20// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 21// |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R| Group Policy ID | 22// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 23// | 24 bit VXLAN Network Identifier | Reserved | 24// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 26// VXLAN is a VXLAN packet header 27type VXLAN struct { 28 BaseLayer 29 ValidIDFlag bool // 'I' bit per RFC 7348 30 VNI uint32 // 'VXLAN Network Identifier' 24 bits per RFC 7348 31 GBPExtension bool // 'G' bit per Group Policy https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 32 GBPDontLearn bool // 'D' bit per Group Policy 33 GBPApplied bool // 'A' bit per Group Policy 34 GBPGroupPolicyID uint16 // 'Group Policy ID' 16 bits per Group Policy 35} 36 37// LayerType returns LayerTypeVXLAN 38func (vx *VXLAN) LayerType() gopacket.LayerType { return LayerTypeVXLAN } 39 40func decodeVXLAN(data []byte, p gopacket.PacketBuilder) error { 41 vx := &VXLAN{} 42 43 // VNI is a 24bit number, Uint32 requires 32 bits 44 var buf [4]byte 45 copy(buf[1:], data[4:7]) 46 47 // RFC 7348 https://tools.ietf.org/html/rfc7348 48 vx.ValidIDFlag = data[0]&0x08 > 0 // 'I' bit per RFC7348 49 vx.VNI = binary.BigEndian.Uint32(buf[:]) // VXLAN Network Identifier per RFC7348 50 51 // Group Based Policy https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 52 vx.GBPExtension = data[0]&0x80 > 0 // 'G' bit per the group policy draft 53 vx.GBPDontLearn = data[1]&0x40 > 0 // 'D' bit - the egress VTEP MUST NOT learn the source address of the encapsulated frame. 54 vx.GBPApplied = data[1]&0x80 > 0 // 'A' bit - indicates that the group policy has already been applied to this packet. 55 vx.GBPGroupPolicyID = binary.BigEndian.Uint16(data[2:4]) // Policy ID as per the group policy draft 56 57 // Layer information 58 const vxlanLength = 8 59 vx.Contents = data[:vxlanLength] 60 vx.Payload = data[vxlanLength:] 61 62 p.AddLayer(vx) 63 return p.NextDecoder(LinkTypeEthernet) 64} 65 66// SerializeTo writes the serialized form of this layer into the 67// SerializationBuffer, implementing gopacket.SerializableLayer. 68// See the docs for gopacket.SerializableLayer for more info. 69func (vx *VXLAN) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 70 bytes, err := b.PrependBytes(8) 71 if err != nil { 72 return err 73 } 74 75 // PrependBytes does not guarantee that bytes are zeroed. Setting flags via OR requires that they start off at zero 76 bytes[0] = 0 77 bytes[1] = 0 78 79 if vx.ValidIDFlag { 80 bytes[0] |= 0x08 81 } 82 if vx.GBPExtension { 83 bytes[0] |= 0x80 84 } 85 if vx.GBPDontLearn { 86 bytes[1] |= 0x40 87 } 88 if vx.GBPApplied { 89 bytes[1] |= 0x80 90 } 91 92 binary.BigEndian.PutUint16(bytes[2:4], vx.GBPGroupPolicyID) 93 if vx.VNI >= 1<<24 { 94 return fmt.Errorf("Virtual Network Identifier = %x exceeds max for 24-bit uint", vx.VNI) 95 } 96 binary.BigEndian.PutUint32(bytes[4:8], vx.VNI<<8) 97 return nil 98} 99