SPON-3043 [WIP] Added Reboot of device admin based on external (northbound) config requests
Change-Id: I0af1e3aa7fd73ddc537327e94894d4050683aa3a
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index d1cb6f3..023a1fa 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -493,6 +493,74 @@
return nil
}
+func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
+ logger.Debugw("reboot-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+ if device.ConnectStatus != voltha.ConnectStatus_REACHABLE {
+ logger.Errorw("device-unreachable", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+ return errors.New("device-unreachable")
+ }
+ dh.pOnuOmciDevice.Reboot(context.TODO())
+ if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_UNREACHABLE,
+ voltha.OperStatus_DISCOVERED); err != nil {
+ logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+ return err
+ }
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "rebooting-onu"); err != nil {
+ logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+ return err
+ }
+ dh.deviceReason = "rebooting-onu"
+ return nil
+}
+
+//GetOfpPortInfo returns the Voltha PortCapabilty with the logical port
+//func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
+// portNo int64) (*ic.PortCapability, error) {
+// logger.Debugw("GetOfpPortInfo start", log.Fields{"deviceID": device.Id, "portNo": portNo})
+
+//function body as per OLTAdapter handler code
+// adapted with values from py dapter code
+// if pUniPort, exist := dh.uniEntityMap[uint32(portNo)]; exist {
+// var macOctets [6]uint8
+// macOctets[5] = 0x08
+// macOctets[4] = uint8(dh.ponPortNumber >> 8)
+// macOctets[3] = uint8(dh.ponPortNumber)
+// macOctets[2] = uint8(portNo >> 16)
+// macOctets[1] = uint8(portNo >> 8)
+// macOctets[0] = uint8(portNo)
+// hwAddr := genMacFromOctets(macOctets)
+// capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
+// name := device.SerialNumber + "-" + strconv.FormatUint(uint64(pUniPort.macBpNo), 10)
+// ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
+// if pUniPort.operState == vc.OperStatus_ACTIVE {
+// ofUniPortState = of.OfpPortState_OFPPS_LIVE
+// }
+// logger.Debugw("setting LogicalPort", log.Fields{"with-name": name,
+// "withUniPort": pUniPort.name, "withMacBase": hwAddr, "OperState": ofUniPortState})
+
+// return &ic.PortCapability{
+// Port: &voltha.LogicalPort{
+// OfpPort: &of.OfpPort{
+// Name: name,
+// //HwAddr: macAddressToUint32Array(dh.device.MacAddress),
+// HwAddr: macAddressToUint32Array(hwAddr),
+// Config: 0,
+// State: uint32(ofUniPortState),
+// Curr: capacity,
+// Advertised: capacity,
+// Peer: capacity,
+// CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
+// MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
+// },
+// DeviceId: device.Id,
+// DevicePortNo: uint32(portNo),
+// },
+// }, nil
+// }
+// logger.Warnw("No UniPort found - abort", log.Fields{"for PortNo": uint32(portNo)})
+// return nil, errors.New("UniPort not found")
+//}
+
// DeviceHandler methods that implement the adapters interface requests## end #########
// #####################################################################################
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 5b2b33e..04d8a39 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -25,7 +25,6 @@
"errors"
"strconv"
"sync"
-
//"time"
"github.com/google/gopacket"
@@ -581,6 +580,40 @@
return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
}
+func (oo *OmciCC) sendReboot(ctx context.Context, timeout int, highPrio bool, responseChannel chan Message) error {
+ logger.Debugw("send Reboot-msg to:", log.Fields{"deviceId": oo.deviceID})
+ request := &omci.RebootRequest{
+ MeBasePacket: omci.MeBasePacket{
+ EntityClass: me.OnuGClassID,
+ },
+ }
+ tid := oo.GetNextTid(highPrio)
+ pkt, err := serialize(omci.RebootRequestType, request, tid)
+ if err != nil {
+ logger.Errorw("Cannot serialize RebootRequest", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return err
+ }
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{oo.pOnuDeviceEntry.omciRebootMessageReceivedChannel, oo.receiveOmciResponse},
+ }
+
+ err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send RebootRequest", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return err
+ }
+ err = oo.pOnuDeviceEntry.waitForRebootResponse(responseChannel)
+ if err != nil {
+ logger.Error("aborting ONU Reboot!")
+ oo.pOnuDeviceEntry.pMibDownloadFsm.pFsm.Event("reset")
+ return err
+ }
+ return nil
+}
+
func (oo *OmciCC) sendMibUpload(ctx context.Context, timeout int, highPrio bool) error {
logger.Debugw("send MibUpload-msg to:", log.Fields{"deviceId": oo.deviceID})
request := &omci.MibUploadRequest{
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index b623bf9..53101be 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -20,6 +20,9 @@
import (
"context"
"errors"
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "time"
//"sync"
//"time"
@@ -195,7 +198,8 @@
pMibDownloadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
//remark: general usage of pAdapterFsm would require generalization of commChan usage and internal event setting
// within the FSM event procedures
- omciMessageReceived chan bool //seperate channel needed by DownloadFsm
+ omciMessageReceived chan bool //seperate channel needed by DownloadFsm
+ omciRebootMessageReceivedChannel chan Message // channel needed by Reboot request
}
//OnuDeviceEntry returns a new instance of a OnuDeviceEntry
@@ -211,6 +215,7 @@
onuDeviceEntry.coreProxy = core_proxy
onuDeviceEntry.adapterProxy = adapter_proxy
onuDeviceEntry.devState = DeviceStatusInit
+ onuDeviceEntry.omciRebootMessageReceivedChannel = make(chan Message, 2048)
//openomciagent.lockDeviceHandlersMap = sync.RWMutex{}
//OMCI related databases are on a per-agent basis. State machines and tasks
//are per ONU Vendor
@@ -389,6 +394,47 @@
return nil
}
+func (oo *OnuDeviceEntry) Reboot(ctx context.Context) error {
+ logger.Info("reboot-OnuDeviceEntry")
+ if err := oo.PDevOmciCC.sendReboot(context.TODO(), ConstDefaultOmciTimeout, true, oo.omciRebootMessageReceivedChannel); err != nil {
+ logger.Errorw("onu didn't reboot", log.Fields{"for device": oo.deviceID})
+ return err
+ }
+ logger.Info("OnuDeviceEntry-reboot")
+ return nil
+}
+
+func (oo *OnuDeviceEntry) waitForRebootResponse(responseChannel chan Message) error {
+ select {
+ case <-time.After(3 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
+ logger.Warnw("Reboot timeout", log.Fields{"for device-id": oo.deviceID})
+ return errors.New("RebootTimeout")
+ case data := <-responseChannel:
+ switch data.Data.(OmciMessage).OmciMsg.MessageType {
+ case omci.RebootResponseType:
+ {
+ msgLayer := (*data.Data.(OmciMessage).OmciPacket).Layer(omci.LayerTypeRebootResponse)
+ if msgLayer == nil {
+ return errors.New("Omci Msg layer could not be detected for RebootResponseType")
+ }
+ msgObj, msgOk := msgLayer.(*omci.GetResponse)
+ if !msgOk {
+ return errors.New("Omci Msg layer could not be assigned for RebootResponseType")
+ }
+ logger.Debugw("CreateResponse Data", log.Fields{"deviceId": oo.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success {
+ logger.Errorw("Omci RebootResponseType Error ", log.Fields{"Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return errors.New("Omci RebootResponse Result Error indication")
+ }
+ return nil
+ }
+ }
+ logger.Warnw("Reboot response error", log.Fields{"for device-id": oo.deviceID})
+ return errors.New("Unexpected OmciResponse type received")
+ }
+}
+
//Relay the InSync message via Handler to Rw core - Status update
func (oo *OnuDeviceEntry) transferSystemEvent(dev_Event OnuDeviceEvent) error {
logger.Debugw("relaying system-event", log.Fields{"Event": dev_Event})
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index 06790bc..7250e18 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -258,7 +258,13 @@
//Reboot_device reboots the given device
func (oo *OpenONUAC) Reboot_device(device *voltha.Device) error {
- return errors.New("unImplemented")
+ logger.Debugw("Reboot-device", log.Fields{"deviceId": device.Id})
+ if handler := oo.getDeviceHandler(device.Id); handler != nil {
+ go handler.RebootDevice(device)
+ return nil
+ }
+ logger.Warnw("no handler found for device-reboot", log.Fields{"deviceId": device.Id})
+ return fmt.Errorf(fmt.Sprintf("handler-not-found-#{device.Id}"))
}
//Self_test_device unimplemented