vxlan.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. package layers
  7. import (
  8. "encoding/binary"
  9. "errors"
  10. "fmt"
  11. "github.com/google/gopacket"
  12. )
  13. // VXLAN is specifed in RFC 7348 https://tools.ietf.org/html/rfc7348
  14. // G, D, A, Group Policy ID from https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00
  15. // 0 1 2 3
  16. // 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
  17. // 0 8 16 24 32
  18. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  19. // |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R| Group Policy ID |
  20. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  21. // | 24 bit VXLAN Network Identifier | Reserved |
  22. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  23. // VXLAN is a VXLAN packet header
  24. type VXLAN struct {
  25. BaseLayer
  26. ValidIDFlag bool // 'I' bit per RFC 7348
  27. VNI uint32 // 'VXLAN Network Identifier' 24 bits per RFC 7348
  28. GBPExtension bool // 'G' bit per Group Policy https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00
  29. GBPDontLearn bool // 'D' bit per Group Policy
  30. GBPApplied bool // 'A' bit per Group Policy
  31. GBPGroupPolicyID uint16 // 'Group Policy ID' 16 bits per Group Policy
  32. }
  33. // LayerType returns LayerTypeVXLAN
  34. func (vx *VXLAN) LayerType() gopacket.LayerType { return LayerTypeVXLAN }
  35. // CanDecode returns the layer type this DecodingLayer can decode
  36. func (vx *VXLAN) CanDecode() gopacket.LayerClass {
  37. return LayerTypeVXLAN
  38. }
  39. // NextLayerType retuns the next layer we should see after vxlan
  40. func (vx *VXLAN) NextLayerType() gopacket.LayerType {
  41. return LayerTypeEthernet
  42. }
  43. // DecodeFromBytes takes a byte buffer and decodes
  44. func (vx *VXLAN) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
  45. if len(data) < 8 {
  46. return errors.New("vxlan packet too small")
  47. }
  48. // VNI is a 24bit number, Uint32 requires 32 bits
  49. var buf [4]byte
  50. copy(buf[1:], data[4:7])
  51. // RFC 7348 https://tools.ietf.org/html/rfc7348
  52. vx.ValidIDFlag = data[0]&0x08 > 0 // 'I' bit per RFC7348
  53. vx.VNI = binary.BigEndian.Uint32(buf[:]) // VXLAN Network Identifier per RFC7348
  54. // Group Based Policy https://tools.ietf.org/html/draft-smith-vxlan-group-policy-00
  55. vx.GBPExtension = data[0]&0x80 > 0 // 'G' bit per the group policy draft
  56. vx.GBPDontLearn = data[1]&0x40 > 0 // 'D' bit - the egress VTEP MUST NOT learn the source address of the encapsulated frame.
  57. vx.GBPApplied = data[1]&0x80 > 0 // 'A' bit - indicates that the group policy has already been applied to this packet.
  58. vx.GBPGroupPolicyID = binary.BigEndian.Uint16(data[2:4]) // Policy ID as per the group policy draft
  59. // Layer information
  60. const vxlanLength = 8
  61. vx.Contents = data[:vxlanLength]
  62. vx.Payload = data[vxlanLength:]
  63. return nil
  64. }
  65. func decodeVXLAN(data []byte, p gopacket.PacketBuilder) error {
  66. vx := &VXLAN{}
  67. err := vx.DecodeFromBytes(data, p)
  68. if err != nil {
  69. return err
  70. }
  71. p.AddLayer(vx)
  72. return p.NextDecoder(LinkTypeEthernet)
  73. }
  74. // SerializeTo writes the serialized form of this layer into the
  75. // SerializationBuffer, implementing gopacket.SerializableLayer.
  76. // See the docs for gopacket.SerializableLayer for more info.
  77. func (vx *VXLAN) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
  78. bytes, err := b.PrependBytes(8)
  79. if err != nil {
  80. return err
  81. }
  82. // PrependBytes does not guarantee that bytes are zeroed. Setting flags via OR requires that they start off at zero
  83. bytes[0] = 0
  84. bytes[1] = 0
  85. if vx.ValidIDFlag {
  86. bytes[0] |= 0x08
  87. }
  88. if vx.GBPExtension {
  89. bytes[0] |= 0x80
  90. }
  91. if vx.GBPDontLearn {
  92. bytes[1] |= 0x40
  93. }
  94. if vx.GBPApplied {
  95. bytes[1] |= 0x80
  96. }
  97. binary.BigEndian.PutUint16(bytes[2:4], vx.GBPGroupPolicyID)
  98. if vx.VNI >= 1<<24 {
  99. return fmt.Errorf("Virtual Network Identifier = %x exceeds max for 24-bit uint", vx.VNI)
  100. }
  101. binary.BigEndian.PutUint32(bytes[4:8], vx.VNI<<8)
  102. return nil
  103. }