blob: c48c493dc7b13f6de7645d4b5f60106bfe642a82 [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
Zdravko Bozakov078a2712019-07-19 23:25:15 +020022 api "github.com/opencord/voltha-bbsim/api"
Zack Williams2abf3932019-08-05 14:07:05 -070023 "github.com/opencord/voltha-bbsim/common/logger"
24 "github.com/opencord/voltha-bbsim/device"
Zdravko Bozakov078a2712019-07-19 23:25:15 +020025 flowHandler "github.com/opencord/voltha-bbsim/flow"
Matt Jeanneret7c9c5f22019-08-09 14:40:12 -040026 openolt "github.com/opencord/voltha-protos/go/openolt"
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020027 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29)
30
31const (
32 // OnuLossOfPloam is state on onu los
33 OnuLossOfPloam = "lossofploam"
34 // OnuLossOfOmciChannel is the state on omci channel loss alarm
35 OnuLossOfOmciChannel = "lossofomcichannel"
36 // OnuSignalDegrade is the state on signal degrade alarm
37 OnuSignalDegrade = "signaldegrade"
38 // AlarmOn is for raising the alarm
39 AlarmOn = "on"
40 // AlarmOff is for clearing the alarm
41 AlarmOff = "off"
42)
43
Zdravko Bozakov078a2712019-07-19 23:25:15 +020044func (s *Server) handleOnuAlarm(in *api.ONUAlarmRequest) (*api.BBSimResponse, error) {
45 logger.Trace("handleOnuAlarm() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020046 value, ok := s.SNmap.Load(in.OnuSerial)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020047 if !ok {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020048 return &api.BBSimResponse{}, status.Errorf(codes.NotFound, "no active or discovered onu found with serial number "+in.OnuSerial)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020049 }
50
Zdravko Bozakov078a2712019-07-19 23:25:15 +020051 onu := value.(*device.Onu)
52 if (onu.InternalState == device.OnuLosRaised || onu.InternalState == device.OnuLosOnOltPonLos) &&
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020053 (in.AlarmType != OnuLossOfPloam) {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020054 return &api.BBSimResponse{}, status.Errorf(codes.Aborted, in.OnuSerial+" is not reachable, can not send onu alarm")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020055 }
56
57 if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && (in.AlarmType != OnuLossOfPloam) {
58 // Don't send onu alarm as OLT-PON is down
Zdravko Bozakov078a2712019-07-19 23:25:15 +020059 return &api.BBSimResponse{}, status.Errorf(codes.Aborted, "pon-port down, can not send onu alarm")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020060 }
61 switch in.AlarmType {
62 case OnuLossOfOmciChannel:
63 Ind := formulateLossOfOmciChannelAlarm(in.Status, onu)
64 if in.Status == AlarmOn {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020065 onu.UpdateIntState(device.OnuOmciChannelLosRaised)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020066 } else {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020067 onu.UpdateIntState(device.OnuActive)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020068 }
69 s.alarmCh <- Ind
Zdravko Bozakov078a2712019-07-19 23:25:15 +020070 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020071
72 case OnuSignalDegrade:
73 Ind := formulateSignalDegradeAlarm(in.Status, onu)
74 s.alarmCh <- Ind
Zdravko Bozakov078a2712019-07-19 23:25:15 +020075 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020076
77 case OnuLossOfPloam:
78 if in.Status == AlarmOn {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020079 onu.UpdateIntState(device.OnuLosRaised)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020080 device.UpdateOnusOpStatus(onu.IntfID, onu, "down")
81 } else {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020082 onu.UpdateIntState(device.OnuActive)
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020083 device.UpdateOnusOpStatus(onu.IntfID, onu, "up")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020084 err := sendOnuDiscInd(*s.EnableServer, onu)
85 if err != nil {
Zdravko Bozakov078a2712019-07-19 23:25:15 +020086 logger.Error("Error: %s", err.Error())
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020087 }
88 }
89 Ind := formulateLossOfPLOAM(in.Status, onu)
90 s.alarmCh <- Ind
Mahir Gunyel32dfd722019-08-05 16:18:06 +030091 er := sendOnuInd(*s.EnableServer, onu, onu.OperState, "up")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +020092 if er != nil {
93 logger.Debug(er.Error())
94 }
95
96 resp, err := s.checkAndSendOltPonLos(in.OnuSerial, in.Status, device.IntfPon) // Send olt los if all the onus attached to a pon-port shows los
97 if err != nil {
98 return resp, err
99 }
100 return resp, nil
101
102 default:
103 logger.Debug("Unhandled alarm type")
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200104 return &api.BBSimResponse{}, status.Errorf(codes.Unimplemented, "Unhandled alarm type")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200105 }
106
107}
108
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200109func (s *Server) handleOltAlarm(in *api.OLTAlarmRequest) (*api.BBSimResponse, error) {
110 logger.Trace("handleOltAlarm() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200111 switch in.PortType {
112 case device.IntfNni:
113
114 if !s.isNniIntfPresentInOlt(in.PortId) {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200115 return &api.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" NNI not present in olt")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200116 }
117
118 Ind := formulateOLTLOSAlarm(in.Status, in.PortId, device.IntfNni)
119 s.alarmCh <- Ind
120 s.setNNIPortState(in.PortId, in.Status)
121
122 case device.IntfPon:
123 if !s.isPonIntfPresentInOlt(in.PortId) {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200124 return &api.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" PON not present in olt")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200125 }
126 Ind := formulateOLTLOSAlarm(in.Status, in.PortId, in.PortType)
127 s.alarmCh <- Ind
128 onusOperstat := s.setPONPortState(in.PortId, in.Status)
129 for _, onu := range s.Onumap[in.PortId] {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200130 if onu.InternalState == device.OnuLosRaised || onu.InternalState == device.OnuFree {
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200131 continue // Skip for onus which have independently raised onu los
132 }
133
Mahir Gunyel32dfd722019-08-05 16:18:06 +0300134 er := sendOnuInd(*s.EnableServer, onu, onusOperstat, "up")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200135 if er != nil {
136 logger.Debug(er.Error())
137 }
138 s.sendOnuLosOnOltPonLos(onu, in.Status)
139 }
140 default:
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200141 return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid interface type provided")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200142 }
143
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200144 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200145}
146
147func (s *Server) setNNIPortState(portID uint32, alarmstatus string) {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200148 logger.Trace("setNNIPortState() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200149 switch alarmstatus {
150 case AlarmOn:
151 s.Olt.UpdateNniPortState(portID, device.NniLosRaised, "down")
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200152 err := flowHandler.PortDown(0)
153 if err != nil {
154 logger.Error("Failed in port down %v", err)
155 }
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200156
157 case AlarmOff:
158 s.Olt.UpdateNniPortState(portID, device.NniLosCleared, "up")
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200159 err := flowHandler.PortUp(0)
160 if err != nil {
161 logger.Error("Failed in port up %v", err)
162 }
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200163 }
164}
165
166func (s *Server) setPONPortState(portID uint32, alarmstatus string) string {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200167 logger.Trace("setPONPortState() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200168 switch alarmstatus {
169 case AlarmOn:
170 s.Olt.UpdatePonPortState(portID, device.PonLosRaised, "down")
171 return "down"
172
173 case AlarmOff:
174 s.Olt.UpdatePonPortState(portID, device.PonLosCleared, "up")
175 return "up"
176 }
177 return ""
178}
179
180func (s *Server) sendOnuLosOnOltPonLos(onu *device.Onu, status string) {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200181 logger.Trace("sendOnuLosOnOltPonLos() invoked")
182 var internalState device.State
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200183
184 if status == AlarmOn {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200185 internalState = device.OnuLosOnOltPonLos
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200186 } else if status == AlarmOff {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200187 internalState = device.OnuActive
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200188 }
189
190 Ind := formulateLossOfPLOAM(status, onu)
191 onu.UpdateIntState(internalState)
192
193 // update onus slice on alarm off
194 if status == "off" {
195 err := sendOnuDiscInd(*s.EnableServer, onu)
196 if err != nil {
197 logger.Error(err.Error())
198 }
199 }
200
201 s.alarmCh <- Ind
202}
203
204func formulateLossOfOmciChannelAlarm(status string, onu *device.Onu) *openolt.Indication {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200205 logger.Trace("formulateLossofOmciChannelAlarm() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200206
207 alarmIndication := &openolt.AlarmIndication_OnuLossOmciInd{
208 OnuLossOmciInd: &openolt.OnuLossOfOmciChannelIndication{
209 IntfId: onu.IntfID,
210 OnuId: onu.OnuID,
211 Status: status,
212 },
213 }
214
215 alarmind := &openolt.AlarmIndication{
216 Data: alarmIndication,
217 }
218
219 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
220 Ind := &openolt.Indication{Data: msg}
221 return Ind
222}
223
224func formulateSignalDegradeAlarm(status string, onu *device.Onu) *openolt.Indication {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200225 logger.Trace("formulateSignalDegrade() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200226 alarmIndication := &openolt.AlarmIndication_OnuSignalDegradeInd{
227 OnuSignalDegradeInd: &openolt.OnuSignalDegradeIndication{
228 IntfId: onu.IntfID,
229 OnuId: onu.OnuID,
230 Status: status,
231 InverseBitErrorRate: 0,
232 },
233 }
234 alarmind := &openolt.AlarmIndication{
235 Data: alarmIndication,
236 }
237 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
238 Ind := &openolt.Indication{Data: msg}
239 return Ind
240}
241
242func formulateLossOfPLOAM(status string, onu *device.Onu) *openolt.Indication {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200243 logger.Trace("formulateLossOfPLOAM() invoked")
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200244
245 alarmIndication := &openolt.AlarmIndication_OnuAlarmInd{OnuAlarmInd: &openolt.OnuAlarmIndication{
246 IntfId: onu.IntfID,
247 OnuId: onu.OnuID,
248 LosStatus: status,
249 LobStatus: status,
250 LopcMissStatus: status,
251 LopcMicErrorStatus: status,
252 }}
253
254 alarmind := &openolt.AlarmIndication{Data: alarmIndication}
255 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
256 Ind := &openolt.Indication{Data: msg}
257 return Ind
258}
259
260func formulateOLTLOSAlarm(status string, PortID uint32, intfType string) *openolt.Indication {
261 intfID := interfaceIDToPortNo(PortID, intfType)
262
263 alarmIndication := &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
264 IntfId: intfID,
265 Status: status,
266 }}
267
268 alarmind := &openolt.AlarmIndication{Data: alarmIndication}
269 msg := &openolt.Indication_AlarmInd{AlarmInd: alarmind}
270 Ind := &openolt.Indication{Data: msg}
271 return Ind
272}
273
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200274func (s *Server) checkAndSendOltPonLos(serial string, status string, intfType string) (*api.BBSimResponse, error) {
275 value, ok := s.SNmap.Load(serial)
276 if !ok {
277 logger.Debug(serial + " not found in OLT-" + strconv.Itoa(int(s.Olt.ID)))
278 return &api.BBSimResponse{}, nil
279 }
280
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200281 onu := value.(*device.Onu)
282 if s.getNoOfActiveOnuByPortID(onu.IntfID) == 0 {
283 logger.Warn("Warning: Sending OLT-LOS, as all onus on pon-port %v raised los", onu.IntfID)
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200284 request := &api.OLTAlarmRequest{PortId: onu.IntfID, Status: AlarmOn, PortType: device.IntfPon}
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200285 resp, err := s.handleOltAlarm(request)
286 return resp, err
287 }
288 if s.Olt.PonIntfs[onu.IntfID].AlarmState == device.PonLosRaised && status == AlarmOff {
289 s.setPONPortState(onu.IntfID, status)
290 Ind := formulateOLTLOSAlarm(status, onu.IntfID, intfType)
291 s.alarmCh <- Ind
292 }
293
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200294 return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200295}
296
297func interfaceIDToPortNo(intfid uint32, intfType string) uint32 {
Zdravko Bozakov078a2712019-07-19 23:25:15 +0200298 logger.Trace("interfaceIDToPortNo() invoked")
299 // Converts interface-id to port-numbers that can be understood by the VOLTHA
Zdravko Bozakov7401ff22019-05-28 22:45:12 +0200300 if intfType == device.IntfNni {
301 // nni at voltha starts with 65536
302 // nni = 65536 + interface_id
303 return 0x1<<16 + intfid
304 } else if intfType == device.IntfPon {
305 // pon = 536,870,912 + interface_id
306 return (0x2 << 28) + intfid // In openolt code, stats_collection.cc line number 196, pon starts from 0
307 // In bbsim, pon starts from 1
308 }
309 return 0
310}