Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package core |
| 18 | |
| 19 | import ( |
| 20 | "strconv" |
| 21 | |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 22 | api "github.com/opencord/voltha-bbsim/api" |
Zack Williams | 2abf393 | 2019-08-05 14:07:05 -0700 | [diff] [blame] | 23 | "github.com/opencord/voltha-bbsim/common/logger" |
| 24 | "github.com/opencord/voltha-bbsim/device" |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 25 | flowHandler "github.com/opencord/voltha-bbsim/flow" |
Matt Jeanneret | 7c9c5f2 | 2019-08-09 14:40:12 -0400 | [diff] [blame] | 26 | openolt "github.com/opencord/voltha-protos/go/openolt" |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 27 | "google.golang.org/grpc/codes" |
| 28 | "google.golang.org/grpc/status" |
| 29 | ) |
| 30 | |
| 31 | const ( |
| 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 44 | func (s *Server) handleOnuAlarm(in *api.ONUAlarmRequest) (*api.BBSimResponse, error) { |
| 45 | logger.Trace("handleOnuAlarm() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 46 | value, ok := s.SNmap.Load(in.OnuSerial) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 47 | if !ok { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 48 | return &api.BBSimResponse{}, status.Errorf(codes.NotFound, "no active or discovered onu found with serial number "+in.OnuSerial) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 49 | } |
| 50 | |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 51 | onu := value.(*device.Onu) |
| 52 | if (onu.InternalState == device.OnuLosRaised || onu.InternalState == device.OnuLosOnOltPonLos) && |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 53 | (in.AlarmType != OnuLossOfPloam) { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 54 | return &api.BBSimResponse{}, status.Errorf(codes.Aborted, in.OnuSerial+" is not reachable, can not send onu alarm") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 55 | } |
| 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 59 | return &api.BBSimResponse{}, status.Errorf(codes.Aborted, "pon-port down, can not send onu alarm") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 60 | } |
| 61 | switch in.AlarmType { |
| 62 | case OnuLossOfOmciChannel: |
| 63 | Ind := formulateLossOfOmciChannelAlarm(in.Status, onu) |
| 64 | if in.Status == AlarmOn { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 65 | onu.UpdateIntState(device.OnuOmciChannelLosRaised) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 66 | } else { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 67 | onu.UpdateIntState(device.OnuActive) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 68 | } |
| 69 | s.alarmCh <- Ind |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 70 | return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 71 | |
| 72 | case OnuSignalDegrade: |
| 73 | Ind := formulateSignalDegradeAlarm(in.Status, onu) |
| 74 | s.alarmCh <- Ind |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 75 | return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 76 | |
| 77 | case OnuLossOfPloam: |
| 78 | if in.Status == AlarmOn { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 79 | onu.UpdateIntState(device.OnuLosRaised) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 80 | device.UpdateOnusOpStatus(onu.IntfID, onu, "down") |
| 81 | } else { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 82 | onu.UpdateIntState(device.OnuActive) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 83 | device.UpdateOnusOpStatus(onu.IntfID, onu, "up") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 84 | err := sendOnuDiscInd(*s.EnableServer, onu) |
| 85 | if err != nil { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 86 | logger.Error("Error: %s", err.Error()) |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | Ind := formulateLossOfPLOAM(in.Status, onu) |
| 90 | s.alarmCh <- Ind |
Mahir Gunyel | 32dfd72 | 2019-08-05 16:18:06 +0300 | [diff] [blame] | 91 | er := sendOnuInd(*s.EnableServer, onu, onu.OperState, "up") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 92 | 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 104 | return &api.BBSimResponse{}, status.Errorf(codes.Unimplemented, "Unhandled alarm type") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | } |
| 108 | |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 109 | func (s *Server) handleOltAlarm(in *api.OLTAlarmRequest) (*api.BBSimResponse, error) { |
| 110 | logger.Trace("handleOltAlarm() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 111 | switch in.PortType { |
| 112 | case device.IntfNni: |
| 113 | |
| 114 | if !s.isNniIntfPresentInOlt(in.PortId) { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 115 | return &api.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" NNI not present in olt") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 116 | } |
| 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 124 | return &api.BBSimResponse{}, status.Errorf(codes.NotFound, strconv.Itoa(int(in.PortId))+" PON not present in olt") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 125 | } |
| 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 130 | if onu.InternalState == device.OnuLosRaised || onu.InternalState == device.OnuFree { |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 131 | continue // Skip for onus which have independently raised onu los |
| 132 | } |
| 133 | |
Mahir Gunyel | 32dfd72 | 2019-08-05 16:18:06 +0300 | [diff] [blame] | 134 | er := sendOnuInd(*s.EnableServer, onu, onusOperstat, "up") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 135 | if er != nil { |
| 136 | logger.Debug(er.Error()) |
| 137 | } |
| 138 | s.sendOnuLosOnOltPonLos(onu, in.Status) |
| 139 | } |
| 140 | default: |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 141 | return &api.BBSimResponse{}, status.Errorf(codes.InvalidArgument, "invalid interface type provided") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 142 | } |
| 143 | |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 144 | return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | func (s *Server) setNNIPortState(portID uint32, alarmstatus string) { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 148 | logger.Trace("setNNIPortState() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 149 | switch alarmstatus { |
| 150 | case AlarmOn: |
| 151 | s.Olt.UpdateNniPortState(portID, device.NniLosRaised, "down") |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 152 | err := flowHandler.PortDown(0) |
| 153 | if err != nil { |
| 154 | logger.Error("Failed in port down %v", err) |
| 155 | } |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 156 | |
| 157 | case AlarmOff: |
| 158 | s.Olt.UpdateNniPortState(portID, device.NniLosCleared, "up") |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 159 | err := flowHandler.PortUp(0) |
| 160 | if err != nil { |
| 161 | logger.Error("Failed in port up %v", err) |
| 162 | } |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 163 | } |
| 164 | } |
| 165 | |
| 166 | func (s *Server) setPONPortState(portID uint32, alarmstatus string) string { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 167 | logger.Trace("setPONPortState() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 168 | 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 | |
| 180 | func (s *Server) sendOnuLosOnOltPonLos(onu *device.Onu, status string) { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 181 | logger.Trace("sendOnuLosOnOltPonLos() invoked") |
| 182 | var internalState device.State |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 183 | |
| 184 | if status == AlarmOn { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 185 | internalState = device.OnuLosOnOltPonLos |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 186 | } else if status == AlarmOff { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 187 | internalState = device.OnuActive |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 188 | } |
| 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 | |
| 204 | func formulateLossOfOmciChannelAlarm(status string, onu *device.Onu) *openolt.Indication { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 205 | logger.Trace("formulateLossofOmciChannelAlarm() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 206 | |
| 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 | |
| 224 | func formulateSignalDegradeAlarm(status string, onu *device.Onu) *openolt.Indication { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 225 | logger.Trace("formulateSignalDegrade() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 226 | 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 | |
| 242 | func formulateLossOfPLOAM(status string, onu *device.Onu) *openolt.Indication { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 243 | logger.Trace("formulateLossOfPLOAM() invoked") |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 244 | |
| 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 | |
| 260 | func 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 274 | func (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 Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 281 | 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 284 | request := &api.OLTAlarmRequest{PortId: onu.IntfID, Status: AlarmOn, PortType: device.IntfPon} |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 285 | 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 Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 294 | return &api.BBSimResponse{StatusMsg: RequestAccepted}, nil |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 295 | } |
| 296 | |
| 297 | func interfaceIDToPortNo(intfid uint32, intfType string) uint32 { |
Zdravko Bozakov | 078a271 | 2019-07-19 23:25:15 +0200 | [diff] [blame] | 298 | logger.Trace("interfaceIDToPortNo() invoked") |
| 299 | // Converts interface-id to port-numbers that can be understood by the VOLTHA |
Zdravko Bozakov | 7401ff2 | 2019-05-28 22:45:12 +0200 | [diff] [blame] | 300 | 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 | } |