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

Change-Id: I634ef62c53813dcf4456f54948f13e06358e263c
diff --git a/internal/pkg/core/l2oam/msg_discovery.go b/internal/pkg/core/l2oam/msg_discovery.go
new file mode 100644
index 0000000..ab104bc
--- /dev/null
+++ b/internal/pkg/core/l2oam/msg_discovery.go
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package l2oam
+
+import (
+	"encoding/binary"
+	"encoding/hex"
+	"fmt"
+
+	"github.com/google/gopacket"
+	"github.com/google/gopacket/layers"
+)
+
+// GenerateDiscoverySOLICIT generates "Discovery: SOLICIT" message
+func GenerateDiscoverySOLICIT() gopacket.SerializableLayer {
+
+	tibitData := &DiscoverySolicit{
+		// IEEE 1904.2
+		Opcode:        0xfd,
+		DiscoveryType: 0x01,
+		// Vendor-specific
+		VendorType: 0xfe,
+		Length:     37,
+		// Vendor ID
+		VendorIDType:   0xfd,
+		VendorIDLength: 3,
+		VendorID:       []byte{0x2a, 0xea, 0x15},
+		// Controller Priority
+		CPType:   0x05,
+		CPLength: 1,
+		CPValue:  []byte{128},
+		//NetworkID
+		NWType:   0x06,
+		NWLength: 16,
+		NWValue:  []byte("tibitcom.com"),
+		//Device Type
+		DVType:   0x07,
+		DVLength: 1,
+		DVValue:  []byte{1},
+		//Supported CLient Protocols
+		SCPType:   0x08,
+		SCPLength: 1,
+		SCPValue:  []byte{0x03},
+		//Padding
+		PadType:   0xff,
+		PadLength: 1,
+		PadValue:  []byte{0},
+	}
+
+	return tibitData
+}
+
+// DiscoverySolicit is a structure for Discovery message
+type DiscoverySolicit struct {
+	layers.BaseLayer
+	Opcode        uint8
+	DiscoveryType uint8
+	VendorType uint8
+	Length     uint16 // length of after this data without Padding
+	VendorIDType   uint8
+	VendorIDLength uint16
+	VendorID       []byte
+	CPType   uint8
+	CPLength uint16
+	CPValue  []byte
+	NWType   uint8
+	NWLength uint16
+	NWValue  []byte
+	DVType   uint8
+	DVLength uint16
+	DVValue  []byte
+	SCPType   uint8
+	SCPLength uint16
+	SCPValue  []byte
+	PadType   uint8
+	PadLength uint16
+	PadValue  []byte
+}
+
+// String returns the string expression of DiscoverySolicit
+func (d *DiscoverySolicit) String() string {
+	message := fmt.Sprintf("Opcode:%v, DiscoveryType:%v, VendorType:%v, Length:%v", d.Opcode, d.DiscoveryType, d.VendorType, d.Length)
+	message = fmt.Sprintf("%s, VendorIDType:%v, VendorIDLength:%v, VendorID:%v", message, d.VendorIDType, d.VendorIDLength, hex.EncodeToString(d.VendorID))
+	message = fmt.Sprintf("%s, CPType:%v, CPLength:%v, CPValue:%v", message, d.CPType, d.CPLength, hex.EncodeToString(d.CPValue))
+	message = fmt.Sprintf("%s, NWType:%v, NWLength:%v, NWValue:%v", message, d.NWType, d.NWLength, hex.EncodeToString(d.NWValue))
+	message = fmt.Sprintf("%s, DVType:%v, DVLength:%v, DVValue:%v", message, d.DVType, d.DVLength, hex.EncodeToString(d.DVValue))
+	message = fmt.Sprintf("%s, SCPType:%v, SCPLength:%v, SCPValue:%v", message, d.SCPType, d.SCPLength, hex.EncodeToString(d.SCPValue))
+	return message
+}
+
+// Len returns the length of DiscoverySolicit
+func (d *DiscoverySolicit) Len() int {
+	len := (2) + (3) + int(d.Length) + (int(d.PadLength) + 3)
+	return len
+}
+
+// LayerType returns the ethernet type of DiscoverySolicit
+func (d *DiscoverySolicit) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
+
+// SerializeTo serializes a data structure to byte arrays
+func (d *DiscoverySolicit) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	plen := int(d.Len())
+	data, err := b.PrependBytes(plen)
+	if err != nil {
+		return err
+	}
+
+	i := 0
+	data[i] = byte(d.Opcode)
+	i++
+	data[i] = byte(d.DiscoveryType)
+	i++
+	data[i] = byte(d.VendorType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.Length)
+	i = i + 2
+
+	data[i] = byte(d.VendorIDType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.VendorIDLength)
+	i = i + 2
+	copy(data[i:i+int(d.VendorIDLength)], d.VendorID)
+	i = i + int(d.VendorIDLength)
+
+	data[i] = byte(d.CPType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.CPLength)
+	i = i + 2
+	copy(data[i:i+int(d.CPLength)], d.CPValue)
+	i = i + int(d.CPLength)
+
+	data[i] = byte(d.NWType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.NWLength)
+	i = i + 2
+	copy(data[i:i+int(d.NWLength)], d.NWValue)
+	i = i + int(d.NWLength)
+
+	data[i] = byte(d.DVType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.DVLength)
+	i = i + 2
+	copy(data[i:i+int(d.DVLength)], d.DVValue)
+	i = i + int(d.DVLength)
+
+	data[i] = byte(d.SCPType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.SCPLength)
+	i = i + 2
+	copy(data[i:i+int(d.SCPLength)], d.SCPValue)
+	i = i + int(d.SCPLength)
+
+	data[i] = byte(d.PadType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.PadLength)
+	i = i + 2
+	copy(data[i:i+int(d.PadLength)], d.PadValue)
+
+	return nil
+}
+
+// Decode decodes byte arrays to a data structure
+func (d *DiscoverySolicit) Decode(data []byte) error {
+	i := 0
+	d.Opcode = data[i]
+	i++
+	d.DiscoveryType = data[i]
+	i++
+	d.VendorType = data[i]
+	i++
+	d.Length = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+
+	d.VendorIDType = data[i]
+	i++
+	d.VendorIDLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.VendorID = data[i : i+int(d.VendorIDLength)]
+	i = i + int(d.VendorIDLength)
+
+	d.CPType = data[i]
+	i++
+	d.CPLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.CPValue = data[i : i+int(d.CPLength)]
+	i = i + int(d.CPLength)
+
+	d.NWType = data[i]
+	i++
+	d.NWLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.NWValue = data[i : i+int(d.NWLength)]
+	i = i + int(d.NWLength)
+
+	d.DVType = data[i]
+	i++
+	d.DVLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.DVValue = data[i : i+int(d.DVLength)]
+	i = i + int(d.DVLength)
+
+	d.SCPType = data[i]
+	i++
+	d.SCPLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.SCPValue = data[i : i+int(d.SCPLength)]
+	i = i + int(d.SCPLength)
+
+	d.PadType = data[i]
+	i++
+	d.PadLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.PadValue = data[i : i+int(d.PadLength)]
+
+	return nil
+}
+
+// DiscoveryHello is a structure for Discovery message
+type DiscoveryHello struct {
+	layers.BaseLayer
+	Opcode        uint8
+	DiscoveryType uint8
+	VendorType uint8
+	Length     uint16 // length of after this data without Padding
+	VendorIDType   uint8
+	VendorIDLength uint16
+	VendorID       []byte
+	NWType   uint8
+	NWLength uint16
+	NWValue  []byte
+	DVType   uint8
+	DVLength uint16
+	DVValue  []byte
+	SCPType   uint8
+	SCPLength uint16
+	SCPValue  []byte
+	TunnelType   uint8
+	TunnelLength uint16
+	TunnelValue  []byte
+	PadType   uint8
+	PadLength uint16
+	PadValue  []byte
+}
+
+// String returns the string expression of DiscoveryHello
+func (d *DiscoveryHello) String() string {
+	message := fmt.Sprintf("Opcode:%v, DiscoveryType:%v, VendorType:%v, Length:%v", d.Opcode, d.DiscoveryType, d.VendorType, d.Length)
+	message = fmt.Sprintf("%s, VendorIDType:%v, VendorIDLength:%v, VendorID:%v", message, d.VendorIDType, d.VendorIDLength, hex.EncodeToString(d.VendorID))
+	message = fmt.Sprintf("%s, NWType:%v, NWLength:%v, NWValue:%v", message, d.NWType, d.NWLength, hex.EncodeToString(d.NWValue))
+	message = fmt.Sprintf("%s, DVType:%v, DVLength:%v, DVValue:%v", message, d.DVType, d.DVLength, hex.EncodeToString(d.DVValue))
+	message = fmt.Sprintf("%s, SCPType:%v, SCPLength:%v, SCPValue:%v", message, d.SCPType, d.SCPLength, hex.EncodeToString(d.SCPValue))
+	message = fmt.Sprintf("%s, TunnelType:%v, TunnelLength:%v, TunnelValue:%v", message, d.TunnelType, d.TunnelLength, hex.EncodeToString(d.TunnelValue))
+	message = fmt.Sprintf("%s, PadType:%v, PadLength:%v, PadValue:%v", message, d.PadType, d.PadLength, hex.EncodeToString(d.PadValue))
+	return message
+}
+
+// Len returns the length of DiscoveryHello
+func (d *DiscoveryHello) Len() int {
+	len := (2) + (3) + int(d.Length) + (int(d.PadLength) + 3)
+	return len
+}
+
+// LayerType returns the ethernet type of DiscoveryHello
+func (d *DiscoveryHello) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
+
+// SerializeTo serializes a data structure to byte arrays
+func (d *DiscoveryHello) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	plen := int(d.Len())
+	data, err := b.PrependBytes(plen)
+	if err != nil {
+		return err
+	}
+
+	i := 0
+	data[i] = byte(d.Opcode)
+	i++
+	data[i] = byte(d.DiscoveryType)
+	i++
+	data[i] = byte(d.VendorType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.Length)
+	i = i + 2
+
+	data[i] = byte(d.VendorIDType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.VendorIDLength)
+	i = i + 2
+	copy(data[i:i+int(d.VendorIDLength)], d.VendorID)
+	i = i + int(d.VendorIDLength)
+
+	data[i] = byte(d.NWType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.NWLength)
+	i = i + 2
+	copy(data[i:i+int(d.NWLength)], d.NWValue)
+	i = i + int(d.NWLength)
+
+	data[i] = byte(d.DVType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.DVLength)
+	i = i + 2
+	copy(data[i:i+int(d.DVLength)], d.DVValue)
+	i = i + int(d.DVLength)
+
+	data[i] = byte(d.SCPType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.SCPLength)
+	i = i + 2
+	copy(data[i:i+int(d.SCPLength)], d.SCPValue)
+	i = i + int(d.SCPLength)
+
+	data[i] = byte(d.TunnelType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.TunnelLength)
+	i = i + 2
+	copy(data[i:i+int(d.TunnelLength)], d.TunnelValue)
+	i = i + int(d.TunnelLength)
+
+	data[i] = byte(d.PadType)
+	i++
+	binary.BigEndian.PutUint16(data[i:i+2], d.PadLength)
+	i = i + 2
+	copy(data[i:i+int(d.PadLength)], d.PadValue)
+
+	return nil
+}
+
+// Decode decodes byte arrays to a data structure
+func (d *DiscoveryHello) Decode(data []byte) error {
+	i := 0
+	d.Opcode = data[i]
+	i++
+	d.DiscoveryType = data[i]
+	i++
+	d.VendorType = data[i]
+	i++
+	d.Length = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+
+	d.VendorIDType = data[i]
+	i++
+	d.VendorIDLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.VendorID = data[i : i+int(d.VendorIDLength)]
+	i = i + int(d.VendorIDLength)
+
+	d.NWType = data[i]
+	i++
+	d.NWLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.NWValue = data[i : i+int(d.NWLength)]
+	i = i + int(d.NWLength)
+
+	d.DVType = data[i]
+	i++
+	d.DVLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.DVValue = data[i : i+int(d.DVLength)]
+	i = i + int(d.DVLength)
+
+	d.SCPType = data[i]
+	i++
+	d.SCPLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.SCPValue = data[i : i+int(d.SCPLength)]
+	i = i + int(d.SCPLength)
+
+	d.TunnelType = data[i]
+	i++
+	d.TunnelLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.TunnelValue = data[i : i+int(d.TunnelLength)]
+	i = i + int(d.TunnelLength)
+
+	d.PadType = data[i]
+	i++
+	d.PadLength = binary.BigEndian.Uint16(data[i : i+2])
+	i = i + 2
+	d.PadValue = data[i : i+int(d.PadLength)]
+
+	return nil
+}