blob: 4f79ea4eae081533122ba750d83e509914806ace [file] [log] [blame]
Takahiro Suzuki241c10e2020-12-17 20:17:57 +09001// 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}