[VOL-4466]  support multi onu sw section download

Change-Id: Iee29866f22a1b3de65aa257fdfaf46112d058c01
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 822d83e..2bdbbb1 100644
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -1148,6 +1148,83 @@
 // 	return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
 // }
 
+// ProxyOmciRequests sends the proxied OMCI message to the target device
+func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
+	if omciMsgs.GetProxyAddress() == nil {
+		onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
+		if err != nil {
+			return olterrors.NewErrNotFound("onu", log.Fields{
+				"parent-device-id": dh.device.Id,
+				"child-device-id":  omciMsgs.ChildDeviceId}, err)
+		}
+		logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
+		if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
+			return olterrors.NewErrCommunication("send-failed", log.Fields{
+				"parent-device-id": dh.device.Id,
+				"child-device-id":  omciMsgs.ChildDeviceId}, err)
+		}
+	} else {
+		logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
+		if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
+			return olterrors.NewErrCommunication("send-failed", log.Fields{
+				"parent-device-id": dh.device.Id,
+				"child-device-id":  omciMsgs.ChildDeviceId}, err)
+		}
+	}
+	return nil
+}
+
+func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
+	var intfID uint32
+	var onuID uint32
+	var connectStatus common.ConnectStatus_Types
+	if onuDevice != nil {
+		intfID = onuDevice.ProxyAddress.GetChannelId()
+		onuID = onuDevice.ProxyAddress.GetOnuId()
+		connectStatus = onuDevice.ConnectStatus
+	} else {
+		intfID = omciMsgs.GetProxyAddress().GetChannelId()
+		onuID = omciMsgs.GetProxyAddress().GetOnuId()
+		connectStatus = omciMsgs.GetConnectStatus()
+	}
+	if connectStatus != voltha.ConnectStatus_REACHABLE {
+		logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
+
+		return olterrors.NewErrCommunication("unreachable", log.Fields{
+			"intf-id": intfID,
+			"onu-id":  onuID}, nil)
+	}
+
+	// TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
+	//  Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
+
+	onuSecOmciMsgList := omciMsgs.GetMessages()
+
+	for _, onuSecOmciMsg := range onuSecOmciMsgList {
+
+		var omciMessage *oop.OmciMsg
+		hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
+		hex.Encode(hexPkt, onuSecOmciMsg)
+		omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
+
+		// TODO: Below logging illustrates the "stringify" of the omci Pkt.
+		//  once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
+		//https://jira.opencord.org/browse/VOL-4604
+		transid := extractOmciTransactionID(onuSecOmciMsg)
+		logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
+			"omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
+
+		_, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
+		if err != nil {
+			return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
+				"intf-id": intfID,
+				"onu-id":  onuID,
+				"message": omciMessage}, err)
+		}
+	}
+	return nil
+}
+
 // ProxyOmciMessage sends the proxied OMCI message to the target device
 func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
 	logger.Debugw(ctx, "proxy-omci-message", log.Fields{"parent-device-id": omciMsg.ParentDeviceId, "child-device-id": omciMsg.ChildDeviceId, "proxy-address": omciMsg.ProxyAddress, "connect-status": omciMsg.ConnectStatus})
@@ -1199,6 +1276,7 @@
 
 	// TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
 	//  Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
+	// https://jira.opencord.org/browse/VOL-4604
 	var omciMessage *oop.OmciMsg
 	hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
 	hex.Encode(hexPkt, omciMsg.Message)