VOL-3052 Onu Software preliminary upgrade test from Adapter to ONU, version 1.2.5-dev168

Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I5f48645fa8b392c2c79f13cf8fd0d2369bfd5ca5
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 1ad4e8b..a21761b 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -25,9 +25,7 @@
 	"fmt"
 	"strconv"
 	"sync"
-	"time"
-
-	//"time"
+	"time" //by now for testing
 
 	"github.com/google/gopacket"
 	// TODO!!! Some references could be resolved auto, but some need specific context ....
@@ -81,6 +79,7 @@
 type callbackPairEntry struct {
 	cbRespChannel chan Message
 	cbFunction    func(context.Context, *omci.OMCI, *gp.Packet, chan Message) error
+	framePrint    bool //true for printing
 }
 
 //callbackPair to be used for ReceiveCallback init
@@ -90,10 +89,11 @@
 }
 
 type omciTransferStructure struct {
-	txFrame  []byte
-	timeout  int
-	retry    int
-	highPrio bool
+	txFrame        []byte
+	timeout        int
+	retry          int
+	highPrio       bool
+	withFramePrint bool
 }
 
 //omciCC structure holds information needed for OMCI communication (to/from OLT Adapter)
@@ -258,6 +258,14 @@
 	*/
 }
 
+func (oo *omciCC) printRxMessage(ctx context.Context, rxMsg []byte) {
+	//assuming omci message content is hex coded!
+	// with restricted output of 16bytes would be ...rxMsg[:16]
+	logger.Debugw(ctx, "omci-message-received:", log.Fields{
+		"RxOmciMessage": hex.EncodeToString(rxMsg),
+		"device-id":     oo.deviceID})
+}
+
 // Rx handler for onu messages
 //    e.g. would call ReceiveOnuMessage() in case of TID=0 or Action=test ...
 func (oo *omciCC) receiveMessage(ctx context.Context, rxMsg []byte) error {
@@ -293,28 +301,33 @@
 	} else {
 		logger.Errorw(ctx, "received omci-message too small for OmciBaseFormat - abort",
 			log.Fields{"Length": len(rxMsg), "device-id": oo.deviceID})
+		oo.printRxMessage(ctx, rxMsg)
 		return fmt.Errorf("rxOmciMessage too small for BaseFormat %s", oo.deviceID)
 	}
 
 	packet := gopacket.NewPacket(rxMsg, omci.LayerTypeOMCI, gopacket.NoCopy)
 	if packet == nil {
 		logger.Errorw(ctx, "omci-message could not be decoded", log.Fields{"device-id": oo.deviceID})
+		oo.printRxMessage(ctx, rxMsg)
 		return fmt.Errorf("could not decode rxMsg as OMCI %s", oo.deviceID)
 	}
 	omciLayer := packet.Layer(omci.LayerTypeOMCI)
 	if omciLayer == nil {
 		logger.Errorw(ctx, "omci-message could not decode omci layer", log.Fields{"device-id": oo.deviceID})
+		oo.printRxMessage(ctx, rxMsg)
 		return fmt.Errorf("could not decode omci layer %s", oo.deviceID)
 	}
 	omciMsg, ok := omciLayer.(*omci.OMCI)
 	if !ok {
 		logger.Errorw(ctx, "omci-message could not assign omci layer", log.Fields{"device-id": oo.deviceID})
+		oo.printRxMessage(ctx, rxMsg)
 		return fmt.Errorf("could not assign omci layer %s", oo.deviceID)
 	}
 	logger.Debugw(ctx, "omci-message-decoded:", log.Fields{"omciMsgType": omciMsg.MessageType,
 		"transCorrId": strconv.FormatInt(int64(omciMsg.TransactionID), 16), "DeviceIdent": omciMsg.DeviceIdentifier})
 	if byte(omciMsg.MessageType)&me.AK == 0 {
 		// Not a response
+		oo.printRxMessage(ctx, rxMsg)
 		logger.Debug(ctx, "RxMsg is no Omci Response Message")
 		if omciMsg.TransactionID == 0 {
 			return oo.receiveOnuMessage(ctx, omciMsg, &packet)
@@ -329,6 +342,9 @@
 	oo.mutexRxSchedMap.Lock()
 	rxCallbackEntry, ok := oo.rxSchedulerMap[omciMsg.TransactionID]
 	if ok && rxCallbackEntry.cbFunction != nil {
+		if rxCallbackEntry.framePrint {
+			oo.printRxMessage(ctx, rxMsg)
+		}
 		//disadvantage of decoupling: error verification made difficult, but anyway the question is
 		// how to react on erroneous frame reception, maybe can simply be ignored
 		go rxCallbackEntry.cbFunction(ctx, omciMsg, &packet, rxCallbackEntry.cbRespChannel)
@@ -339,13 +355,13 @@
 		// having posted the response the request is regarded as 'done'
 		delete(oo.rxSchedulerMap, omciMsg.TransactionID)
 		oo.mutexRxSchedMap.Unlock()
-	} else {
-		oo.mutexRxSchedMap.Unlock()
-		logger.Errorw(ctx, "omci-message-response for not registered transCorrId", log.Fields{"device-id": oo.deviceID, "omciMsg": omciMsg, "transCorrId": omciMsg.TransactionID})
-		return fmt.Errorf("could not find registered response handler tor transCorrId %s", oo.deviceID)
+		return nil
 	}
+	oo.mutexRxSchedMap.Unlock()
+	logger.Errorw(ctx, "omci-message-response for not registered transCorrId", log.Fields{"device-id": oo.deviceID})
+	oo.printRxMessage(ctx, rxMsg)
+	return fmt.Errorf("could not find registered response handler tor transCorrId %s", oo.deviceID)
 
-	return nil
 	/* py code was:
 	           Receive and OMCI message from the proxy channel to the OLT.
 
@@ -464,6 +480,7 @@
 	// it could be checked, if the callback keay is already registered - but simply overwrite may be acceptable ...
 	oo.mutexRxSchedMap.Lock()
 	oo.rxSchedulerMap[receiveCallbackPair.cbKey] = receiveCallbackPair.cbEntry
+	printFrame := receiveCallbackPair.cbEntry.framePrint //printFrame true means debug print of frame is requested
 	oo.mutexRxSchedMap.Unlock()
 
 	//just use a simple list for starting - might need some more effort, especially for multi source write access
@@ -472,6 +489,7 @@
 		timeout,
 		retry,
 		highPrio,
+		printFrame,
 	}
 	oo.mutexTxQueue.Lock()
 	oo.txQueue.PushBack(omciTxRequest) // enqueue
@@ -556,12 +574,13 @@
 			return fmt.Errorf("failed to fetch device %s", oo.deviceID)
 		}
 
-		logger.Debugw(ctx, "omci-message-to-send:", log.Fields{
-			"TxOmciMessage": hex.EncodeToString(omciTxRequest.txFrame),
-			"device-id":     oo.deviceID,
-			"toDeviceType":  oo.pBaseDeviceHandler.ProxyAddressType,
-			"proxyDeviceID": oo.pBaseDeviceHandler.ProxyAddressID})
-
+		if omciTxRequest.withFramePrint {
+			logger.Debugw(ctx, "omci-message-to-send:", log.Fields{
+				"TxOmciMessage": hex.EncodeToString(omciTxRequest.txFrame),
+				"device-id":     oo.deviceID,
+				"toDeviceType":  oo.pBaseDeviceHandler.ProxyAddressType,
+				"proxyDeviceID": oo.pBaseDeviceHandler.ProxyAddressID})
+		}
 		omciMsg := &ic.InterAdapterOmciMessage{Message: omciTxRequest.txFrame}
 		if sendErr := oo.adapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
 			ic.InterAdapterMessageType_OMCI_REQUEST,
@@ -673,7 +692,7 @@
 	}
 	omciRxCallbackPair := callbackPair{
 		cbKey:   tid,
-		cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+		cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse, true},
 	}
 	return oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 }
@@ -694,7 +713,7 @@
 	}
 	omciRxCallbackPair := callbackPair{
 		cbKey:   tid,
-		cbEntry: callbackPairEntry{oo.pOnuDeviceEntry.omciRebootMessageReceivedChannel, oo.receiveOmciResponse},
+		cbEntry: callbackPairEntry{oo.pOnuDeviceEntry.omciRebootMessageReceivedChannel, oo.receiveOmciResponse, true},
 	}
 
 	err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
@@ -731,7 +750,7 @@
 
 	omciRxCallbackPair := callbackPair{
 		cbKey:   tid,
-		cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+		cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse, true},
 	}
 	return oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 }
@@ -754,8 +773,11 @@
 	oo.uploadSequNo++
 
 	omciRxCallbackPair := callbackPair{
-		cbKey:   tid,
-		cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+		cbKey: tid,
+		//frame printing for MibUpload frames disabled now per default to avoid log file abort situations (size/speed?)
+		// if wanted, rx frame printing should be specifically done within the MibUpload FSM or controlled via extra parameter
+		// compare also software upgrade download section handling
+		cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse, false},
 	}
 	return oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 }
@@ -788,7 +810,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -836,7 +858,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -890,7 +912,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -942,7 +964,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -999,7 +1021,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1044,7 +1066,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1089,7 +1111,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1136,7 +1158,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1182,7 +1204,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1224,7 +1246,7 @@
 		}
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1279,7 +1301,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1322,7 +1344,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1365,7 +1387,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1408,7 +1430,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1449,7 +1471,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1490,7 +1512,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1531,7 +1553,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1577,7 +1599,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1623,7 +1645,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1664,7 +1686,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1705,7 +1727,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1746,7 +1768,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1792,7 +1814,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1838,7 +1860,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1884,7 +1906,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1930,7 +1952,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1976,7 +1998,7 @@
 
 		omciRxCallbackPair := callbackPair{
 			cbKey:   tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -1992,7 +2014,6 @@
 	return nil
 }
 
-// nolint: unused
 func (oo *omciCC) sendCreateMulticastGemIWTPVar(ctx context.Context, timeout int, highPrio bool,
 	rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
 	tid := oo.getNextTid(highPrio)
@@ -2016,7 +2037,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2031,7 +2052,6 @@
 	return nil
 }
 
-// nolint: unused
 func (oo *omciCC) sendSetMulticastGemIWTPVar(ctx context.Context, timeout int, highPrio bool,
 	rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
 	tid := oo.getNextTid(highPrio)
@@ -2055,7 +2075,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2070,7 +2090,6 @@
 	return nil
 }
 
-// nolint: unused
 func (oo *omciCC) sendCreateMulticastOperationProfileVar(ctx context.Context, timeout int, highPrio bool,
 	rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
 	tid := oo.getNextTid(highPrio)
@@ -2096,7 +2115,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2112,7 +2131,6 @@
 	return nil
 }
 
-// nolint: unused
 func (oo *omciCC) sendSetMulticastOperationProfileVar(ctx context.Context, timeout int, highPrio bool,
 	rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
 	tid := oo.getNextTid(highPrio)
@@ -2138,7 +2156,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2154,7 +2172,6 @@
 	return nil
 }
 
-// nolint: unused
 func (oo *omciCC) sendCreateMulticastSubConfigInfoVar(ctx context.Context, timeout int, highPrio bool,
 	rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
 	tid := oo.getNextTid(highPrio)
@@ -2180,7 +2197,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2229,7 +2246,7 @@
 	}
 
 	omciRxCallbackPair := callbackPair{cbKey: tid,
-		cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+		cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 	}
 	err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 	if err != nil {
@@ -2279,7 +2296,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2331,7 +2348,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2383,7 +2400,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2435,7 +2452,7 @@
 		}
 
 		omciRxCallbackPair := callbackPair{cbKey: tid,
-			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
 		}
 		err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
@@ -2452,6 +2469,364 @@
 	return nil
 }
 
+func (oo *omciCC) sendStartSoftwareDownload(ctx context.Context, timeout int, highPrio bool,
+	rxChan chan Message, aImageMeID uint16, aDownloadWindowSize uint8, aFileLen uint32) error {
+	tid := oo.getNextTid(highPrio)
+	logger.Debugw(ctx, "send StartSwDlRequest:", log.Fields{"device-id": oo.deviceID,
+		"SequNo": strconv.FormatInt(int64(tid), 16),
+		"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+
+	omciLayer := &omci.OMCI{
+		TransactionID: tid,
+		MessageType:   omci.StartSoftwareDownloadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &omci.StartSoftwareDownloadRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: aImageMeID, //inactive image
+		},
+		WindowSize:           aDownloadWindowSize,
+		ImageSize:            aFileLen,
+		NumberOfCircuitPacks: 1,           //parallel download to multiple circuit packs not supported
+		CircuitPacks:         []uint16{0}, //circuit pack indication don't care for NumberOfCircuitPacks=1, but needed by omci-lib
+	}
+
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	if err != nil {
+		logger.Errorw(ctx, "Cannot serialize StartSwDlRequest", log.Fields{"Err": err,
+			"device-id": oo.deviceID})
+		return err
+	}
+	outgoingPacket := buffer.Bytes()
+
+	omciRxCallbackPair := callbackPair{cbKey: tid,
+		cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+	}
+	err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
+	if err != nil {
+		logger.Errorw(ctx, "Cannot send StartSwDlRequest", log.Fields{"Err": err,
+			"device-id": oo.deviceID})
+		return err
+	}
+	logger.Debug(ctx, "send StartSwDlRequest done")
+
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+	time.Sleep(time.Millisecond * 200) //give some response time
+	respOmciLayer := &omci.OMCI{
+		TransactionID: tid,
+		MessageType:   omci.StartSoftwareDownloadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	response := &omci.StartSoftwareDownloadResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: aImageMeID, //inactive image
+		},
+		Result:            0,
+		WindowSize:        aDownloadWindowSize,
+		NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
+		//MeResults: cannot set here: downloadResults type not exported from omci-lib!
+	}
+	var respOptions gopacket.SerializeOptions
+	respOptions.FixLengths = true
+	respBuffer := gopacket.NewSerializeBuffer()
+	respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+	if respErr != nil {
+		logger.Errorw(ctx, "Cannot serialize StartSwDlResponse", log.Fields{"Err": respErr,
+			"device-id": oo.deviceID})
+		return respErr
+	}
+	respPacket := respBuffer.Bytes()
+	logger.Debugw(ctx, "simulate StartSwDlResponse", log.Fields{"device-id": oo.deviceID,
+		"SequNo":     strconv.FormatInt(int64(tid), 16),
+		"InstId":     strconv.FormatInt(int64(aImageMeID), 16),
+		"windowSize": aDownloadWindowSize})
+	go func(oo *omciCC) {
+		_ = oo.receiveMessage(ctx, respPacket)
+	}(oo)
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+	return nil
+}
+
+func (oo *omciCC) sendDownloadSection(ctx context.Context, timeout int, highPrio bool,
+	rxChan chan Message, aImageMeID uint16, aAckRequest uint8, aDownloadSectionNo uint8, aSection []byte, aPrint bool) error {
+	tid := oo.getNextTid(highPrio)
+	logger.Debugw(ctx, "send DlSectionRequest:", log.Fields{"device-id": oo.deviceID,
+		"SequNo": strconv.FormatInt(int64(tid), 16),
+		"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+
+	//TODO!!!: don't know by now on how to generate the possibly needed AR (or enforce it to 0) with current omci-lib
+	//    by now just try to send it as defined by omci-lib
+	omciLayer := &omci.OMCI{
+		TransactionID: tid,
+		MessageType:   omci.DownloadSectionRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	//TODO!!!: omci-lib wrongly defines just 29 byte data section (which should be 31 bytes)
+	//  as long as this is valid and testing is done with some dummy image we omit the last two bytes in each section!!!
+	var localSectionData [29]byte
+	copy(localSectionData[:], aSection)
+	request := &omci.DownloadSectionRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: aImageMeID, //inactive image
+		},
+		SectionNumber: aDownloadSectionNo,
+		SectionData:   localSectionData,
+	}
+
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	if err != nil {
+		logger.Errorw(ctx, "Cannot serialize DlSectionRequest", log.Fields{"Err": err,
+			"device-id": oo.deviceID})
+		return err
+	}
+	outgoingPacket := buffer.Bytes()
+
+	omciRxCallbackPair := callbackPair{cbKey: tid,
+		cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, aPrint},
+	}
+	err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
+	if err != nil {
+		logger.Errorw(ctx, "Cannot send DlSectionRequest", log.Fields{"Err": err,
+			"device-id": oo.deviceID})
+		return err
+	}
+	logger.Debug(ctx, "send DlSectionRequest done")
+
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+	if aAckRequest > 0 {
+		time.Sleep(time.Millisecond * 200) //give some response time
+		respOmciLayer := &omci.OMCI{
+			TransactionID: tid,
+			MessageType:   omci.DownloadSectionResponseType,
+			// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+			// Length:           0x28,						// Optional, defaults to 40 octets
+		}
+		response := &omci.DownloadSectionResponse{
+			MeBasePacket: omci.MeBasePacket{
+				EntityClass:    me.SoftwareImageClassID,
+				EntityInstance: aImageMeID, //inactive image
+			},
+			Result:        0,
+			SectionNumber: aDownloadSectionNo,
+		}
+		var respOptions gopacket.SerializeOptions
+		respOptions.FixLengths = true
+		respBuffer := gopacket.NewSerializeBuffer()
+		respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+		if respErr != nil {
+			logger.Errorw(ctx, "Cannot serialize DlSectionResponse", log.Fields{"Err": respErr,
+				"device-id": oo.deviceID})
+			return err
+		}
+		respPacket := respBuffer.Bytes()
+		if aPrint {
+			logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
+				"SequNo": strconv.FormatInt(int64(tid), 16),
+				"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+				"packet": hex.EncodeToString(respPacket)})
+		} else {
+			logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
+				"SequNo": strconv.FormatInt(int64(tid), 16),
+				"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+		}
+		go func(oo *omciCC) {
+			_ = oo.receiveMessage(ctx, respPacket)
+		}(oo)
+	}
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+	return nil
+}
+
+func (oo *omciCC) sendEndSoftwareDownload(ctx context.Context, timeout int, highPrio bool,
+	rxChan chan Message, aImageMeID uint16, aFileLen uint32, aImageCrc uint32) error {
+	tid := oo.getNextTid(highPrio)
+	logger.Debugw(ctx, "send EndSwDlRequest:", log.Fields{"device-id": oo.deviceID,
+		"SequNo": strconv.FormatInt(int64(tid), 16),
+		"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+
+	//**** test simulation - as long as omci-lib serialize for this type is not corrected - just bypass sending *** start *****
+	/*
+		omciLayer := &omci.OMCI{
+			TransactionID: tid,
+			MessageType:   omci.EndSoftwareDownloadRequestType,
+			// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+			// Length:           0x28,						// Optional, defaults to 40 octets
+		}
+		request := &omci.EndSoftwareDownloadRequest{
+			MeBasePacket: omci.MeBasePacket{
+				EntityClass:    me.SoftwareImageClassID,
+				EntityInstance: aImageMeID, //inactive image
+			},
+			CRC32:             aImageCrc,
+			ImageSize:         aFileLen,
+			NumberOfInstances: 1,           //parallel download to multiple circuit packs not supported
+			ImageInstances:    []uint16{0}, //don't care for NumberOfInstances=1, but probably needed by omci-lib as in startSwDlRequest
+		}
+
+		var options gopacket.SerializeOptions
+		options.FixLengths = true
+		buffer := gopacket.NewSerializeBuffer()
+		err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+		if err != nil {
+			logger.Errorw(ctx, "Cannot serialize EndSwDlRequest", log.Fields{"Err": err,
+				"device-id": oo.deviceID})
+			return err
+		}
+		outgoingPacket := buffer.Bytes()
+
+		omciRxCallbackPair := callbackPair{cbKey: tid,
+			cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+		}
+		err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
+		if err != nil {
+			logger.Errorw(ctx, "Cannot send EndSwDlRequest", log.Fields{"Err": err,
+				"device-id": oo.deviceID})
+			return err
+		}
+	*/
+	//**** test simulation - as long as omci-lib serialize for this type is not corrected - just bypass sending *** end *****
+	logger.Debug(ctx, "send EndSwDlRequest done")
+
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+	//callback code necessary here only as long as sending the request is not possible
+	omciRxCallbackPair := callbackPair{cbKey: tid,
+		cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+	}
+	oo.mutexRxSchedMap.Lock()
+	oo.rxSchedulerMap[omciRxCallbackPair.cbKey] = omciRxCallbackPair.cbEntry
+	oo.mutexRxSchedMap.Unlock()
+	//callback code necessary here only as long as sending the request is not possible
+
+	time.Sleep(time.Millisecond * 200) //give some response time
+	respOmciLayer := &omci.OMCI{
+		TransactionID: tid,
+		MessageType:   omci.EndSoftwareDownloadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	response := &omci.EndSoftwareDownloadResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: aImageMeID, //inactive image
+		},
+		Result:            0, //simulate done, option would be busy
+		NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
+		//MeResults: cannot set here: downloadResults type not exported from omci-lib!
+	}
+	var respOptions gopacket.SerializeOptions
+	respOptions.FixLengths = true
+	respBuffer := gopacket.NewSerializeBuffer()
+	respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+	if respErr != nil {
+		logger.Errorw(ctx, "Cannot serialize EndSwDlResponse", log.Fields{"Err": respErr,
+			"device-id": oo.deviceID})
+		return respErr
+	}
+	respPacket := respBuffer.Bytes()
+	logger.Debugw(ctx, "simulate EndSwDlResponse", log.Fields{"device-id": oo.deviceID,
+		"SequNo": strconv.FormatInt(int64(tid), 16),
+		"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+		"result": 0})
+	go func(oo *omciCC) {
+		_ = oo.receiveMessage(ctx, respPacket)
+	}(oo)
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+	return nil
+}
+
+func (oo *omciCC) sendActivateSoftware(ctx context.Context, timeout int, highPrio bool,
+	rxChan chan Message, aImageMeID uint16) error {
+	tid := oo.getNextTid(highPrio)
+	logger.Debugw(ctx, "send ActivateSwRequest:", log.Fields{"device-id": oo.deviceID,
+		"SequNo": strconv.FormatInt(int64(tid), 16),
+		"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+
+	omciLayer := &omci.OMCI{
+		TransactionID: tid,
+		MessageType:   omci.ActivateSoftwareRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &omci.ActivateSoftwareRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: aImageMeID, //inactive image
+		},
+		ActivateFlags: 0, //unconditionally reset as the only relevant option here (regardless of VOIP)
+	}
+
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	if err != nil {
+		logger.Errorw(ctx, "Cannot serialize ActivateSwRequest", log.Fields{"Err": err,
+			"device-id": oo.deviceID})
+		return err
+	}
+	outgoingPacket := buffer.Bytes()
+
+	omciRxCallbackPair := callbackPair{cbKey: tid,
+		cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+	}
+	err = oo.send(ctx, outgoingPacket, timeout, 0, highPrio, omciRxCallbackPair)
+	if err != nil {
+		logger.Errorw(ctx, "Cannot send ActivateSwRequest", log.Fields{"Err": err,
+			"device-id": oo.deviceID})
+		return err
+	}
+	logger.Debug(ctx, "send ActivateSwRequest done")
+
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+
+	time.Sleep(time.Millisecond * 50) //give some response time
+
+	respOmciLayer := &omci.OMCI{
+		TransactionID: tid,
+		MessageType:   omci.ActivateSoftwareResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	response := &omci.ActivateSoftwareResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: aImageMeID, //inactive image
+		},
+		Result: 0, //simulate done, option would be busy
+	}
+	var respOptions gopacket.SerializeOptions
+	respOptions.FixLengths = true
+	respBuffer := gopacket.NewSerializeBuffer()
+	respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+	if respErr != nil {
+		logger.Errorw(ctx, "Cannot serialize ActivateSwResponse", log.Fields{"Err": respErr,
+			"device-id": oo.deviceID})
+		return respErr
+	}
+	respPacket := respBuffer.Bytes()
+	logger.Debugw(ctx, "simulate ActivateSwResponse", log.Fields{"device-id": oo.deviceID,
+		"SequNo": strconv.FormatInt(int64(tid), 16),
+		"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+		"result": 0})
+	go func(oo *omciCC) {
+		_ = oo.receiveMessage(ctx, respPacket)
+	}(oo)
+	//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+	return nil
+}
+
 func isResponseWithMibDataSync(msgType omci.MessageType) bool {
 	for _, v := range responsesWithMibDataSync {
 		if v == msgType {