diff --git a/vendor/github.com/opencord/omci-lib-go/v2/omci.go b/vendor/github.com/opencord/omci-lib-go/v2/omci.go
new file mode 100644
index 0000000..f778382
--- /dev/null
+++ b/vendor/github.com/opencord/omci-lib-go/v2/omci.go
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
+ * 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 omci provides a library of routines to create, manipulate, serialize, and
+// decode ITU-T G.988 OMCI messages/packets
+package omci
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+
+	"github.com/aead/cmac/aes"
+	"github.com/google/gopacket"
+	"github.com/google/gopacket/layers"
+	me "github.com/opencord/omci-lib-go/v2/generated"
+)
+
+// DeviceIdent identifies the OMCI message format. Currently either baseline or extended.
+type DeviceIdent byte
+
+// LayerTypeOMCI provides a gopacket LayerType for OMCI messages
+var (
+	LayerTypeOMCI gopacket.LayerType
+)
+
+func init() {
+	LayerTypeOMCI = gopacket.RegisterLayerType(1000,
+		gopacket.LayerTypeMetadata{
+			Name:    "OMCI",
+			Decoder: gopacket.DecodeFunc(decodeOMCI),
+		})
+}
+
+const (
+	// Device Identifiers
+	_ = iota
+	// BaselineIdent message are composed of a fixed 40 octet packet + 8-octet trailer. All
+	// G-PON OLTs and ONUs support the baseline message set
+	BaselineIdent DeviceIdent = 0x0A
+
+	// ExtendedIdent messages are up to 1920 octets but may not be supported by all ONUs or OLTs.
+	ExtendedIdent DeviceIdent = 0x0B
+)
+
+var omciIK = []byte{0x18, 0x4b, 0x8a, 0xd4, 0xd1, 0xac, 0x4a, 0xf4,
+	0xdd, 0x4b, 0x33, 0x9e, 0xcc, 0x0d, 0x33, 0x70}
+
+func (di DeviceIdent) String() string {
+	switch di {
+	default:
+		return "Unknown"
+
+	case BaselineIdent:
+		return "Baseline"
+
+	case ExtendedIdent:
+		return "Extended"
+	}
+}
+
+// MaxBaselineLength is the maximum number of octets allowed in an OMCI Baseline
+// message.  Depending on the adapter, it may or may not include the
+const MaxBaselineLength = 48
+
+// MaxExtendedLength is the maximum number of octets allowed in an OMCI Extended
+// message (including header).
+const MaxExtendedLength = 1980
+
+// MaxAttributeMibUploadNextBaselineLength is the maximum payload size for attributes for
+// a Baseline MIB Upload Next message.29
+const MaxAttributeMibUploadNextBaselineLength = MaxBaselineLength - 14 - 8
+
+// MaxAttributeGetNextBaselineLength is the maximum payload size for attributes for
+// a Baseline MIB Get Next message for the baseline message set. This is just the
+// attribute portion of the message contents and does not include the Result Code & Attribute Mask.
+const MaxAttributeGetNextBaselineLength = MaxBaselineLength - 11 - 8
+
+// MaxDownloadSectionLength is the maximum payload size for section data of
+// a Download Section request message for the baseline message set.
+const MaxDownloadSectionLength = 31
+
+// MaxTestRequestLength is the maximum payload size for test request message
+// for the baseline message set.
+const MaxTestRequestLength = MaxBaselineLength - 8 - 8
+
+// MaxTestResultsLength is the maximum payload size for test results message
+// for the baseline message set.
+const MaxTestResultsLength = MaxBaselineLength - 8 - 8
+
+// MaxManagedEntityMibUploadNextExtendedLength is the maximum payload size for ME
+// entries for an Extended MIB Upload Next message. Extended messages differ from
+// the baseline as multiple MEs can be reported in a single frame, just not multiple
+// attributes.
+const MaxManagedEntityMibUploadNextExtendedLength = MaxExtendedLength - 10 - 4
+
+// MaxAttributeGetNextExtendedLength is the maximum payload size for attributes for
+// a Extended MIB Get Next message. This is just the attribute portion of the
+// message contents and does not include the Result Code & Attribute Mask.
+const MaxAttributeGetNextExtendedLength = MaxExtendedLength - 13 - 4
+
+// MaxDownloadSectionExtendedLength is the maximum payload size for section data of
+// a Download Section request message for the extended message set.
+const MaxDownloadSectionExtendedLength = MaxExtendedLength - 11 - 4
+
+// NullEntityID is often used as the Null/void Managed Entity ID for attributes
+// that are used to refer to other Managed Entities but are currently not provisioned.
+const NullEntityID = uint16(0xffff)
+
+// OMCI defines the common protocol. Extended will be added once
+// I can get basic working (and layered properly).  See ITU-T G.988 11/2017 section
+// A.3 for more information
+type OMCI struct {
+	layers.BaseLayer
+	TransactionID    uint16
+	MessageType      MessageType
+	DeviceIdentifier DeviceIdent
+	ResponseExpected bool   // Significant for Download Section Request only
+	Payload          []byte // TODO: Deprecated.  Use layers.BaseLayer.Payload
+	Length           uint16
+	MIC              uint32
+}
+
+func (omci *OMCI) String() string {
+	return fmt.Sprintf("Type: %v, TID: %d (%#x), Ident: %v",
+		omci.MessageType, omci.TransactionID, omci.TransactionID, omci.DeviceIdentifier)
+}
+
+// LayerType returns LayerTypeOMCI
+func (omci *OMCI) LayerType() gopacket.LayerType {
+	return LayerTypeOMCI
+}
+
+// CanDecode returns the layers that this class can decode
+func (omci *OMCI) CanDecode() gopacket.LayerClass {
+	return LayerTypeOMCI
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *OMCI) NextLayerType() gopacket.LayerType {
+	if next, ok := nextLayerMapping[omci.MessageType]; ok {
+		return next
+	}
+	return gopacket.LayerTypePayload
+}
+
+// LayerContents returns the OMCI specific layer information
+func (omci *OMCI) LayerContents() []byte {
+	b := make([]byte, 4)
+	binary.BigEndian.PutUint16(b, omci.TransactionID)
+	b[2] = byte(omci.MessageType)
+	b[3] = byte(omci.DeviceIdentifier)
+	return b
+}
+
+func decodeOMCI(data []byte, p gopacket.PacketBuilder) error {
+	// Allow baseline messages without Length & MIC, but no less
+	if len(data) < 4 {
+		p.SetTruncated()
+		return errors.New("frame header too small")
+	}
+	omci := &OMCI{}
+
+	switch DeviceIdent(data[3]) {
+	default:
+		return errors.New("unsupported message set/device identifier")
+
+	case BaselineIdent:
+		if len(data) < MaxBaselineLength-8 {
+			p.SetTruncated()
+			return fmt.Errorf("frame too small. OMCI baseline frame length %v, %v required",
+				len(data), MaxBaselineLength-8)
+		}
+		return omci.DecodeFromBytes(data, p)
+
+	case ExtendedIdent:
+		if len(data) < 10 {
+			p.SetTruncated()
+			return fmt.Errorf("frame too small. OMCI minimal extended frame length %v, 10 required",
+				len(data))
+		}
+		return omci.DecodeFromBytes(data, p)
+	}
+}
+
+func calculateMicAes128(data []byte) (uint32, error) {
+	// See if upstream or downstream
+	var downstreamCDir = [...]byte{0x01}
+	var upstreamCDir = [...]byte{0x02}
+
+	tid := binary.BigEndian.Uint16(data[0:2])
+	var sum []byte
+	var err error
+
+	if (data[2]&me.AK) == me.AK || tid == 0 {
+		sum, err = aes.Sum(append(upstreamCDir[:], data[:44]...), omciIK, 4)
+	} else {
+		sum, err = aes.Sum(append(downstreamCDir[:], data[:44]...), omciIK, 4)
+	}
+	if err != nil {
+		return 0, err
+	}
+	return binary.BigEndian.Uint32(sum), nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//   Baseline Message encode / decode
+
+// DecodeFromBytes will decode the OMCI layer of a packet/message
+func (omci *OMCI) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Minimal Baseline and Extended message set length has already been checked
+	omci.TransactionID = binary.BigEndian.Uint16(data[0:])
+	omci.MessageType = MessageType(data[2])
+	omci.DeviceIdentifier = DeviceIdent(data[3])
+	omci.ResponseExpected = byte(omci.MessageType)&me.AR == me.AR
+
+	isNotification := (int(omci.MessageType) & ^me.MsgTypeMask) == 0
+	if omci.TransactionID == 0 && !isNotification {
+		return errors.New("omci Transaction ID is zero for non-Notification type message")
+	}
+	// Decode length
+	var payloadOffset int
+	var micOffset int
+	var eomOffset int
+	if omci.DeviceIdentifier == BaselineIdent {
+		omci.Length = MaxBaselineLength - 8
+		payloadOffset = 8
+		micOffset = MaxBaselineLength - 4
+		eomOffset = MaxBaselineLength - 8
+
+		if len(data) >= micOffset {
+			length := binary.BigEndian.Uint32(data[micOffset-4:])
+			if uint16(length) != omci.Length {
+				return me.NewProcessingError("invalid baseline message length")
+			}
+		}
+	} else {
+		payloadOffset = 10
+		omci.Length = binary.BigEndian.Uint16(data[8:10])
+		micOffset = int(omci.Length) + payloadOffset
+		eomOffset = micOffset
+
+		if omci.Length > uint16(MaxExtendedLength-payloadOffset) {
+			return me.NewProcessingError("extended frame exceeds maximum allowed")
+		}
+		if len(data) < micOffset {
+			p.SetTruncated()
+			return me.NewProcessingError("extended frame too small")
+		}
+	}
+	// Extract MIC if present in the data
+	if len(data) >= micOffset+4 {
+		omci.MIC = binary.BigEndian.Uint32(data[micOffset:])
+		actual, _ := calculateMicAes128(data[:micOffset])
+		if omci.MIC != actual {
+			_ = fmt.Sprintf("invalid MIC, expected %#x, got %#x",
+				omci.MIC, actual)
+			//return errors.New(msg)
+		}
+	}
+	omci.BaseLayer = layers.BaseLayer{
+		Contents: data[:4],
+		Payload:  data[4:eomOffset],
+	}
+	p.AddLayer(omci)
+	nextLayer, err := MsgTypeToNextLayer(omci.MessageType, omci.DeviceIdentifier == ExtendedIdent)
+	if err != nil {
+		return err
+	}
+	return p.NextDecoder(nextLayer)
+}
+
+// SerializeTo writes the serialized form of this layer into the
+// SerializationBuffer, implementing gopacket.SerializableLayer.
+// See the docs for gopacket.SerializableLayer for more info.
+func (omci *OMCI) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	bytes, err := b.PrependBytes(4)
+	if err != nil {
+		return err
+	}
+	// OMCI layer error checks
+	// Self-initiated Test Results have a TID of 0, OLT-requested do not.
+	isNotification := omci.MessageType == AlarmNotificationType ||
+		omci.MessageType == AttributeValueChangeType
+
+	if omci.TransactionID == 0 && !isNotification && omci.MessageType != TestResultType {
+		return errors.New("omci Transaction ID is zero for non-Notification type message")
+	}
+	if omci.TransactionID != 0 && isNotification {
+		return errors.New("omci Transaction ID is not zero for Notification type message")
+	}
+	if omci.DeviceIdentifier == 0 {
+		omci.DeviceIdentifier = BaselineIdent // Allow uninitialized device identifier
+	}
+	if omci.DeviceIdentifier == BaselineIdent {
+		if omci.Length == 0 {
+			omci.Length = MaxBaselineLength - 8 // Allow uninitialized length
+		} else if omci.Length != MaxBaselineLength-8 {
+			msg := fmt.Sprintf("invalid Baseline message length: %v", omci.Length)
+			return errors.New(msg)
+		}
+	} else if omci.DeviceIdentifier == ExtendedIdent {
+		omci.Length = uint16(len(b.Bytes()) - 10)
+
+		// Is length larger than maximum packet (less header and trailing MIC)
+		if omci.Length > MaxExtendedLength-10-4 {
+			msg := fmt.Sprintf("invalid Extended message length: %v", omci.Length)
+			return errors.New(msg)
+		}
+	} else {
+		msg := fmt.Sprintf("invalid device identifier: %#x, Baseline or Extended expected",
+			omci.DeviceIdentifier)
+		return errors.New(msg)
+	}
+	binary.BigEndian.PutUint16(bytes, omci.TransactionID)
+	// Download section request can optionally have the AR bit set or cleared.  If user passes in this
+	// message type and sets download requested, fix up the message type for them.
+	if omci.MessageType == DownloadSectionRequestType && omci.ResponseExpected {
+		bytes[2] = byte(DownloadSectionRequestWithResponseType)
+	} else {
+		bytes[2] = byte(omci.MessageType)
+	}
+	bytes[3] = byte(omci.DeviceIdentifier)
+	b.PushLayer(LayerTypeOMCI)
+
+	if omci.DeviceIdentifier == BaselineIdent {
+		bufLen := len(b.Bytes())
+		padSize := int(omci.Length) - bufLen + 4
+		if padSize < 0 {
+			msg := fmt.Sprintf("invalid OMCI Message Type length, exceeded allowed frame size by %d bytes",
+				-padSize)
+			return errors.New(msg)
+		}
+		padding, err := b.AppendBytes(padSize)
+		if err != nil {
+			return err
+		}
+		copy(padding, lotsOfZeros[:])
+
+		// For baseline, always provide the length
+		binary.BigEndian.PutUint32(b.Bytes()[MaxBaselineLength-8:], 40)
+	}
+	if opts.ComputeChecksums {
+		micBytes, err := b.AppendBytes(4)
+		if err != nil {
+			return err
+		}
+		omci.MIC, _ = calculateMicAes128(bytes[:MaxBaselineLength-4])
+		binary.BigEndian.PutUint32(micBytes, omci.MIC)
+	}
+	return nil
+}
+
+// hacky way to zero out memory... there must be a better way?
+var lotsOfZeros [MaxExtendedLength]byte // Extended OMCI messages may be up to 1980 bytes long, including headers
