[VOL-1349] EPON OLT adapter (package B)

Change-Id: I634ef62c53813dcf4456f54948f13e06358e263c
diff --git a/vendor/github.com/google/gopacket/layers/modbustcp.go b/vendor/github.com/google/gopacket/layers/modbustcp.go
new file mode 100644
index 0000000..bafbd74
--- /dev/null
+++ b/vendor/github.com/google/gopacket/layers/modbustcp.go
@@ -0,0 +1,150 @@
+// Copyright 2018, The GoPacket Authors, All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree.
+//
+//******************************************************************************
+
+package layers
+
+import (
+	"encoding/binary"
+	"errors"
+	"github.com/google/gopacket"
+)
+
+//******************************************************************************
+//
+// ModbusTCP Decoding Layer
+// ------------------------------------------
+// This file provides a GoPacket decoding layer for ModbusTCP.
+//
+//******************************************************************************
+
+const mbapRecordSizeInBytes int = 7
+const modbusPDUMinimumRecordSizeInBytes int = 2
+const modbusPDUMaximumRecordSizeInBytes int = 253
+
+// ModbusProtocol type
+type ModbusProtocol uint16
+
+// ModbusProtocol known values.
+const (
+	ModbusProtocolModbus ModbusProtocol = 0
+)
+
+func (mp ModbusProtocol) String() string {
+	switch mp {
+	default:
+		return "Unknown"
+	case ModbusProtocolModbus:
+		return "Modbus"
+	}
+}
+
+//******************************************************************************
+
+// ModbusTCP Type
+// --------
+// Type ModbusTCP implements the DecodingLayer interface. Each ModbusTCP object
+// represents in a structured form the MODBUS Application Protocol header (MBAP) record present as the TCP
+// payload in an ModbusTCP TCP packet.
+//
+type ModbusTCP struct {
+	BaseLayer // Stores the packet bytes and payload (Modbus PDU) bytes .
+
+	TransactionIdentifier uint16         // Identification of a MODBUS Request/Response transaction
+	ProtocolIdentifier    ModbusProtocol // It is used for intra-system multiplexing
+	Length                uint16         // Number of following bytes (includes 1 byte for UnitIdentifier + Modbus data length
+	UnitIdentifier        uint8          // Identification of a remote slave connected on a serial line or on other buses
+}
+
+//******************************************************************************
+
+// LayerType returns the layer type of the ModbusTCP object, which is LayerTypeModbusTCP.
+func (d *ModbusTCP) LayerType() gopacket.LayerType {
+	return LayerTypeModbusTCP
+}
+
+//******************************************************************************
+
+// decodeModbusTCP analyses a byte slice and attempts to decode it as an ModbusTCP
+// record of a TCP packet.
+//
+// If it succeeds, it loads p with information about the packet and returns nil.
+// If it fails, it returns an error (non nil).
+//
+// This function is employed in layertypes.go to register the ModbusTCP layer.
+func decodeModbusTCP(data []byte, p gopacket.PacketBuilder) error {
+
+	// Attempt to decode the byte slice.
+	d := &ModbusTCP{}
+	err := d.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	// If the decoding worked, add the layer to the packet and set it
+	// as the application layer too, if there isn't already one.
+	p.AddLayer(d)
+	p.SetApplicationLayer(d)
+
+	return p.NextDecoder(d.NextLayerType())
+
+}
+
+//******************************************************************************
+
+// DecodeFromBytes analyses a byte slice and attempts to decode it as an ModbusTCP
+// record of a TCP packet.
+//
+// Upon succeeds, it loads the ModbusTCP object with information about the packet
+// and returns nil.
+// Upon failure, it returns an error (non nil).
+func (d *ModbusTCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
+
+	// If the data block is too short to be a MBAP record, then return an error.
+	if len(data) < mbapRecordSizeInBytes+modbusPDUMinimumRecordSizeInBytes {
+		df.SetTruncated()
+		return errors.New("ModbusTCP packet too short")
+	}
+
+	if len(data) > mbapRecordSizeInBytes+modbusPDUMaximumRecordSizeInBytes {
+		df.SetTruncated()
+		return errors.New("ModbusTCP packet too long")
+	}
+
+	// ModbusTCP type embeds type BaseLayer which contains two fields:
+	//    Contents is supposed to contain the bytes of the data at this level (MPBA).
+	//    Payload is supposed to contain the payload of this level (PDU).
+	d.BaseLayer = BaseLayer{Contents: data[:mbapRecordSizeInBytes], Payload: data[mbapRecordSizeInBytes:len(data)]}
+
+	// Extract the fields from the block of bytes.
+	// The fields can just be copied in big endian order.
+	d.TransactionIdentifier = binary.BigEndian.Uint16(data[:2])
+	d.ProtocolIdentifier = ModbusProtocol(binary.BigEndian.Uint16(data[2:4]))
+	d.Length = binary.BigEndian.Uint16(data[4:6])
+
+	// Length should have the size of the payload plus one byte (size of UnitIdentifier)
+	if d.Length != uint16(len(d.BaseLayer.Payload)+1) {
+		df.SetTruncated()
+		return errors.New("ModbusTCP packet with wrong field value (Length)")
+	}
+	d.UnitIdentifier = uint8(data[6])
+
+	return nil
+}
+
+//******************************************************************************
+
+// NextLayerType returns the layer type of the ModbusTCP payload, which is LayerTypePayload.
+func (d *ModbusTCP) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+//******************************************************************************
+
+// Payload returns Modbus Protocol Data Unit (PDU) composed by Function Code and Data, it is carried within ModbusTCP packets
+func (d *ModbusTCP) Payload() []byte {
+	return d.BaseLayer.Payload
+}