[VOL-1349] EPON OLT adapter (package B)
Change-Id: I634ef62c53813dcf4456f54948f13e06358e263c
diff --git a/internal/pkg/core/l2oam/msg_oampdu_information.go b/internal/pkg/core/l2oam/msg_oampdu_information.go
new file mode 100644
index 0000000..6d7a9f8
--- /dev/null
+++ b/internal/pkg/core/l2oam/msg_oampdu_information.go
@@ -0,0 +1,263 @@
+/*
+ * 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"
+)
+
+// OampduTlvTypeLocalInfo means that TLV type is "Local Information"
+var OampduTlvTypeLocalInfo uint8 = 0x01
+
+// OampduTlvTypeRemoteInfo means that TLV type is "Remote Information"
+var OampduTlvTypeRemoteInfo uint8 = 0x02
+
+// OampduTlvTypeOrganizationSpecificInfo means that TLV type is "Organization Specific Information"
+var OampduTlvTypeOrganizationSpecificInfo uint8 = 0xfe
+
+// GeneateKeepAlive1 generates "OAMPDU Information(first)"
+func GeneateKeepAlive1(isOnuPkgA bool) gopacket.SerializableLayer {
+ var osiLength uint8
+ var osiValue []byte
+ if isOnuPkgA {
+ osiLength = 7
+ osiValue = []byte{0x00, 0x10, 0x00, 0x00, 0x23}
+ } else {
+ osiLength = 8
+ osiValue = []byte{0x90, 0x82, 0x60, 0x02, 0x01, 0x01}
+ }
+ tibitData := &OAMPDUInformation{
+ // IEEE 1904.2
+ Opcode: 0x03,
+ // OAM Protocol
+ Flags: 0x0008,
+ Code: 0x00,
+ // Local Information TLV
+ LIType: OampduTlvTypeLocalInfo,
+ LILength: 16,
+ LIValue: []byte{0x01, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x2a, 0xea, 0x15, 0x00, 0x00, 0x00, 0x23},
+ // Organization Specific Information TLV
+ OSIType: OampduTlvTypeOrganizationSpecificInfo,
+ OSILength: osiLength,
+ OSIValue: osiValue,
+ }
+
+ return tibitData
+}
+
+// GeneateKeepAlive2 generates "OAMPDU Information(second)"
+func GeneateKeepAlive2(riValue []byte, isOnuPkgA bool) gopacket.SerializableLayer {
+ var osiLength uint8
+ var osiValue []byte
+ if isOnuPkgA {
+ osiLength = 7
+ osiValue = []byte{0x00, 0x10, 0x00, 0x00, 0x23}
+ } else {
+ osiLength = 8
+ osiValue = []byte{0x90, 0x82, 0x60, 0x02, 0x01, 0x01}
+ }
+ tibitData := &OAMPDUInformation{
+ // IEEE 1904.2
+ Opcode: 0x03,
+ // OAM Protocol
+ Flags: 0x0030,
+ Code: 0x00,
+ // Local Information TLV
+ LIType: OampduTlvTypeLocalInfo,
+ LILength: 16,
+ LIValue: []byte{0x01, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x2a, 0xea, 0x15, 0x00, 0x00, 0x00, 0x23},
+ // Remote Information TLV
+ RIType: OampduTlvTypeRemoteInfo,
+ RILength: 16,
+ RIValue: riValue,
+ // Organization Specific Information TLV
+ OSIType: OampduTlvTypeOrganizationSpecificInfo,
+ OSILength: osiLength,
+ OSIValue: osiValue,
+ }
+
+ return tibitData
+
+}
+
+// GeneateKeepAlive3 generates "OAMPDU Information(third)"
+func GeneateKeepAlive3(riValue []byte) gopacket.SerializableLayer {
+ tibitData := &OAMPDUInformation{
+ // IEEE 1904.2
+ Opcode: 0x03,
+ // OAM Protocol
+ Flags: 0x0050,
+ Code: 0x00,
+ // Local Information TLV
+ LIType: OampduTlvTypeLocalInfo,
+ LILength: 16,
+ LIValue: []byte{0x01, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x2a, 0xea, 0x15, 0x00, 0x00, 0x00, 0x23},
+ // Remote Information TLV
+ RIType: OampduTlvTypeRemoteInfo,
+ RILength: 16,
+ RIValue: riValue,
+ }
+
+ return tibitData
+
+}
+
+// OAMPDUInformation is a structure for "OAMPDU Information" message
+type OAMPDUInformation struct {
+ layers.BaseLayer
+ Opcode uint8
+ Flags uint16
+ Code uint8
+ LIType uint8
+ LILength uint8
+ LIValue []byte
+ RIType uint8
+ RILength uint8
+ RIValue []byte
+ OSIType uint8
+ OSILength uint8
+ OSIValue []byte
+}
+
+// String returns the string expression of OAMPDUInformation
+func (d *OAMPDUInformation) String() string {
+ message := fmt.Sprintf("Opcode:%v, Flags:%v, Code:%v", d.Opcode, d.Flags, d.Code)
+ message = fmt.Sprintf("%s, LIType:%v, LILength:%v, LIValue:%v", message, d.LIType, d.LILength, hex.EncodeToString(d.LIValue))
+ message = fmt.Sprintf("%s, RIType:%v, RILength:%v, RIValue:%v", message, d.RIType, d.RILength, hex.EncodeToString(d.RIValue))
+ message = fmt.Sprintf("%s, OSIType:%v, OSILength:%v, OSIValue:%v", message, d.OSIType, d.OSILength, hex.EncodeToString(d.OSIValue))
+ return message
+}
+
+// Len returns the length of OAMPDUInformation
+func (d *OAMPDUInformation) Len() int {
+ len := (1) + (3) + int(d.LILength) + int(d.RILength) + int(d.OSILength)
+ return len
+}
+
+// LayerType returns the ethernet type of OAMPDUInformation
+func (d *OAMPDUInformation) LayerType() gopacket.LayerType { return layers.LayerTypeEthernet }
+
+// SerializeTo serializes a data structure to byte arrays
+func (d *OAMPDUInformation) 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++
+ binary.BigEndian.PutUint16(data[i:i+2], d.Flags)
+ i = i + 2
+ data[i] = byte(d.Code)
+ i++
+
+ if d.LILength != 0 {
+ data[i] = byte(d.LIType)
+ data[i+1] = byte(d.LILength)
+ copy(data[i+2:i+int(d.LILength)], d.LIValue)
+ i = i + int(d.LILength)
+ }
+
+ if d.RILength != 0 {
+ data[i] = byte(d.RIType)
+ data[i+1] = byte(d.RILength)
+ copy(data[i+2:i+int(d.RILength)], d.RIValue)
+ i = i + int(d.RILength)
+ }
+
+ if d.OSILength != 0 {
+ data[i] = byte(d.OSIType)
+ data[i+1] = byte(d.OSILength)
+ copy(data[i+2:i+int(d.OSILength)], d.OSIValue)
+ //i = i + int(d.OSILength)
+ }
+
+ return nil
+}
+
+// Decode decodes byte arrays to a data structure
+func (d *OAMPDUInformation) Decode(data []byte) error {
+ i := 0
+ d.Opcode = data[i]
+ i++
+
+ d.Flags = binary.BigEndian.Uint16(data[i : i+2])
+ i = i + 2
+ d.Code = data[i]
+ i++
+
+ for {
+ if len(data) <= i {
+ break
+ }
+ tlvType := data[i]
+ tlvLength := data[i+1]
+ if tlvLength == 0 {
+ break
+ }
+ tlvValue := data[i+2 : i+int(tlvLength)]
+ i = i + int(tlvLength)
+
+ switch tlvType {
+ case OampduTlvTypeLocalInfo:
+ d.LIType = tlvType
+ d.LILength = tlvLength
+ d.LIValue = tlvValue
+ case OampduTlvTypeRemoteInfo:
+ d.RIType = tlvType
+ d.RILength = tlvLength
+ d.RIValue = tlvValue
+ case OampduTlvTypeOrganizationSpecificInfo:
+ d.OSIType = tlvType
+ d.OSILength = tlvLength
+ d.OSIValue = tlvValue
+ default:
+ return fmt.Errorf("tlvType Error: %v", tlvType)
+ }
+ }
+
+ return nil
+}
+
+// IsOnuPkgA returns true if message type of OAMPDUInformation is PkgA
+func (d *OAMPDUInformation) IsOnuPkgA() bool {
+ if d.OSILength == 0 {
+ // return true if OSILength is 0, this means the message is KeepAlive3
+ return true
+ } else if d.OSILength == 7 {
+ return (d.OSIValue[0] == 0x00 && d.OSIValue[1] == 0x10 && d.OSIValue[2] == 0x00)
+ }
+ return false
+}
+
+// IsOnuPkgB returns true if message type of OAMPDUInformation is PkgA
+func (d *OAMPDUInformation) IsOnuPkgB() bool {
+ if d.OSILength == 0 {
+ // return true if OSILength is 0, this means the message is KeepAlive3
+ return true
+ } else if d.OSILength == 7 {
+ return (d.OSIValue[0] == 0x90 && d.OSIValue[1] == 0x82 && d.OSIValue[2] == 0x60)
+ }
+ return false
+}