blob: 0e46594aeedf09c06d5cca8ab184cae636f28be1 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
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 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Girish Gowdra491a9c62021-01-06 16:43:07 -080024 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "fmt"
Girish Gowdra0f3190e2022-02-11 14:18:28 -080026 "github.com/opencord/voltha-lib-go/v7/pkg/db"
27 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040029 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070030 "strconv"
31 "strings"
32 "sync"
33 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053034
khenaidoo106c61a2021-08-11 18:05:46 -040035 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040036
Matteo Scandolo945e4012019-12-12 14:16:11 -080037 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070038 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000039 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
40 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040041 "github.com/opencord/voltha-lib-go/v7/pkg/config"
42 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
43 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
44 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070045 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040046 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080047
khenaidoo106c61a2021-08-11 18:05:46 -040048 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053049 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080050 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040051 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040052 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040053 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040054 "github.com/opencord/voltha-protos/v5/go/health"
55 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Manikkaraj kb1d51442019-07-23 10:41:02 -040076)
77
Phaneendra Manda4c62c802019-03-06 21:37:49 +053078//DeviceHandler will interact with the OLT device.
79type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040080 cm *config.ConfigManager
81 device *voltha.Device
82 cfg *conf.AdapterFlags
83 coreClient *vgrpc.Client
84 childAdapterClients map[string]*vgrpc.Client
85 lockChildAdapterClients sync.RWMutex
86 EventProxy eventif.EventProxy
87 openOLT *OpenOLT
88 exitChannel chan int
89 lockDevice sync.RWMutex
90 Client oop.OpenoltClient
91 transitionMap *TransitionMap
92 clientCon *grpc.ClientConn
93 flowMgr []*OpenOltFlowMgr
94 groupMgr *OpenOltGroupMgr
95 eventMgr *OpenOltEventMgr
96 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070097
98 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053099
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700100 discOnus sync.Map
101 onus sync.Map
102 portStats *OpenOltStatisticsMgr
103 metrics *pmmetrics.PmMetrics
104 stopCollector chan bool
105 stopHeartbeatCheck chan bool
106 activePorts sync.Map
107 stopIndications chan bool
108 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700109
Mahir Gunyelb0046752021-02-26 13:51:05 -0800110 totalPonPorts uint32
111 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
112 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800113
114 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
115 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700116 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
117 stopMcastHandlerRoutine []chan bool
118 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000119
120 adapterPreviouslyConnected bool
121 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700122
123 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700124}
125
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700127type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400128 deviceID string
129 deviceType string
130 serialNumber string
131 onuID uint32
132 intfID uint32
133 proxyDeviceID string
134 losRaised bool
135 rdiRaised bool
136 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137}
138
Mahir Gunyelb0046752021-02-26 13:51:05 -0800139type onuIndicationMsg struct {
140 ctx context.Context
141 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800142}
143
144type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800145 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800146 stopChannel chan struct{}
147}
148
Girish Gowdra491a9c62021-01-06 16:43:07 -0800149//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
150//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
151//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
152//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
153type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400154 ctx context.Context // Flow/group handler context
155 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
156 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
157 group *of.OfpGroupEntry // Group message (can be nil or valid group)
158 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800159}
160
Naga Manjunath7615e552019-10-11 22:35:47 +0530161var pmNames = []string{
162 "rx_bytes",
163 "rx_packets",
164 "rx_mcast_packets",
165 "rx_bcast_packets",
166 "tx_bytes",
167 "tx_packets",
168 "tx_mcast_packets",
169 "tx_bcast_packets",
170}
171
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700172//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400173func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700174 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700175 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700176 device.deviceType = deviceTp
177 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700178 device.onuID = onuID
179 device.intfID = intfID
180 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530181 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400182 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700183 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530184}
185
186//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400187func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700188 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800189 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400190 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400191 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700192 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700193 dh.device = cloned
194 dh.openOLT = adapter
Girish Gowdraae56c722021-11-22 14:31:11 -0800195 dh.exitChannel = make(chan int, 1) // TODO: Why buffered?
cuilin20187b2a8c32019-03-26 19:52:28 -0700196 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800197 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
198 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530199 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500200 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800201 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800202 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400203 dh.childAdapterClients = make(map[string]*vgrpc.Client)
204 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800205 // Create a slice of buffered channels for handling concurrent mcast flow/group.
206 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700207 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
208 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800209 for i := range dh.incomingMcastFlowOrGroup {
210 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800211 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800212 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
213 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
214 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
215 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700216 dh.mcastHandlerRoutineActive[i] = true
217 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800218 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700219 //TODO initialize the support classes.
220 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530221}
222
223// start save the device to the data model
224func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700225 dh.lockDevice.Lock()
226 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700228 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000229 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530230}
231
232// stop stops the device dh. Not much to do for now
233func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 dh.lockDevice.Lock()
235 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000236 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 dh.exitChannel <- 1
khenaidoo106c61a2021-08-11 18:05:46 -0400238
Neha Sharma96b7bf22020-06-15 10:37:32 +0000239 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530240}
241
ssiddiqui04386ee2021-08-23 21:58:25 +0530242func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
243 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
244 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
245 if pooledIntfID == intfID {
246 return resourceRanges.GetTechnology()
247 }
248 }
249 }
250 return ""
251}
252
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400253func macifyIP(ip net.IP) string {
254 if len(ip) > 0 {
255 oct1 := strconv.FormatInt(int64(ip[12]), 16)
256 oct2 := strconv.FormatInt(int64(ip[13]), 16)
257 oct3 := strconv.FormatInt(int64(ip[14]), 16)
258 oct4 := strconv.FormatInt(int64(ip[15]), 16)
259 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
260 }
261 return ""
262}
263
Neha Sharma96b7bf22020-06-15 10:37:32 +0000264func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400265 var genmac string
266 var addr net.IP
267 var ips []string
268 var err error
269
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400271
272 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000273 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400274
275 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000276 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400277 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000278 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400279 }
280 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000281 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530282 log.Fields{"host": ips[0],
283 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400284 return genmac, nil
285 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000286 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400287 }
288
289 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000290 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530291 log.Fields{"host": host,
292 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400293 return genmac, nil
294}
295
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530296func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700297 slist := strings.Split(mac, ":")
298 result := make([]uint32, len(slist))
299 var err error
300 var tmp int64
301 for index, val := range slist {
302 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
303 return []uint32{1, 2, 3, 4, 5, 6}
304 }
305 result[index] = uint32(tmp)
306 }
307 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308}
309
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700310//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800311func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530312
David K. Bainbridge794735f2020-02-11 21:01:37 -0800313 switch portType {
314 case voltha.Port_ETHERNET_NNI:
315 return fmt.Sprintf("nni-%d", portNum), nil
316 case voltha.Port_PON_OLT:
317 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700318 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800319
Girish Kumarf26e4882020-03-05 06:49:10 +0000320 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530321}
322
Elia Battiston596406d2022-02-02 12:19:00 +0100323func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
324 if speedMbps == 0 {
325 //In case it was not set in the indication
326 //and no other value was provided
327 speedMbps = defaultPortSpeedMbps
328 }
329
330 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
331 switch speedMbps {
332 case 1000000:
333 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
334 case 100000:
335 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
336 case 40000:
337 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
338 case 10000:
339 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
340 case 1000:
341 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
342 case 100:
343 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
344 case 10:
345 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
346 }
347
348 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
349
350 port := &of.OfpPort{
351 HwAddr: macAddressToUint32Array(macAddress),
352 Config: 0,
353 State: uint32(of.OfpPortState_OFPPS_LIVE),
354 Curr: capacity,
355 Advertised: capacity,
356 Peer: capacity,
357 CurrSpeed: speedMbps * 1000, //kbps
358 MaxSpeed: speedMbps * 1000, //kbps
359 }
360
361 return port
362}
363
364func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000365 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700366 if state == "up" {
367 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500368 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500369 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700370 } else {
371 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500372 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700373 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700374 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400375 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800376 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000377 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400378 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500379
khenaidoo106c61a2021-08-11 18:05:46 -0400380 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400381 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400382 DeviceId: dh.device.Id,
383 Port: portNum,
384 })
385 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000386 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400387 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400388 DeviceId: dh.device.Id,
389 PortType: portType,
390 PortNo: portNum,
391 OperStatus: operStatus})
392 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400393 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
394 "device-id": dh.device.Id,
395 "port-type": portType,
396 "port-number": portNum,
397 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500398 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400399 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500400 }
khenaidoo106c61a2021-08-11 18:05:46 -0400401
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400402 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400403 port = &voltha.Port{
404 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700405 PortNo: portNum,
406 Label: label,
407 Type: portType,
408 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100409 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700410 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000411 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700412 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400413 err = dh.createPortInCore(ctx, port)
414 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000415 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800416 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000417 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400418 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000419 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530420 return nil
421}
422
Kent Hagermane6ff1012020-07-14 15:07:53 -0400423func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400424 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530425 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400426 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
427 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530428 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800429 dh.lockDevice.Lock()
430 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530431 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530432}
433
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700434// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530435// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800436func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000437 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700438 defer func() {
439 dh.lockDevice.Lock()
440 dh.isReadIndicationRoutineActive = false
441 dh.lockDevice.Unlock()
442 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700443 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700444 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700445 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700446 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400447
David Bainbridgef5879ca2019-12-13 21:17:54 +0000448 // Create an exponential backoff around re-enabling indications. The
449 // maximum elapsed time for the back off is set to 0 so that we will
450 // continue to retry. The max interval defaults to 1m, but is set
451 // here for code clarity
452 indicationBackoff := backoff.NewExponentialBackOff()
453 indicationBackoff.MaxElapsedTime = 0
454 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700455
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700456 dh.lockDevice.Lock()
457 dh.isReadIndicationRoutineActive = true
458 dh.lockDevice.Unlock()
459
Girish Gowdra3f974912020-03-23 20:35:18 -0700460Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700461 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400462 select {
463 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000464 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700465 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400466 default:
467 indication, err := indications.Recv()
468 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000469 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530470 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530471 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400472 // Use an exponential back off to prevent getting into a tight loop
473 duration := indicationBackoff.NextBackOff()
474 if duration == backoff.Stop {
475 // If we reach a maximum then warn and reset the backoff
476 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000477 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530478 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530479 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400480 indicationBackoff.Reset()
481 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700482
483 // On failure process a backoff timer while watching for stopIndications
484 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700485 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700486 select {
487 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000488 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700489 if !backoffTimer.Stop() {
490 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700491 }
492 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700493 case <-backoffTimer.C:
494 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700495 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700496 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
497 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400498 }
499 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000500 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530501 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000502 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530503 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530504 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700505 // Close the stream, and re-initialize it
506 if err = indications.CloseSend(); err != nil {
507 // Ok to ignore here, because we landed here due to a problem on the stream
508 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000509 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530510 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530511 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700512 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000513 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700514 return err
515 }
516 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400517 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530518 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400519 // Reset backoff if we have a successful receive
520 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400521 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700522 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530524 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530525 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400526 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400527 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400528 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700529 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700531 // Close the send stream
532 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700533
Girish Gowdra3f974912020-03-23 20:35:18 -0700534 return nil
535}
536
537func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700538 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700539 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
540 if err != nil {
541 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
542 }
543 if indications == nil {
544 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
545 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700546 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700547 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400548}
549
550// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
551func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
552 switch indication.Data.(type) {
553 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
554 return true
555
556 default:
557 return false
558 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559}
560
David K. Bainbridge794735f2020-02-11 21:01:37 -0800561func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700562 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000563 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530564 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530566 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000568 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000569 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530570 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000571 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000573 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800574 }
575 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576}
577
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530579func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700580 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700581 switch indication.Data.(type) {
582 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000583 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
584 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700585 logger.Infow(ctx, "received olt indication", log.Fields{"device-id": dh.device.Id, "olt-ind": indication.GetOltInd()})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800586 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400587 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800588 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700589 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000590 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
591 defer span.Finish()
592
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800594 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100595 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400596 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800597 }
598 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000599 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700600 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000601 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
602 defer span.Finish()
603
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700604 intfOperInd := indication.GetIntfOperInd()
605 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800606 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100607 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400608 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800609 }
610 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 } else if intfOperInd.GetType() == "pon" {
612 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
613 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800614 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100615 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400616 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800617 }
618 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000619 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700620 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000621 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530622 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530623 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000625 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
626 defer span.Finish()
627
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000629 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800630 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800631 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000633 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
634 defer span.Finish()
635
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000637 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800638 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800639 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000641 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
642 defer span.Finish()
643
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700644 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000645 logger.Debugw(ctx, "received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800646 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000647 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400648 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800649 }
650 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000652 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
653 defer span.Finish()
654
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700657 "intf-type": pktInd.IntfId,
658 "intf-id": pktInd.IntfId,
659 "gem-port-id": pktInd.GemportId,
660 "port-no": pktInd.PortNo,
661 "device-id": dh.device.Id,
662 })
663
664 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000665 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700666 "intf-type": pktInd.IntfId,
667 "intf-id": pktInd.IntfId,
668 "gem-port-id": pktInd.GemportId,
669 "port-no": pktInd.PortNo,
670 "packet": hex.EncodeToString(pktInd.Pkt),
671 "device-id": dh.device.Id,
672 })
673 }
674
David K. Bainbridge794735f2020-02-11 21:01:37 -0800675 go func() {
676 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400677 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800678 }
679 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000681 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
682 defer span.Finish()
683
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700685 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000687 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
688 defer span.Finish()
689
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000691 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000693 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
694 defer span.Finish()
695
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700696 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000697 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
698 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700699 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530700}
701
702// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530703func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530704 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000705 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530706
Girish Gowdra618fa572021-09-01 17:19:29 -0700707 // instantiate the mcast handler routines.
708 for i := range dh.incomingMcastFlowOrGroup {
709 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
710 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
711 if !dh.mcastHandlerRoutineActive[i] {
712 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
713 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
714 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
715 // for incoming mcast flow/group to be processed serially.
716 dh.mcastHandlerRoutineActive[i] = true
717 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
718 }
719 }
720
Girish Gowdru0c588b22019-04-23 23:24:56 -0400721 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400722 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400723 DeviceId: dh.device.Id,
724 OperStatus: voltha.OperStatus_ACTIVE,
725 ConnStatus: voltha.ConnectStatus_REACHABLE,
726 }); err != nil {
727 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400728 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000729
730 //Clear olt communication failure event
731 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
732 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700733 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000734 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
735
Gamze Abakac2c32a62021-03-11 11:44:18 +0000736 //check adapter and agent reconcile status
737 //reboot olt if needed (olt disconnection case)
738 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
739 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
740 log.Fields{
741 "device-id": dh.device.Id,
742 "adapter-status": dh.adapterPreviouslyConnected,
743 "agent-status": dh.agentPreviouslyConnected,
744 })
745 _ = dh.RebootDevice(ctx, dh.device)
746 }
747
Girish Gowdru0c588b22019-04-23 23:24:56 -0400748 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530749}
750
751// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530752func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000753 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400754
khenaidoo106c61a2021-08-11 18:05:46 -0400755 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400756 if err != nil || device == nil {
757 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000758 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400759 }
760
761 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400762
763 //Update the device oper state and connection status
764 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800765 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400766 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800767 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400768
khenaidoodc2116e2021-10-19 17:33:19 -0400769 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400770 DeviceId: cloned.Id,
771 OperStatus: cloned.OperStatus,
772 ConnStatus: cloned.ConnectStatus,
773 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000774 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400775 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400776
777 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400778 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400779 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000780 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400781 }
782 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400783 // Update onu state as down in onu adapter
784 onuInd := oop.OnuIndication{}
785 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400786
787 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
788 if err != nil {
789 return err
790 }
791 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400792 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400793 DeviceId: onuDevice.Id,
794 OnuIndication: &onuInd,
795 })
796 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800797 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400798 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400799 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800800 "onu-indicator": onuInd,
801 "device-type": onuDevice.Type,
802 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700803 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800804 } else {
805 logger.Debugw(ctx, "sending inter adapter down ind to onu success", log.Fields{"olt-device-id": device.Id, "onu-device-id": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400807 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800808 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700809 /* Discovered ONUs entries need to be cleared , since after OLT
810 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530811 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800812 dh.lockDevice.Unlock()
813
Neha Sharma96b7bf22020-06-15 10:37:32 +0000814 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700815 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816}
817
818// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530819func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400820 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000821
822 // if the connection is already available, close the previous connection (olt reboot case)
823 if dh.clientCon != nil {
824 if err = dh.clientCon.Close(); err != nil {
825 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
826 } else {
827 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
828 }
829 }
830
831 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000832 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
833 grpc.WithInsecure(),
834 grpc.WithBlock(),
835 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000836 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000837 )),
838 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000839 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000840 )))
841
842 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530843 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530844 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000845 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400846 }
847 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530848}
849
850// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530851func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400852 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530853 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400854 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530855}
856
857// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530858func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530859 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000860 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400861
862 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400863 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530864 if err != nil || device == nil {
865 /*TODO: needs to handle error scenarios */
866 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
867 }
868 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000869 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400870
871 cloned := proto.Clone(device).(*voltha.Device)
872 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
873 cloned.OperStatus = voltha.OperStatus_UNKNOWN
874 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400875
khenaidoodc2116e2021-10-19 17:33:19 -0400876 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400877 DeviceId: cloned.Id,
878 OperStatus: cloned.OperStatus,
879 ConnStatus: cloned.ConnectStatus,
880 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530881 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400882 }
883
Chaitrashree G S44124192019-08-07 20:21:36 -0400884 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +0530885 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400886 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530887 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400888 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400889 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
890 // all the modules initialized and ready to handle incoming ONUs.
891
Thomas Lee S985938d2020-05-04 11:40:41 +0530892 err = dh.initializeDeviceHandlerModules(ctx)
893 if err != nil {
894 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400895 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400896
897 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800898 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530899 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400900 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 }
902 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700903
904 go startHeartbeatCheck(ctx, dh)
905
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400906 return nil
907 }
908
khenaidoo106c61a2021-08-11 18:05:46 -0400909 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400910 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400911 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400912 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400913 }
khenaidoo106c61a2021-08-11 18:05:46 -0400914 dh.populateActivePorts(ctx, ports.Items)
915 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400916 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400917 }
918
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400919 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530920 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400921 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530922
cuilin20187b2a8c32019-03-26 19:52:28 -0700923 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 go func() {
925 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400926 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800927 }
928 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000929 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000930
931 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000932 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000933 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700934
935 go startHeartbeatCheck(ctx, dh)
936
cuilin20187b2a8c32019-03-26 19:52:28 -0700937 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530938}
939
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400940func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700941 var err error
942 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400943
944 if err != nil {
945 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
946 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700947 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
948 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000949 // +1 is for NNI
950 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
951 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700952 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000953 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
954 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
955 // There is only one NNI manager since multiple NNI is not supported for now
956 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700957 // Instantiate resource manager
958 if dh.resourceMgr[i] = rsrcMgr.NewResourceMgr(ctx, i, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, dh.deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700959 return olterrors.ErrResourceManagerInstantiating
960 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400961 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700962 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
963 // the KV store to manage mcast group data. Provide the first instance (0th index)
964 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
965 return olterrors.ErrGroupManagerInstantiating
966 }
yasin saplid0566272021-12-21 09:10:30 +0000967 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700968 // Instantiate flow manager
969 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
970 return olterrors.ErrFlowManagerInstantiating
971 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700972 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700973 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400974 /* TODO: Instantiate Alarm , stats , BW managers */
975 /* Instantiating Event Manager to handle Alarms and KPIs */
976 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
977
978 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000979 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400980
981 return nil
982
983}
984
Neha Sharma96b7bf22020-06-15 10:37:32 +0000985func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400986 var err error
987 var deviceInfo *oop.DeviceInfo
988
Neha Sharma8f4e4322020-08-06 10:51:53 +0000989 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400990
991 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000992 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400993 }
994 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000995 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400996 }
997
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400999 dh.device.Root = true
1000 dh.device.Vendor = deviceInfo.Vendor
1001 dh.device.Model = deviceInfo.Model
1002 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1003 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1004 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1005
1006 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001008 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001009 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001010 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001011 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001012 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001013 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001014 dh.device.MacAddress = genmac
1015 } else {
1016 dh.device.MacAddress = deviceInfo.DeviceId
1017 }
1018
1019 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001020 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001021 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001022 }
1023
1024 return deviceInfo, nil
1025}
1026
Neha Sharma96b7bf22020-06-15 10:37:32 +00001027func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001028 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301029 for {
1030 select {
1031 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001032 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301033 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001034 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001035
khenaidoo106c61a2021-08-11 18:05:46 -04001036 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001037 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001038 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001039 continue
1040 }
khenaidoo106c61a2021-08-11 18:05:46 -04001041 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301042 // NNI Stats
1043 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001044 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301045 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001047 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001048 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301049 }
1050 // PON Stats
1051 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001052 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301053 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1054 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001055 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001056 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301057 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001058 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001059
yasin sapli9e4c5092022-02-01 13:52:33 +00001060 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001061 if len(onuGemInfoLst) > 0 {
1062 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001063 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001064 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301065 }
1066 }
1067 }
1068}
1069
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001070//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301071func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001072 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001073 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301074 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301075
1076 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001077 cgClient, err := dh.coreClient.GetCoreServiceClient()
1078 if err != nil {
1079 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1080 return
1081 }
1082
1083 // Now, set the initial PM configuration for that device
1084 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001085 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301086 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301087}
1088
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001089//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001090func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1091 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001092 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301093 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001094 HwDesc: "open_pon",
1095 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001096 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001097 },
1098 SwitchFeatures: &of.OfpSwitchFeatures{
1099 NBuffers: 256,
1100 NTables: 2,
1101 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1102 of.OfpCapabilities_OFPC_TABLE_STATS |
1103 of.OfpCapabilities_OFPC_PORT_STATS |
1104 of.OfpCapabilities_OFPC_GROUP_STATS),
1105 },
1106 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301107}
1108
khenaidoo106c61a2021-08-11 18:05:46 -04001109// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001110func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001111 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001112 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001113 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001114 }
khenaidoo106c61a2021-08-11 18:05:46 -04001115 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001116}
1117
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001119 logger.Debugw(ctx, "omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "parent-device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001120 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001121 var deviceID string
1122 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001123 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001124
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001125 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001126 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001127 logger.Debugw(ctx, "recv-omci-msg", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id,
Matteo Scandolo92186242020-06-12 10:54:18 -07001128 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1129 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001130
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001131 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301132
1133 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1134
Neha Sharma96b7bf22020-06-15 10:37:32 +00001135 logger.Debugw(ctx, "omci-indication-for-a-device-not-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001136 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001137
khenaidoodc2116e2021-10-19 17:33:19 -04001138 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001139 ParentId: dh.device.Id,
1140 OnuId: omciInd.OnuId,
1141 ParentPortNo: ponPort,
1142 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301144 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001145 "intf-id": omciInd.IntfId,
1146 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001147 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001148 deviceType = onuDevice.Type
1149 deviceID = onuDevice.Id
1150 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001151 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001153 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001154 } else {
1155 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001156 logger.Debugw(ctx, "omci-indication-for-a-device-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301157 deviceType = onuInCache.(*OnuDevice).deviceType
1158 deviceID = onuInCache.(*OnuDevice).deviceID
1159 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001160 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001161 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001162
khenaidoodc2116e2021-10-19 17:33:19 -04001163 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001164 ParentDeviceId: proxyDeviceID,
1165 ChildDeviceId: deviceID,
1166 Message: omciInd.Pkt,
1167 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301168 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001169 "source": dh.openOLT.config.AdapterEndpoint,
1170 "device-type": deviceType,
1171 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001173 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001174 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301176}
1177
khenaidoo106c61a2021-08-11 18:05:46 -04001178// //ProcessInterAdapterMessage sends the proxied messages to the target device
1179// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1180// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001181// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001182// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001183// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001184// return dh.handleInterAdapterOmciMsg(ctx, msg)
1185// }
1186// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1187// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001188
kesavandb9f54fd2021-11-25 20:08:04 +05301189// ProxyOmciRequests sends the proxied OMCI message to the target device
1190func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1191 if omciMsgs.GetProxyAddress() == nil {
1192 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1193 if err != nil {
1194 return olterrors.NewErrNotFound("onu", log.Fields{
1195 "parent-device-id": dh.device.Id,
1196 "child-device-id": omciMsgs.ChildDeviceId}, err)
1197 }
1198 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1199 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1200 return olterrors.NewErrCommunication("send-failed", log.Fields{
1201 "parent-device-id": dh.device.Id,
1202 "child-device-id": omciMsgs.ChildDeviceId}, err)
1203 }
1204 } else {
1205 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1206 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1207 return olterrors.NewErrCommunication("send-failed", log.Fields{
1208 "parent-device-id": dh.device.Id,
1209 "child-device-id": omciMsgs.ChildDeviceId}, err)
1210 }
1211 }
1212 return nil
1213}
1214
1215func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1216 var intfID uint32
1217 var onuID uint32
1218 var connectStatus common.ConnectStatus_Types
1219 if onuDevice != nil {
1220 intfID = onuDevice.ProxyAddress.GetChannelId()
1221 onuID = onuDevice.ProxyAddress.GetOnuId()
1222 connectStatus = onuDevice.ConnectStatus
1223 } else {
1224 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1225 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1226 connectStatus = omciMsgs.GetConnectStatus()
1227 }
1228 if connectStatus != voltha.ConnectStatus_REACHABLE {
1229 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1230
1231 return olterrors.NewErrCommunication("unreachable", log.Fields{
1232 "intf-id": intfID,
1233 "onu-id": onuID}, nil)
1234 }
1235
1236 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1237 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1238
1239 onuSecOmciMsgList := omciMsgs.GetMessages()
1240
1241 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1242
1243 var omciMessage *oop.OmciMsg
1244 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1245 hex.Encode(hexPkt, onuSecOmciMsg)
1246 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1247
1248 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1249 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1250 //https://jira.opencord.org/browse/VOL-4604
1251 transid := extractOmciTransactionID(onuSecOmciMsg)
1252 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1253 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1254
1255 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1256 if err != nil {
1257 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1258 "intf-id": intfID,
1259 "onu-id": onuID,
1260 "message": omciMessage}, err)
1261 }
1262 }
1263 return nil
1264}
1265
khenaidoo106c61a2021-08-11 18:05:46 -04001266// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001267func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001268 logger.Debugw(ctx, "proxy-omci-message", log.Fields{"parent-device-id": omciMsg.ParentDeviceId, "child-device-id": omciMsg.ChildDeviceId, "proxy-address": omciMsg.ProxyAddress, "connect-status": omciMsg.ConnectStatus})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001269
1270 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001271 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001272 if err != nil {
1273 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001274 "parent-device-id": dh.device.Id,
1275 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001276 }
khenaidoo106c61a2021-08-11 18:05:46 -04001277 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1278 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001279 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001280 "parent-device-id": dh.device.Id,
1281 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001282 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001283 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001284 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1285 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001286 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001287 "parent-device-id": dh.device.Id,
1288 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001289 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001290 }
1291 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301292}
1293
khenaidoodc2116e2021-10-19 17:33:19 -04001294func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295 var intfID uint32
1296 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001297 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001298 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001299 intfID = onuDevice.ProxyAddress.GetChannelId()
1300 onuID = onuDevice.ProxyAddress.GetOnuId()
1301 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001302 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 intfID = omciMsg.GetProxyAddress().GetChannelId()
1304 onuID = omciMsg.GetProxyAddress().GetOnuId()
1305 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001306 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001308 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309
Thomas Lee S94109f12020-03-03 16:39:29 +05301310 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001311 "intf-id": intfID,
1312 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001313 }
1314
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001315 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1316 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301317 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001318 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001319 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1320 hex.Encode(hexPkt, omciMsg.Message)
1321 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1322
1323 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1324 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1325 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001326 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001327 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001328
Neha Sharma8f4e4322020-08-06 10:51:53 +00001329 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301331 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001332 "intf-id": intfID,
1333 "onu-id": onuID,
1334 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001335 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001337}
1338
David K. Bainbridge794735f2020-02-11 21:01:37 -08001339func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301340 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
yasin saplibddc2d72022-02-08 13:10:17 +00001341 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001342 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001343 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001344 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301345 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301346 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001347 st, _ := status.FromError(err)
1348 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001349 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1350
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001351 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301352 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001353 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001354 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001355 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001356 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001358}
1359
Mahir Gunyelb0046752021-02-26 13:51:05 -08001360func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001362 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001363
Mahir Gunyelb0046752021-02-26 13:51:05 -08001364 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001365 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301366
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301367 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001368 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001369 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301370
1371 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1372 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1373 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1374 OnuLosRaise event sent for it */
1375 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1376 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1377 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001378 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301379 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1380 "currentIntfId": onuDiscInd.GetIntfId()})
1381 // TODO:: Should we need to ignore raising OnuLosClear event
1382 // when onu connected to different PON?
1383 }
1384 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1385 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1386 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001387 go func() {
1388 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001389 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001390 }
1391 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301392 }
1393 return true
1394 })
1395
Neha Sharma96b7bf22020-06-15 10:37:32 +00001396 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001398 }
1399
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001400 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001401
1402 // check the ONU is already know to the OLT
1403 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001404 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001405 ParentId: dh.device.Id,
1406 SerialNumber: sn,
1407 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001408
1409 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001410 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001411 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001412 logger.Debugw(ctx, "core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001413 switch e.Code() {
1414 case codes.Internal:
1415 // this probably means NOT FOUND, so just create a new device
1416 onuDevice = nil
1417 case codes.DeadlineExceeded:
1418 // if the call times out, cleanup and exit
1419 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001420 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001421 }
1422 }
1423 }
1424
1425 if onuDevice == nil {
1426 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001428 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001429 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001430 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001431
Neha Sharma96b7bf22020-06-15 10:37:32 +00001432 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001433
1434 if err != nil {
1435 // if we can't create an ID in resource manager,
1436 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001437 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001438 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001439 "pon-intf-id": ponintfid,
1440 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001441 }
1442
khenaidoodc2116e2021-10-19 17:33:19 -04001443 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001444 ParentId: dh.device.Id,
1445 ParentPortNo: parentPortNo,
1446 ChannelId: channelID,
1447 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1448 SerialNumber: sn,
1449 OnuId: onuID,
1450 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001451 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001452 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301453 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001454 "pon-intf-id": ponintfid,
1455 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001456 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001457 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001458 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001459 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301461 log.Fields{"onuDevice": onuDevice,
1462 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001463 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301464 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001465 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001466
khenaidoo106c61a2021-08-11 18:05:46 -04001467 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1468 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1469 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1470 cancel()
1471 if err != nil {
1472 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1473 }
1474
Matteo Scandolo945e4012019-12-12 14:16:11 -08001475 // we can now use the existing ONU Id
1476 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001477 //Insert the ONU into cache to use in OnuIndication.
1478 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001480 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301481 "intfId": onuDiscInd.GetIntfId(),
1482 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001483 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001484
khenaidoo106c61a2021-08-11 18:05:46 -04001485 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301486 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001487 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301488 log.Fields{"onu": onuDev,
1489 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001490
khenaidoodc2116e2021-10-19 17:33:19 -04001491 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001492 DeviceId: onuDevice.Id,
1493 ParentDeviceId: dh.device.Id,
1494 OperStatus: common.OperStatus_DISCOVERED,
1495 ConnStatus: common.ConnectStatus_REACHABLE,
1496 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301497 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001498 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001499 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001500 }
khenaidoo106c61a2021-08-11 18:05:46 -04001501
Neha Sharma96b7bf22020-06-15 10:37:32 +00001502 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001503 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301504 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001505 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001506 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001507 }
1508 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001509}
1510
Mahir Gunyelb0046752021-02-26 13:51:05 -08001511func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001512
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001513 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001514 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001515 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001516 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001517 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301518 log.Fields{"onuId": onuInd.OnuId,
1519 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301520 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001521 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001522 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301523
David K. Bainbridge794735f2020-02-11 21:01:37 -08001524 errFields := log.Fields{"device-id": dh.device.Id}
1525
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301526 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1527
Mahir Gunyele77977b2019-06-27 05:36:22 -07001528 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1529 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001530 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001531 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001532 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001533 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1534 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001535 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001536 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001537 errFields["onu-id"] = onuInd.OnuId
1538 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001539 }
khenaidoodc2116e2021-10-19 17:33:19 -04001540 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001541 ParentId: dh.device.Id,
1542 SerialNumber: serialNumber,
1543 OnuId: onuInd.OnuId,
1544 ParentPortNo: ponPort,
1545 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001546 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001547
David K. Bainbridge794735f2020-02-11 21:01:37 -08001548 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001549 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001550 }
1551
David K. Bainbridge794735f2020-02-11 21:01:37 -08001552 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001553 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001554 "previousIntfId": onuDevice.ParentPortNo,
1555 "currentIntfId": ponPort})
1556 }
1557
1558 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301560 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1561 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301562 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001563 }
1564 if !foundInCache {
1565 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1566
khenaidoo106c61a2021-08-11 18:05:46 -04001567 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001568
1569 }
kesavand7cf3a052020-08-28 12:49:18 +05301570 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001571 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001572 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301573 }
1574 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001575 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001576 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 }
1578 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001579}
1580
Neha Sharma96b7bf22020-06-15 10:37:32 +00001581func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001582 logger.Debugw(ctx, "onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdra748de5c2020-07-01 10:27:52 -07001583 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1584 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1585 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1586 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001587 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001588 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1589 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001590 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001591 onuInd.OperState = "down"
1592 }
1593 }
1594
David K. Bainbridge794735f2020-02-11 21:01:37 -08001595 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001596 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
khenaidoo106c61a2021-08-11 18:05:46 -04001598
khenaidoodc2116e2021-10-19 17:33:19 -04001599 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001600 DeviceId: onuDevice.Id,
1601 OnuIndication: onuInd,
1602 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001603 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301604 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001606 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001608 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001609 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001611 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001612 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001613 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001614}
1615
cuilin20187b2a8c32019-03-26 19:52:28 -07001616func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1617 if serialNum != nil {
1618 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001619 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001620 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001621}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001622func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1623 decodedStr, err := hex.DecodeString(serialNum[4:])
1624 if err != nil {
1625 return nil, err
1626 }
1627 return &oop.SerialNumber{
1628 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001629 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001630 }, nil
1631}
cuilin20187b2a8c32019-03-26 19:52:28 -07001632
1633func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001634 if len(vendorSpecific) > 3 {
1635 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1636 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1637 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1638 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1639 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1640 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1641 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1642 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1643 return tmp
1644 }
1645 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001646}
1647
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001648//UpdateFlowsBulk upates the bulk flow
1649func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301650 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001651}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001652
1653//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1655 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301656 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001657 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301658 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001659
khenaidoodc2116e2021-10-19 17:33:19 -04001660 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001661 ParentId: dh.device.Id,
1662 OnuId: onuID,
1663 ParentPortNo: parentPort,
1664 })
1665
Girish Gowdru0c588b22019-04-23 23:24:56 -04001666 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001667 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001668 "intf-id": parentPort,
1669 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Debugw(ctx, "successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001672 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301673}
1674
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001675// SendPacketInToCore sends packet-in to core
1676// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1677// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001679 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001681 "port": logicalPort,
1682 "packet": hex.EncodeToString(packetPayload),
1683 "device-id": dh.device.Id,
1684 })
1685 }
khenaidoo106c61a2021-08-11 18:05:46 -04001686
khenaidoodc2116e2021-10-19 17:33:19 -04001687 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001688 DeviceId: dh.device.Id,
1689 Port: logicalPort,
1690 Packet: packetPayload,
1691 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301692 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 "source": "adapter",
1694 "destination": "core",
1695 "device-id": dh.device.Id,
1696 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001697 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001698 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001699 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001701 "packet": hex.EncodeToString(packetPayload),
1702 "device-id": dh.device.Id,
1703 })
1704 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001705 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001706}
1707
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001708// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001710 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001711
1712 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1713 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001715 }
1716
Kent Hagermane6ff1012020-07-14 15:07:53 -04001717 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001718 metrics := dh.metrics.GetSubscriberMetrics()
1719 for _, m := range pmConfigs.Metrics {
1720 metrics[m.Name].Enabled = m.Enabled
1721
1722 }
1723 }
1724}
1725
khenaidoodc2116e2021-10-19 17:33:19 -04001726func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001727 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001728 var errorsList []error
1729
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001730 if dh.getDeviceDeletionInProgressFlag() {
1731 // The device itself is going to be reset as part of deletion. So nothing to be done.
1732 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1733 return nil
1734 }
1735
Girish Gowdru0c588b22019-04-23 23:24:56 -04001736 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001737 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001738 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001739
Neha Sharma96b7bf22020-06-15 10:37:32 +00001740 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301741 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001742 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301743 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001744 if flow_utils.HasGroup(flow) {
1745 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1746 } else {
yasin saplid0566272021-12-21 09:10:30 +00001747 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001748 }
Girish Gowdracefae192020-03-19 18:14:10 -07001749 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001750 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1751 //The flow we want to remove is not there, there is no need to throw an error
1752 logger.Warnw(ctx, "flow-to-remove-not-found",
1753 log.Fields{
1754 "ponIf": intfID,
1755 "flowToRemove": flow,
1756 "error": err,
1757 })
1758 } else {
1759 errorsList = append(errorsList, err)
1760 }
Girish Gowdracefae192020-03-19 18:14:10 -07001761 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001762 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301763
1764 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001765 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301767 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001768 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301769 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001770 if flow_utils.HasGroup(flow) {
1771 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1772 } else {
yasin saplid0566272021-12-21 09:10:30 +00001773 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001774 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1775 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1776 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1777 } else {
yasin saplid0566272021-12-21 09:10:30 +00001778 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001779 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001780 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001781 if err != nil {
1782 errorsList = append(errorsList, err)
1783 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301784 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001785 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001786
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001787 return errorsList
1788}
1789
1790func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1791 var err error
1792 var errorsList []error
1793
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001794 if dh.getDeviceDeletionInProgressFlag() {
1795 // The device itself is going to be reset as part of deletion. So nothing to be done.
1796 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1797 return nil
1798 }
1799
Girish Gowdracefae192020-03-19 18:14:10 -07001800 // Whether we need to synchronize multicast group adds and modifies like flow add and delete needs to be investigated
Esin Karamanccb714b2019-11-29 15:02:06 +00001801 if groups != nil {
1802 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001803 // err = dh.groupMgr.AddGroup(ctx, group)
1804 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001805 if err != nil {
1806 errorsList = append(errorsList, err)
1807 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001808 }
1809 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001810 // err = dh.groupMgr.ModifyGroup(ctx, group)
1811 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001812 if err != nil {
1813 errorsList = append(errorsList, err)
1814 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001815 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001816 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001817 // err = dh.groupMgr.DeleteGroup(ctx, group)
1818 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001819 if err != nil {
1820 errorsList = append(errorsList, err)
1821 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001822 }
1823 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001824
1825 return errorsList
1826}
1827
1828//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001829func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *of.FlowMetadata) error {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001830
1831 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001832
1833 if dh.getDeviceDeletionInProgressFlag() {
1834 // The device itself is going to be reset as part of deletion. So nothing to be done.
1835 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1836 return nil
1837 }
1838
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001839 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1840 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1841 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001842 if len(errorsList) > 0 {
1843 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1844 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001845 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001846 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301847}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001848
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001849//DisableDevice disables the given device
1850//It marks the following for the given device:
1851//Device-Handler Admin-State : down
1852//Device Port-State: UNKNOWN
1853//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001854func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001855 /* On device disable ,admin state update has to be done prior sending request to agent since
1856 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001857 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001858 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001859 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001860 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001861 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001862 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001863 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001864 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001865 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001866 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301867
1868 dh.discOnus = sync.Map{}
1869 dh.onus = sync.Map{}
1870
Thomas Lee S85f37312020-04-03 17:06:12 +05301871 //stopping the stats collector
1872 dh.stopCollector <- true
1873
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001875 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301876 //Update device Admin state
1877 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001878
kdarapu1afeceb2020-02-12 01:38:09 -05001879 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
khenaidoodc2116e2021-10-19 17:33:19 -04001880 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001881 DeviceId: cloned.Id,
1882 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1883 OperStatus: voltha.OperStatus_UNKNOWN,
1884 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001885 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001886 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001888 return nil
1889}
1890
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001892 // Update onu state as unreachable in onu adapter
1893 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301894 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001895
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001896 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001897 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001898 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001899 logger.Errorw(ctx, "failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001900 }
1901 if onuDevices != nil {
1902 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001903 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001904 DeviceId: onuDevice.Id,
1905 OnuIndication: &onuInd,
1906 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001907 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001908 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001909 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001910 }
1911
1912 }
1913 }
1914
1915}
1916
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001917//ReenableDevice re-enables the olt device after disable
1918//It marks the following for the given device:
1919//Device-Handler Admin-State : up
1920//Device Port-State: ACTIVE
1921//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001922func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001923 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301924 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001925 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301926 }
1927 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001928 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001929
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001930 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001931 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001932 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001933 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001934 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1935 } else {
1936 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1937 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1938 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001939 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001940 if retError == nil {
1941 //Update the device oper status as ACTIVE
1942 device.OperStatus = voltha.OperStatus_ACTIVE
1943 } else {
1944 //Update the device oper status as FAILED
1945 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001946 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001947 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001948
khenaidoodc2116e2021-10-19 17:33:19 -04001949 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001950 DeviceId: device.Id,
1951 OperStatus: device.OperStatus,
1952 ConnStatus: device.ConnectStatus,
1953 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301954 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001955 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001956 "connect-status": device.ConnectStatus,
1957 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001958 }
kesavand39e0aa32020-01-28 20:58:50 -05001959
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001961
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001962 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001963}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001964
npujarec5762e2020-01-01 14:08:48 +05301965func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001966 var uniID uint32
1967 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301968 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001969 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001970 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001971 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001972 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001973 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001974 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001976 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001977 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00001978 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001980 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001982 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001983 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001984 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301986 }
yasin saplibddc2d72022-02-08 13:10:17 +00001987 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
1988 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001989 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301990 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001991 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001992 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001993 logger.Debugw(ctx, "failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001994 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001995 }
1996 return nil
1997}
1998
Devmalya Paul495b94a2019-08-27 19:42:00 -04001999// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
npujarec5762e2020-01-01 14:08:48 +05302000func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002001 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002002 /* Clear the KV store data associated with the all the UNI ports
2003 This clears up flow data and also resource map data for various
2004 other pon resources like alloc_id and gemport_id
2005 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002006
2007 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002008 var wg sync.WaitGroup
2009 wg.Add(1) // for the mcast routine below to finish
2010 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2011 for _, flMgr := range dh.flowMgr {
2012 wg.Add(1) // for the flow handler routine below to finish
2013 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2014 }
2015 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2016 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2017 } else {
2018 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2019 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002020
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002021 dh.cleanupDeviceResources(ctx)
2022 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002023 // Stop the Stats collector
2024 dh.stopCollector <- true
2025 // stop the heartbeat check routine
2026 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302027 dh.lockDevice.RLock()
2028 // Stop the read indication only if it the routine is active
2029 if dh.isReadIndicationRoutineActive {
2030 dh.stopIndications <- true
2031 }
2032 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002033 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002034 //Reset the state
2035 if dh.Client != nil {
2036 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302037 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002038 }
2039 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002040 // There is no need to update the core about operation status and connection status of the OLT.
2041 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2042 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2043 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002044
khenaidoo7eb2d672021-10-22 19:08:50 -04002045 // Stop the adapter grpc clients for that parent device
2046 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002047 return nil
2048}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002049func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002050
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002051 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302052 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002053 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002054 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002055 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002056 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002057 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002058 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002059 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302060 }
2061 }
yasin saplibddc2d72022-02-08 13:10:17 +00002062 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2063 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002064 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002065 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2066 logger.Debug(ctx, err)
2067 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002068 }
yasin saplibddc2d72022-02-08 13:10:17 +00002069 // Clean up NNI manager's data
2070 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002071 }
A R Karthick1f85b802019-10-11 05:06:05 +00002072
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002073 // Take one final sweep at cleaning up KV store for the OLT device
2074 // Clean everything at <base-path-prefix>/openolt/<device-id>
2075 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2076 if err == nil {
2077 kvBackend := &db.Backend{
2078 Client: kvClient,
2079 StoreType: dh.openOLT.KVStoreType,
2080 Address: dh.openOLT.KVStoreAddress,
2081 Timeout: rsrcMgr.KvstoreTimeout,
2082 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2083 _ = kvBackend.DeleteWithPrefix(ctx, "")
2084 }
2085
Devmalya Paul495b94a2019-08-27 19:42:00 -04002086 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302087 dh.onus.Range(func(key interface{}, value interface{}) bool {
2088 dh.onus.Delete(key)
2089 return true
2090 })
2091
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002092 /*Delete discovered ONU map for the device*/
2093 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2094 dh.discOnus.Delete(key)
2095 return true
2096 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002097}
2098
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002099//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002100func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002101 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302102 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002103 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002105 return nil
2106}
2107
David K. Bainbridge794735f2020-02-11 21:01:37 -08002108func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002109 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002111 "packet-indication": *packetIn,
2112 "device-id": dh.device.Id,
2113 "packet": hex.EncodeToString(packetIn.Pkt),
2114 })
2115 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002116 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002117 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002118 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002119 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002120 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002121 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002122 "logical-port-num": logicalPortNum,
2123 "device-id": dh.device.Id,
2124 "packet": hex.EncodeToString(packetIn.Pkt),
2125 })
2126 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002127
khenaidoodc2116e2021-10-19 17:33:19 -04002128 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002129 DeviceId: dh.device.Id,
2130 Port: logicalPortNum,
2131 Packet: packetIn.Pkt,
2132 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302133 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002134 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302135 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002136 "device-id": dh.device.Id,
2137 "packet": hex.EncodeToString(packetIn.Pkt),
2138 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002139 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140
Matteo Scandolo92186242020-06-12 10:54:18 -07002141 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002142 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002143 "packet": hex.EncodeToString(packetIn.Pkt),
2144 "device-id": dh.device.Id,
2145 })
2146 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002147 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002148}
2149
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002150// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002151func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002152 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002153 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002154 "device-id": dh.device.Id,
2155 "egress-port-no": egressPortNo,
2156 "pkt-length": len(packet.Data),
2157 "packet": hex.EncodeToString(packet.Data),
2158 })
2159 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002160
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002161 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002162 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002163 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2164 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302165 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2166 // Do not packet-out lldp packets on uni port.
2167 // ONOS has no clue about uni/nni ports, it just packets out on all
2168 // available ports on the Logical Switch. It should not be interested
2169 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002170 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002171 "device-id": dh.device.Id,
2172 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302173 return nil
2174 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002175 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2176 if innerEthType == 0x8100 {
2177 // q-in-q 802.1ad or 802.1q double tagged packet.
2178 // slice out the outer tag.
2179 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002180 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002182 "packet-data": hex.EncodeToString(packet.Data),
2183 "device-id": dh.device.Id,
2184 })
2185 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002186 }
2187 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002188 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2189 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2190 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002191
Girish Gowdra9602eb42020-09-09 15:50:39 -07002192 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002193 if err != nil {
2194 // In this case the openolt agent will receive the gemPortID as 0.
2195 // The agent tries to retrieve the gemPortID in this case.
2196 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002198 "intf-id": intfID,
2199 "onu-id": onuID,
2200 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002201 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302202 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002203 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002204 }
2205
2206 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002207 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002209 "egress-port-no": egressPortNo,
2210 "intf-id": intfID,
2211 "onu-id": onuID,
2212 "uni-id": uniID,
2213 "gem-port-id": gemPortID,
2214 "packet": hex.EncodeToString(packet.Data),
2215 "device-id": dh.device.Id,
2216 })
2217 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002218
npujarec5762e2020-01-01 14:08:48 +05302219 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302220 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002221 "source": "adapter",
2222 "destination": "onu",
2223 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002224 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002225 "oni-id": onuID,
2226 "uni-id": uniID,
2227 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002228 "packet": hex.EncodeToString(packet.Data),
2229 "device-id": dh.device.Id,
2230 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002231 }
2232 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002233 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002234 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002235 return olterrors.NewErrInvalidValue(log.Fields{
2236 "egress-nni-port": egressPortNo,
2237 "device-id": dh.device.Id,
2238 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002239 }
2240 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002241
Matteo Scandolo92186242020-06-12 10:54:18 -07002242 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002244 "uplink-pkt": uplinkPkt,
2245 "packet": hex.EncodeToString(packet.Data),
2246 "device-id": dh.device.Id,
2247 })
2248 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002249
npujarec5762e2020-01-01 14:08:48 +05302250 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002251 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2252 "packet": hex.EncodeToString(packet.Data),
2253 "device-id": dh.device.Id,
2254 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002255 }
2256 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002257 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302258 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002259 "egressPortType": egressPortType,
2260 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302261 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002262 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002263 }
2264 return nil
2265}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002267func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2268 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002269}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302270
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002271func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002272
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302273 // start the heartbeat check towards the OLT.
2274 var timerCheck *time.Timer
2275
2276 for {
2277 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2278 select {
2279 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002280 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002281 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002282 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302283 if timerCheck == nil {
2284 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002285 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302286 }
2287 } else {
2288 if timerCheck != nil {
2289 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002290 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302291 }
2292 timerCheck = nil
2293 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002294 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302295 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302296 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302297 }
2298 cancel()
2299 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002300 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302301 return
2302 }
2303 }
2304}
2305
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002306func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002307 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002308 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002309 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2310 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2311 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2312 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2313 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002314 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002315 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2316 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002317 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302318
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002319 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2320 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002321 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002322 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002323 DeviceId: dh.device.Id,
2324 OperStatus: voltha.OperStatus_UNKNOWN,
2325 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2326 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002327 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002328 }
khenaidoo106c61a2021-08-11 18:05:46 -04002329
khenaidoodc2116e2021-10-19 17:33:19 -04002330 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002331 DeviceId: dh.device.Id,
2332 PortTypeFilter: 0,
2333 OperStatus: voltha.OperStatus_UNKNOWN,
2334 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002335 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002336 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002337
2338 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002339 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002340 cloned := proto.Clone(device).(*voltha.Device)
2341 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2342 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2343 dh.device = cloned // update local copy of the device
2344 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002345
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002346 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002347 // Stop the Stats collector
2348 dh.stopCollector <- true
2349 // stop the heartbeat check routine
2350 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002351
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002352 dh.lockDevice.RLock()
2353 // Stop the read indication only if it the routine is active
2354 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2355 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2356 // on next execution of the readIndication routine.
2357 if dh.isReadIndicationRoutineActive {
2358 dh.stopIndications <- true
2359 }
2360 dh.lockDevice.RUnlock()
2361
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002362 var wg sync.WaitGroup
2363 wg.Add(1) // for the multicast handler routine
2364 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002365 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002366 wg.Add(1) // for the flow handler routine
2367 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2368 }
2369 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2370 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2371 } else {
2372 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002373 }
2374
Gamze Abakac2c32a62021-03-11 11:44:18 +00002375 //reset adapter reconcile flag
2376 dh.adapterPreviouslyConnected = false
2377
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002378 dh.transitionMap.Handle(ctx, DeviceInit)
2379
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302380 }
2381}
kesavand39e0aa32020-01-28 20:58:50 -05002382
2383// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2385 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2386 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002387}
2388
2389// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2391 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2392 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002393}
2394
kdarapu1afeceb2020-02-12 01:38:09 -05002395//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002396func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2397 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002398 if port.GetType() == voltha.Port_ETHERNET_NNI {
2399 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302401 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302402 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002403 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002404 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002405 }
2406 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002407 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002408 ponIntf := &oop.Interface{IntfId: ponID}
2409 var operStatus voltha.OperStatus_Types
2410 if enablePort {
2411 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302412 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002413
2414 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302415 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002416 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002417 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002418 }
2419 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002420 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002421 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002422 } else {
2423 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302424 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002425 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302426 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002427 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002428 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002429 }
2430 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002431 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002433 }
khenaidoodc2116e2021-10-19 17:33:19 -04002434 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002435 DeviceId: dh.device.Id,
2436 PortType: voltha.Port_PON_OLT,
2437 PortNo: port.PortNo,
2438 OperStatus: operStatus,
2439 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302440 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302441 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002442 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002443 }
2444 return nil
2445}
2446
kdarapu1afeceb2020-02-12 01:38:09 -05002447//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002448func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002449 // Disable the port and update the oper_port_status to core
2450 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002451 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002452 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002453 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302454 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302455 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002456 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002457 }
2458 }
2459 }
2460 return nil
2461}
2462
2463//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002464func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2465 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2466 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002467 if port.Type == voltha.Port_ETHERNET_NNI {
2468 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002469 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002470 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002471 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002472 }
2473 }
2474 if port.Type == voltha.Port_PON_OLT {
2475 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002476 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002477 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002478 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002479 }
2480 }
2481 }
2482}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002483
2484// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002485func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002486 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002487 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002488 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002489
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002490 var sn *oop.SerialNumber
2491 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002492 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302493 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002494 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302495 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002496 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002497 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002498
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002499 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002500 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002501 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002502 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2503 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2504 "device-id": dh.device.Id,
2505 "intf-id": intfID,
2506 "onuID": onuID,
2507 "err": err})
2508 } else {
2509 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2510 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2511 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2512 "device-id": dh.device.Id,
2513 "onu-device": onu,
2514 "err": err})
2515 }
2516 // Clear flowids for gem cache.
2517 for _, gem := range onuGem.GemPorts {
yasin saplibddc2d72022-02-08 13:10:17 +00002518 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002519 }
yasin saplibddc2d72022-02-08 13:10:17 +00002520 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002521 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2522 "intf-id": intfID,
2523 "onu-device": onu,
2524 "onu-gem": onuGem,
2525 "err": err})
2526 //Not returning error on cleanup.
2527 }
2528 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302529
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002530 }
yasin saplibddc2d72022-02-08 13:10:17 +00002531 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002532 dh.onus.Delete(onuKey)
2533 dh.discOnus.Delete(onuSn)
2534
2535 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002536 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302537 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302538 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002539 "onu-id": onuID}, err).Log()
2540 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002541
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002542 return nil
2543}
Girish Gowdracefae192020-03-19 18:14:10 -07002544
2545func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002546 for _, field := range flow_utils.GetOfbFields(flow) {
2547 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002548 return field.GetPort()
2549 }
2550 }
2551 return InvalidPort
2552}
2553
2554func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002555 for _, action := range flow_utils.GetActions(flow) {
2556 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002557 if out := action.GetOutput(); out != nil {
2558 return out.GetPort()
2559 }
2560 }
2561 }
2562 return InvalidPort
2563}
2564
Girish Gowdracefae192020-03-19 18:14:10 -07002565func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2566 inPort := getInPortFromFlow(flow)
2567 outPort := getOutPortFromFlow(flow)
2568
2569 if inPort == InvalidPort || outPort == InvalidPort {
2570 return inPort, outPort
2571 }
2572
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002573 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002574 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002575 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002576 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002577 return uniPort, outPort
2578 }
2579 }
2580 } else {
2581 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002582 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002583 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002584 return inPort, uniPort
2585 }
2586 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002587 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002588 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002589 return uniPort, outPort
2590 }
2591 }
2592 }
2593
2594 return InvalidPort, InvalidPort
2595}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002596
2597func extractOmciTransactionID(omciPkt []byte) uint16 {
2598 if len(omciPkt) > 3 {
2599 d := omciPkt[0:2]
2600 transid := binary.BigEndian.Uint16(d)
2601 return transid
2602 }
2603 return 0
2604}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002605
2606// StoreOnuDevice stores the onu parameters to the local cache.
2607func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2608 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2609 dh.onus.Store(onuKey, onuDevice)
2610}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002611
khenaidoodc2116e2021-10-19 17:33:19 -04002612func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002613 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002614 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002615 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002616 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002617 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002618 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002619 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002620 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2621 return nil, err
2622 }
2623 ID = device.ProxyAddress.GetOnuId()
2624 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2625 valueparam.Onu = &Onu
2626 valueparam.Value = value
2627
2628 // This API is unsupported until agent patch is added
2629 resp.Unsupported = uint32(value)
2630 _ = ctx
2631
2632 // Uncomment this code once agent changes are complete and tests
2633 /*
2634 resp, err = dh.Client.GetValue(ctx, valueparam)
2635 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002636 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002637 return nil, err
2638 }
2639 */
2640
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002641 logger.Infow(ctx, "get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002642 return resp, nil
2643}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002644
yasin saplid0566272021-12-21 09:10:30 +00002645func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2646 // Default to NNI
2647 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002648 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002649 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002650 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002651 }
2652 return intfID
2653}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002654
Mahir Gunyelb0046752021-02-26 13:51:05 -08002655func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2656 dh.perPonOnuIndicationChannelLock.Lock()
2657 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2658 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002659 return ch.indicationChannel
2660 }
2661 channels := onuIndicationChannels{
2662 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002663 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002664 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002665 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002666 stopChannel: make(chan struct{}),
2667 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002668 dh.perPonOnuIndicationChannel[intfID] = channels
2669 dh.perPonOnuIndicationChannelLock.Unlock()
2670 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002671 return channels.indicationChannel
2672
2673}
2674
Mahir Gunyelb0046752021-02-26 13:51:05 -08002675func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2676 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2677 dh.perPonOnuIndicationChannelLock.Lock()
2678 defer dh.perPonOnuIndicationChannelLock.Unlock()
2679 for _, v := range dh.perPonOnuIndicationChannel {
2680 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002681 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002682 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002683}
2684
Mahir Gunyelb0046752021-02-26 13:51:05 -08002685func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2686 ind := onuIndicationMsg{
2687 ctx: ctx,
2688 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002689 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002690 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002691 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002692 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002693}
2694
Mahir Gunyelb0046752021-02-26 13:51:05 -08002695func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002696 for {
2697 select {
2698 // process one indication per onu, before proceeding to the next one
2699 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002700 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002701 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002702 "ind": indication})
2703 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002704 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002705 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002706 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2707 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002708 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002709 }
2710 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002711 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002712 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2713 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002714 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002715 }
2716 }
2717 case <-onuChannels.stopChannel:
2718 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2719 close(onuChannels.indicationChannel)
2720 return
2721 }
2722 }
2723}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002724
2725// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2726// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002727func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002728 if dh.getDeviceDeletionInProgressFlag() {
2729 // The device itself is going to be reset as part of deletion. So nothing to be done.
2730 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2731 return nil
2732 }
2733
Girish Gowdra491a9c62021-01-06 16:43:07 -08002734 // Step1 : Fill McastFlowOrGroupControlBlock
2735 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2736 // Step3 : Wait on response channel for response
2737 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002738 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002739 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2740 errChan := make(chan error)
2741 var groupID uint32
2742 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2743 ctx: ctx,
2744 flowOrGroupAction: action,
2745 flow: flow,
2746 group: group,
2747 errChan: &errChan,
2748 }
2749 if flow != nil {
2750 groupID = flow_utils.GetGroup(flow)
2751 } else if group != nil {
2752 groupID = group.Desc.GroupId
2753 } else {
2754 return errors.New("flow-and-group-both-nil")
2755 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002756 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2757 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2758 // Derive the appropriate go routine to handle the request by a simple module operation.
2759 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2760 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2761 // Wait for handler to return error value
2762 err := <-errChan
2763 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2764 return err
2765 }
2766 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2767 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002768}
2769
2770// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002771func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002772 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002773 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002774 // block on the channel to receive an incoming mcast flow/group
2775 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002776 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2777 if mcastFlowOrGroupCb.flow != nil {
2778 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2779 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2780 log.Fields{"device-id": dh.device.Id,
2781 "flowToAdd": mcastFlowOrGroupCb.flow})
2782 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2783 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2784 // Pass the return value over the return channel
2785 *mcastFlowOrGroupCb.errChan <- err
2786 } else { // flow remove
2787 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2788 log.Fields{"device-id": dh.device.Id,
2789 "flowToRemove": mcastFlowOrGroupCb.flow})
2790 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2791 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2792 // Pass the return value over the return channel
2793 *mcastFlowOrGroupCb.errChan <- err
2794 }
2795 } else { // mcast group
2796 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2797 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2798 log.Fields{"device-id": dh.device.Id,
2799 "groupToAdd": mcastFlowOrGroupCb.group})
2800 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2801 // Pass the return value over the return channel
2802 *mcastFlowOrGroupCb.errChan <- err
2803 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2804 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2805 log.Fields{"device-id": dh.device.Id,
2806 "groupToModify": mcastFlowOrGroupCb.group})
2807 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2808 // Pass the return value over the return channel
2809 *mcastFlowOrGroupCb.errChan <- err
2810 } else { // group remove
2811 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2812 log.Fields{"device-id": dh.device.Id,
2813 "groupToRemove": mcastFlowOrGroupCb.group})
2814 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2815 // Pass the return value over the return channel
2816 *mcastFlowOrGroupCb.errChan <- err
2817 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002818 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002819 case <-stopHandler:
2820 dh.mcastHandlerRoutineActive[routineIndex] = false
2821 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002822 }
2823 }
2824}
kesavand62126212021-01-12 04:56:06 -05002825
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002826// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002827func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002828 for i, v := range dh.stopMcastHandlerRoutine {
2829 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002830 select {
2831 case v <- true:
2832 case <-time.After(time.Second * 5):
2833 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2834 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002835 }
2836 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002837 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002838 logger.Debug(ctx, "stopped all mcast handler routines")
2839}
2840
kesavand62126212021-01-12 04:56:06 -05002841func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2842
2843 singleValResp := extension.SingleGetValueResponse{
2844 Response: &extension.GetValueResponse{
2845 Response: &extension.GetValueResponse_PortCoutners{
2846 PortCoutners: &extension.GetOltPortCountersResponse{},
2847 },
2848 },
2849 }
2850
2851 errResp := func(status extension.GetValueResponse_Status,
2852 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2853 return &extension.SingleGetValueResponse{
2854 Response: &extension.GetValueResponse{
2855 Status: status,
2856 ErrReason: reason,
2857 },
2858 }
2859 }
2860
2861 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2862 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2863 //send error response
2864 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2865 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2866 }
2867 statIndChn := make(chan bool, 1)
2868 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2869 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2870 //request openOlt agent to send the the port statistics indication
2871
2872 go func() {
2873 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2874 if err != nil {
2875 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2876 }
2877 }()
2878 select {
2879 case <-statIndChn:
2880 //indication received for ports stats
2881 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2882 case <-time.After(oltPortInfoTimeout * time.Second):
2883 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2884 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2885 case <-ctx.Done():
2886 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2887 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2888 }
2889 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2890 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002891 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002892 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2893 cmnni := dh.portStats.collectNNIMetrics(intfID)
2894 if cmnni == nil {
2895 //TODO define the error reason
2896 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2897 }
2898 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2899 return &singleValResp
2900
2901 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2902 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002903 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002904 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2905 cmpon := dh.portStats.collectPONMetrics(intfID)
2906 if cmpon == nil {
2907 //TODO define the error reason
2908 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2909 }
2910 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2911 return &singleValResp
2912 }
2913 }
2914 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2915}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302916
2917func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2918
2919 singleValResp := extension.SingleGetValueResponse{
2920 Response: &extension.GetValueResponse{
2921 Response: &extension.GetValueResponse_OnuPonCounters{
2922 OnuPonCounters: &extension.GetOnuCountersResponse{},
2923 },
2924 },
2925 }
2926
2927 errResp := func(status extension.GetValueResponse_Status,
2928 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2929 return &extension.SingleGetValueResponse{
2930 Response: &extension.GetValueResponse{
2931 Status: status,
2932 ErrReason: reason,
2933 },
2934 }
2935 }
2936 intfID := onuPonInfo.IntfId
2937 onuID := onuPonInfo.OnuId
2938 onuKey := dh.formOnuKey(intfID, onuID)
2939
2940 if _, ok := dh.onus.Load(onuKey); !ok {
2941 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2942 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2943 }
2944 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2945 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2946 if cmnni == nil {
2947 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2948 }
2949 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2950 return &singleValResp
2951
2952}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002953
2954func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2955
2956 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2957 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2958 if err != nil {
2959 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2960 return generateSingleGetValueErrorResponse(err)
2961 }
2962 return &extension.SingleGetValueResponse{
2963 Response: &extension.GetValueResponse{
2964 Status: extension.GetValueResponse_OK,
2965 Response: &extension.GetValueResponse_RxPower{
2966 RxPower: &extension.GetRxPowerResponse{
2967 IntfId: rxPowerRequest.IntfId,
2968 OnuId: rxPowerRequest.OnuId,
2969 Status: rxPower.Status,
2970 FailReason: rxPower.FailReason.String(),
2971 RxPower: rxPower.RxPowerMeanDbm,
2972 },
2973 },
2974 },
2975 }
2976}
2977
2978func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2979 errResp := func(status extension.GetValueResponse_Status,
2980 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2981 return &extension.SingleGetValueResponse{
2982 Response: &extension.GetValueResponse{
2983 Status: status,
2984 ErrReason: reason,
2985 },
2986 }
2987 }
2988
2989 if err != nil {
2990 if e, ok := status.FromError(err); ok {
2991 switch e.Code() {
2992 case codes.Internal:
2993 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2994 case codes.DeadlineExceeded:
2995 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2996 case codes.Unimplemented:
2997 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2998 case codes.NotFound:
2999 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3000 }
3001 }
3002 }
3003
3004 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3005}
khenaidoo106c61a2021-08-11 18:05:46 -04003006
3007/*
3008Helper functions to communicate with Core
3009*/
3010
3011func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3012 cClient, err := dh.coreClient.GetCoreServiceClient()
3013 if err != nil || cClient == nil {
3014 return nil, err
3015 }
3016 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3017 defer cancel()
3018 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3019}
3020
khenaidoodc2116e2021-10-19 17:33:19 -04003021func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003022 cClient, err := dh.coreClient.GetCoreServiceClient()
3023 if err != nil || cClient == nil {
3024 return nil, err
3025 }
3026 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3027 defer cancel()
3028 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3029}
3030
khenaidoodc2116e2021-10-19 17:33:19 -04003031func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003032 cClient, err := dh.coreClient.GetCoreServiceClient()
3033 if err != nil || cClient == nil {
3034 return err
3035 }
3036 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3037 defer cancel()
3038 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3039 return err
3040}
3041
3042func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3043 cClient, err := dh.coreClient.GetCoreServiceClient()
3044 if err != nil || cClient == nil {
3045 return nil, err
3046 }
3047 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3048 defer cancel()
3049 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3050}
3051
3052func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3053 cClient, err := dh.coreClient.GetCoreServiceClient()
3054 if err != nil || cClient == nil {
3055 return nil, err
3056 }
3057 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3058 defer cancel()
3059 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3060}
3061
3062func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3063 cClient, err := dh.coreClient.GetCoreServiceClient()
3064 if err != nil || cClient == nil {
3065 return err
3066 }
3067 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3068 defer cancel()
3069 _, err = cClient.DeviceUpdate(subCtx, device)
3070 return err
3071}
3072
khenaidoodc2116e2021-10-19 17:33:19 -04003073func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003074 cClient, err := dh.coreClient.GetCoreServiceClient()
3075 if err != nil || cClient == nil {
3076 return nil, err
3077 }
3078 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3079 defer cancel()
3080 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3081}
3082
khenaidoodc2116e2021-10-19 17:33:19 -04003083func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003084 cClient, err := dh.coreClient.GetCoreServiceClient()
3085 if err != nil || cClient == nil {
3086 return err
3087 }
3088 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3089 defer cancel()
3090 _, err = cClient.SendPacketIn(subCtx, pkt)
3091 return err
3092}
3093
3094func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3095 cClient, err := dh.coreClient.GetCoreServiceClient()
3096 if err != nil || cClient == nil {
3097 return err
3098 }
3099 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3100 defer cancel()
3101 _, err = cClient.PortCreated(subCtx, port)
3102 return err
3103}
3104
khenaidoodc2116e2021-10-19 17:33:19 -04003105func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003106 cClient, err := dh.coreClient.GetCoreServiceClient()
3107 if err != nil || cClient == nil {
3108 return err
3109 }
3110 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3111 defer cancel()
3112 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3113 return err
3114}
3115
khenaidoodc2116e2021-10-19 17:33:19 -04003116func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003117 cClient, err := dh.coreClient.GetCoreServiceClient()
3118 if err != nil || cClient == nil {
3119 return err
3120 }
3121 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3122 defer cancel()
3123 _, err = cClient.PortStateUpdate(subCtx, portState)
3124 return err
3125}
3126
khenaidoodc2116e2021-10-19 17:33:19 -04003127func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003128 cClient, err := dh.coreClient.GetCoreServiceClient()
3129 if err != nil || cClient == nil {
3130 return nil, err
3131 }
3132 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3133 defer cancel()
3134 return cClient.GetDevicePort(subCtx, portFilter)
3135}
3136
3137/*
3138Helper functions to communicate with child adapter
3139*/
3140
khenaidoodc2116e2021-10-19 17:33:19 -04003141func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003142 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3143 if err != nil || aClient == nil {
3144 return err
3145 }
3146 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3147 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3148 defer cancel()
3149 _, err = aClient.OmciIndication(subCtx, response)
3150 return err
3151}
3152
khenaidoodc2116e2021-10-19 17:33:19 -04003153func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003154 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3155 if err != nil || aClient == nil {
3156 return err
3157 }
3158 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3159 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3160 defer cancel()
3161 _, err = aClient.OnuIndication(subCtx, onuInd)
3162 return err
3163}
3164
khenaidoodc2116e2021-10-19 17:33:19 -04003165func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003166 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3167 if err != nil || aClient == nil {
3168 return err
3169 }
3170 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3171 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3172 defer cancel()
3173 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3174 return err
3175}
3176
khenaidoodc2116e2021-10-19 17:33:19 -04003177func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003178 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3179 if err != nil || aClient == nil {
3180 return err
3181 }
3182 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3183 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3184 defer cancel()
3185 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3186 return err
3187}
3188
khenaidoodc2116e2021-10-19 17:33:19 -04003189func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003190 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3191 if err != nil || aClient == nil {
3192 return err
3193 }
3194 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3195 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3196 defer cancel()
3197 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3198 return err
3199}
3200
3201/*
3202Helper functions for remote communication
3203*/
3204
3205// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3206// supports is deleted
3207func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3208 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3209
3210 dh.lockChildAdapterClients.Lock()
3211 defer dh.lockChildAdapterClients.Unlock()
3212 if _, ok := dh.childAdapterClients[endpoint]; ok {
3213 // Already set
3214 return nil
3215 }
3216
3217 // Setup child's adapter grpc connection
3218 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003219 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3220 dh.cfg.AdapterEndpoint,
3221 endpoint,
3222 dh.onuAdapterRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003223 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3224 return err
3225 }
khenaidoo27e7ac92021-12-08 14:43:09 -05003226 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.setAndTestOnuInterAdapterServiceHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003227
3228 // Wait until we have a connection to the child adapter.
3229 // Unlimited retries or until context expires
3230 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3231 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3232 for {
3233 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3234 if err == nil && client != nil {
3235 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3236 break
3237 }
3238 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3239 // Backoff
3240 if err = backoff.Backoff(subCtx); err != nil {
3241 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3242 break
3243 }
3244 }
3245 return nil
3246}
3247
khenaidoodc2116e2021-10-19 17:33:19 -04003248func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003249
3250 // First check from cache
3251 dh.lockChildAdapterClients.RLock()
3252 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3253 dh.lockChildAdapterClients.RUnlock()
3254 return cgClient.GetOnuInterAdapterServiceClient()
3255 }
3256 dh.lockChildAdapterClients.RUnlock()
3257
3258 // Set the child connection - can occur on restarts
3259 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3260 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3261 cancel()
3262 if err != nil {
3263 return nil, err
3264 }
3265
3266 // Get the child client now
3267 dh.lockChildAdapterClients.RLock()
3268 defer dh.lockChildAdapterClients.RUnlock()
3269 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3270 return cgClient.GetOnuInterAdapterServiceClient()
3271 }
3272 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3273}
3274
3275func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3276 dh.lockChildAdapterClients.Lock()
3277 defer dh.lockChildAdapterClients.Unlock()
3278 for key, client := range dh.childAdapterClients {
3279 client.Stop(ctx)
3280 delete(dh.childAdapterClients, key)
3281 }
3282}
3283
3284// TODO: Any action the adapter needs to do following a onu adapter restart?
3285func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003286 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003287 return nil
3288}
3289
khenaidoo27e7ac92021-12-08 14:43:09 -05003290// setAndTestOnuInterAdapterServiceHandler is used to test whether the remote gRPC service is up
3291func (dh *DeviceHandler) setAndTestOnuInterAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn, clientConn *common.Connection) interface{} {
3292 // The onu adapter needs to know whether the olt adapter can connect to it. Since the olt adapter
3293 // has a grpc client connection per device handler (i.e. per olt device) to the onu adapter
3294 // then the onu adapter needs to know whether that specific client can connect to it. Because the
3295 // client uses a polling mechanism then not all grpc clients could be connected at the same time,
3296 // a maximum difference of 5 sec. We therefore add the parent device as additional contextual information
3297 // to this request.
3298 dh.lockDevice.RLock()
3299 if dh.device != nil {
3300 clientConn.ContextInfo = dh.device.Id
3301 }
3302 dh.lockDevice.RUnlock()
khenaidoodc2116e2021-10-19 17:33:19 -04003303 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo27e7ac92021-12-08 14:43:09 -05003304 if h, err := svc.GetHealthStatus(ctx, clientConn); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003305 return nil
3306 }
3307 return svc
3308}
Girish Gowdra950326e2021-11-05 12:43:24 -07003309
3310func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3311 dh.lockDevice.Lock()
3312 defer dh.lockDevice.Unlock()
3313 dh.isDeviceDeletionInProgress = flag
3314}
3315
3316func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3317 dh.lockDevice.RLock()
3318 defer dh.lockDevice.RUnlock()
3319 return dh.isDeviceDeletionInProgress
3320}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003321
3322// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3323// Returns false if waiting timed out.
3324func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3325 c := make(chan struct{})
3326 go func() {
3327 defer close(c)
3328 wg.Wait()
3329 }()
3330 select {
3331 case <-c:
3332 return true // completed normally
3333 case <-time.After(timeout):
3334 return false // timed out
3335 }
3336}