github.com/gopacket/gopacket@v1.1.0/layers/vxlan.go (about) 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 7 package layers 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 14 "github.com/gopacket/gopacket" 15 ) 16 17 // VXLAN is specifed in RFC 7348 https://tools.ietf.org/html/rfc7348 18 // G, D, A, Group Policy ID from https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 19 // 0 1 2 3 20 // 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 21 // 0 8 16 24 32 22 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 23 // |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R| Group Policy ID | 24 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 // | 24 bit VXLAN Network Identifier | Reserved | 26 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 27 28 // VXLAN is a VXLAN packet header 29 type VXLAN struct { 30 BaseLayer 31 ValidIDFlag bool // 'I' bit per RFC 7348 32 VNI uint32 // 'VXLAN Network Identifier' 24 bits per RFC 7348 33 GBPExtension bool // 'G' bit per Group Policy https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 34 GBPDontLearn bool // 'D' bit per Group Policy 35 GBPApplied bool // 'A' bit per Group Policy 36 GBPGroupPolicyID uint16 // 'Group Policy ID' 16 bits per Group Policy 37 } 38 39 // LayerType returns LayerTypeVXLAN 40 func (vx *VXLAN) LayerType() gopacket.LayerType { return LayerTypeVXLAN } 41 42 // CanDecode returns the layer type this DecodingLayer can decode 43 func (vx *VXLAN) CanDecode() gopacket.LayerClass { 44 return LayerTypeVXLAN 45 } 46 47 // NextLayerType retuns the next layer we should see after vxlan 48 func (vx *VXLAN) NextLayerType() gopacket.LayerType { 49 return LayerTypeEthernet 50 } 51 52 // DecodeFromBytes takes a byte buffer and decodes 53 func (vx *VXLAN) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 54 if len(data) < 8 { 55 return errors.New("vxlan packet too small") 56 } 57 // VNI is a 24bit number, Uint32 requires 32 bits 58 var buf [4]byte 59 copy(buf[1:], data[4:7]) 60 61 // RFC 7348 https://tools.ietf.org/html/rfc7348 62 vx.ValidIDFlag = data[0]&0x08 > 0 // 'I' bit per RFC7348 63 vx.VNI = binary.BigEndian.Uint32(buf[:]) // VXLAN Network Identifier per RFC7348 64 65 // Group Based Policy https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 66 vx.GBPExtension = data[0]&0x80 > 0 // 'G' bit per the group policy draft 67 vx.GBPDontLearn = data[1]&0x40 > 0 // 'D' bit - the egress VTEP MUST NOT learn the source address of the encapsulated frame. 68 vx.GBPApplied = data[1]&0x80 > 0 // 'A' bit - indicates that the group policy has already been applied to this packet. 69 vx.GBPGroupPolicyID = binary.BigEndian.Uint16(data[2:4]) // Policy ID as per the group policy draft 70 71 // Layer information 72 const vxlanLength = 8 73 vx.Contents = data[:vxlanLength] 74 vx.Payload = data[vxlanLength:] 75 76 return nil 77 78 } 79 80 func decodeVXLAN(data []byte, p gopacket.PacketBuilder) error { 81 vx := &VXLAN{} 82 err := vx.DecodeFromBytes(data, p) 83 if err != nil { 84 return err 85 } 86 87 p.AddLayer(vx) 88 return p.NextDecoder(LinkTypeEthernet) 89 } 90 91 // SerializeTo writes the serialized form of this layer into the 92 // SerializationBuffer, implementing gopacket.SerializableLayer. 93 // See the docs for gopacket.SerializableLayer for more info. 94 func (vx *VXLAN) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 95 bytes, err := b.PrependBytes(8) 96 if err != nil { 97 return err 98 } 99 100 // PrependBytes does not guarantee that bytes are zeroed. Setting flags via OR requires that they start off at zero 101 bytes[0] = 0 102 bytes[1] = 0 103 104 if vx.ValidIDFlag { 105 bytes[0] |= 0x08 106 } 107 if vx.GBPExtension { 108 bytes[0] |= 0x80 109 } 110 if vx.GBPDontLearn { 111 bytes[1] |= 0x40 112 } 113 if vx.GBPApplied { 114 bytes[1] |= 0x80 115 } 116 117 binary.BigEndian.PutUint16(bytes[2:4], vx.GBPGroupPolicyID) 118 if vx.VNI >= 1<<24 { 119 return fmt.Errorf("Virtual Network Identifier = %x exceeds max for 24-bit uint", vx.VNI) 120 } 121 binary.BigEndian.PutUint32(bytes[4:8], vx.VNI<<8) 122 return nil 123 }