[VOL-2451] Reporting UNI Link Up alarm via OMCI

Change-Id: I6fd30af5f558cd41bca617247d859bdcc2ff2ed9
diff --git a/Makefile b/Makefile
index 8e9935a..2cf851e 100644
--- a/Makefile
+++ b/Makefile
@@ -68,7 +68,7 @@
 
 test: test-unit test-bbr
 
-test-unit: clean dep fmt # @HELP Execute unit tests
+test-unit: clean dep fmt local-omci-sim # @HELP Execute unit tests
 	GO111MODULE=on go test -v -mod vendor $(TEST_PACKAGES) -timeout 10s -covermode count -coverprofile ./tests/results/go-test-coverage.out 2>&1 | tee ./tests/results/go-test-results.out
 	go-junit-report < ./tests/results/go-test-results.out > ./tests/results/go-test-results.xml
 	gocover-cobertura < ./tests/results/go-test-coverage.out > ./tests/results/go-test-coverage.xml
@@ -168,7 +168,7 @@
 	rm -f bbr
 	rm -rf tools/bin
 
-build-bbr:
+build-bbr: local-omci-sim
 	GO111MODULE=on go build -i -v -mod vendor \
     	-ldflags "-w -X main.buildTime=$(shell date +”%Y/%m/%d-%H:%M:%S”) \
     		-X main.commitHash=$(shell git log --pretty=format:%H -n 1) \
diff --git a/VERSION b/VERSION
index 4b9e5b0..7c1886b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.0.10-dev
+0.0.10
diff --git a/go.mod b/go.mod
index 5b0eb25..085c3e5 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@
 	github.com/jhump/protoreflect v1.5.0
 	github.com/looplab/fsm v0.1.0
 	github.com/opencord/cordctl v0.0.0-20190909161711-01e9c1f04bf4
-	github.com/opencord/omci-sim v0.0.1
+	github.com/opencord/omci-sim v0.0.2
 	github.com/opencord/voltha-protos/v2 v2.1.2
 	github.com/pkg/errors v0.8.1 // indirect
 	github.com/sirupsen/logrus v1.4.2
diff --git a/internal/bbsim/devices/olt.go b/internal/bbsim/devices/olt.go
index db25f32..3cbb5fc 100644
--- a/internal/bbsim/devices/olt.go
+++ b/internal/bbsim/devices/olt.go
@@ -24,9 +24,9 @@
 	"sync"
 	"time"
 
-	"github.com/google/gopacket/pcap"
 	"github.com/google/gopacket"
 	"github.com/google/gopacket/layers"
+	"github.com/google/gopacket/pcap"
 	"github.com/looplab/fsm"
 	"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
 	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
@@ -324,7 +324,7 @@
 		o.channel <- msg
 	}
 
-	go o.processOmciMessages(o.enableContext, &wg)
+	go o.processOmciMessages(o.enableContext, stream, &wg)
 
 	// send PON Port indications
 	for i, pon := range o.Pons {
@@ -354,7 +354,7 @@
 	return nil
 }
 
-func (o *OltDevice) processOmciMessages(ctx context.Context, wg *sync.WaitGroup) {
+func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
 	ch := omcisim.GetChannel()
 
 	oltLogger.Debug("Starting OMCI Indication Channel")
@@ -370,6 +370,13 @@
 				oltLogger.Debug("OMCI processing canceled via channel close")
 				break loop
 			}
+
+			oltLogger.WithFields(log.Fields{
+				"messageType": message.Type,
+				"OnuId":       message.Data.OnuId,
+				"IntfId":      message.Data.IntfId,
+			}).Info("Received message on OMCI Sim channel")
+
 			onuId := message.Data.OnuId
 			intfId := message.Data.IntfId
 			onu, err := o.FindOnuById(intfId, onuId)
@@ -377,7 +384,7 @@
 				oltLogger.Errorf("Failed to find onu: %v", err)
 				continue
 			}
