blob: 5c7d28736bb69f9bf4423fb2bf9c3f97dd95f623 [file] [log] [blame]
Zdravko Bozakov7401ff22019-05-28 22:45:12 +02001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package core
18
19import (
20 "strconv"
21
22 pb "gerrit.opencord.org/voltha-bbsim/api"
23 "gerrit.opencord.org/voltha-bbsim/common/logger"
24 "gerrit.opencord.org/voltha-bbsim/device"
25 openolt "gerrit.opencord.org/voltha-bbsim/protos"
26 "google.golang.org/grpc/codes"
27 "google.golang.org/grpc/status"
28)
29
30const (
31 // OnuLossOfPloam is state on onu los
32 OnuLossOfPloam = "lossofploam"
33 // OnuLossOfOmciChannel is the state on omci channel loss alarm
34 OnuLossOfOmciChannel = "lossofomcichannel"
35 // OnuSignalDegrade is the state on signal degrade alarm
36 OnuSignalDegrade = "signaldegrade"
37 // AlarmOn is for raising the alarm
38 AlarmOn = "on"
39 // AlarmOff is for clearing the alarm
40 AlarmOff = "off"
41)
42
43func (s *Server) handleOnuAlarm(in *pb.ONUAlarmRequest) (*pb.BBSimResponse, error) {
44 value, ok := s.SNmap.Load(in.OnuSerial)
45 onu := value.(*device.Onu)
46 if !ok {
47 return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, "no active or discovered onu found with serial number "+in.OnuSerial)
48 }
49
50 if (onu.InternalState == device.ONU_LOS_RAISED || onu.InternalState == device.ONU_LOS_ON_OLT_PON_LOS) &&
51 (in.AlarmType != OnuLossOfPloam) {
52 return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, in.OnuSerial+" is not reachable, can not send onu alarm")
53 }
54
55 if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && (in.AlarmType != OnuLossOfPloam) {
56 // Don't send onu alarm as OLT-PON is down
57 return &pb.BBSimResponse{}, status.Errorf(codes.Aborted, "pon-port down, can not send onu alarm")
58 }
59 switch in.AlarmType {
60 case OnuLossOfOmciChannel:
61 Ind := formulateLossOfOmciChannelAlarm(in.Status, onu)
62 if in.Status == AlarmOn {
63 onu.UpdateIntState(device.ONU_OMCI_CHANNEL_LOS_RAISED)
64 } else {
65 onu.UpdateIntState(device.ONU_ACTIVE)
66 }
67 s.alarmCh <- Ind
68 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
69
70 case OnuSignalDegrade:
71 Ind := formulateSignalDegradeAlarm(in.Status, onu)
72 s.alarmCh <- Ind
73 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
74
75 case OnuLossOfPloam:
76 if in.Status == AlarmOn {
77 onu.UpdateIntState(device.ONU_LOS_RAISED)
78 device.UpdateOnusOpStatus(onu.IntfID, onu, "down")
79 } else {
80 onu.UpdateIntState(device.ONU_ACTIVE)
81 device.UpdateOnusOpStatus(onu.IntfID, onu, "up")
82 // TODO is it required to check onu state?
83 err := sendOnuDiscInd(*s.EnableServer, onu)
84 if err != nil {
85 logger.Error("Error: %v", err.Error())
86 }
87 }
88 Ind := formulateLossOfPLOAM(in.Status, onu)
89 s.alarmCh <- Ind
90 er := sendOnuInd(*s.EnableServer, onu, 0, onu.OperState, "up")
91 if er != nil {
92 logger.Debug(er.Error())
93 }
94
95 resp, err := s.checkAndSendOltPonLos(in.OnuSerial, in.Status, device.IntfPon) // Send olt los if all the onus attached to a pon-port shows los
96 if err != nil {
97 return resp, err
98 }
99 return resp, nil
100
101 default:
102 logger.Debug("Unhandled alarm type")
103 return &pb.BBSimResponse{}, status.Errorf(codes.Unimplemented, "Unhandled alarm type")
104 }
105
106}
107
108func (s *Server) handleOltAlarm(in *pb.OLTAlarmRequest) (*pb.BBSimResponse, error) {
109 switch in.PortType {
110 case device.IntfNni:
111
112 if !s.isNniIntfPresentInOlt(in.PortId) {
113 return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" NNI not present in olt")
114 }
115
116 Ind := formulateOLTLOSAlarm(in.Status, in.PortId, device.IntfNni)
117 s.alarmCh <- Ind
118 s.setNNIPortState(in.PortId, in.Status)
119
120 case device.IntfPon:
121 if !s.isPonIntfPresentInOlt(in.PortId) {
122 return &pb.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" PON not present in olt")
123 }
124 Ind := formulateOLTLOSAlarm(in.Status, in.PortId, in.PortType)
125 s.alarmCh <- Ind
126 onusOperstat := s.setPONPortState(in.PortId, in.Status)
127 for _, onu := range s.Onumap[in.PortId] {
128 if onu.InternalState == device.ONU_LOS_RAISED || onu.InternalState == device.ONU_FREE {
129 continue // Skip for onus which have independently raised onu los
130 }
131
132 er := sendOnuInd(*s.EnableServer, onu, 0, onusOperstat, "up")
133 if er != nil {
134 logger.Debug(er.Error())
135 }
136 s.sendOnuLosOnOltPonLos(onu, in.Status)
137 }
138 default:
139 return &pb.BBSimResponse{}, status.Errorf(codes.Internal, "invalid interface type provided")
140 }
141
142 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
143}
144
145func (s *Server) setNNIPortState(portID uint32, alarmstatus string) {
146 switch alarmstatus {
147 case AlarmOn:
148 s.Olt.UpdateNniPortState(portID, device.NniLosRaised, "down")
149
150 case AlarmOff:
151 s.Olt.UpdateNniPortState(portID, device.NniLosCleared, "up")
152 }
153}
154
155func (s *Server) setPONPortState(portID uint32, alarmstatus string) string {
156 switch alarmstatus {
157 case AlarmOn:
158 s.Olt.UpdatePonPortState(portID, device.PonLosRaised, "down")
159 return "down"
160
161 case AlarmOff:
162 s.Olt.UpdatePonPortState(portID, device.PonLosCleared, "up")
163 return "up"
164 }
165 return ""
166}
167
168func (s *Server) sendOnuLosOnOltPonLos(onu *device.Onu, status string) {
169 var internalState device.DeviceState
170
171 if status == AlarmOn {
172 internalState = device.ONU_LOS_ON_OLT_PON_LOS
173 } else if status == AlarmOff {
174 internalState = device.ONU_ACTIVE
175 }
176
177 Ind := formulateLossOfPLOAM(status, onu)
178 onu.UpdateIntState(internalState)
179
180 // update onus slice on alarm off
181 if status == "off" {
182 err := sendOnuDiscInd(*s.EnableServer, onu)
183 if err != nil {
184 logger.Error(err.Error())
185 }
186 }
187
188 s.alarmCh <- Ind
189}
190
191func formulateLossOfOmciChannelAlarm(status string, onu *device.Onu) *openolt.Indication {
192 logger.Debug("formulateLossofOmciChannelAlarm() invoked")
193
194 alarmIndication := &openolt.AlarmIndication_OnuLossOmciInd{
195 OnuLossOmciInd: &openolt.OnuLossOfOmciChannelIndication{
196 IntfId: onu.IntfID,
197 OnuId: onu.OnuID,
198 Status: status,
199 },
200 }
201
202 alarmind := &openolt.AlarmIndication{
203 Data: alarmIndication,
204 }
205
206 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
207 Ind := &openolt.Indication{Data: msg}
208 return Ind
209}
210
211func formulateSignalDegradeAlarm(status string, onu *device.Onu) *openolt.Indication {
212 logger.Debug("formulateSignalDegrade() invoked")
213 alarmIndication := &openolt.AlarmIndication_OnuSignalDegradeInd{
214 OnuSignalDegradeInd: &openolt.OnuSignalDegradeIndication{
215 IntfId: onu.IntfID,
216 OnuId: onu.OnuID,
217 Status: status,
218 InverseBitErrorRate: 0,
219 },
220 }
221 alarmind := &openolt.AlarmIndication{
222 Data: alarmIndication,
223 }
224 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
225 Ind := &openolt.Indication{Data: msg}
226 return Ind
227}
228
229func formulateLossOfPLOAM(status string, onu *device.Onu) *openolt.Indication {
230 logger.Debug("formulateLossOfPLOAM() invoked")
231
232 alarmIndication := &openolt.AlarmIndication_OnuAlarmInd{OnuAlarmInd: &openolt.OnuAlarmIndication{
233 IntfId: onu.IntfID,
234 OnuId: onu.OnuID,
235 LosStatus: status,
236 LobStatus: status,
237 LopcMissStatus: status,
238 LopcMicErrorStatus: status,
239 }}
240
241 alarmind := &openolt.AlarmIndication{Data: alarmIndication}
242 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
243 Ind := &openolt.Indication{Data: msg}
244 return Ind
245}
246
247func formulateOLTLOSAlarm(status string, PortID uint32, intfType string) *openolt.Indication {
248 intfID := interfaceIDToPortNo(PortID, intfType)
249
250 alarmIndication := &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
251 IntfId: intfID,
252 Status: status,
253 }}
254
255 alarmind := &openolt.AlarmIndication{Data: alarmIndication}
256 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
257 Ind := &openolt.Indication{Data: msg}
258 return Ind
259}
260
261func (s *Server) checkAndSendOltPonLos(serial string, status string, intfType string) (*pb.BBSimResponse, error) {
262 value, _ := s.SNmap.Load(serial)
263 onu := value.(*device.Onu)
264 if s.getNoOfActiveOnuByPortID(onu.IntfID) == 0 {
265 logger.Warn("Warning: Sending OLT-LOS, as all onus on pon-port %v raised los", onu.IntfID)
266 request := &pb.OLTAlarmRequest{PortId: onu.IntfID, Status: AlarmOn, PortType: device.IntfPon}
267 resp, err := s.handleOltAlarm(request)
268 return resp, err
269 }
270 if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && status == AlarmOff {
271 s.setPONPortState(onu.IntfID, status)
272 Ind := formulateOLTLOSAlarm(status, onu.IntfID, intfType)
273 s.alarmCh <- Ind
274 }
275
276 return &pb.BBSimResponse{StatusMsg: RequestAccepted}, nil
277}
278
279func interfaceIDToPortNo(intfid uint32, intfType string) uint32 {
280 // Converts interface-id to port-numbers that can be understood by the voltha
281 if intfType == device.IntfNni {
282 // nni at voltha starts with 65536
283 // nni = 65536 + interface_id
284 return 0x1<<16 + intfid
285 } else if intfType == device.IntfPon {
286 // pon = 536,870,912 + interface_id
287 return (0x2 << 28) + intfid // In openolt code, stats_collection.cc line number 196, pon starts from 0
288 // In bbsim, pon starts from 1
289 }
290 return 0
291}