[VOL-3606] Multiple ONUs do not reach proper activation with MIB template (BBSIM issue)
Change-Id: Ic954f202c858a561876d3cfe5bd6569b152b2d17
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index 2d1ea5a..5fbaa31 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -38,6 +38,7 @@
//OpenONUAC structure holds the ONU core information
type OpenONUAC struct {
deviceHandlers map[string]*deviceHandler
+ deviceHandlersCreateChan map[string]chan bool //channels for deviceHandler create events
coreProxy adapterif.CoreProxy
adapterProxy adapterif.AdapterProxy
eventProxy adapterif.EventProxy
@@ -66,6 +67,7 @@
var openOnuAc OpenONUAC
openOnuAc.exitChannel = make(chan int, 1)
openOnuAc.deviceHandlers = make(map[string]*deviceHandler)
+ openOnuAc.deviceHandlersCreateChan = make(map[string]chan bool)
openOnuAc.kafkaICProxy = kafkaICProxy
openOnuAc.config = cfg
openOnuAc.numOnus = cfg.OnuNumber
@@ -127,24 +129,45 @@
if _, exist := oo.deviceHandlers[agent.deviceID]; !exist {
oo.deviceHandlers[agent.deviceID] = agent
oo.deviceHandlers[agent.deviceID].start(ctx)
+ if _, exist := oo.deviceHandlersCreateChan[agent.deviceID]; exist {
+ logger.Debugw("deviceHandler created - trigger processing of pending ONU_IND_REQUEST", log.Fields{"device-id": agent.deviceID})
+ oo.deviceHandlersCreateChan[agent.deviceID] <- true
+ }
}
}
-/*
func (oo *OpenONUAC) deleteDeviceHandlerToMap(agent *deviceHandler) {
oo.lockDeviceHandlersMap.Lock()
defer oo.lockDeviceHandlersMap.Unlock()
delete(oo.deviceHandlers, agent.deviceID)
+ delete(oo.deviceHandlersCreateChan, agent.deviceID)
}
-*/
-func (oo *OpenONUAC) getDeviceHandler(deviceID string) *deviceHandler {
+//getDeviceHandler gets the ONU deviceHandler and may wait until it is created
+func (oo *OpenONUAC) getDeviceHandler(deviceID string, aWait bool) *deviceHandler {
oo.lockDeviceHandlersMap.Lock()
- defer oo.lockDeviceHandlersMap.Unlock()
- if agent, ok := oo.deviceHandlers[deviceID]; ok {
- return agent
+ agent, ok := oo.deviceHandlers[deviceID]
+ if aWait && !ok {
+ logger.Debugw("deviceHandler not present - wait for creation or timeout", log.Fields{"device-id": deviceID})
+ if _, exist := oo.deviceHandlersCreateChan[deviceID]; !exist {
+ oo.deviceHandlersCreateChan[deviceID] = make(chan bool, 1)
+ }
+ //keep the read sema short to allow for subsequent write
+ oo.lockDeviceHandlersMap.Unlock()
+ // based on concurrent processing the deviceHandler creation may not yet be finished at his point
+ // so it might be needed to wait here for that event with some timeout
+ select {
+ case <-time.After(1 * time.Second): //timer may be discussed ...
+ logger.Warnw("No valid deviceHandler created after max WaitTime", log.Fields{"device-id": deviceID})
+ return nil
+ case <-oo.deviceHandlersCreateChan[deviceID]:
+ logger.Debugw("deviceHandler is ready now - continue", log.Fields{"device-id": deviceID})
+ // if written now, we can return the written value without sema
+ return oo.deviceHandlers[deviceID]
+ }
}
- return nil
+ oo.lockDeviceHandlersMap.Unlock()
+ return agent
}
// Adapter interface required methods ############## begin #########
@@ -162,7 +185,7 @@
ctx := context.Background()
logger.Infow("adopt-device", log.Fields{"device-id": device.Id})
var handler *deviceHandler
- if handler = oo.getDeviceHandler(device.Id); handler == nil {
+ if handler = oo.getDeviceHandler(device.Id, false); handler == nil {
handler := newDeviceHandler(oo.coreProxy, oo.adapterProxy, oo.eventProxy, device, oo)
oo.addDeviceHandlerToMap(ctx, handler)
go handler.adoptOrReconcileDevice(ctx, device)
@@ -187,9 +210,22 @@
logger.Debugw("Process_inter_adapter_message", log.Fields{"msgId": msg.Header.Id,
"msgProxyDeviceId": msg.Header.ProxyDeviceId, "msgToDeviceId": msg.Header.ToDeviceId})
+ var waitForDhInstPresent bool
+ //ToDeviceId should address a DeviceHandler instance
targetDevice := msg.Header.ToDeviceId
- //ToDeviceId should address an DeviceHandler instance
- if handler := oo.getDeviceHandler(targetDevice); handler != nil {
+ // As a workaround this handling is only required for the OnuIndication with OperState=Up event.
+ // But we live without that further check and use this processing also for OperState down/unreachable events to avoid
+ // the deeper message processing at this stage. Should do no harm on the other events (except for run time)
+ if msg.Header.Type != ic.InterAdapterMessageType_ONU_IND_REQUEST {
+ waitForDhInstPresent = false
+ } else {
+ //Race condition (relevant in BBSIM-environment only): Due to unsynchronized processing of olt-adapter and rw_core,
+ //ONU_IND_REQUEST msg by olt-adapter could arrive a little bit earlier than rw_core was able to announce the corresponding
+ //ONU by RPC of Adopt_device()
+ logger.Debugw("ONU_IND_REQUEST - potentially wait until DeviceHandler instance is created", log.Fields{"device-id": targetDevice})
+ waitForDhInstPresent = true
+ }
+ if handler := oo.getDeviceHandler(targetDevice, waitForDhInstPresent); handler != nil {
/* 200724: modification towards synchronous implementation - possible errors within processing shall be
* in the accordingly delayed response, some timing effect might result in Techprofile processing for multiple UNI's
*/
@@ -232,7 +268,7 @@
ctx := context.Background()
logger.Infow("Reconcile_device", log.Fields{"device-id": device.Id})
var handler *deviceHandler
- if handler = oo.getDeviceHandler(device.Id); handler == nil {
+ if handler = oo.getDeviceHandler(device.Id, false); handler == nil {
handler := newDeviceHandler(oo.coreProxy, oo.adapterProxy, oo.eventProxy, device, oo)
oo.addDeviceHandlerToMap(ctx, handler)
handler.device = device
@@ -253,7 +289,7 @@
//Disable_device disables the given device
func (oo *OpenONUAC) Disable_device(device *voltha.Device) error {
logger.Debugw("Disable_device", log.Fields{"device-id": device.Id})
- if handler := oo.getDeviceHandler(device.Id); handler != nil {
+ if handler := oo.getDeviceHandler(device.Id, false); handler != nil {
go handler.disableDevice(device)
return nil
}
@@ -264,7 +300,7 @@
//Reenable_device enables the onu device after disable
func (oo *OpenONUAC) Reenable_device(device *voltha.Device) error {
logger.Debugw("Reenable_device", log.Fields{"device-id": device.Id})
- if handler := oo.getDeviceHandler(device.Id); handler != nil {
+ if handler := oo.getDeviceHandler(device.Id, false); handler != nil {
go handler.reEnableDevice(device)
return nil
}
@@ -275,7 +311,7 @@
//Reboot_device reboots the given device
func (oo *OpenONUAC) Reboot_device(device *voltha.Device) error {
logger.Debugw("Reboot-device", log.Fields{"device-id": device.Id})
- if handler := oo.getDeviceHandler(device.Id); handler != nil {
+ if handler := oo.getDeviceHandler(device.Id, false); handler != nil {
go handler.rebootDevice(device)
return nil
}
@@ -291,12 +327,15 @@
// Delete_device deletes the given device
func (oo *OpenONUAC) Delete_device(device *voltha.Device) error {
logger.Debugw("Delete_device", log.Fields{"device-id": device.Id})
- if handler := oo.getDeviceHandler(device.Id); handler != nil {
- if err := handler.deleteDevice(device); err != nil {
+ if handler := oo.getDeviceHandler(device.Id, false); handler != nil {
+ err := handler.deleteDevice(device)
+ //don't leave any garbage - even in error case
+ oo.deleteDeviceHandlerToMap(handler)
+ if err != nil {
return err
}
} else {
- logger.Warnw("no handler found for device-reconcilement", log.Fields{"device-id": device.Id})
+ logger.Warnw("no handler found for device-deletion", log.Fields{"device-id": device.Id})
return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", device.Id))
}
return nil
@@ -332,7 +371,7 @@
logger.Warnw("Update-flow-incr: group update not supported (ignored)", log.Fields{"device-id": device.Id})
}
- if handler := oo.getDeviceHandler(device.Id); handler != nil {
+ if handler := oo.getDeviceHandler(device.Id, false); handler != nil {
err := handler.FlowUpdateIncremental(flows, groups, flowMetadata)
return err
}