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  }