SEBA-432
SEBA-565
SEBA-654 (alarms)
implemented
fix Jenkins make errors
fix merge conflicts
address review comments
Change-Id: Ia2e95afb33ce55054afa1fcbd9beb6ada62dd764
diff --git a/core/alarms.go b/core/alarms.go
new file mode 100644
index 0000000..5c7d287
--- /dev/null
+++ b/core/alarms.go
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package core
+
+import (
+ "strconv"
+
+ pb "gerrit.opencord.org/voltha-bbsim/api"
+ "gerrit.opencord.org/voltha-bbsim/common/logger"
+ "gerrit.opencord.org/voltha-bbsim/device"
+ openolt "gerrit.opencord.org/voltha-bbsim/protos"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+const (
+ // OnuLossOfPloam is state on onu los
+ OnuLossOfPloam = "lossofploam"
+ // OnuLossOfOmciChannel is the state on omci channel loss alarm
+ OnuLossOfOmciChannel = "lossofomcichannel"
+ // OnuSignalDegrade is the state on signal degrade alarm
+ OnuSignalDegrade = "signaldegrade"
+ // AlarmOn is for raising the alarm
+ AlarmOn = "on"
+ // AlarmOff is for clearing the alarm
+ AlarmOff = "off"
+)
+
+func (s *Server) handleOnuAlarm(in *pb.ONUAlarmRequest) (*pb.BBSimResponse, error) {
+ value, ok := s.SNmap.Load(in.OnuSerial)
+ onu := value.(*device.Onu)
+ if !ok {
+ return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, "no active or discovered onu found with serial number "+in.OnuSerial)
+ }
+
+ if (onu.InternalState == device.ONU_LOS_RAISED || onu.InternalState == device.ONU_LOS_ON_OLT_PON_LOS) &&
+ (in.AlarmType != OnuLossOfPloam) {
+ return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, in.OnuSerial+" is not reachable, can not send onu alarm")
+ }
+
+ if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && (in.AlarmType != OnuLossOfPloam) {
+ // Don't send onu alarm as OLT-PON is down
+ return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, "pon-port down, can not send onu alarm")
+ }
+ switch in.AlarmType {
+ case OnuLossOfOmciChannel:
+ Ind := formulateLossOfOmciChannelAlarm(in.Status, onu)
+ if in.Status == AlarmOn {
+ onu.UpdateIntState(device.ONU_OMCI_CHANNEL_LOS_RAISED)
+ } else {
+ onu.UpdateIntState(device.ONU_ACTIVE)
+ }
+ s.alarmCh <- Ind
+ return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+
+ case OnuSignalDegrade:
+ Ind := formulateSignalDegradeAlarm(in.Status, onu)
+ s.alarmCh <- Ind
+ return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+
+ case OnuLossOfPloam:
+ if in.Status == AlarmOn {
+ onu.UpdateIntState(device.ONU_LOS_RAISED)
+ device.UpdateOnusOpStatus(onu.IntfID, onu, "down")
+ } else {
+ onu.UpdateIntState(device.ONU_ACTIVE)
+ device.UpdateOnusOpStatus(onu.IntfID, onu, "up")
+ // TODO is it required to check onu state?
+ err := sendOnuDiscInd(*s.EnableServer, onu)
+ if err != nil {
+ logger.Error("Error: %v", err.Error())
+ }
+ }
+ Ind := formulateLossOfPLOAM(in.Status, onu)
+ s.alarmCh <- Ind
+ er := sendOnuInd(*s.EnableServer, onu, 0, onu.OperState, "up")
+ if er != nil {
+ logger.Debug(er.Error())
+ }
+
+ resp, err := s.checkAndSendOltPonLos(in.OnuSerial, in.Status, device.IntfPon) // Send olt los if all the onus attached to a pon-port shows los
+ if err != nil {
+ return resp, err
+ }
+ return resp, nil
+
+ default:
+ logger.Debug("Unhandled alarm type")
+ return &pb.BBSimResponse{}, status.Errorf(codes.Unimplemented, "Unhandled alarm type")
+ }
+
+}
+
+func (s *Server) handleOltAlarm(in *pb.OLTAlarmRequest) (*pb.BBSimResponse, error) {
+ switch in.PortType {
+ case device.IntfNni:
+
+ if !s.isNniIntfPresentInOlt(in.PortId) {
+ return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" NNI not present in olt")
+ }
+
+ Ind := formulateOLTLOSAlarm(in.Status, in.PortId, device.IntfNni)
+ s.alarmCh <- Ind
+ s.setNNIPortState(in.PortId, in.Status)
+
+ case device.IntfPon:
+ if !s.isPonIntfPresentInOlt(in.PortId) {
+ return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" PON not present in olt")
+ }
+ Ind := formulateOLTLOSAlarm(in.Status, in.PortId, in.PortType)
+ s.alarmCh <- Ind
+ onusOperstat := s.setPONPortState(in.PortId, in.Status)
+ for _, onu := range s.Onumap[in.PortId] {
+ if onu.InternalState == device.ONU_LOS_RAISED || onu.InternalState == device.ONU_FREE {
+ continue // Skip for onus which have independently raised onu los
+ }
+
+ er := sendOnuInd(*s.EnableServer, onu, 0, onusOperstat, "up")
+ if er != nil {
+ logger.Debug(er.Error())
+ }
+ s.sendOnuLosOnOltPonLos(onu, in.Status)
+ }
+ default:
+ return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "invalid interface type provided")
+ }
+
+ return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+}
+
+func (s *Server) setNNIPortState(portID uint32, alarmstatus string) {
+ switch alarmstatus {
+ case AlarmOn:
+ s.Olt.UpdateNniPortState(portID, device.NniLosRaised, "down")
+
+ case AlarmOff:
+ s.Olt.UpdateNniPortState(portID, device.NniLosCleared, "up")
+ }
+}
+
+func (s *Server) setPONPortState(portID uint32, alarmstatus string) string {
+ switch alarmstatus {
+ case AlarmOn:
+ s.Olt.UpdatePonPortState(portID, device.PonLosRaised, "down")
+ return "down"
+
+ case AlarmOff:
+ s.Olt.UpdatePonPortState(portID, device.PonLosCleared, "up")
+ return "up"
+ }
+ return ""
+}
+
+func (s *Server) sendOnuLosOnOltPonLos(onu *device.Onu, status string) {
+ var internalState device.DeviceState
+
+ if status == AlarmOn {
+ internalState = device.ONU_LOS_ON_OLT_PON_LOS
+ } else if status == AlarmOff {
+ internalState = device.ONU_ACTIVE
+ }
+
+ Ind := formulateLossOfPLOAM(status, onu)
+ onu.UpdateIntState(internalState)
+
+ // update onus slice on alarm off
+ if status == "off" {
+ err := sendOnuDiscInd(*s.EnableServer, onu)
+ if err != nil {
+ logger.Error(err.Error())
+ }
+ }
+
+ s.alarmCh <- Ind
+}
+
+func formulateLossOfOmciChannelAlarm(status string, onu *device.Onu) *openolt.Indication {
+ logger.Debug("formulateLossofOmciChannelAlarm() invoked")
+
+ alarmIndication := &openolt.AlarmIndication_OnuLossOmciInd{
+ OnuLossOmciInd: &openolt.OnuLossOfOmciChannelIndication{
+ IntfId: onu.IntfID,
+ OnuId: onu.OnuID,
+ Status: status,
+ },
+ }
+
+ alarmind := &openolt.AlarmIndication{
+ Data: alarmIndication,
+ }
+
+ msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
+ Ind := &openolt.Indication{Data: msg}
+ return Ind
+}
+
+func formulateSignalDegradeAlarm(status string, onu *device.Onu) *openolt.Indication {
+ logger.Debug("formulateSignalDegrade() invoked")
+ alarmIndication := &openolt.AlarmIndication_OnuSignalDegradeInd{
+ OnuSignalDegradeInd: &openolt.OnuSignalDegradeIndication{
+ IntfId: onu.IntfID,
+ OnuId: onu.OnuID,
+ Status: status,
+ InverseBitErrorRate: 0,
+ },
+ }
+ alarmind := &openolt.AlarmIndication{
+ Data: alarmIndication,
+ }
+ msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
+ Ind := &openolt.Indication{Data: msg}
+ return Ind
+}
+
+func formulateLossOfPLOAM(status string, onu *device.Onu) *openolt.Indication {
+ logger.Debug("formulateLossOfPLOAM() invoked")
+
+ alarmIndication := &openolt.AlarmIndication_OnuAlarmInd{OnuAlarmInd: &openolt.OnuAlarmIndication{
+ IntfId: onu.IntfID,
+ OnuId: onu.OnuID,
+ LosStatus: status,
+ LobStatus: status,
+ LopcMissStatus: status,
+ LopcMicErrorStatus: status,
+ }}
+
+ alarmind := &openolt.AlarmIndication{Data: alarmIndication}
+ msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
+ Ind := &openolt.Indication{Data: msg}
+ return Ind
+}
+
+func formulateOLTLOSAlarm(status string, PortID uint32, intfType string) *openolt.Indication {
+ intfID := interfaceIDToPortNo(PortID, intfType)
+
+ alarmIndication := &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
+ IntfId: intfID,
+ Status: status,
+ }}
+
+ alarmind := &openolt.AlarmIndication{Data: alarmIndication}
+ msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
+ Ind := &openolt.Indication{Data: msg}
+ return Ind
+}
+
+func (s *Server) checkAndSendOltPonLos(serial string, status string, intfType string) (*pb.BBSimResponse, error) {
+ value, _ := s.SNmap.Load(serial)
+ onu := value.(*device.Onu)
+ if s.getNoOfActiveOnuByPortID(onu.IntfID) == 0 {
+ logger.Warn("Warning: Sending OLT-LOS, as all onus on pon-port %v raised los", onu.IntfID)
+ request := &pb.OLTAlarmRequest{PortId: onu.IntfID, Status: AlarmOn, PortType: device.IntfPon}
+ resp, err := s.handleOltAlarm(request)
+ return resp, err
+ }
+ if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && status == AlarmOff {
+ s.setPONPortState(onu.IntfID, status)
+ Ind := formulateOLTLOSAlarm(status, onu.IntfID, intfType)
+ s.alarmCh <- Ind
+ }
+
+ return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
+}
+
+func interfaceIDToPortNo(intfid uint32, intfType string) uint32 {
+ // Converts interface-id to port-numbers that can be understood by the voltha
+ if intfType == device.IntfNni {
+ // nni at voltha starts with 65536
+ // nni = 65536 + interface_id
+ return 0x1<<16 + intfid
+ } else if intfType == device.IntfPon {
+ // pon = 536,870,912 + interface_id
+ return (0x2 << 28) + intfid // In openolt code, stats_collection.cc line number 196, pon starts from 0
+ // In bbsim, pon starts from 1
+ }
+ return 0
+}