blob: e479cd81f3ec86b2bb1e69cf506b6aa574449f89 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// 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 "errors"
12 "fmt"
13
14 "github.com/google/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
29type 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
40func (vx *VXLAN) LayerType() gopacket.LayerType { return LayerTypeVXLAN }
41
42// CanDecode returns the layer type this DecodingLayer can decode
43func (vx *VXLAN) CanDecode() gopacket.LayerClass {
44 return LayerTypeVXLAN
45}
46
47// NextLayerType retuns the next layer we should see after vxlan
48func (vx *VXLAN) NextLayerType() gopacket.LayerType {
49 return LayerTypeEthernet
50}
51
52// DecodeFromBytes takes a byte buffer and decodes
53func (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
80func 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.
94func (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}