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

Change-Id: I634ef62c53813dcf4456f54948f13e06358e263c
diff --git a/internal/pkg/core/l2oam_if.go b/internal/pkg/core/l2oam_if.go
new file mode 100644
index 0000000..87daab5
--- /dev/null
+++ b/internal/pkg/core/l2oam_if.go
@@ -0,0 +1,1339 @@
+/*
+ * 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 core
+
+import (
+	"context"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"strings"
+	"time"
+
+	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-openolt-adapter/internal/pkg/core/l2oam"
+	oop "github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/opencord/voltha-protos/v3/go/voltha"
+)
+
+func readTechProfile() {
+	address := "172.17.0.1:2379"
+	timeout := time.Second * 10
+
+	client, err := kvstore.NewEtcdClient(context.Background(), address, timeout, log.FatalLevel)
+	if err != nil {
+		return
+	}
+	defer client.Close(context.Background())
+	ctx, cancel := context.WithTimeout(context.Background(), timeout)
+	resp, err := client.Get(ctx, "service/voltha/technology_profiles/EPON/64")
+	cancel()
+	if resp == nil || err != nil {
+		l2oam.OnuPkgType = l2oam.OnuPkgTypeB
+		logger.Error(ctx, fmt.Sprintf("readTechProfile() etcd get error. resp=%v, err=%v", resp, err))
+		return
+	}
+	bytes := resp.Value.([]byte)
+	bytesString := string(bytes)
+	logger.Debug(ctx, fmt.Sprintf("readTechProfile() bytes string=%s", bytesString))
+	if strings.Index(bytesString, "\"profile_type\":\"EPON\"") > 0 && strings.Index(bytesString, "\"package_type\":\"B\"") > 0 {
+		l2oam.OnuPkgType = l2oam.OnuPkgTypeB
+	} else {
+		l2oam.OnuPkgType = l2oam.OnuPkgTypeA
+	}
+	logger.Debug(ctx, fmt.Sprintf("readTechProfile() onu package=%s", l2oam.OnuPkgType))
+
+}
+
+// L2oamGetDeviceInfo provides GetDeviceInfo for L2OAM
+func L2oamGetDeviceInfo(ctx context.Context, dh *DeviceHandler) (*oop.DeviceInfo, error) {
+	logger.Debug(ctx, "GetDeviceInfo() Start.")
+	readTechProfile()
+
+	dstMac := dh.device.MacAddress
+	deviceInfo := &oop.DeviceInfo{
+		Vendor: "Tibit",
+		// Model				string	`protobuf:"bytes,2,opt,name=model,proto3" json:"model,omitempty"`
+		// HardwareVersion		string	`protobuf:"bytes,3,opt,name=hardware_version,json=hardwareVersion,proto3" json:"hardware_version,omitempty"`
+		// FirmwareVersion		string	`protobuf:"bytes,4,opt,name=firmware_version,json=firmwareVersion,proto3" json:"firmware_version,omitempty"`
+		DeviceId: dstMac,
+		// DeviceSerialNumber	string	`protobuf:"bytes,17,opt,name=device_serial_number,json=deviceSerialNumber,proto3" json:"device_serial_number,omitempty"`
+		PonPorts:       1,
+		Technology:     "EPON",
+		OnuIdStart:     1,
+		OnuIdEnd:       128,
+		AllocIdStart:   5121,
+		AllocIdEnd:     9216,
+		GemportIdStart: 1,
+		GemportIdEnd:   65535,
+		FlowIdStart:    1,
+		FlowIdEnd:      16383,
+		// Ranges				[]*DeviceInfo_DeviceResourceRanges	protobuf:"bytes,15,rep,name=ranges,proto3" json:"ranges,omitempty"`
+	}
+	olt := FindL2oamDevice(dstMac)
+	if olt == nil {
+		olt, _ = NewL2oamOltDevice(dstMac, dh)
+		olt.startKeepAlive()
+	}
+
+	err00 := sendDiscoverySOLICIT(ctx, olt)
+	logger.Debug(ctx, fmt.Sprintf("Sequence returts: %v", err00))
+	vendorName, err01 := sendGetVendorName(ctx, olt)
+	moduleNumber, err02 := sendGetModuleNumber(ctx, olt)
+	manuFacturer, err03 := sendManuFacturerInfo(ctx, olt)
+	firmwareVersion, err04 := sendGetFirmwareVersion(ctx, olt)
+	macAddress, err05 := sendGetMacAddress(ctx, olt)
+	serialNumber, err06 := sendGetSerialNumber(ctx, olt)
+	deviceInfo.Vendor = vendorName
+	deviceInfo.Model = moduleNumber
+	deviceInfo.HardwareVersion = manuFacturer
+	deviceInfo.FirmwareVersion = firmwareVersion
+	deviceInfo.DeviceId = macAddress
+	deviceInfo.DeviceSerialNumber = serialNumber
+	logger.Debug(ctx, fmt.Sprintf("Sequence returts: deviceInfo=%v, %v, %v, %v, %v, %v, %v, %v", deviceInfo, err00, err01, err02, err03, err04, err05, err06))
+
+	dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
+	olt.setActiveState(ctx, true)
+	return deviceInfo, nil
+}
+
+// L2oamEnableIndication runs EnableIndication sequence
+func L2oamEnableIndication(ctx context.Context, dh *DeviceHandler) {
+	logger.Debug(ctx, "L2oamEnableIndication() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamEnableIndication() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+		return
+	}
+
+	err01 := sendSetHbtxPeriod(ctx, olt)
+	err02 := sendSetHbtxTemplate(ctx, olt)
+	ponMode, err03 := sendGetPonMode(ctx, olt)
+	err04 := sendSetMPCPSync(ctx, olt)
+	err05 := sendSetAdminState(ctx, olt, true)
+	ponPortAction := sendSetGenericActionCreate(ctx, olt, l2oam.ActionTypeProtocolFilter)
+	if ponPortAction == nil {
+		return
+	}
+	actionIDPonPort := binary.BigEndian.Uint32(ponPortAction.GetTrafficProfile())
+	err07 := sendSetIngressPort(ctx, olt, actionIDPonPort, true)
+	err08 := sendSetCaptureProtocols(ctx, olt, actionIDPonPort)
+	ethPortAction := sendSetGenericActionCreate(ctx, olt, l2oam.ActionTypeProtocolFilter)
+	if ethPortAction == nil {
+		return
+	}
+	actionIDEthPort := binary.BigEndian.Uint32(ethPortAction.GetTrafficProfile())
+	err09 := sendSetIngressPort(ctx, olt, actionIDEthPort, false)
+	err10 := sendSetCaptureProtocols(ctx, olt, actionIDEthPort)
+
+	oltDev := olt.(*L2oamOltDevice)
+	oltDev.Base.ActionIds = make(map[int]uint32)
+	oltDev.Base.ActionIds[ActionIDFilterPonPort] = actionIDPonPort
+	oltDev.Base.ActionIds[ActionIDFilterEthPort] = actionIDEthPort
+	olt.updateMap()
+
+	err06 := sendSetAdminState(ctx, olt, false)
+	olt.setAutonomousFlag(true)
+
+	logger.Debug(ctx, fmt.Sprintf("Sequence returns: ponMode=%s, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v",
+		ponMode, err01, err02, err03, err04, err05, err06, err07, err08, err09, err10))
+
+}
+
+// L2oamAfterKeepAlive ... [obsoluted]
+func L2oamAfterKeepAlive(ctx context.Context, dh *DeviceHandler) error {
+
+
+
+	return nil
+}
+
+//var flowVersion int = 1 // run add-flow each OLT
+//var flowVersion int = 2 // run add-flow each ONU
+var flowVersion int = 3 // run add-flow at specified ONU
+
+// L2oamAddFlow runs add-flow sequence
+func L2oamAddFlow(ctx context.Context, dh *DeviceHandler, cmd *L2oamCmd) {
+	logger.Debug(ctx, "L2oamAddFlow() Start.")
+	if cmd.OnuDeviceID == "" {
+		flowVersion = 2
+	} else {
+		flowVersion = 3
+	}
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamAddFlow() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+		return
+	}
+
+	if flowVersion == 1 {
+		oc := &l2oam.TomiObjectContext{
+			Branch:   0x0c,
+			Type:     0x0011,
+			Length:   4,
+			Instance: 0x00000002,
+		}
+		getTrafficControl := sendGetTrafficControlReferenceTable(ctx, olt, oc)
+		if getTrafficControl == nil {
+			logger.Error(ctx, "L2oamAddFlow() sendGetTrafficControlReferenceTable() error. ")
+			return
+		}
+		downProfile := sendSetGenericActionCreate(ctx, olt, l2oam.ActionTypeTrafficProfile)
+		if downProfile == nil {
+			logger.Error(ctx, "L2oamAddFlow() sendSetGenericActionCreate(down) error. ")
+			return
+		}
+		upProfile := sendSetGenericActionCreate(ctx, olt, l2oam.ActionTypeTrafficProfile)
+		if upProfile == nil {
+			logger.Error(ctx, "L2oamAddFlow() sendSetGenericActionCreate(up) error. ")
+			return
+		}
+		olt.setReferenceTable(getTrafficControl)
+		olt.setProfile(downProfile, upProfile)
+		olt.updateMap()
+
+		err01 := sendSetTrafficControl(ctx, olt, getTrafficControl.GetReferenceControlDown(), downProfile.GetTrafficProfile())
+		err02 := sendSetTrafficControl(ctx, olt, getTrafficControl.GetReferenceControlUp(), upProfile.GetTrafficProfile())
+
+		err03 := sendSetPriority(ctx, olt, downProfile.GetTrafficProfile())
+		err04 := sendSetGuranteedRate(ctx, olt, cmd.Cir, downProfile.GetTrafficProfile())
+		err05 := sendSetGuranteedRate(ctx, olt, cmd.Cir, upProfile.GetTrafficProfile())
+		err06 := sendSetBestEffortRate(ctx, olt, cmd.Pir, downProfile.GetTrafficProfile())
+		err07 := sendSetBestEffortRate(ctx, olt, cmd.Pir, upProfile.GetTrafficProfile())
+
+		logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v, %v, %v, %v, %v, %v", err01, err02, err03, err04, err05, err06, err07))
+	} else if flowVersion == 2 {
+		// add-flow to all ONUs
+		// Traffic Profile(priority, guranteed rate, best effort rate) are set as common settings
+		onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
+		if err != nil {
+			logger.Error(ctx, fmt.Sprintf("catnnot-get-child-devices: %v", err))
+			return
+		}
+
+		isFirst := true
+		var downProfile *l2oam.SetGenericActionCreateRes
+		var upProfile *l2oam.SetGenericActionCreateRes
+		for _, onuDevice := range onuDevices.Items {
+			//onu := FindL2oamDevice(onuDevice.MacAddress)
+			onu := FindL2oamDeviceByDeviceID(onuDevice.Id)
+			if onu == nil {
+				logger.Error(ctx, fmt.Sprintf("catnnot-get-onu-device. device-id:%s, mac-address:%s",
+					onuDevice.Id, onuDevice.MacAddress))
+				continue
+			}
+			if !(onu.(*L2oamOnuDevice)).Base.isActive() {
+				logger.Debug(ctx, fmt.Sprintf("onu is not active. device-id:%s, mac-address:%s",
+					onuDevice.Id, onuDevice.MacAddress))
+				continue
+			}
+			logger.Debug(ctx, fmt.Sprintf("add-flow-for-onu. device-id:%s, mac-address:%s",
+				onuDevice.Id, onuDevice.MacAddress))
+
+			oc := onu.getObjectContext()
+			if oc == nil {
+				logger.Error(ctx, fmt.Sprintf("catnnot-get-onu-object-context. device-id:%s, mac-address:%s",
+					onuDevice.Id, onuDevice.MacAddress))
+				continue
+			}
+			getTrafficControl := sendGetTrafficControlReferenceTable(ctx, olt, oc)
+			if getTrafficControl == nil {
+				logger.Error(ctx, "L2oamAddFlow() sendGetTrafficControlReferenceTable() error. ")
+				continue
+			}
+			onu.setReferenceTable(getTrafficControl)
+			onu.updateMap()
+
+			// create one Traffic Profile at OLT
+			if isFirst {
+				downProfile = sendSetGenericActionCreate(ctx, olt, l2oam.ActionTypeTrafficProfile)
+				if downProfile == nil {
+					logger.Error(ctx, "L2oamAddFlow() sendSetGenericActionCreate(down) error. ")
+					break
+				}
+				upProfile = sendSetGenericActionCreate(ctx, olt, l2oam.ActionTypeTrafficProfile)
+				if upProfile == nil {
+					logger.Error(ctx, "L2oamAddFlow() sendSetGenericActionCreate(up) error. ")
+					break
+				}
+				olt.setProfile(downProfile, upProfile)
+				olt.updateMap()
+			}
+
+			err01 := sendSetTrafficControl(ctx, olt, getTrafficControl.GetReferenceControlDown(), downProfile.GetTrafficProfile())
+			err02 := sendSetTrafficControl(ctx, olt, getTrafficControl.GetReferenceControlUp(), upProfile.GetTrafficProfile())
+			logger.Debug(ctx, fmt.Sprintf("traffic-control/traffic-profile results: %v, %v", err01, err02))
+
+			if isFirst {
+				err03 := sendSetPriority(ctx, olt, downProfile.GetTrafficProfile())
+				err04 := sendSetGuranteedRate(ctx, olt, cmd.Cir, downProfile.GetTrafficProfile())
+				err05 := sendSetGuranteedRate(ctx, olt, cmd.Cir, upProfile.GetTrafficProfile())
+				err06 := sendSetBestEffortRate(ctx, olt, cmd.Pir, downProfile.GetTrafficProfile())
+				err07 := sendSetBestEffortRate(ctx, olt, cmd.Pir, upProfile.GetTrafficProfile())
+				isFirst = false
+				logger.Debug(ctx, fmt.Sprintf("traffic-profile-settings-results: %v, %v, %v, %v, %v",
+					err03, err04, err05, err06, err07))
+			}
+		}
+	} else if flowVersion == 3 {
+		if err := olt.addFlow(ctx, cmd); err != nil {
+			logger.Errorf(ctx, "failed-to-add-flow: %v", err)
+		}
+	}
+}
+
+// L2oamAddFlowAndMount adds flow to device and start mount sequence
+func (d *DeviceHandler) L2oamAddFlowAndMount(ctx context.Context, onuDeviceID string, vid []byte, ivid []byte) {
+	l2oamCmd := &L2oamCmd{
+		Type:        "add-flow-dev",
+		Tpid:        []byte{0x88, 0xa8},
+		Vid:         vid,
+		Itpid:       []byte{0x81, 0x00},
+		Ivid:        ivid,
+		OnuDeviceID: onuDeviceID,
+	}
+	olt := FindL2oamDeviceByDeviceID(d.device.Id)
+	if olt == nil {
+		logger.Errorf(ctx, "olt not found.")
+	}
+	if err := olt.updateFlow(ctx, l2oamCmd); err != nil {
+		logger.Errorf(ctx, "failed-to-update-flow. %v", err)
+	} else {
+		onu := FindL2oamDeviceByDeviceID(onuDeviceID)
+		if onu == nil {
+			logger.Debug(ctx, fmt.Sprintf("L2oamAddFlowAndMount() FindL2oamDevice() onu not found. deviceId=%s", onuDeviceID))
+		} else {
+			// start ONU mount sequence
+			onu.startMountSequence(ctx, l2oam.OnuPkgType, l2oamCmd)
+		}
+	}
+}
+
+// L2oamAddFlowToDeviceAll adds a flow to specified device.
+// If some flows are added already, all flows are removed from all devices before adding.
+func L2oamAddFlowToDeviceAll(ctx context.Context, dh *DeviceHandler, cmd *L2oamCmd) error {
+	logger.Debug(ctx, "L2oamAddFlowToDeviceAll() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamAddFlowToDeviceAll() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+		return nil
+	}
+
+	oc := olt.getObjectContext()
+	var onuList []*L2oamOnuDevice
+	onuDeviceID := cmd.OnuDeviceID
+	onu := FindL2oamDeviceByDeviceID(onuDeviceID)
+	if onu == nil {
+		return nil
+	}
+	onuDev, ok := onu.(*L2oamOnuDevice)
+	if !ok {
+		return nil
+	}
+	if oc != nil {
+		onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
+		if err != nil {
+			logger.Error(ctx, fmt.Sprintf("catnnot-get-child-devices: %v", err))
+			return err
+		}
+		// create flow added onu list
+		reflow := false
+		for _, onuDevice := range onuDevices.Items {
+			//onu := FindL2oamDevice(onuDevice.MacAddress)
+			onu := FindL2oamDeviceByDeviceID(onuDevice.Id)
+			if onu != nil {
+				if onuDev, ok := onu.(*L2oamOnuDevice); ok {
+					if onuDev.Base.FlowAdded {
+						onuList = append(onuList, onuDev)
+						if onuDeviceID == onuDev.Base.DeviceID {
+							reflow = true
+						}
+					}
+				}
+			}
+		}
+		if !reflow {
+			onuList = append(onuList, onuDev)
+		}
+		L2oamRemoveFlowFromDevice(ctx, dh, onuDevices)
+	} else {
+		onuList = append(onuList, onuDev)
+	}
+	localCmd := *cmd
+	for _, onuDev := range onuList {
+		localCmd.OnuDeviceID = onuDev.Base.DeviceID
+		if err := L2oamAddFlowToDevice(ctx, dh, &localCmd); err != nil {
+			continue
+		}
+	}
+
+	return nil
+}
+
+// L2oamAddFlowToDevice runs add-flow-device sequence
+func L2oamAddFlowToDevice(ctx context.Context, dh *DeviceHandler, cmd *L2oamCmd) error {
+	if flowVersion == 1 {
+		oc := L2oamAddFlowToDeviceDS(ctx, dh, cmd)
+		if oc == nil {
+			return errors.New("failed-to-add-flow-to-device-for-down-stream")
+		}
+		L2oamAddFlowToDeviceUS(ctx, dh, oc, cmd)
+	} else if flowVersion > 1 {
+		logger.Debug(ctx, "L2oamAddFlowToDevice() Start.")
+
+		olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+		if olt == nil {
+			logger.Error(ctx, fmt.Sprintf("L2oamAddFlowToDevice() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+			return nil
+		}
+
+		// add flow for downstream
+		oc := olt.getObjectContext()
+		var err01 error
+		var err02 error
+		onuDeviceID := cmd.OnuDeviceID
+		// "Generic/Action Create, L2 Switching Domain/Action Inlet entry" is created only first
+		if oc == nil {
+			oc, err01 = sendSetGenericActionCreateForDS(ctx, olt)
+			if oc == nil {
+				logger.Error(ctx, fmt.Sprintf("error. %v", err01))
+				return errors.New("failed-to-add-flow-to-device-for-down-stream")
+			}
+			// TODO ignore tpid, vid after the second time
+			err02 = sendSetL2SwitchingDomainForDS(ctx, olt, oc, cmd.Tpid, cmd.Vid)
+			olt.setL2oamCmd(cmd)
+			olt.setObjectContext(oc)
+			if oltDev, ok := olt.(*L2oamOltDevice); ok {
+				oltDev.Base.FlowAdded = true
+			}
+			olt.updateMap()
+		} else {
+			cmd = olt.getL2oamCmd()
+		}
+
+		onu := FindL2oamDeviceByDeviceID(onuDeviceID)
+		if onu == nil {
+			logger.Debug(ctx, fmt.Sprintf("L2oamCmdRequest() FindL2oamDevice() onu not found. deviceId=%s", onuDeviceID))
+		} else {
+			onuID := onu.getObjectContext()
+			if onuID == nil {
+				logger.Error(ctx, "catnnot-get-onu-object-context.")
+			} else {
+				err03 := sendSetDefaultOutlet(ctx, olt, oc, onuID)
+				err04 := sendSetL2SwitchingDomainForUS(ctx, olt, oc, cmd.Tpid, cmd.Vid, onuID)
+
+				logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v, %v, %v", err01, err02, err03, err04))
+				if onuDev, ok := onu.(*L2oamOnuDevice); ok {
+					onuDev.Base.FlowAdded = true
+					onu.updateMap()
+				} else {
+					logger.Error(ctx, fmt.Sprintf("assertion failed. device-id:%s", onuDeviceID))
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// L2oamAddFlowToDeviceDS runs add-flow-device sequence for downstream
+func L2oamAddFlowToDeviceDS(ctx context.Context, dh *DeviceHandler, cmd *L2oamCmd) *l2oam.TomiObjectContext {
+	logger.Debug(ctx, "L2oamAddFlowToDeviceDS() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamAddFlowToDeviceDS() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+	}
+
+	oc, err01 := sendSetGenericActionCreateForDS(ctx, olt)
+	if oc != nil {
+		onuID := &l2oam.TomiObjectContext{
+			Branch:   0x0c,
+			Type:     0x0011,
+			Length:   4,
+			Instance: 0x00000001,
+		}
+		err02 := sendSetL2SwitchingDomainForDS(ctx, olt, oc, cmd.Tpid, cmd.Vid)
+		err03 := sendSetDefaultOutlet(ctx, olt, oc, onuID)
+		logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v, %v", err01, err02, err03))
+	} else {
+		logger.Debug(ctx, fmt.Sprintf("Sequence results: %v", err01))
+	}
+	olt.setL2oamCmd(cmd)
+	olt.setObjectContext(oc)
+	olt.updateMap()
+
+	return oc
+}
+
+// L2oamAddFlowToDeviceUS runs add-flow-device sequence for upstream
+func L2oamAddFlowToDeviceUS(ctx context.Context, dh *DeviceHandler, oc *l2oam.TomiObjectContext, cmd *L2oamCmd) {
+	logger.Debug(ctx, "L2oamAddFlowToDeviceUS() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamAddFlowToDeviceUS() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+	}
+
+	onuID := &l2oam.TomiObjectContext{
+		Branch:   0x0c,
+		Type:     0x0011,
+		Length:   4,
+		Instance: 0x00000002,
+	}
+	err01 := sendSetL2SwitchingDomainForUS(ctx, olt, oc, cmd.Tpid, cmd.Vid, onuID)
+
+	logger.Debug(ctx, fmt.Sprintf("Sequence results: %v", err01))
+}
+
+// L2oamRebootDevice reboots the device
+func L2oamRebootDevice(ctx context.Context, dh *DeviceHandler, device *voltha.Device) {
+	logger.Debug(ctx, "L2oamRebootDevice() Start.")
+
+	L2oamDisableOlt(ctx, dh)
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamRebootDevice() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+		return
+	}
+
+	err01 := sendSetActionReset(ctx, olt)
+
+	logger.Debug(ctx, fmt.Sprintf("Sequence results: %v", err01))
+
+}
+
+// L2oamDeleteOlt deletes the OLT device
+func L2oamDeleteOlt(ctx context.Context, dh *DeviceHandler) {
+	logger.Debug(ctx, fmt.Sprintf("L2oamDeleteOlt() Start. deviceId=%s", dh.device.Id))
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamDeleteOlt() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+		return
+	}
+	olt.setAutonomousFlag(false)
+	if !SetupL2oamDeleteFlag(dh.device.Id) {
+		logger.Warn(ctx, fmt.Sprintf("L2oamDeleteOlt() olt deleted deviceId=%s", dh.device.Id))
+		return
+	}
+	err01 := sendSetAdminState(ctx, olt, true)
+	DeleteAllDevice()
+
+	logger.Debug(ctx, fmt.Sprintf("L2oamDeleteOlt() End. deviceId=%s, %v", dh.device.Id, err01))
+}
+
+// L2oamDisableOlt disables the OLT device
+func L2oamDisableOlt(ctx context.Context, dh *DeviceHandler) {
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamDisableOlt() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+		return
+	}
+	olt.setAutonomousFlag(false)
+
+	onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
+	if err != nil {
+		logger.Error(ctx, fmt.Sprintf("catnnot-get-child-devices: %v", err))
+	}
+
+	if err = olt.removeFlow(ctx); err != nil {
+		logger.Error(ctx, fmt.Sprintf("failed-to-remove-flows: %v", err))
+	}
+	L2oamRemoveFlow(ctx, dh, onuDevices)
+	L2oamChildDeviceLost(ctx, dh, onuDevices)
+	L2oamDisableDevice(ctx, dh)
+	resetFlowMap()
+}
+
+// L2oamRemoveFlowFromDevice removes flows from the device
+func L2oamRemoveFlowFromDevice(ctx context.Context, dh *DeviceHandler, onuDevices *voltha.Devices) {
+	logger.Debug(ctx, "L2oamRemoveFlowFromDeviceDS() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamRemoveFlowFromDeviceDS() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+	}
+	oc := olt.getObjectContext()
+	cmd := olt.getL2oamCmd()
+	if cmd == nil {
+		logger.Warn(ctx, fmt.Sprintf("L2oamRemoveFlowFromDeviceDS() tpid, vid are not specified. deviceId=%s",
+			dh.device.Id))
+		return
+	}
+	logger.Debug(ctx, fmt.Sprintf("TPID:%v, VID:%v", cmd.Tpid, cmd.Vid))
+
+	for _, onuDevice := range onuDevices.Items {
+		//onu := FindL2oamDevice(onuDevice.MacAddress)
+		onu := FindL2oamDeviceByDeviceID(onuDevice.Id)
+		if onu == nil {
+			logger.Error(ctx, fmt.Sprintf("catnnot-get-onu-device. device-id:%s, mac-address:%s",
+				onuDevice.Id, onuDevice.MacAddress))
+			continue
+		}
+		var onuDev *L2oamOnuDevice
+		var ok bool
+		if onuDev, ok = onu.(*L2oamOnuDevice); ok {
+			if !onuDev.Base.FlowAdded {
+				logger.Error(ctx, fmt.Sprintf("flow is not added. device-id:%s, mac-address:%s",
+					onuDevice.Id, onuDevice.MacAddress))
+				continue
+			}
+		} else {
+			logger.Error(ctx, fmt.Sprintf("assertion failed. device-id:%s, mac-address:%s",
+				onuDevice.Id, onuDevice.MacAddress))
+			continue
+		}
+		onuID := onu.getObjectContext()
+		if onuID == nil {
+			logger.Error(ctx, fmt.Sprintf("catnnot-get-onu-object-context. device-id:%s, mac-address:%s",
+				onuDevice.Id, onuDevice.MacAddress))
+			continue
+		}
+		logger.Debug(ctx, fmt.Sprintf("Switching Domain/Action Remove Inlet entry. device-id:%s, instance-id:%d",
+			onuDevice.Id, onuID.Instance))
+		err := sendSetActionInletEntryUsDel(ctx, olt, oc, cmd.Tpid, cmd.Vid, onuID)
+		logger.Debug(ctx, fmt.Sprintf("Sequence results: %v", err))
+		onuDev.Base.FlowAdded = false
+		onu.updateMap()
+	}
+
+	if oltDev, ok := olt.(*L2oamOltDevice); ok {
+		if oltDev.Base.FlowAdded {
+			err02 := sendSetActionInletEntryDsDel(ctx, olt, oc, cmd.Tpid, cmd.Vid)
+			err03 := sendSetActionDeleteStream(ctx, olt, oc)
+
+			logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v", err02, err03))
+			olt.setObjectContext(nil)
+			oltDev.Base.FlowAdded = false
+			olt.updateMap()
+		} else {
+			logger.Debug(ctx, fmt.Sprintf("flow is not added. device-id:%s", dh.device.Id))
+		}
+	} else {
+		logger.Debug(ctx, fmt.Sprintf("assersion failed. device-id:%s", dh.device.Id))
+	}
+}
+
+// L2oamRemoveFlow removes flows
+func L2oamRemoveFlow(ctx context.Context, dh *DeviceHandler, onuDevices *voltha.Devices) {
+	logger.Debug(ctx, "L2oamRemoveFlow() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamRemoveFlow() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+	}
+
+	if flowVersion == 2 {
+		//refTbl := olt.getReferenceTable()
+		downProfile, upProfile := olt.getProfile()
+		//if refTbl == nil || downProfile == nil || upProfile == nil {
+		if downProfile == nil || upProfile == nil {
+			logger.Warn(ctx, fmt.Sprintf("L2oamRemoveFlow() profiles are not specified. deviceId=%s",
+				dh.device.Id))
+			return
+		}
+		downInstanceID := downProfile.GetTrafficProfile()
+		upInstanceID := upProfile.GetTrafficProfile()
+		//err01 := sendSetTrafficProfile(ctx, olt,
+		//	refTbl.GetReferenceControlDown(), downInstanceId)
+		//err02 := sendSetTrafficProfile(ctx, olt,
+		//	refTbl.GetReferenceControlUp(), upInstanceId)
+		err03 := sendSetActionDelete(ctx, olt, downInstanceID, l2oam.ActionTypeTrafficProfile)
+		err04 := sendSetActionDelete(ctx, olt, upInstanceID, l2oam.ActionTypeTrafficProfile)
+		olt.setProfile(nil, nil)
+		olt.updateMap()
+
+		//logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v, %v, %v", err01, err02, err03, err04))
+		logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v", err03, err04))
+	} else if flowVersion == 3 {
+		for _, onuDevice := range onuDevices.Items {
+			logger.Debugf(ctx, "remove-traffic-schedule. onu-device-id:%s", onuDevice.Id)
+			onu := FindL2oamDeviceByDeviceID(onuDevice.Id)
+			if onu == nil {
+				logger.Errorf(ctx, "catnnot-get-onu-device")
+				continue
+			}
+			refTbl := onu.getReferenceTable()
+			if refTbl == nil {
+				logger.Debug(ctx, "traffic-profile-is-not-created")
+				continue
+			}
+			downProfile, upProfile := onu.getProfile()
+			if downProfile == nil || upProfile == nil {
+				logger.Debug(ctx, "flow is not added")
+				continue
+			}
+			downInstanceID := downProfile.GetTrafficProfile()
+			upInstanceID := upProfile.GetTrafficProfile()
+			err01 := sendSetTrafficProfile(ctx, olt,
+				refTbl.GetReferenceControlDown(), downInstanceID)
+			err02 := sendSetTrafficProfile(ctx, olt,
+				refTbl.GetReferenceControlUp(), upInstanceID)
+			err03 := sendSetActionDelete(ctx, olt, downInstanceID, l2oam.ActionTypeTrafficProfile)
+			err04 := sendSetActionDelete(ctx, olt, upInstanceID, l2oam.ActionTypeTrafficProfile)
+			onu.setReferenceTable(nil)
+			onu.setProfile(nil, nil)
+			onu.updateMap()
+			logger.Debug(ctx, fmt.Sprintf("remove-traffic-schedule-results: %v, %v, %v, %v", err01, err02, err03, err04))
+		}
+	}
+}
+
+// L2oamChildDeviceLost sends DeviceLost message
+func L2oamChildDeviceLost(ctx context.Context, dh *DeviceHandler, onuDevices *voltha.Devices) {
+	logger.Debug(ctx, "L2oamChildDeviceLost() Start.")
+	if onuDevices == nil {
+		return
+	}
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamChildDeviceLost() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+	}
+
+	for _, onuDevice := range onuDevices.Items {
+		//onu := FindL2oamDevice(onuDevice.MacAddress)
+		onu := FindL2oamDeviceByDeviceID(onuDevice.Id)
+		if onu == nil {
+			logger.Error(ctx, fmt.Sprintf("catnnot-get-onu-device. device-id:%s, mac-address:%s",
+				onuDevice.Id, onuDevice.MacAddress))
+		} else {
+			oc := onu.getObjectContext()
+			if oc == nil {
+				logger.Error(ctx, fmt.Sprintf("catnnot-get-onu-object-context. device-id:%s, mac-address:%s",
+					onuDevice.Id, onuDevice.MacAddress))
+			} else {
+				logger.Debug(ctx, fmt.Sprintf("onu-object-context. instance-id:%x", oc.Instance))
+				err01 := sendSetActionDeleteOnu(ctx, olt, oc)
+
+				logger.Debug(ctx, fmt.Sprintf("Sequence results: %v", err01))
+			}
+		}
+	}
+}
+
+// L2oamDisableDevice disables the device
+func L2oamDisableDevice(ctx context.Context, dh *DeviceHandler) {
+	logger.Debug(ctx, "L2oamDisableDevice() Start.")
+
+	olt := FindL2oamDeviceByDeviceID(dh.device.Id)
+	if olt == nil {
+		logger.Error(ctx, fmt.Sprintf("L2oamDisableDevice() FindL2oamDeviceByDeviceId() error. olt not found. deviceId=%s", dh.device.Id))
+	}
+
+	oltDev := olt.(*L2oamOltDevice)
+	if oltDev.Base.ActionIds != nil {
+		var bytes [4]byte
+		if id, ok := oltDev.Base.ActionIds[ActionIDFilterPonPort]; ok {
+			binary.BigEndian.PutUint32(bytes[:], id)
+			if err := sendSetActionDelete(ctx, olt, bytes[:], l2oam.ActionTypeProtocolFilter); err != nil {
+				return
+			}
+		}
+		if id, ok := oltDev.Base.ActionIds[ActionIDFilterEthPort]; ok {
+			binary.BigEndian.PutUint32(bytes[:], id)
+			if err := sendSetActionDelete(ctx, olt, bytes[:], l2oam.ActionTypeProtocolFilter); err != nil {
+				return
+			}
+		}
+		oltDev.Base.ActionIds = nil
+		olt.updateMap()
+	}
+	err01 := sendSetAdminState(ctx, olt, true)
+	err02 := sendSetManagementLock(ctx, olt)
+
+	logger.Debug(ctx, fmt.Sprintf("Sequence results: %v, %v", err01, err02))
+}
+
+func sendDiscoverySOLICIT(ctx context.Context, device L2oamDevice) error {
+	if err := device.send(l2oam.GenerateDiscoverySOLICIT()); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendDiscoverySOLICIT() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.DiscoveryHello{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendDiscoverySOLICIT() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return nil
+}
+
+func sendGetVendorName(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GnerateGetVendorName()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendGetVendorName() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.GetVendorNameRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendGetVendorName() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetVendorName(), nil
+}
+
+func sendGetModuleNumber(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GenerateGetModuleNumber()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendGetModuleNumber() Send Error: %v", device.getDeviceName(), err)
+	}
+	packet := &l2oam.GetModuleNumberRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendGetModuleNumber() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetModuleNumber(), nil
+}
+
+func sendManuFacturerInfo(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GenerateManuFacturerInfo()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendManuFacturerInfo() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.GetManufacturerRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendManuFacturerInfo() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetManufacturer(), nil
+}
+
+func sendGetFirmwareVersion(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GenerateGetFirmwareVersion()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendGetFirmwareVersion() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.GetFirmwareVersionRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendGetFirmwareVersion() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetFirmwareVersionNumber(), nil
+}
+
+func sendGetMacAddress(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GenerateGetMacAddress()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendGetMacAddress() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.GetMacAddressRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendGetMacAddress() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetMacAddress(), nil
+}
+
+func sendGetSerialNumber(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GenerateGetSerialNumber()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendGetSerialNumber() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.GetSerialNumberRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendGetSerialNumber() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetSerialNumber(), nil
+}
+
+func sendSetHbtxTemplate(ctx context.Context, device L2oamDevice) error {
+	if err := device.send(l2oam.GenerateSetHbtxTemplate()); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetHbtxTemplate() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetHbtxTemplate() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return nil
+}
+
+func sendGetPonMode(ctx context.Context, device L2oamDevice) (string, error) {
+	if err := device.send(l2oam.GenerateGetPonMode()); err != nil {
+		return "", nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return "", fmt.Errorf("[%s] sendGetPonMode() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.GetPonMode{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return "", nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendGetPonMode() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return packet.GetPonMode(), nil
+}
+
+func sendSetMPCPSync(ctx context.Context, device L2oamDevice) error {
+	if err := device.send(l2oam.GenerateSetMPCPSync()); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetMPCPSync() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetMPCPSync() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return nil
+}
+
+func sendSetAdminState(ctx context.Context, device L2oamDevice, isDelete bool) error {
+	if isDelete {
+		if err := device.send(l2oam.GenerateSetAdminStateDelete()); err != nil {
+			return nil
+		}
+	} else {
+		if err := device.send(l2oam.GenerateSetAdminState()); err != nil {
+			return nil
+		}
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetAdminState() Send Error: isDelete=%v, %v", device.getDeviceName(), isDelete, err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetAdminState() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return nil
+}
+
+func sendSetHbtxPeriod(ctx context.Context, device L2oamDevice) error {
+	if err := device.send(l2oam.GenerateSetHbtxPeriod()); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetHbtxPeriod() Send Error: %v", device.getDeviceName(), err)
+	}
+	packet := &l2oam.TOAMSetResponse{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetHbtxPeriod() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+func sendSetIngressPort(ctx context.Context, device L2oamDevice, actionID uint32, isPonPort bool) error {
+	if err := device.send(l2oam.GenerateIngressPort(actionID, isPonPort)); err != nil {
+		return nil
+	}
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		logger.Error(ctx, fmt.Sprintf("sendSetIngressPort() send error. %s ", err))
+		return nil
+	}
+
+	return nil
+}
+
+func sendSetCaptureProtocols(ctx context.Context, device L2oamDevice, actionID uint32) error {
+	if err := device.send(l2oam.GenerateCaptureProtocols(actionID)); err != nil {
+		return nil
+	}
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		logger.Error(ctx, fmt.Sprintf("sendSetCaptureProtocols() send error. %s ", err))
+		return nil
+	}
+
+	return nil
+}
+
+func sendGetTrafficControlReferenceTable(ctx context.Context, device L2oamDevice, oc *l2oam.TomiObjectContext) *l2oam.GetTrafficControlReferenceTableRes {
+	if err := device.send(l2oam.GenerateGetTrafficControlReferenceTableReq(oc)); err != nil {
+		return nil
+	}
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		logger.Error(ctx, fmt.Sprintf("sendGetTrafficControlReferenceTable() send error. %s ", err))
+		return nil
+	}
+	packet := &l2oam.GetTrafficControlReferenceTableRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	return packet
+}
+
+func sendSetGenericActionCreate(ctx context.Context, device L2oamDevice, actionType int) *l2oam.SetGenericActionCreateRes {
+	if err := device.send(l2oam.GenerateGenericActionCreate(actionType)); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		logger.Error(ctx, fmt.Sprintf("[%s] sendSetGenericActionCreate() Send Error: %v", device.getDeviceName(), err))
+		return nil
+	}
+	packet := &l2oam.SetGenericActionCreateRes{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetGenericActionCreate() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return packet
+}
+
+func sendSetTrafficControl(ctx context.Context, device L2oamDevice, trafficControl []byte, trafficProfile []byte) error {
+
+	if err := device.send(l2oam.GenerateTrafficControlTrafficProfile(trafficControl, trafficProfile)); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetTrafficControl() Send Error: %v", device.getDeviceName(), err)
+	}
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetTrafficControl() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+func sendSetPriority(ctx context.Context, device L2oamDevice, trafficProfile []byte) error {
+	if err := device.send(l2oam.GeneratePriority(trafficProfile)); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetPriority() Send Error: %v", device.getDeviceName(), err)
+	}
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetPriority() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+func sendSetGuranteedRate(ctx context.Context, device L2oamDevice, cir []byte, trafficProfile []byte) error {
+	if err := device.send(l2oam.GenerateGuaranteedRate(cir, trafficProfile)); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetGuranteedRate() Send Error: %v", device.getDeviceName(), err)
+	}
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetGuranteedRate() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+// func sendSetGuranteedMbs(ctx context.Context, device L2oamDevice) error {
+// 	if err := device.send(l2oam.GenerateGuaranteedMbs()); err != nil {
+// 		return nil
+// 	}
+
+// 	ether, err := device.waitResponse(ResponseTimer)
+// 	if err != nil {
+// 		return fmt.Errorf("[%s] sendSetGuranteedMbs() Send Error: %v", device.getDeviceName(), err)
+// 	}
+// 	packet := &l2oam.TOAMSetResponse{}
+// 	//packet.Decode(ether.Payload)
+
+// 	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetGuranteedMbs() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+// 	return nil
+// }
+
+func sendSetBestEffortRate(ctx context.Context, device L2oamDevice, pir []byte, trafficProfile []byte) error {
+	if err := device.send(l2oam.GenerateBestEffortRate(pir, trafficProfile)); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetBestEffortRate() Send Error: %v", device.getDeviceName(), err)
+	}
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetBestEffortRate() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+// func sendSetBestEffortMbs(ctx context.Context, device L2oamDevice) error {
+// 	if err := device.send(l2oam.GenerateBestEffortMbs()); err != nil {
+// 		return nil
+// 	}
+
+// 	ether, err := device.waitResponse(ResponseTimer)
+// 	if err != nil {
+// 		return fmt.Errorf("[%s] sendSetBestEffortMbs() Send Error: %v", device.getDeviceName(), err)
+// 	}
+// 	packet := &l2oam.TOAMSetResponse{}
+// 	//packet.Decode(ether.Payload)
+
+// 	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetBestEffortMbs() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+// 	return nil
+// }
+
+func sendSetGenericActionCreateForDS(ctx context.Context, device L2oamDevice) (*l2oam.TomiObjectContext, error) {
+	if err := device.send(l2oam.GenerateGenericActionCreateDs()); err != nil {
+		return nil, nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return nil, fmt.Errorf("[%s] sendSetGenericActionCreateForDS() Send Error: %v", device.getDeviceName(), err)
+	}
+	oc := &l2oam.TomiObjectContext{}
+
+	i := 29
+	oc.Branch = ether.Payload[i]
+	i++
+	oc.Type = binary.BigEndian.Uint16(ether.Payload[i : i+2])
+	i += 2
+	oc.Length = ether.Payload[i]
+	i++
+	oc.Instance = binary.BigEndian.Uint32(ether.Payload[i : i+4])
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetGenericActionCreateForDS() Success, response=%x, branch=%x, type=%x, length=%x, instance=%x",
+		device.getDeviceName(), ether.Payload, oc.Branch, oc.Type, oc.Length, oc.Instance))
+
+	return oc, nil
+}
+
+func sendSetL2SwitchingDomainForDS(ctx context.Context, device L2oamDevice, oc *l2oam.TomiObjectContext, tpid []byte, vid []byte) error {
+	tibitData := l2oam.GenerateL2switchingDomainActionLnletEntryDs(oc, tpid, vid)
+	if err := device.send(tibitData); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetL2SwitchingDomain() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetL2SwitchingDomain() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+func sendSetDefaultOutlet(ctx context.Context, device L2oamDevice, oc *l2oam.TomiObjectContext, onuID *l2oam.TomiObjectContext) error {
+	tibitData := l2oam.GenerateSetDefaultOutlet(oc, onuID)
+	if err := device.send(tibitData); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetDefaultOutlet() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetDefaultOutlet() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+func sendSetL2SwitchingDomainForUS(ctx context.Context, device L2oamDevice, oc *l2oam.TomiObjectContext,
+	tpid []byte, vid []byte, onuID *l2oam.TomiObjectContext) error {
+	tibitData := l2oam.GenerateL2switchingDomainActionLnletEntryUs(oc, tpid, vid, onuID)
+	if err := device.send(tibitData); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetL2SwitchingDomainForUS() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetL2SwitchingDomainForUS() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+
+	return nil
+}
+
+func sendSetActionReset(ctx context.Context, device L2oamDevice) error {
+	if err := device.send(l2oam.GenerateSetActionReset()); err != nil {
+		return nil
+	}
+
+	ether, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetActionReset() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	packet := &l2oam.TOAMSetResponse{}
+	if err := packet.Decode(ether.Payload); err != nil {
+		return nil
+	}
+	logger.Debug(ctx, fmt.Sprintf("[%s] sendSetActionReset() Success, response=%x:%s", device.getDeviceName(), ether.Payload, packet))
+	return nil
+}
+
+func sendSetTrafficProfile(ctx context.Context, device L2oamDevice,
+	trafficControl []byte, trafficProfile []byte) error {
+	if err := device.send(l2oam.GenerateSetTrafficProfile(trafficControl, trafficProfile)); err != nil {
+		return err
+	}
+
+	if _, err := device.waitResponse(ResponseTimer); err != nil {
+		return fmt.Errorf("[%s] sendSetTrafficProfile() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}
+
+func sendSetActionDelete(ctx context.Context, device L2oamDevice, trafficProfile []byte, actionType int) error {
+	if err := device.send(l2oam.GenerateSetActionDelete(trafficProfile, actionType)); err != nil {
+		return nil
+	}
+
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetActionDelete() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}
+
+func sendSetActionDeleteOnu(ctx context.Context, device L2oamDevice, oc *l2oam.TomiObjectContext) error {
+	logger.Debug(ctx, "sendSetActionDeleteOnu() Start.")
+	if err := device.send(l2oam.GenerateSetActionDeleteOnu(oc)); err != nil {
+		return nil
+	}
+
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetActionDeleteOnu() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}
+
+func sendSetManagementLock(ctx context.Context, device L2oamDevice) error {
+	if err := device.send(l2oam.GenerateSetManagementLock()); err != nil {
+		return nil
+	}
+
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetManagementLock() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}
+
+func sendSetActionInletEntryDsDel(ctx context.Context, device L2oamDevice,
+	oc *l2oam.TomiObjectContext, tpid []byte, vid []byte) error {
+	if err := device.send(l2oam.GenerateL2switchingDomainActionInletEntryDsDel(oc, tpid, vid)); err != nil {
+		return nil
+	}
+
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetActionInletEntryDsDel() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}
+
+func sendSetActionInletEntryUsDel(ctx context.Context, device L2oamDevice,
+	oc *l2oam.TomiObjectContext, tpid []byte, vid []byte, onuID *l2oam.TomiObjectContext) error {
+	if err := device.send(l2oam.GenerateL2switchingDomainActionInletEntryUsDel(oc, tpid, vid, onuID)); err != nil {
+		return nil
+	}
+
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetActionInletEntryUsDel() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}
+
+func sendSetActionDeleteStream(ctx context.Context, device L2oamDevice, oc *l2oam.TomiObjectContext) error {
+	if err := device.send(l2oam.GenerateSetActionDeleteStream(oc)); err != nil {
+		return nil
+	}
+
+	_, err := device.waitResponse(ResponseTimer)
+	if err != nil {
+		return fmt.Errorf("[%s] sendSetActionDeleteStream() Send Error: %v", device.getDeviceName(), err)
+	}
+
+	return nil
+}