github.com/gopacket/gopacket@v1.1.0/layers/geneve.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 // Geneve is specifed here https://tools.ietf.org/html/draft-ietf-nvo3-geneve-03 18 // Geneve Header: 19 // 20 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 21 // |Ver| Opt Len |O|C| Rsvd. | Protocol Type | 22 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 23 // | Virtual Network Identifier (VNI) | Reserved | 24 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25 // | Variable Length Options | 26 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 27 type Geneve struct { 28 BaseLayer 29 Version uint8 // 2 bits 30 OptionsLength uint8 // 6 bits 31 OAMPacket bool // 1 bits 32 CriticalOption bool // 1 bits 33 Protocol EthernetType // 16 bits 34 VNI uint32 // 24bits 35 Options []*GeneveOption 36 } 37 38 // Geneve Tunnel Options 39 // 40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 41 // | Option Class | Type |R|R|R| Length | 42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43 // | Variable Option Data | 44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45 type GeneveOption struct { 46 Class uint16 // 16 bits 47 Type uint8 // 8 bits 48 Flags uint8 // 3 bits 49 Length uint8 // 5 bits 50 Data []byte 51 } 52 53 // LayerType returns LayerTypeGeneve 54 func (gn *Geneve) LayerType() gopacket.LayerType { return LayerTypeGeneve } 55 56 func decodeGeneveOption(data []byte, gn *Geneve, df gopacket.DecodeFeedback) (*GeneveOption, uint8, error) { 57 if len(data) < 3 { 58 df.SetTruncated() 59 return nil, 0, errors.New("geneve option too small") 60 } 61 opt := &GeneveOption{} 62 63 opt.Class = binary.BigEndian.Uint16(data[0:2]) 64 opt.Type = data[2] 65 opt.Flags = data[3] >> 4 66 opt.Length = (data[3]&0xf)*4 + 4 67 68 if len(data) < int(opt.Length) { 69 df.SetTruncated() 70 return nil, 0, errors.New("geneve option too small") 71 } 72 opt.Data = make([]byte, opt.Length-4) 73 copy(opt.Data, data[4:opt.Length]) 74 75 return opt, opt.Length, nil 76 } 77 78 func (gn *Geneve) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 79 if len(data) < 7 { 80 df.SetTruncated() 81 return errors.New("geneve packet too short") 82 } 83 84 gn.Version = data[0] >> 7 85 gn.OptionsLength = (data[0] & 0x3f) * 4 86 87 gn.OAMPacket = data[1]&0x80 > 0 88 gn.CriticalOption = data[1]&0x40 > 0 89 gn.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4])) 90 91 var buf [4]byte 92 copy(buf[1:], data[4:7]) 93 gn.VNI = binary.BigEndian.Uint32(buf[:]) 94 95 offset, length := uint8(8), int32(gn.OptionsLength) 96 if len(data) < int(length+7) { 97 df.SetTruncated() 98 return errors.New("geneve packet too short") 99 } 100 101 for length > 0 { 102 opt, len, err := decodeGeneveOption(data[offset:], gn, df) 103 if err != nil { 104 return err 105 } 106 gn.Options = append(gn.Options, opt) 107 108 length -= int32(len) 109 offset += len 110 } 111 112 gn.BaseLayer = BaseLayer{data[:offset], data[offset:]} 113 114 return nil 115 } 116 117 func (gn *Geneve) NextLayerType() gopacket.LayerType { 118 return gn.Protocol.LayerType() 119 } 120 121 func decodeGeneve(data []byte, p gopacket.PacketBuilder) error { 122 gn := &Geneve{} 123 return decodingLayerDecoder(gn, data, p) 124 } 125 126 // SerializeTo writes the serialized form of this layer into the 127 // SerializationBuffer, implementing gopacket.SerializableLayer. 128 // See the docs for gopacket.SerializableLayer for more info. 129 func (gn *Geneve) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 130 var optionsLength int 131 for _, o := range gn.Options { 132 dataLen := len(o.Data) & ^3 133 optionsLength += 4 + dataLen 134 } 135 if opts.FixLengths { 136 gn.OptionsLength = uint8(optionsLength) 137 } 138 139 plen := int(8 + optionsLength) 140 bytes, err := b.PrependBytes(plen) 141 if err != nil { 142 return err 143 } 144 145 // PrependBytes does not guarantee that bytes are zeroed. Setting flags via OR requires that they start off at zero 146 bytes[0] = 0 147 bytes[1] = 0 148 149 // Construct Geneve 150 151 bytes[0] |= gn.Version << 6 152 bytes[0] |= ((gn.OptionsLength >> 2) & 0x3f) 153 154 if gn.OAMPacket { 155 bytes[1] |= 0x80 156 } 157 158 if gn.CriticalOption { 159 bytes[1] |= 0x40 160 } 161 162 binary.BigEndian.PutUint16(bytes[2:4], uint16(gn.Protocol)) 163 164 if gn.VNI >= 1<<24 { 165 return fmt.Errorf("Virtual Network Identifier = %x exceeds max for 24-bit uint", gn.VNI) 166 } 167 binary.BigEndian.PutUint32(bytes[4:8], gn.VNI<<8) 168 169 // Construct Options 170 171 offset := 8 172 for _, o := range gn.Options { 173 dataLen := len(o.Data) & ^3 174 if opts.FixLengths { 175 o.Length = uint8(4 + dataLen) 176 } 177 178 binary.BigEndian.PutUint16(bytes[offset:(offset+2)], uint16(o.Class)) 179 180 offset += 2 181 bytes[offset] = o.Type 182 183 offset += 1 184 bytes[offset] |= o.Flags << 5 185 bytes[offset] |= ((o.Length - 4) >> 2) & 0x1f 186 187 offset += 1 188 copy(bytes[offset:(offset+dataLen)], o.Data) 189 190 offset += dataLen 191 } 192 193 return nil 194 }