VOL-3049 patch for alarm notification, audit and sync

Change-Id: I18fa616e94e7c33bbd8c1080bee0ab16afe505da
diff --git a/internal/common/omci/alarms.go b/internal/common/omci/alarms.go
index aaa2fdd..5d8144b 100644
--- a/internal/common/omci/alarms.go
+++ b/internal/common/omci/alarms.go
@@ -16,32 +16,168 @@
 
 package omci
 
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	log "github.com/sirupsen/logrus"
+)
+
+type OnuAlarmInfo struct {
+	SequenceNo  uint8
+	AlarmBitMap [28]byte
+}
+type OnuAlarmInfoMapKey struct {
+	MeInstance uint16
+	MeClassID  me.ClassID
+}
+
 // CreateUniStatusAlarm will generate an Alarm packet to report that the Link is UP or DOWN
 // as a consequence of a SetRequest on PhysicalPathTerminationPointEthernetUniClassID
-func CreateUniStatusAlarm(adminState uint8, entityId uint16) []byte {
+func CreateUniStatusAlarm(raiseAlarm bool, entityId uint16, sequenceNo uint8) ([]byte, [28]byte) {
+	notif := &omci.AlarmNotificationMsg{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+			EntityInstance: entityId,
+		},
+		AlarmSequenceNumber: byte(sequenceNo),
+	}
+	if raiseAlarm {
+		//PPTP class has only 0th bit alarm for UNI LOS
+		if err := notif.ActivateAlarm(0); err != nil {
+			omciLogger.WithFields(log.Fields{
+				"Err": err,
+			}).Error("Cannot Create AlarmNotificationMsg")
+			return nil, [28]byte{}
+		}
+	} else {
+		if err := notif.ClearAlarm(0); err != nil {
+			omciLogger.WithFields(log.Fields{
+				"Err": err,
+			}).Error("Cannot Create AlarmNotificationMsg")
+			return nil, [28]byte{}
+		}
+	}
+	pkt, err := Serialize(omci.AlarmNotificationType, notif, 0)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("Cannot Serialize AlarmNotificationMsg")
+		return nil, [28]byte{}
+	}
+	return pkt, notif.AlarmBitmap
+}
 
-	// TODO generate using omci-lib-go
-	linkMsgDown := []byte{
-		0x00, 0x00, 0x10, 0x0a, 0x00, 0x0b, 0x01, 0x01,
-		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+func CreateGetAllAlarmsResponse(tid uint16, onuAlarmDetails map[OnuAlarmInfoMapKey]OnuAlarmInfo) ([]byte, error) {
+	var alarmEntityClass me.ClassID
+	var meInstance uint16
+	var noOfCommands uint16 = 0
+	alarmEntityClass = me.PhysicalPathTerminationPointEthernetUniClassID //Currently doing for PPTP classID
+	meInstance = 257
+	key := OnuAlarmInfoMapKey{
+		MeInstance: meInstance,
+		MeClassID:  alarmEntityClass,
+	}
+	if _, ok := onuAlarmDetails[key]; ok {
+		noOfCommands = 1
+	}
+	numberOfCommands := uint16(noOfCommands)
 
-	linkMsgUp := []byte{
-		0x00, 0x00, 0x10, 0x0a, 0x00, 0x0b, 0x01, 0x01,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	request := &omci.GetAllAlarmsResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+		},
+		NumberOfCommands: numberOfCommands,
+	}
+	pkt, err := Serialize(omci.GetAllAlarmsResponseType, request, tid)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("Cannot Serialize GetAllAlarmsResponse")
+		return nil, err
+	}
+	return pkt, nil
+}
+func ParseGetAllAlarmsNextRequest(omciPkt gopacket.Packet) (*omci.GetAllAlarmsNextRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeGetAllAlarmsNextRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeGetAllAlarmsNextRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.GetAllAlarmsNextRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for GetAllAlarmsNextRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
 
-	if adminState == 0 {
-		return linkMsgUp
-	} else if adminState == 1 {
-		return linkMsgDown
+func CreateGetAllAlarmsNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, onuAlarmDetails map[OnuAlarmInfoMapKey]OnuAlarmInfo) ([]byte, error) {
+
+	msgObj, err := ParseGetAllAlarmsNextRequest(omciPkt)
+	if err != nil {
+		err := "omci Msg layer could not be assigned for LayerTypeGetRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
 	}
 
-	return nil
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":           msgObj.EntityClass,
+		"EntityInstance":        msgObj.EntityInstance,
+		"CommandSequenceNumber": msgObj.CommandSequenceNumber,
+	}).Trace("received-omci-get-all-alarms-next-request")
+
+	var alarmEntityClass me.ClassID
+	var meInstance uint16
+	var alarmBitMap [28]byte
+
+	switch msgObj.CommandSequenceNumber {
+	case 0:
+		alarmEntityClass = me.PhysicalPathTerminationPointEthernetUniClassID
+		meInstance = 257
+		//Checking if the alarm is raised in the bitmap, we will send clear just to generate missed clear alarm and
+		// vice versa.
+		key := OnuAlarmInfoMapKey{
+			MeInstance: meInstance,
+			MeClassID:  alarmEntityClass,
+		}
+		if alarmInfo, ok := onuAlarmDetails[key]; ok {
+			alarmBitMap = alarmInfo.AlarmBitMap
+		} else {
+			return nil, fmt.Errorf("alarm-info-for-me-not-present-in-alarm-info-map")
+		}
+	default:
+		omciLogger.Warn("unsupported-CommandSequenceNumber-in-get-all-alarm-next", msgObj.CommandSequenceNumber)
+		return nil, fmt.Errorf("unspported-command-sequence-number-in-get-all-alarms-next")
+	}
+
+	response := &omci.GetAllAlarmsNextResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+		},
+		AlarmEntityClass:    alarmEntityClass,
+		AlarmEntityInstance: meInstance,
+		AlarmBitMap:         alarmBitMap,
+	}
+
+	omciLogger.WithFields(log.Fields{
+		"AlarmEntityClass":    alarmEntityClass,
+		"AlarmEntityInstance": meInstance,
+		"AlarmBitMap":         alarmBitMap,
+	}).Trace("created-omci-getAllAlarmsNext-response")
+
+	pkt, err := Serialize(omci.GetAllAlarmsNextResponseType, response, omciMsg.TransactionID)
+
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Fatalf("Cannot Serialize GetAllAlarmsNextRequest")
+		return nil, err
+	}
+
+	return pkt, nil
 }