-			go onu.processOmciMessage(message)
+			go onu.processOmciMessage(message, stream)
 		}
 	}
 
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index a37455e..ef25770 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -120,7 +120,7 @@
 			// NOTE should disabled state be different for oper_disabled (emulating an error) and admin_disabled (received a disabled call via VOLTHA)?
 			{Name: "disable", Src: []string{"enabled", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst: "disabled"},
 			// ONU state when PON port is disabled but ONU is power ON(more states should be added in src?)
-			{Name: "pon_disabled", Src: []string{"enabled", "gem_port_added", "eapol_flow_received", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst:"pon_disabled"},
+			{Name: "pon_disabled", Src: []string{"enabled", "gem_port_added", "eapol_flow_received", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst: "pon_disabled"},
 			// EAPOL
 			{Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added", "eap_start_sent", "eap_response_identity_sent", "eap_response_challenge_sent", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst: "auth_started"},
 			{Name: "eap_start_sent", Src: []string{"auth_started"}, Dst: "eap_start_sent"},
@@ -355,8 +355,40 @@
 	}).Debug("Stopped handling ONU Indication Channel")
 }
 
-func (o *Onu) processOmciMessage(message omcisim.OmciChMessage) {
+func (o *Onu) processOmciMessage(message omcisim.OmciChMessage, stream openolt.Openolt_EnableIndicationServer) {
 	switch message.Type {
+	case omcisim.UniLinkUp, omcisim.UniLinkDown:
+		onuLogger.WithFields(log.Fields{
+			"OnuId":  message.Data.OnuId,
+			"IntfId": message.Data.IntfId,
+			"Type":   message.Type,
+		}).Infof("UNI Link Alarm")
+		// TODO send to OLT
+
+		omciInd := openolt.OmciIndication{
+			IntfId: message.Data.IntfId,
+			OnuId:  message.Data.OnuId,
+			Pkt:    message.Packet,
+		}
+
+		omci := &openolt.Indication_OmciInd{OmciInd: &omciInd}
+		if err := stream.Send(&openolt.Indication{Data: omci}); err != nil {
+			onuLogger.WithFields(log.Fields{
+				"IntfId":       o.PonPortID,
+				"SerialNumber": o.Sn(),
+				"Type":         message.Type,
+				"omciPacket":   omciInd.Pkt,
+			}).Errorf("Failed to send UNI Link Alarm: %v", err)
+			return
+		}
+
+		onuLogger.WithFields(log.Fields{
+			"IntfId":       o.PonPortID,
+			"SerialNumber": o.Sn(),
+			"Type":         message.Type,
+			"omciPacket":   omciInd.Pkt,
+		}).Info("UNI Link alarm sent")
+
 	case omcisim.GemPortAdded:
 		log.WithFields(log.Fields{
 			"OnuId":  message.Data.OnuId,
diff --git a/vendor/github.com/opencord/omci-sim/VERSION b/vendor/github.com/opencord/omci-sim/VERSION
index 8acdd82..4e379d2 100644
--- a/vendor/github.com/opencord/omci-sim/VERSION
+++ b/vendor/github.com/opencord/omci-sim/VERSION
@@ -1 +1 @@
-0.0.1
+0.0.2
diff --git a/vendor/github.com/opencord/omci-sim/omci_defs.go b/vendor/github.com/opencord/omci-sim/omci_defs.go
index 44347ef..d84e878 100644
--- a/vendor/github.com/opencord/omci-sim/omci_defs.go
+++ b/vendor/github.com/opencord/omci-sim/omci_defs.go
@@ -28,12 +28,16 @@
 type ChMessageType int
 
 const (
-	GemPortAdded ChMessageType = iota
+	GemPortAdded ChMessageType = 0
+	UniLinkUp ChMessageType = 1
+	UniLinkDown ChMessageType = 2
 )
 
 func (m ChMessageType) String() string {
 	names := [...]string{
 		"GemPortAdded",
+		"UniLinkUp",
+		"UniLinkDown",
 	}
 	return names[m]
 }
@@ -46,6 +50,7 @@
 type OmciChMessage struct {
 	Type ChMessageType
 	Data OmciChMessageData
+	Packet []byte
 }
 
 //
diff --git a/vendor/github.com/opencord/omci-sim/omci_sim.go b/vendor/github.com/opencord/omci-sim/omci_sim.go
index a792911..c971d54 100644
--- a/vendor/github.com/opencord/omci-sim/omci_sim.go
+++ b/vendor/github.com/opencord/omci-sim/omci_sim.go
@@ -21,7 +21,7 @@
 	log "github.com/sirupsen/logrus"
 )
 
-var omciCh = make(chan OmciChMessage)
+var omciCh = make(chan OmciChMessage, 4096)
 
 func GetChannel() chan OmciChMessage {
 	return omciCh
@@ -48,7 +48,7 @@
 		"MeInstance": instance,
 		//"Conent": content,
 		"omciMsg": fmt.Sprintf("%x", content),
-	}).Tracef("Processing OMCI pakcet")
+	}).Tracef("Processing OMCI packet")
 
 	key := OnuKey{intfId, onuId}
 	OnuOmciStateMapLock.Lock()
@@ -105,6 +105,62 @@
 		}
 	}
 
+	if (class == 11 && instance == 257 && msgType == Set) {
+		// This is a set on a PPTP instance 257 (lan port 1)
+		// Determine if its setting admin up or down and alarm appropriately
+
+		// attrmask for what specifically sets/gets is 2 bytes
+		attrmask := content[0:2]
+		// actual content is the rest, as specified by attrmask.  but for this case we are only interested in 1 byte
+		firstattr := content[2:3]
+
+		// attribute bit 5 (admin state) in the PPTP is being set, its value is 1, lock
+		if (attrmask[0] == 0x08 && firstattr[0] == 0x01) {
+			log.Info("Send UNI Link Down Alarm on OMCI Sim channel")
+
+			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}
+
+			msg := OmciChMessage{
+				Type: UniLinkDown,
+				Data: OmciChMessageData{
+					OnuId:  key.OnuId,
+					IntfId: key.IntfId,
+				},
+				Packet: linkMsgDown,
+			}
+			omciCh <- msg
+		}
+
+		// attribute bit 5 (admin state) in the PPTP is being set, its value is 0, unlock
+		if (attrmask[0] == 0x08 && firstattr[0] == 0x00) {
+			log.Info("Send UNI Link Up Alarm on OMCI Sim channel")
+
+			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}
+
+			msg := OmciChMessage{
+				Type: UniLinkUp,
+				Data: OmciChMessageData{
+					OnuId:  key.OnuId,
+					IntfId: key.IntfId,
+				},
+				Packet: linkMsgUp,
+			}
+			omciCh <- msg
+		}
+	}
+
 	log.WithFields(log.Fields{
 		"IntfId": intfId,
 		"OnuId": onuId,