blob: e9a1428809abdc5717a9b41011f3babde234e59b [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
13 "github.com/google/gopacket"
14)
15
16// Geneve is specifed here https://tools.ietf.org/html/draft-ietf-nvo3-geneve-03
17// Geneve Header:
18// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19// |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
20// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21// | Virtual Network Identifier (VNI) | Reserved |
22// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23// | Variable Length Options |
24// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25type Geneve struct {
26 BaseLayer
27 Version uint8 // 2 bits
28 OptionsLength uint8 // 6 bits
29 OAMPacket bool // 1 bits
30 CriticalOption bool // 1 bits
31 Protocol EthernetType // 16 bits
32 VNI uint32 // 24bits
33 Options []*GeneveOption
34}
35
36// Geneve Tunnel Options
37// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38// | Option Class | Type |R|R|R| Length |
39// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40// | Variable Option Data |
41// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42type GeneveOption struct {
43 Class uint16 // 16 bits
44 Type uint8 // 8 bits
45 Flags uint8 // 3 bits
46 Length uint8 // 5 bits
47 Data []byte
48}
49
50// LayerType returns LayerTypeGeneve
51func (gn *Geneve) LayerType() gopacket.LayerType { return LayerTypeGeneve }
52
53func decodeGeneveOption(data []byte, gn *Geneve, df gopacket.DecodeFeedback) (*GeneveOption, uint8, error) {
54 if len(data) < 3 {
55 df.SetTruncated()
56 return nil, 0, errors.New("geneve option too small")
57 }
58 opt := &GeneveOption{}
59
60 opt.Class = binary.BigEndian.Uint16(data[0:2])
61 opt.Type = data[2]
62 opt.Flags = data[3] >> 4
63 opt.Length = (data[3]&0xf)*4 + 4
64
65 if len(data) < int(opt.Length) {
66 df.SetTruncated()
67 return nil, 0, errors.New("geneve option too small")
68 }
69 opt.Data = make([]byte, opt.Length-4)
70 copy(opt.Data, data[4:opt.Length])
71
72 return opt, opt.Length, nil
73}
74
75func (gn *Geneve) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
76 if len(data) < 7 {
77 df.SetTruncated()
78 return errors.New("geneve packet too short")
79 }
80
81 gn.Version = data[0] >> 7
82 gn.OptionsLength = (data[0] & 0x3f) * 4
83
84 gn.OAMPacket = data[1]&0x80 > 0
85 gn.CriticalOption = data[1]&0x40 > 0
86 gn.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4]))
87
88 var buf [4]byte
89 copy(buf[1:], data[4:7])
90 gn.VNI = binary.BigEndian.Uint32(buf[:])
91
92 offset, length := uint8(8), int32(gn.OptionsLength)
93 if len(data) < int(length+7) {
94 df.SetTruncated()
95 return errors.New("geneve packet too short")
96 }
97
98 for length > 0 {
99 opt, len, err := decodeGeneveOption(data[offset:], gn, df)
100 if err != nil {
101 return err
102 }
103 gn.Options = append(gn.Options, opt)
104
105 length -= int32(len)
106 offset += len
107 }
108
109 gn.BaseLayer = BaseLayer{data[:offset], data[offset:]}
110
111 return nil
112}
113
114func (gn *Geneve) NextLayerType() gopacket.LayerType {
115 return gn.Protocol.LayerType()
116}
117
118func decodeGeneve(data []byte, p gopacket.PacketBuilder) error {
119 gn := &Geneve{}
120 return decodingLayerDecoder(gn, data, p)
121}