[VOL-5561] Handle Multiple ONU Indications for a device at ONU Adapter
Change-Id: I5ecbd46b2e186c76357d82171f8bf01de2729fc2
Signed-off-by: bseeniva <balaji.seenivasan@radisys.com>
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 6b12134..adaa761 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -25,6 +25,7 @@
"sync"
"time"
+ "github.com/golang/protobuf/ptypes/empty"
"github.com/opencord/voltha-openonu-adapter-go/internal/pkg/config"
"github.com/gogo/protobuf/proto"
@@ -77,19 +78,16 @@
const (
// events of Device FSM
- devEvDeviceInit = "devEvDeviceInit"
- devEvGrpcConnected = "devEvGrpcConnected"
- devEvGrpcDisconnected = "devEvGrpcDisconnected"
- devEvDeviceUpInd = "devEvDeviceUpInd"
- devEvDeviceDownInd = "devEvDeviceDownInd"
+ devEvDeviceInit = "devEvDeviceInit"
+ devEvDeviceUpInd = "devEvDeviceUpInd"
+ devEvDeviceDownInd = "devEvDeviceDownInd"
)
const (
// states of Device FSM
- devStNull = "devStNull"
- devStDown = "devStDown"
- devStInit = "devStInit"
- devStConnected = "devStConnected"
- devStUp = "devStUp"
+ devStNull = "devStNull"
+ devStDown = "devStDown"
+ devStInit = "devStInit"
+ devStUp = "devStUp"
)
// Event category and subcategory definitions - same as defiend for OLT in eventmgr.go - should be done more centrally
@@ -301,20 +299,15 @@
devStNull,
fsm.Events{
{Name: devEvDeviceInit, Src: []string{devStNull, devStDown}, Dst: devStInit},
- {Name: devEvGrpcConnected, Src: []string{devStInit}, Dst: devStConnected},
- {Name: devEvGrpcDisconnected, Src: []string{devStConnected, devStDown}, Dst: devStInit},
- {Name: devEvDeviceUpInd, Src: []string{devStConnected, devStDown}, Dst: devStUp},
+ {Name: devEvDeviceUpInd, Src: []string{devStInit, devStDown}, Dst: devStUp},
{Name: devEvDeviceDownInd, Src: []string{devStUp}, Dst: devStDown},
},
fsm.Callbacks{
- "before_event": func(e *fsm.Event) { dh.logStateChange(ctx, e) },
- ("before_" + devEvDeviceInit): func(e *fsm.Event) { dh.doStateInit(ctx, e) },
- ("after_" + devEvDeviceInit): func(e *fsm.Event) { dh.postInit(ctx, e) },
- ("before_" + devEvGrpcConnected): func(e *fsm.Event) { dh.doStateConnected(ctx, e) },
- ("before_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.doStateInit(ctx, e) },
- ("after_" + devEvGrpcDisconnected): func(e *fsm.Event) { dh.postInit(ctx, e) },
- ("before_" + devEvDeviceUpInd): func(e *fsm.Event) { dh.doStateUp(ctx, e) },
- ("before_" + devEvDeviceDownInd): func(e *fsm.Event) { dh.doStateDown(ctx, e) },
+ "before_event": func(e *fsm.Event) { dh.logStateChange(ctx, e) },
+ ("before_" + devEvDeviceInit): func(e *fsm.Event) { dh.doStateInit(ctx, e) },
+ ("after_" + devEvDeviceInit): func(e *fsm.Event) { dh.postInit(ctx, e) },
+ ("before_" + devEvDeviceUpInd): func(e *fsm.Event) { dh.doStateUp(ctx, e) },
+ ("before_" + devEvDeviceDownInd): func(e *fsm.Event) { dh.doStateDown(ctx, e) },
},
)
@@ -914,7 +907,13 @@
}
}
if onuIndication.OperState == "up" {
- if err := dh.createInterface(ctx, &onuIndication); err != nil {
+ if !dh.pDeviceStateFsm.Can(devEvDeviceUpInd) {
+ logger.Errorw(ctx, "invalid state transition for event device up indication", log.Fields{"currentState": dh.pDeviceStateFsm.Current()})
+ dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
+ return
+ }
+ err := dh.pDeviceStateFsm.Event(devEvDeviceUpInd, &onuIndication)
+ if err != nil {
logger.Errorw(ctx, "failed to handle device up indication", log.Fields{"device-id": dh.DeviceID, "error": err})
dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
return
@@ -2172,25 +2171,15 @@
logger.Debugw(ctx, "postInit-done", log.Fields{"device-id": dh.DeviceID})
}
-// doStateConnected get the device info and update to voltha core
-// for comparison of the original method (not that easy to uncomment): compare here:
-//
-// voltha-openolt-adapter/adaptercore/device_handler.go
-// -> this one obviously initiates all communication interfaces of the device ...?
-func (dh *deviceHandler) doStateConnected(ctx context.Context, e *fsm.Event) {
-
- logger.Debugw(ctx, "doStateConnected-started", log.Fields{"device-id": dh.DeviceID})
- err := errors.New("device FSM: function not implemented yet")
- e.Cancel(err)
- logger.Debugw(ctx, "doStateConnected-done", log.Fields{"device-id": dh.DeviceID})
-}
-
// doStateUp handle the onu up indication and update to voltha core
func (dh *deviceHandler) doStateUp(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "doStateUp-started", log.Fields{"device-id": dh.DeviceID})
- err := errors.New("device FSM: function not implemented yet")
- e.Cancel(err)
+ onuIndication := e.Args[0].(*oop.OnuIndication)
+ if err := dh.createInterface(ctx, onuIndication); err != nil {
+ logger.Errorw(ctx, "failed to create interface", log.Fields{"device-id": dh.DeviceID, "error": err})
+ e.Cancel(err)
+ }
logger.Debugw(ctx, "doStateUp-done", log.Fields{"device-id": dh.DeviceID})
/*
@@ -2219,7 +2208,12 @@
}
cloned := proto.Clone(device).(*voltha.Device)
+
logger.Debugw(ctx, "do-state-down", log.Fields{"ClonedDeviceID": cloned.Id})
+ if err := dh.UpdateInterface(ctx); err != nil {
+ logger.Errorw(ctx, "failed to update interface", log.Fields{"device-id": dh.DeviceID, "error": err})
+ e.Cancel(err)
+ }
/*
// Update the all ports state on that device to disable
if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
@@ -2262,8 +2256,6 @@
logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
return nil
*/
- err = errors.New("device FSM: function not implemented yet")
- e.Cancel(err)
logger.Debugw(ctx, "doStateDown-done", log.Fields{"device-id": dh.DeviceID})
}
@@ -2343,12 +2335,7 @@
"OnuIntfId": onuind.GetIntfId(), "OnuSerialNumber": onuind.GetSerialNumber()})
dh.pOnuIndication = onuind // let's revise if storing the pointer is sufficient...
-
- pDevEntry := dh.GetOnuDeviceEntry(ctx, true)
- if pDevEntry == nil {
- logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.DeviceID})
- return fmt.Errorf("no valid OnuDevice: %s", dh.DeviceID)
- }
+ pDevEntry := dh.pOnuOmciDevice
if !dh.IsReconciling() {
logger.Debugw(ctx, "call DeviceStateUpdate upon create interface", log.Fields{"ConnectStatus": voltha.ConnectStatus_REACHABLE,
@@ -5338,6 +5325,55 @@
return dh.deviceDeleteCommChan
}
+func (dh *deviceHandler) processOnuIndication(ctx context.Context, onuInd *ia.OnuIndicationMessage) (*empty.Empty, error) {
+
+ onuIndication := onuInd.OnuIndication
+ onuOperstate := onuIndication.GetOperState()
+
+ if dh.GetDeletionInProgress() {
+ logger.Warnw(ctx, "device deletion in progress, ignoring the ONU Indication", log.Fields{"device-id": dh.DeviceID})
+ return nil, fmt.Errorf("device deletion in progress for device-id: %s", dh.DeviceID)
+ }
+
+ logger.Infow(ctx, "onu-ind-request", log.Fields{"device-id": dh.DeviceID,
+ "OnuId": onuIndication.GetOnuId(),
+ "AdminState": onuIndication.GetAdminState(), "OperState": onuOperstate,
+ "SNR": onuIndication.GetSerialNumber()})
+
+ pDevEntry := dh.GetOnuDeviceEntry(ctx, true)
+ if pDevEntry == nil {
+ logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.DeviceID})
+ return nil, fmt.Errorf("no valid OnuDevice: %s", dh.DeviceID)
+ }
+
+ var event string
+
+ switch onuOperstate {
+ case "up":
+ if dh.pDeviceStateFsm.Current() == devStUp {
+ logger.Errorw(ctx, "invalid state transition", log.Fields{"expectedState": devStDown, "currentState": dh.pDeviceStateFsm.Current()})
+ return nil, fmt.Errorf("invalid state transition: expected %s, got %s", devStDown, dh.pDeviceStateFsm.Current())
+ }
+ event = devEvDeviceUpInd
+ case "down", "unreachable":
+ if dh.pDeviceStateFsm.Current() == devStDown {
+ logger.Errorw(ctx, "invalid state transition", log.Fields{"expectedState": devStUp, "currentState": dh.pDeviceStateFsm.Current()})
+ return nil, fmt.Errorf("invalid state transition: expected %s, got %s", devStUp, dh.pDeviceStateFsm.Current())
+ }
+ event = devEvDeviceDownInd
+ default:
+ logger.Errorw(ctx, "unknown-onu-ind-request operState", log.Fields{"OnuId": onuIndication.GetOnuId()})
+ return nil, fmt.Errorf("invalidOperState: %s, %s", onuOperstate, dh.DeviceID)
+ }
+
+ err := dh.pDeviceStateFsm.Event(event, onuIndication)
+ if err != nil {
+ return nil, err
+ }
+
+ return &empty.Empty{}, nil
+}
+
// PrepareForGarbageCollection - remove references to prepare for garbage collection
func (dh *deviceHandler) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})