blob: 50e05399b3cecc3e04815c0f7988fb8c3d8b8d33 [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"
26 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
khenaidoo106c61a2021-08-11 18:05:46 -040033 "github.com/golang/protobuf/ptypes/empty"
34 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
35 "github.com/opencord/voltha-protos/v5/go/adapter_services"
36
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"
52 "github.com/opencord/voltha-protos/v5/go/extension"
53 ic "github.com/opencord/voltha-protos/v5/go/inter_container"
54 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
55 oop "github.com/opencord/voltha-protos/v5/go/openolt"
56 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070057 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040058 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040059 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053060)
61
salmansiddiqui7ac62132019-08-22 03:58:50 +000062// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040063const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080064 InvalidPort = 0xffffffff
65 MaxNumOfGroupHandlerChannels = 256
66
67 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
68 McastFlowOrGroupModify = "McastFlowOrGroupModify"
69 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050070 oltPortInfoTimeout = 3
Manikkaraj kb1d51442019-07-23 10:41:02 -040071)
72
Phaneendra Manda4c62c802019-03-06 21:37:49 +053073//DeviceHandler will interact with the OLT device.
74type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040075 cm *config.ConfigManager
76 device *voltha.Device
77 cfg *conf.AdapterFlags
78 coreClient *vgrpc.Client
79 childAdapterClients map[string]*vgrpc.Client
80 lockChildAdapterClients sync.RWMutex
81 EventProxy eventif.EventProxy
82 openOLT *OpenOLT
83 exitChannel chan int
84 lockDevice sync.RWMutex
85 Client oop.OpenoltClient
86 transitionMap *TransitionMap
87 clientCon *grpc.ClientConn
88 flowMgr []*OpenOltFlowMgr
89 groupMgr *OpenOltGroupMgr
90 eventMgr *OpenOltEventMgr
91 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070092
93 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053094
Girish Gowdra3ab6d212020-03-24 17:33:15 -070095 discOnus sync.Map
96 onus sync.Map
97 portStats *OpenOltStatisticsMgr
98 metrics *pmmetrics.PmMetrics
99 stopCollector chan bool
100 stopHeartbeatCheck chan bool
101 activePorts sync.Map
102 stopIndications chan bool
103 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700104
Mahir Gunyelb0046752021-02-26 13:51:05 -0800105 totalPonPorts uint32
106 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
107 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800108
109 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
110 // 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 -0700111 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
112 stopMcastHandlerRoutine []chan bool
113 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000114
115 adapterPreviouslyConnected bool
116 agentPreviouslyConnected bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700117}
118
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700119//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700120type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400121 deviceID string
122 deviceType string
123 serialNumber string
124 onuID uint32
125 intfID uint32
126 proxyDeviceID string
127 losRaised bool
128 rdiRaised bool
129 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700130}
131
Mahir Gunyelb0046752021-02-26 13:51:05 -0800132type onuIndicationMsg struct {
133 ctx context.Context
134 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800135}
136
137type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800138 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800139 stopChannel chan struct{}
140}
141
Girish Gowdra491a9c62021-01-06 16:43:07 -0800142//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
143//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
144//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
145//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
146type McastFlowOrGroupControlBlock struct {
147 ctx context.Context // Flow/group handler context
148 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
149 flow *voltha.OfpFlowStats // Flow message (can be nil or valid flow)
150 group *voltha.OfpGroupEntry // Group message (can be nil or valid group)
151 errChan *chan error // channel to report the mcast Flow/group handling error
152}
153
Naga Manjunath7615e552019-10-11 22:35:47 +0530154var pmNames = []string{
155 "rx_bytes",
156 "rx_packets",
157 "rx_mcast_packets",
158 "rx_bcast_packets",
159 "tx_bytes",
160 "tx_packets",
161 "tx_mcast_packets",
162 "tx_bcast_packets",
163}
164
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700165//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400166func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700167 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700168 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700169 device.deviceType = deviceTp
170 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700171 device.onuID = onuID
172 device.intfID = intfID
173 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530174 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400175 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700176 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530177}
178
179//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400180func 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 -0700181 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800182 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400183 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400184 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700185 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700186 dh.device = cloned
187 dh.openOLT = adapter
188 dh.exitChannel = make(chan int, 1)
189 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530190 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530191 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530192 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 -0500193 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400194 dh.stopIndications = make(chan bool, 1)
Mahir Gunyelb0046752021-02-26 13:51:05 -0800195 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400196 dh.childAdapterClients = make(map[string]*vgrpc.Client)
197 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800198 // Create a slice of buffered channels for handling concurrent mcast flow/group.
199 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700200 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
201 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800202 for i := range dh.incomingMcastFlowOrGroup {
203 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700204 dh.stopMcastHandlerRoutine[i] = make(chan bool, 1)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800205 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
206 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
207 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
208 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700209 dh.mcastHandlerRoutineActive[i] = true
210 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800211 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700212 //TODO initialize the support classes.
213 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530214}
215
216// start save the device to the data model
217func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 dh.lockDevice.Lock()
219 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000220 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000222 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530223}
224
225// stop stops the device dh. Not much to do for now
226func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700227 dh.lockDevice.Lock()
228 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000229 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 dh.exitChannel <- 1
khenaidoo106c61a2021-08-11 18:05:46 -0400231
232 // Stop the adapter grpc clients for that parent device
233 dh.deleteAdapterClients(ctx)
234
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530236}
237
ssiddiqui04386ee2021-08-23 21:58:25 +0530238func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
239 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
240 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
241 if pooledIntfID == intfID {
242 return resourceRanges.GetTechnology()
243 }
244 }
245 }
246 return ""
247}
248
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400249func macifyIP(ip net.IP) string {
250 if len(ip) > 0 {
251 oct1 := strconv.FormatInt(int64(ip[12]), 16)
252 oct2 := strconv.FormatInt(int64(ip[13]), 16)
253 oct3 := strconv.FormatInt(int64(ip[14]), 16)
254 oct4 := strconv.FormatInt(int64(ip[15]), 16)
255 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
256 }
257 return ""
258}
259
Neha Sharma96b7bf22020-06-15 10:37:32 +0000260func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400261 var genmac string
262 var addr net.IP
263 var ips []string
264 var err error
265
Neha Sharma96b7bf22020-06-15 10:37:32 +0000266 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400267
268 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400270
271 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400273 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000274 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400275 }
276 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530278 log.Fields{"host": ips[0],
279 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400280 return genmac, nil
281 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000282 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400283 }
284
285 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000286 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530287 log.Fields{"host": host,
288 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400289 return genmac, nil
290}
291
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530292func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 slist := strings.Split(mac, ":")
294 result := make([]uint32, len(slist))
295 var err error
296 var tmp int64
297 for index, val := range slist {
298 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
299 return []uint32{1, 2, 3, 4, 5, 6}
300 }
301 result[index] = uint32(tmp)
302 }
303 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530304}
305
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700306//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 -0800307func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308
David K. Bainbridge794735f2020-02-11 21:01:37 -0800309 switch portType {
310 case voltha.Port_ETHERNET_NNI:
311 return fmt.Sprintf("nni-%d", portNum), nil
312 case voltha.Port_PON_OLT:
313 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800315
Girish Kumarf26e4882020-03-05 06:49:10 +0000316 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530317}
318
Neha Sharma96b7bf22020-06-15 10:37:32 +0000319func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000320 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 if state == "up" {
322 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500323 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500324 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700325 } else {
326 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500327 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700328 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700329 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400330 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800331 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000332 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400333 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500334
khenaidoo106c61a2021-08-11 18:05:46 -0400335 // Check if port exists
336 port, err := dh.getPortFromCore(ctx, &ic.PortFilter{
337 DeviceId: dh.device.Id,
338 Port: portNum,
339 })
340 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000341 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoo106c61a2021-08-11 18:05:46 -0400342 err = dh.updatePortStateInCore(ctx, &ic.PortState{
343 DeviceId: dh.device.Id,
344 PortType: portType,
345 PortNo: portNum,
346 OperStatus: operStatus})
347 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400348 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
349 "device-id": dh.device.Id,
350 "port-type": portType,
351 "port-number": portNum,
352 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500353 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400354 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500355 }
khenaidoo106c61a2021-08-11 18:05:46 -0400356
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400357 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700358 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
khenaidoo106c61a2021-08-11 18:05:46 -0400359 port = &voltha.Port{
360 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700361 PortNo: portNum,
362 Label: label,
363 Type: portType,
364 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700365 OfpPort: &of.OfpPort{
366 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
367 Config: 0,
368 State: uint32(of.OfpPortState_OFPPS_LIVE),
369 Curr: capacity,
370 Advertised: capacity,
371 Peer: capacity,
372 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
373 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
374 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700375 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000376 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700377 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400378 err = dh.createPortInCore(ctx, port)
379 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000380 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800381 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000382 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000384 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530385 return nil
386}
387
Kent Hagermane6ff1012020-07-14 15:07:53 -0400388func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400389 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530390 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400391 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
392 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530393 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800394 dh.lockDevice.Lock()
395 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530396 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530397}
398
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700399// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530400// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000402 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700403 defer func() {
404 dh.lockDevice.Lock()
405 dh.isReadIndicationRoutineActive = false
406 dh.lockDevice.Unlock()
407 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700408 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700409 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700410 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400412
David Bainbridgef5879ca2019-12-13 21:17:54 +0000413 // Create an exponential backoff around re-enabling indications. The
414 // maximum elapsed time for the back off is set to 0 so that we will
415 // continue to retry. The max interval defaults to 1m, but is set
416 // here for code clarity
417 indicationBackoff := backoff.NewExponentialBackOff()
418 indicationBackoff.MaxElapsedTime = 0
419 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700420
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700421 dh.lockDevice.Lock()
422 dh.isReadIndicationRoutineActive = true
423 dh.lockDevice.Unlock()
424
Girish Gowdra3f974912020-03-23 20:35:18 -0700425Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700426 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400427 select {
428 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000429 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700430 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400431 default:
432 indication, err := indications.Recv()
433 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530435 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530436 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400437 // Use an exponential back off to prevent getting into a tight loop
438 duration := indicationBackoff.NextBackOff()
439 if duration == backoff.Stop {
440 // If we reach a maximum then warn and reset the backoff
441 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530443 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530444 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400445 indicationBackoff.Reset()
446 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700447
448 // On failure process a backoff timer while watching for stopIndications
449 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700450 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700451 select {
452 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000453 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700454 if !backoffTimer.Stop() {
455 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700456 }
457 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700458 case <-backoffTimer.C:
459 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700460 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700461 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
462 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400463 }
464 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000465 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530466 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530468 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530469 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700470 // Close the stream, and re-initialize it
471 if err = indications.CloseSend(); err != nil {
472 // Ok to ignore here, because we landed here due to a problem on the stream
473 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530475 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530476 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700477 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000478 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700479 return err
480 }
481 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400482 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530483 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400484 // Reset backoff if we have a successful receive
485 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400486 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700487 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000488 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530489 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530490 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400491 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400492 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400493 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700494 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700496 // Close the send stream
497 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700498
Girish Gowdra3f974912020-03-23 20:35:18 -0700499 return nil
500}
501
502func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700503 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700504 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
505 if err != nil {
506 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
507 }
508 if indications == nil {
509 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
510 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700511 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700512 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400513}
514
515// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
516func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
517 switch indication.Data.(type) {
518 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
519 return true
520
521 default:
522 return false
523 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524}
525
David K. Bainbridge794735f2020-02-11 21:01:37 -0800526func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700527 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000528 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530529 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530531 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700532 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000533 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000534 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530535 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000536 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800537 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000538 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800539 }
540 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541}
542
David K. Bainbridge794735f2020-02-11 21:01:37 -0800543// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530544func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700545 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700546 switch indication.Data.(type) {
547 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000548 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
549 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700550 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 -0800551 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400552 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800553 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700554 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000555 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
556 defer span.Finish()
557
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800559 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400561 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800562 }
563 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000564 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000566 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
567 defer span.Finish()
568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 intfOperInd := indication.GetIntfOperInd()
570 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800571 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400573 _ = 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 -0800574 }
575 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 } else if intfOperInd.GetType() == "pon" {
577 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
578 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800579 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400581 _ = 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 -0800582 }
583 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530587 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530588 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700589 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000590 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
591 defer span.Finish()
592
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800595 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800596 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000598 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
599 defer span.Finish()
600
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800603 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800604 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000606 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
607 defer span.Finish()
608
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 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 -0800611 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000612 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400613 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800614 }
615 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000617 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
618 defer span.Finish()
619
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700620 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000621 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700622 "intf-type": pktInd.IntfId,
623 "intf-id": pktInd.IntfId,
624 "gem-port-id": pktInd.GemportId,
625 "port-no": pktInd.PortNo,
626 "device-id": dh.device.Id,
627 })
628
629 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700631 "intf-type": pktInd.IntfId,
632 "intf-id": pktInd.IntfId,
633 "gem-port-id": pktInd.GemportId,
634 "port-no": pktInd.PortNo,
635 "packet": hex.EncodeToString(pktInd.Pkt),
636 "device-id": dh.device.Id,
637 })
638 }
639
David K. Bainbridge794735f2020-02-11 21:01:37 -0800640 go func() {
641 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400642 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800643 }
644 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000646 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
647 defer span.Finish()
648
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700650 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000652 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
653 defer span.Finish()
654
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000658 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
659 defer span.Finish()
660
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000662 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
663 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700664 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530665}
666
667// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530668func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530669 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000670 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530671
Girish Gowdra618fa572021-09-01 17:19:29 -0700672 // instantiate the mcast handler routines.
673 for i := range dh.incomingMcastFlowOrGroup {
674 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
675 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
676 if !dh.mcastHandlerRoutineActive[i] {
677 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
678 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
679 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
680 // for incoming mcast flow/group to be processed serially.
681 dh.mcastHandlerRoutineActive[i] = true
682 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
683 }
684 }
685
Girish Gowdru0c588b22019-04-23 23:24:56 -0400686 // Synchronous call to update device state - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400687 if err := dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
688 DeviceId: dh.device.Id,
689 OperStatus: voltha.OperStatus_ACTIVE,
690 ConnStatus: voltha.ConnectStatus_REACHABLE,
691 }); err != nil {
692 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400693 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000694
695 //Clear olt communication failure event
696 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
697 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700698 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000699 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
700
Gamze Abakac2c32a62021-03-11 11:44:18 +0000701 //check adapter and agent reconcile status
702 //reboot olt if needed (olt disconnection case)
703 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
704 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
705 log.Fields{
706 "device-id": dh.device.Id,
707 "adapter-status": dh.adapterPreviouslyConnected,
708 "agent-status": dh.agentPreviouslyConnected,
709 })
710 _ = dh.RebootDevice(ctx, dh.device)
711 }
712
Girish Gowdru0c588b22019-04-23 23:24:56 -0400713 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530714}
715
716// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530717func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000718 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400719
khenaidoo106c61a2021-08-11 18:05:46 -0400720 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400721 if err != nil || device == nil {
722 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000723 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400724 }
725
726 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400727
728 //Update the device oper state and connection status
729 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800730 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400731 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800732 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400733
khenaidoo106c61a2021-08-11 18:05:46 -0400734 if err = dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
735 DeviceId: cloned.Id,
736 OperStatus: cloned.OperStatus,
737 ConnStatus: cloned.ConnectStatus,
738 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000739 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400740 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400741
742 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400743 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400744 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000745 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400746 }
747 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400748 // Update onu state as down in onu adapter
749 onuInd := oop.OnuIndication{}
750 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400751
752 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
753 if err != nil {
754 return err
755 }
756 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
757 _, err = ogClient.OnuIndication(subCtx, &ic.OnuIndicationMessage{
758 DeviceId: onuDevice.Id,
759 OnuIndication: &onuInd,
760 })
761 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800762 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400763 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400764 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800765 "onu-indicator": onuInd,
766 "device-type": onuDevice.Type,
767 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700768 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800769 } else {
770 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 -0700771 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400772 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800773 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700774 /* Discovered ONUs entries need to be cleared , since after OLT
775 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530776 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800777 dh.lockDevice.Unlock()
778
Neha Sharma96b7bf22020-06-15 10:37:32 +0000779 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700780 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530781}
782
783// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530784func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400785 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000786
787 // if the connection is already available, close the previous connection (olt reboot case)
788 if dh.clientCon != nil {
789 if err = dh.clientCon.Close(); err != nil {
790 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
791 } else {
792 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
793 }
794 }
795
796 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000797 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
798 grpc.WithInsecure(),
799 grpc.WithBlock(),
800 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000801 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000802 )),
803 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000804 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000805 )))
806
807 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530808 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530809 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000810 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400811 }
812 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
815// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530816func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400817 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530818 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400819 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530820}
821
822// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530823func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530824 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400826
827 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400828 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530829 if err != nil || device == nil {
830 /*TODO: needs to handle error scenarios */
831 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
832 }
833 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400835
836 cloned := proto.Clone(device).(*voltha.Device)
837 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
838 cloned.OperStatus = voltha.OperStatus_UNKNOWN
839 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400840
841 if err = dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
842 DeviceId: cloned.Id,
843 OperStatus: cloned.OperStatus,
844 ConnStatus: cloned.ConnectStatus,
845 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530846 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 -0400847 }
848
Chaitrashree G S44124192019-08-07 20:21:36 -0400849 // 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 +0530850 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400851 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530852 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400853 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400854 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
855 // all the modules initialized and ready to handle incoming ONUs.
856
Thomas Lee S985938d2020-05-04 11:40:41 +0530857 err = dh.initializeDeviceHandlerModules(ctx)
858 if err != nil {
859 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 -0400860 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400861
862 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800863 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530864 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400865 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 }
867 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700868
869 go startHeartbeatCheck(ctx, dh)
870
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400871 return nil
872 }
873
khenaidoo106c61a2021-08-11 18:05:46 -0400874 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400875 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400876 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400877 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400878 }
khenaidoo106c61a2021-08-11 18:05:46 -0400879 dh.populateActivePorts(ctx, ports.Items)
880 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400881 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400882 }
883
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400884 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530885 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 -0400886 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530887
cuilin20187b2a8c32019-03-26 19:52:28 -0700888 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889 go func() {
890 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400891 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 }
893 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000894 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000895
896 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000897 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000898 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700899
900 go startHeartbeatCheck(ctx, dh)
901
cuilin20187b2a8c32019-03-26 19:52:28 -0700902 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530903}
904
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400905func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700906 var err error
907 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400908
909 if err != nil {
910 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
911 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700912 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
913 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700914
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700915 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700916 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700917 var i uint32
918 for i = 0; i < dh.totalPonPorts; i++ {
919 // Instantiate resource manager
920 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 -0700921 return olterrors.ErrResourceManagerInstantiating
922 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400923 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700924 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
925 // the KV store to manage mcast group data. Provide the first instance (0th index)
926 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
927 return olterrors.ErrGroupManagerInstantiating
928 }
929 for i = 0; i < dh.totalPonPorts; i++ {
930 // Instantiate flow manager
931 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
932 return olterrors.ErrFlowManagerInstantiating
933 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700934 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700935 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400936 /* TODO: Instantiate Alarm , stats , BW managers */
937 /* Instantiating Event Manager to handle Alarms and KPIs */
938 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
939
940 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000941 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400942
943 return nil
944
945}
946
Neha Sharma96b7bf22020-06-15 10:37:32 +0000947func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400948 var err error
949 var deviceInfo *oop.DeviceInfo
950
Neha Sharma8f4e4322020-08-06 10:51:53 +0000951 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400952
953 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000954 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400955 }
956 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000957 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400958 }
959
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400961 dh.device.Root = true
962 dh.device.Vendor = deviceInfo.Vendor
963 dh.device.Model = deviceInfo.Model
964 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
965 dh.device.HardwareVersion = deviceInfo.HardwareVersion
966 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
967
968 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000969 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400970 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000971 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400972 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000973 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400974 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400976 dh.device.MacAddress = genmac
977 } else {
978 dh.device.MacAddress = deviceInfo.DeviceId
979 }
980
981 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400982 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000983 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400984 }
985
986 return deviceInfo, nil
987}
988
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -0700990 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530991 for {
992 select {
993 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000994 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530995 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000996 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700997
khenaidoo106c61a2021-08-11 18:05:46 -0400998 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400999 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001000 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001001 continue
1002 }
khenaidoo106c61a2021-08-11 18:05:46 -04001003 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301004 // NNI Stats
1005 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001006 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301007 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001008 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001009 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001010 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301011 }
1012 // PON Stats
1013 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001014 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301015 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1016 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001017 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001018 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301019 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001020 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001021
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001022 onuGemInfoLst := dh.flowMgr[intfID].getOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001023 if len(onuGemInfoLst) > 0 {
1024 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001025 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001026 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301027 }
1028 }
1029 }
1030}
1031
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301033func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001034 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301036 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301037
1038 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001039 cgClient, err := dh.coreClient.GetCoreServiceClient()
1040 if err != nil {
1041 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1042 return
1043 }
1044
1045 // Now, set the initial PM configuration for that device
1046 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001047 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301048 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301049}
1050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301052func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -07001053 return &ic.SwitchCapability{
1054 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301055 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001056 HwDesc: "open_pon",
1057 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001058 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001059 },
1060 SwitchFeatures: &of.OfpSwitchFeatures{
1061 NBuffers: 256,
1062 NTables: 2,
1063 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1064 of.OfpCapabilities_OFPC_TABLE_STATS |
1065 of.OfpCapabilities_OFPC_PORT_STATS |
1066 of.OfpCapabilities_OFPC_GROUP_STATS),
1067 },
1068 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301069}
1070
khenaidoo106c61a2021-08-11 18:05:46 -04001071// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
1072func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ic.TechProfileInstanceRequestMessage) (*ic.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001073 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001074 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001075 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001076 }
khenaidoo106c61a2021-08-11 18:05:46 -04001077 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001078}
1079
Neha Sharma96b7bf22020-06-15 10:37:32 +00001080func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001081 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 -07001082 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083 var deviceID string
1084 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001085 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001086
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001087 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001088 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001089 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 -07001090 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1091 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001092
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001093 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301094
1095 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1096
Neha Sharma96b7bf22020-06-15 10:37:32 +00001097 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 -07001098 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001099
khenaidoo106c61a2021-08-11 18:05:46 -04001100 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ic.ChildDeviceFilter{
1101 ParentId: dh.device.Id,
1102 OnuId: omciInd.OnuId,
1103 ParentPortNo: ponPort,
1104 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001105 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301106 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001107 "intf-id": omciInd.IntfId,
1108 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001109 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001110 deviceType = onuDevice.Type
1111 deviceID = onuDevice.Id
1112 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001113 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001115 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001116 } else {
1117 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 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 +05301119 deviceType = onuInCache.(*OnuDevice).deviceType
1120 deviceID = onuInCache.(*OnuDevice).deviceID
1121 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001122 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001123 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001124
khenaidoo106c61a2021-08-11 18:05:46 -04001125 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ic.OmciMessage{
1126 ParentDeviceId: proxyDeviceID,
1127 ChildDeviceId: deviceID,
1128 Message: omciInd.Pkt,
1129 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301130 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001131 "source": dh.openOLT.config.AdapterEndpoint,
1132 "device-type": deviceType,
1133 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001134 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001135 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001136 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301138}
1139
khenaidoo106c61a2021-08-11 18:05:46 -04001140// //ProcessInterAdapterMessage sends the proxied messages to the target device
1141// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1142// // is meant, and then send the unmarshalled omci message to this onu
1143// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1144// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
1145// if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
1146// return dh.handleInterAdapterOmciMsg(ctx, msg)
1147// }
1148// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1149// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001150
khenaidoo106c61a2021-08-11 18:05:46 -04001151// ProxyOmciMessage sends the proxied OMCI message to the target device
1152func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ic.OmciMessage) error {
1153 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 -07001154
1155 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001156 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001157 if err != nil {
1158 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001159 "parent-device-id": dh.device.Id,
1160 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001161 }
khenaidoo106c61a2021-08-11 18:05:46 -04001162 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1163 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001164 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001165 "parent-device-id": dh.device.Id,
1166 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001167 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001168 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001169 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1170 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001171 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001172 "parent-device-id": dh.device.Id,
1173 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001174 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001175 }
1176 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301177}
1178
khenaidoo106c61a2021-08-11 18:05:46 -04001179func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001180 var intfID uint32
1181 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001182 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001183 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001184 intfID = onuDevice.ProxyAddress.GetChannelId()
1185 onuID = onuDevice.ProxyAddress.GetOnuId()
1186 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001187 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 intfID = omciMsg.GetProxyAddress().GetChannelId()
1189 onuID = omciMsg.GetProxyAddress().GetOnuId()
1190 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001191 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001193 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 -08001194
Thomas Lee S94109f12020-03-03 16:39:29 +05301195 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001196 "intf-id": intfID,
1197 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001198 }
1199
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001200 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1201 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001202 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001203 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1204 hex.Encode(hexPkt, omciMsg.Message)
1205 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1206
1207 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1208 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1209 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001210 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001211 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001212
Neha Sharma8f4e4322020-08-06 10:51:53 +00001213 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301215 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001216 "intf-id": intfID,
1217 "onu-id": onuID,
1218 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001219 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001221}
1222
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301224 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})
Girish Gowdra197acc12021-08-16 10:59:45 -07001225 if err := dh.flowMgr[intfID].AddOnuInfoToFlowMgrCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001226 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001227 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001228 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301229 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301230 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001231 st, _ := status.FromError(err)
1232 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001233 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1234
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001235 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301236 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001237 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001238 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001239 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001240 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001242}
1243
Mahir Gunyelb0046752021-02-26 13:51:05 -08001244func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001246 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001247
Mahir Gunyelb0046752021-02-26 13:51:05 -08001248 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001249 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301250
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301251 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001252 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001253 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301254
1255 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1256 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1257 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1258 OnuLosRaise event sent for it */
1259 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1260 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1261 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001262 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301263 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1264 "currentIntfId": onuDiscInd.GetIntfId()})
1265 // TODO:: Should we need to ignore raising OnuLosClear event
1266 // when onu connected to different PON?
1267 }
1268 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1269 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1270 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001271 go func() {
1272 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001273 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001274 }
1275 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301276 }
1277 return true
1278 })
1279
Neha Sharma96b7bf22020-06-15 10:37:32 +00001280 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001282 }
1283
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001284 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001285
1286 // check the ONU is already know to the OLT
1287 // NOTE the second time the ONU is discovered this should return a device
khenaidoo106c61a2021-08-11 18:05:46 -04001288 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ic.ChildDeviceFilter{
1289 ParentId: dh.device.Id,
1290 SerialNumber: sn,
1291 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001292
1293 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001294 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 -08001295 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001296 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 -08001297 switch e.Code() {
1298 case codes.Internal:
1299 // this probably means NOT FOUND, so just create a new device
1300 onuDevice = nil
1301 case codes.DeadlineExceeded:
1302 // if the call times out, cleanup and exit
1303 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001304 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001305 }
1306 }
1307 }
1308
1309 if onuDevice == nil {
1310 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001312 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001313 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001314 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001315
Neha Sharma96b7bf22020-06-15 10:37:32 +00001316 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001317
1318 if err != nil {
1319 // if we can't create an ID in resource manager,
1320 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001321 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001322 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001323 "pon-intf-id": ponintfid,
1324 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001325 }
1326
khenaidoo106c61a2021-08-11 18:05:46 -04001327 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ic.DeviceDiscovery{
1328 ParentId: dh.device.Id,
1329 ParentPortNo: parentPortNo,
1330 ChannelId: channelID,
1331 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1332 SerialNumber: sn,
1333 OnuId: onuID,
1334 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001335 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001336 dh.resourceMgr[ponintfid].FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301337 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001338 "pon-intf-id": ponintfid,
1339 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001340 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001341 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 -07001342 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301345 log.Fields{"onuDevice": onuDevice,
1346 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001347 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301348 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001349 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001350
khenaidoo106c61a2021-08-11 18:05:46 -04001351 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1352 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1353 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1354 cancel()
1355 if err != nil {
1356 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1357 }
1358
Matteo Scandolo945e4012019-12-12 14:16:11 -08001359 // we can now use the existing ONU Id
1360 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001361 //Insert the ONU into cache to use in OnuIndication.
1362 //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 +00001363 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001364 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301365 "intfId": onuDiscInd.GetIntfId(),
1366 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001367 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001368
khenaidoo106c61a2021-08-11 18:05:46 -04001369 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301370 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001371 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301372 log.Fields{"onu": onuDev,
1373 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001374
khenaidoo106c61a2021-08-11 18:05:46 -04001375 if err := dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
1376 DeviceId: onuDevice.Id,
1377 ParentDeviceId: dh.device.Id,
1378 OperStatus: common.OperStatus_DISCOVERED,
1379 ConnStatus: common.ConnectStatus_REACHABLE,
1380 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301381 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001382 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001383 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001384 }
khenaidoo106c61a2021-08-11 18:05:46 -04001385
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001387 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301388 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 }
1392 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001393}
1394
Mahir Gunyelb0046752021-02-26 13:51:05 -08001395func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001396
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001397 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001398 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001400 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001401 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301402 log.Fields{"onuId": onuInd.OnuId,
1403 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301404 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001405 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001406 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301407
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 errFields := log.Fields{"device-id": dh.device.Id}
1409
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301410 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1411
Mahir Gunyele77977b2019-06-27 05:36:22 -07001412 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1413 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001415 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001416 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001417 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1418 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001419 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001420 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 errFields["onu-id"] = onuInd.OnuId
1422 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001423 }
khenaidoo106c61a2021-08-11 18:05:46 -04001424 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ic.ChildDeviceFilter{
1425 ParentId: dh.device.Id,
1426 SerialNumber: serialNumber,
1427 OnuId: onuInd.OnuId,
1428 ParentPortNo: ponPort,
1429 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001430 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001431
David K. Bainbridge794735f2020-02-11 21:01:37 -08001432 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001433 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001434 }
1435
David K. Bainbridge794735f2020-02-11 21:01:37 -08001436 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001438 "previousIntfId": onuDevice.ParentPortNo,
1439 "currentIntfId": ponPort})
1440 }
1441
1442 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001443 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301444 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1445 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301446 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 }
1448 if !foundInCache {
1449 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1450
khenaidoo106c61a2021-08-11 18:05:46 -04001451 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 -08001452
1453 }
kesavand7cf3a052020-08-28 12:49:18 +05301454 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001455 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001456 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301457 }
1458 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001459 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001460 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001461 }
1462 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001463}
1464
Neha Sharma96b7bf22020-06-15 10:37:32 +00001465func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466 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 -07001467 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1468 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1469 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1470 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001471 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001472 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1473 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001474 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001475 onuInd.OperState = "down"
1476 }
1477 }
1478
David K. Bainbridge794735f2020-02-11 21:01:37 -08001479 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001480 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001481 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 -04001482
1483 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ic.OnuIndicationMessage{
1484 DeviceId: onuDevice.Id,
1485 OnuIndication: onuInd,
1486 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001487 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301488 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001489 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001490 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001491 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001492 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001493 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001494 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001495 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001497 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001498}
1499
cuilin20187b2a8c32019-03-26 19:52:28 -07001500func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1501 if serialNum != nil {
1502 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001503 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001505}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001506func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1507 decodedStr, err := hex.DecodeString(serialNum[4:])
1508 if err != nil {
1509 return nil, err
1510 }
1511 return &oop.SerialNumber{
1512 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001513 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001514 }, nil
1515}
cuilin20187b2a8c32019-03-26 19:52:28 -07001516
1517func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001518 if len(vendorSpecific) > 3 {
1519 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1520 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1521 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1522 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1523 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1524 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1525 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1526 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1527 return tmp
1528 }
1529 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001530}
1531
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532//UpdateFlowsBulk upates the bulk flow
1533func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301534 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001535}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536
1537//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1539 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301540 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001541 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301542 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001543
1544 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ic.ChildDeviceFilter{
1545 ParentId: dh.device.Id,
1546 OnuId: onuID,
1547 ParentPortNo: parentPort,
1548 })
1549
Girish Gowdru0c588b22019-04-23 23:24:56 -04001550 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001551 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001552 "intf-id": parentPort,
1553 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001554 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 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 -08001556 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301557}
1558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001559// SendPacketInToCore sends packet-in to core
1560// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1561// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001563 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001565 "port": logicalPort,
1566 "packet": hex.EncodeToString(packetPayload),
1567 "device-id": dh.device.Id,
1568 })
1569 }
khenaidoo106c61a2021-08-11 18:05:46 -04001570
1571 if err := dh.sendPacketToCore(ctx, &ic.PacketIn{
1572 DeviceId: dh.device.Id,
1573 Port: logicalPort,
1574 Packet: packetPayload,
1575 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301576 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 "source": "adapter",
1578 "destination": "core",
1579 "device-id": dh.device.Id,
1580 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001581 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001582 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001583 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001584 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001585 "packet": hex.EncodeToString(packetPayload),
1586 "device-id": dh.device.Id,
1587 })
1588 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001590}
1591
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001592// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001593func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001595
1596 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1597 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001599 }
1600
Kent Hagermane6ff1012020-07-14 15:07:53 -04001601 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001602 metrics := dh.metrics.GetSubscriberMetrics()
1603 for _, m := range pmConfigs.Metrics {
1604 metrics[m.Name].Enabled = m.Enabled
1605
1606 }
1607 }
1608}
1609
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001610//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301611func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001612 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001613
Girish Gowdra491a9c62021-01-06 16:43:07 -08001614 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001615 var errorsList []error
1616
Girish Gowdru0c588b22019-04-23 23:24:56 -04001617 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001618 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001619 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001620
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301622 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001623 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301624 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001625 if flow_utils.HasGroup(flow) {
1626 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1627 } else {
1628 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1629 }
Girish Gowdracefae192020-03-19 18:14:10 -07001630 if err != nil {
1631 errorsList = append(errorsList, err)
1632 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001633 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301634
1635 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001636 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001637 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301638 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001639 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301640 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001641 if flow_utils.HasGroup(flow) {
1642 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1643 } else {
1644 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1645 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001646 if err != nil {
1647 errorsList = append(errorsList, err)
1648 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301649 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001650 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001651
Girish Gowdracefae192020-03-19 18:14:10 -07001652 // 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 +00001653 if groups != nil {
1654 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001655 // err = dh.groupMgr.AddGroup(ctx, group)
1656 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001657 if err != nil {
1658 errorsList = append(errorsList, err)
1659 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001660 }
1661 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001662 // err = dh.groupMgr.ModifyGroup(ctx, group)
1663 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001664 if err != nil {
1665 errorsList = append(errorsList, err)
1666 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001667 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001668 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001669 // err = dh.groupMgr.DeleteGroup(ctx, group)
1670 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001671 if err != nil {
1672 errorsList = append(errorsList, err)
1673 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001674 }
1675 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001676 if len(errorsList) > 0 {
1677 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1678 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001680 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301681}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001682
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001683//DisableDevice disables the given device
1684//It marks the following for the given device:
1685//Device-Handler Admin-State : down
1686//Device Port-State: UNKNOWN
1687//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001688func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001689 /* On device disable ,admin state update has to be done prior sending request to agent since
1690 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001691 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001692 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001693 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001694 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001695 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001696 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001697 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001698 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001699 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001700 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301701
1702 dh.discOnus = sync.Map{}
1703 dh.onus = sync.Map{}
1704
Thomas Lee S85f37312020-04-03 17:06:12 +05301705 //stopping the stats collector
1706 dh.stopCollector <- true
1707
Neha Sharma96b7bf22020-06-15 10:37:32 +00001708 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001709 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301710 //Update device Admin state
1711 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001712
kdarapu1afeceb2020-02-12 01:38:09 -05001713 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
khenaidoo106c61a2021-08-11 18:05:46 -04001714 if err := dh.updatePortsStateInCore(ctx, &ic.PortStateFilter{
1715 DeviceId: cloned.Id,
1716 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1717 OperStatus: voltha.OperStatus_UNKNOWN,
1718 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001719 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001720 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001721 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001722 return nil
1723}
1724
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001726 // Update onu state as unreachable in onu adapter
1727 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301728 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001729
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001730 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001731 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001732 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001733 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 -04001734 }
1735 if onuDevices != nil {
1736 for _, onuDevice := range onuDevices.Items {
khenaidoo106c61a2021-08-11 18:05:46 -04001737 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ic.OnuIndicationMessage{
1738 DeviceId: onuDevice.Id,
1739 OnuIndication: &onuInd,
1740 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001741 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001743 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001744 }
1745
1746 }
1747 }
1748
1749}
1750
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001751//ReenableDevice re-enables the olt device after disable
1752//It marks the following for the given device:
1753//Device-Handler Admin-State : up
1754//Device Port-State: ACTIVE
1755//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001757 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301758 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001759 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301760 }
1761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001763
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001764 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001765 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001766 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001767 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001768 }
khenaidoo106c61a2021-08-11 18:05:46 -04001769 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001770 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001771 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001772 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001773 device.OperStatus = voltha.OperStatus_ACTIVE
1774 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001775
khenaidoo106c61a2021-08-11 18:05:46 -04001776 if err := dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
1777 DeviceId: device.Id,
1778 OperStatus: device.OperStatus,
1779 ConnStatus: device.ConnectStatus,
1780 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301781 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001782 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001783 "connect-status": device.ConnectStatus,
1784 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001785 }
kesavand39e0aa32020-01-28 20:58:50 -05001786
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001788
1789 return nil
1790}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001791
npujarec5762e2020-01-01 14:08:48 +05301792func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001793 var uniID uint32
1794 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301795 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001796 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001798 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001799 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001801 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001803 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001804 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001805 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001807 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001809 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001811 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001812 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301813 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001814 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1815 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001816 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301817 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001819 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 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 +00001821 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001822 }
1823 return nil
1824}
1825
Devmalya Paul495b94a2019-08-27 19:42:00 -04001826// 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 +05301827func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001828 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001829 /* Clear the KV store data associated with the all the UNI ports
1830 This clears up flow data and also resource map data for various
1831 other pon resources like alloc_id and gemport_id
1832 */
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001833 dh.cleanupDeviceResources(ctx)
1834 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 -04001835 // Stop the Stats collector
1836 dh.stopCollector <- true
1837 // stop the heartbeat check routine
1838 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301839 dh.lockDevice.RLock()
1840 // Stop the read indication only if it the routine is active
1841 if dh.isReadIndicationRoutineActive {
1842 dh.stopIndications <- true
1843 }
1844 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001845 dh.removeOnuIndicationChannels(ctx)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001846 go dh.StopAllMcastHandlerRoutines(ctx)
1847 for _, flMgr := range dh.flowMgr {
1848 go flMgr.StopAllFlowHandlerRoutines(ctx)
1849 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001850 //Reset the state
1851 if dh.Client != nil {
1852 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301853 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001854 }
1855 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001856 // There is no need to update the core about operation status and connection status of the OLT.
1857 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1858 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1859 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001860
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001861 return nil
1862}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001863func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001864
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001865 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301866 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001867 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001868 var err error
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001869 onuGemData := dh.flowMgr[ponPort].getOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001870 for i, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301871 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001872 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001873 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301875 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301876 // Clear flowids for gem cache.
1877 for _, gem := range onu.GemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001878 dh.resourceMgr[ponPort].DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301879 }
1880 onuID[0] = onu.OnuID
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001881 dh.resourceMgr[ponPort].FreeonuID(ctx, ponPort, onuID)
1882 err = dh.resourceMgr[ponPort].DelOnuGemInfo(ctx, ponPort, onu.OnuID)
1883 if err != nil {
1884 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
1885 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301886 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001887 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
1888 logger.Debug(ctx, err)
1889 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001890 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001891 }
A R Karthick1f85b802019-10-11 05:06:05 +00001892
Devmalya Paul495b94a2019-08-27 19:42:00 -04001893 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301894 dh.onus.Range(func(key interface{}, value interface{}) bool {
1895 dh.onus.Delete(key)
1896 return true
1897 })
1898
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001899 /*Delete discovered ONU map for the device*/
1900 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1901 dh.discOnus.Delete(key)
1902 return true
1903 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001904}
1905
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001906//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001907func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001908 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301909 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001910 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001911 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001912 return nil
1913}
1914
David K. Bainbridge794735f2020-02-11 21:01:37 -08001915func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001916 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001917 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001918 "packet-indication": *packetIn,
1919 "device-id": dh.device.Id,
1920 "packet": hex.EncodeToString(packetIn.Pkt),
1921 })
1922 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001923 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001924 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001925 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001926 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001927 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001928 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001929 "logical-port-num": logicalPortNum,
1930 "device-id": dh.device.Id,
1931 "packet": hex.EncodeToString(packetIn.Pkt),
1932 })
1933 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001934
khenaidoo106c61a2021-08-11 18:05:46 -04001935 if err := dh.sendPacketToCore(ctx, &ic.PacketIn{
1936 DeviceId: dh.device.Id,
1937 Port: logicalPortNum,
1938 Packet: packetIn.Pkt,
1939 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301940 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001941 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301942 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001943 "device-id": dh.device.Id,
1944 "packet": hex.EncodeToString(packetIn.Pkt),
1945 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001946 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001947
Matteo Scandolo92186242020-06-12 10:54:18 -07001948 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001949 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001950 "packet": hex.EncodeToString(packetIn.Pkt),
1951 "device-id": dh.device.Id,
1952 })
1953 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001954 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001955}
1956
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001957// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04001958func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001959 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001961 "device-id": dh.device.Id,
1962 "egress-port-no": egressPortNo,
1963 "pkt-length": len(packet.Data),
1964 "packet": hex.EncodeToString(packet.Data),
1965 })
1966 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001967
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001968 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001969 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001970 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1971 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301972 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1973 // Do not packet-out lldp packets on uni port.
1974 // ONOS has no clue about uni/nni ports, it just packets out on all
1975 // available ports on the Logical Switch. It should not be interested
1976 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001977 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001978 "device-id": dh.device.Id,
1979 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301980 return nil
1981 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001982 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1983 if innerEthType == 0x8100 {
1984 // q-in-q 802.1ad or 802.1q double tagged packet.
1985 // slice out the outer tag.
1986 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001987 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001988 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001989 "packet-data": hex.EncodeToString(packet.Data),
1990 "device-id": dh.device.Id,
1991 })
1992 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001993 }
1994 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001995 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
1996 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
1997 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001998
Girish Gowdra9602eb42020-09-09 15:50:39 -07001999 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002000 if err != nil {
2001 // In this case the openolt agent will receive the gemPortID as 0.
2002 // The agent tries to retrieve the gemPortID in this case.
2003 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002004 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002005 "intf-id": intfID,
2006 "onu-id": onuID,
2007 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002008 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302009 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002010 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002011 }
2012
2013 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002014 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002015 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002016 "egress-port-no": egressPortNo,
2017 "intf-id": intfID,
2018 "onu-id": onuID,
2019 "uni-id": uniID,
2020 "gem-port-id": gemPortID,
2021 "packet": hex.EncodeToString(packet.Data),
2022 "device-id": dh.device.Id,
2023 })
2024 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002025
npujarec5762e2020-01-01 14:08:48 +05302026 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302027 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002028 "source": "adapter",
2029 "destination": "onu",
2030 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002031 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002032 "oni-id": onuID,
2033 "uni-id": uniID,
2034 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002035 "packet": hex.EncodeToString(packet.Data),
2036 "device-id": dh.device.Id,
2037 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002038 }
2039 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002040 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002041 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002042 return olterrors.NewErrInvalidValue(log.Fields{
2043 "egress-nni-port": egressPortNo,
2044 "device-id": dh.device.Id,
2045 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002046 }
2047 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002048
Matteo Scandolo92186242020-06-12 10:54:18 -07002049 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002051 "uplink-pkt": uplinkPkt,
2052 "packet": hex.EncodeToString(packet.Data),
2053 "device-id": dh.device.Id,
2054 })
2055 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002056
npujarec5762e2020-01-01 14:08:48 +05302057 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002058 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2059 "packet": hex.EncodeToString(packet.Data),
2060 "device-id": dh.device.Id,
2061 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002062 }
2063 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302065 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002066 "egressPortType": egressPortType,
2067 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302068 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002069 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002070 }
2071 return nil
2072}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002073
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002074func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2075 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002076}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302077
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002078func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002079
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302080 // start the heartbeat check towards the OLT.
2081 var timerCheck *time.Timer
2082
2083 for {
2084 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2085 select {
2086 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002087 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002088 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002089 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302090 if timerCheck == nil {
2091 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002092 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302093 }
2094 } else {
2095 if timerCheck != nil {
2096 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002097 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302098 }
2099 timerCheck = nil
2100 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002101 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302102 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302103 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302104 }
2105 cancel()
2106 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002107 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302108 return
2109 }
2110 }
2111}
2112
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002113func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002114 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002115 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002116 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2117 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2118 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2119 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2120 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002121 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002122 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2123 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002124 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302125
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002126 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2127 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002128 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoo106c61a2021-08-11 18:05:46 -04002129 if err = dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
2130 DeviceId: dh.device.Id,
2131 OperStatus: voltha.OperStatus_UNKNOWN,
2132 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2133 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002134 _ = 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 -04002135 }
khenaidoo106c61a2021-08-11 18:05:46 -04002136
2137 if err = dh.updatePortsStateInCore(ctx, &ic.PortStateFilter{
2138 DeviceId: dh.device.Id,
2139 PortTypeFilter: 0,
2140 OperStatus: voltha.OperStatus_UNKNOWN,
2141 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002142 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002143 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002144
2145 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002146 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002147 cloned := proto.Clone(device).(*voltha.Device)
2148 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2149 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2150 dh.device = cloned // update local copy of the device
2151 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002152
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002153 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002154 // Stop the Stats collector
2155 dh.stopCollector <- true
2156 // stop the heartbeat check routine
2157 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002158
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002159 dh.lockDevice.RLock()
2160 // Stop the read indication only if it the routine is active
2161 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2162 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2163 // on next execution of the readIndication routine.
2164 if dh.isReadIndicationRoutineActive {
2165 dh.stopIndications <- true
2166 }
2167 dh.lockDevice.RUnlock()
2168
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002169 go dh.StopAllMcastHandlerRoutines(ctx)
2170 for _, flMgr := range dh.flowMgr {
2171 go flMgr.StopAllFlowHandlerRoutines(ctx)
2172 }
2173
Gamze Abakac2c32a62021-03-11 11:44:18 +00002174 //reset adapter reconcile flag
2175 dh.adapterPreviouslyConnected = false
2176
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002177 dh.transitionMap.Handle(ctx, DeviceInit)
2178
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302179 }
2180}
kesavand39e0aa32020-01-28 20:58:50 -05002181
2182// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002183func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2184 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2185 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002186}
2187
2188// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002189func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2190 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2191 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002192}
2193
kdarapu1afeceb2020-02-12 01:38:09 -05002194//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 +00002195func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2196 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002197 if port.GetType() == voltha.Port_ETHERNET_NNI {
2198 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002199 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302200 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302201 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002202 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002203 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002204 }
2205 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002206 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002207 ponIntf := &oop.Interface{IntfId: ponID}
2208 var operStatus voltha.OperStatus_Types
2209 if enablePort {
2210 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302211 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002212
2213 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302214 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002215 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002216 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002217 }
2218 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002219 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002220 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002221 } else {
2222 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302223 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002224 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302225 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002226 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002227 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002228 }
2229 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002230 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002232 }
khenaidoo106c61a2021-08-11 18:05:46 -04002233 if err := dh.updatePortStateInCore(ctx, &ic.PortState{
2234 DeviceId: dh.device.Id,
2235 PortType: voltha.Port_PON_OLT,
2236 PortNo: port.PortNo,
2237 OperStatus: operStatus,
2238 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302239 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302240 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002241 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002242 }
2243 return nil
2244}
2245
kdarapu1afeceb2020-02-12 01:38:09 -05002246//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002247func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002248 // Disable the port and update the oper_port_status to core
2249 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002250 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002251 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302253 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302254 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002255 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002256 }
2257 }
2258 }
2259 return nil
2260}
2261
2262//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002263func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2264 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2265 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002266 if port.Type == voltha.Port_ETHERNET_NNI {
2267 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002268 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002269 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002270 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002271 }
2272 }
2273 if port.Type == voltha.Port_PON_OLT {
2274 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002275 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002276 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002277 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002278 }
2279 }
2280 }
2281}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002282
2283// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002284func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002285 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002286 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002287 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002288
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002289 var sn *oop.SerialNumber
2290 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002291 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302292 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002293 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302294 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002295 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002296 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002297
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002298 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002299 //clear PON resources associated with ONU
2300 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2301 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2302 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2303 "device-id": dh.device.Id,
2304 "intf-id": intfID,
2305 "onuID": onuID,
2306 "err": err})
2307 } else {
2308 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2309 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2310 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2311 "device-id": dh.device.Id,
2312 "onu-device": onu,
2313 "err": err})
2314 }
2315 // Clear flowids for gem cache.
2316 for _, gem := range onuGem.GemPorts {
2317 dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
2318 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002319 if err := dh.flowMgr[intfID].RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002320 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2321 "intf-id": intfID,
2322 "onu-device": onu,
2323 "onu-gem": onuGem,
2324 "err": err})
2325 //Not returning error on cleanup.
2326 }
2327 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
2328 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuGem.OnuID})
2329 }
2330 dh.onus.Delete(onuKey)
2331 dh.discOnus.Delete(onuSn)
2332
2333 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002334 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302335 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302336 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002337 "onu-id": onuID}, err).Log()
2338 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002339
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002340 return nil
2341}
Girish Gowdracefae192020-03-19 18:14:10 -07002342
2343func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002344 for _, field := range flow_utils.GetOfbFields(flow) {
2345 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002346 return field.GetPort()
2347 }
2348 }
2349 return InvalidPort
2350}
2351
2352func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002353 for _, action := range flow_utils.GetActions(flow) {
2354 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002355 if out := action.GetOutput(); out != nil {
2356 return out.GetPort()
2357 }
2358 }
2359 }
2360 return InvalidPort
2361}
2362
Girish Gowdracefae192020-03-19 18:14:10 -07002363func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2364 inPort := getInPortFromFlow(flow)
2365 outPort := getOutPortFromFlow(flow)
2366
2367 if inPort == InvalidPort || outPort == InvalidPort {
2368 return inPort, outPort
2369 }
2370
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002371 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002372 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002373 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002374 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002375 return uniPort, outPort
2376 }
2377 }
2378 } else {
2379 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002380 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002381 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002382 return inPort, uniPort
2383 }
2384 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002385 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002386 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002387 return uniPort, outPort
2388 }
2389 }
2390 }
2391
2392 return InvalidPort, InvalidPort
2393}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002394
2395func extractOmciTransactionID(omciPkt []byte) uint16 {
2396 if len(omciPkt) > 3 {
2397 d := omciPkt[0:2]
2398 transid := binary.BigEndian.Uint16(d)
2399 return transid
2400 }
2401 return 0
2402}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002403
2404// StoreOnuDevice stores the onu parameters to the local cache.
2405func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2406 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2407 dh.onus.Store(onuKey, onuDevice)
2408}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002409
Neha Sharma8f4e4322020-08-06 10:51:53 +00002410func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002411 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002412 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002413 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002414 resp := new(voltha.ReturnValues)
2415 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002416 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002417 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002418 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2419 return nil, err
2420 }
2421 ID = device.ProxyAddress.GetOnuId()
2422 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2423 valueparam.Onu = &Onu
2424 valueparam.Value = value
2425
2426 // This API is unsupported until agent patch is added
2427 resp.Unsupported = uint32(value)
2428 _ = ctx
2429
2430 // Uncomment this code once agent changes are complete and tests
2431 /*
2432 resp, err = dh.Client.GetValue(ctx, valueparam)
2433 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002434 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002435 return nil, err
2436 }
2437 */
2438
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002439 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 -08002440 return resp, nil
2441}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002442
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002443func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002444 // Default to PON0
2445 var intfID uint32
2446 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002447 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002448 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002449 }
2450 return intfID
2451}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002452
Mahir Gunyelb0046752021-02-26 13:51:05 -08002453func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2454 dh.perPonOnuIndicationChannelLock.Lock()
2455 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2456 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002457 return ch.indicationChannel
2458 }
2459 channels := onuIndicationChannels{
2460 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002461 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002462 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002463 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002464 stopChannel: make(chan struct{}),
2465 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002466 dh.perPonOnuIndicationChannel[intfID] = channels
2467 dh.perPonOnuIndicationChannelLock.Unlock()
2468 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002469 return channels.indicationChannel
2470
2471}
2472
Mahir Gunyelb0046752021-02-26 13:51:05 -08002473func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2474 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2475 dh.perPonOnuIndicationChannelLock.Lock()
2476 defer dh.perPonOnuIndicationChannelLock.Unlock()
2477 for _, v := range dh.perPonOnuIndicationChannel {
2478 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002479 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002480 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002481}
2482
Mahir Gunyelb0046752021-02-26 13:51:05 -08002483func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2484 ind := onuIndicationMsg{
2485 ctx: ctx,
2486 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002487 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002488 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002489 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002490 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002491}
2492
Mahir Gunyelb0046752021-02-26 13:51:05 -08002493func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002494 for {
2495 select {
2496 // process one indication per onu, before proceeding to the next one
2497 case onuInd := <-onuChannels.indicationChannel:
2498 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Mahir Gunyelb0046752021-02-26 13:51:05 -08002499 "ind": onuInd.indication})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002500 switch onuInd.indication.Data.(type) {
2501 case *oop.Indication_OnuInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002502 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002503 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2504 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002505 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002506 }
2507 case *oop.Indication_OnuDiscInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002508 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002509 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2510 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002511 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002512 }
2513 }
2514 case <-onuChannels.stopChannel:
2515 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2516 close(onuChannels.indicationChannel)
2517 return
2518 }
2519 }
2520}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002521
2522// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2523// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2524func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2525 // Step1 : Fill McastFlowOrGroupControlBlock
2526 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2527 // Step3 : Wait on response channel for response
2528 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002529 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002530 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2531 errChan := make(chan error)
2532 var groupID uint32
2533 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2534 ctx: ctx,
2535 flowOrGroupAction: action,
2536 flow: flow,
2537 group: group,
2538 errChan: &errChan,
2539 }
2540 if flow != nil {
2541 groupID = flow_utils.GetGroup(flow)
2542 } else if group != nil {
2543 groupID = group.Desc.GroupId
2544 } else {
2545 return errors.New("flow-and-group-both-nil")
2546 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002547 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2548 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2549 // Derive the appropriate go routine to handle the request by a simple module operation.
2550 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2551 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2552 // Wait for handler to return error value
2553 err := <-errChan
2554 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2555 return err
2556 }
2557 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2558 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002559}
2560
2561// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002562func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002563 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002564 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002565 // block on the channel to receive an incoming mcast flow/group
2566 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002567 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2568 if mcastFlowOrGroupCb.flow != nil {
2569 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2570 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2571 log.Fields{"device-id": dh.device.Id,
2572 "flowToAdd": mcastFlowOrGroupCb.flow})
2573 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2574 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2575 // Pass the return value over the return channel
2576 *mcastFlowOrGroupCb.errChan <- err
2577 } else { // flow remove
2578 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2579 log.Fields{"device-id": dh.device.Id,
2580 "flowToRemove": mcastFlowOrGroupCb.flow})
2581 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2582 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2583 // Pass the return value over the return channel
2584 *mcastFlowOrGroupCb.errChan <- err
2585 }
2586 } else { // mcast group
2587 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2588 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2589 log.Fields{"device-id": dh.device.Id,
2590 "groupToAdd": mcastFlowOrGroupCb.group})
2591 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2592 // Pass the return value over the return channel
2593 *mcastFlowOrGroupCb.errChan <- err
2594 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2595 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2596 log.Fields{"device-id": dh.device.Id,
2597 "groupToModify": mcastFlowOrGroupCb.group})
2598 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2599 // Pass the return value over the return channel
2600 *mcastFlowOrGroupCb.errChan <- err
2601 } else { // group remove
2602 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2603 log.Fields{"device-id": dh.device.Id,
2604 "groupToRemove": mcastFlowOrGroupCb.group})
2605 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2606 // Pass the return value over the return channel
2607 *mcastFlowOrGroupCb.errChan <- err
2608 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002609 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002610 case <-stopHandler:
2611 dh.mcastHandlerRoutineActive[routineIndex] = false
2612 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002613 }
2614 }
2615}
kesavand62126212021-01-12 04:56:06 -05002616
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002617// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2618func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context) {
2619 for i, v := range dh.stopMcastHandlerRoutine {
2620 if dh.mcastHandlerRoutineActive[i] {
2621 v <- true
2622 }
2623 }
2624 logger.Debug(ctx, "stopped all mcast handler routines")
2625}
2626
kesavand62126212021-01-12 04:56:06 -05002627func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2628
2629 singleValResp := extension.SingleGetValueResponse{
2630 Response: &extension.GetValueResponse{
2631 Response: &extension.GetValueResponse_PortCoutners{
2632 PortCoutners: &extension.GetOltPortCountersResponse{},
2633 },
2634 },
2635 }
2636
2637 errResp := func(status extension.GetValueResponse_Status,
2638 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2639 return &extension.SingleGetValueResponse{
2640 Response: &extension.GetValueResponse{
2641 Status: status,
2642 ErrReason: reason,
2643 },
2644 }
2645 }
2646
2647 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2648 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2649 //send error response
2650 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2651 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2652 }
2653 statIndChn := make(chan bool, 1)
2654 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2655 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2656 //request openOlt agent to send the the port statistics indication
2657
2658 go func() {
2659 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2660 if err != nil {
2661 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2662 }
2663 }()
2664 select {
2665 case <-statIndChn:
2666 //indication received for ports stats
2667 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2668 case <-time.After(oltPortInfoTimeout * time.Second):
2669 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2670 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2671 case <-ctx.Done():
2672 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2673 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2674 }
2675 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2676 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002677 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002678 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2679 cmnni := dh.portStats.collectNNIMetrics(intfID)
2680 if cmnni == nil {
2681 //TODO define the error reason
2682 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2683 }
2684 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2685 return &singleValResp
2686
2687 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2688 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002689 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002690 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2691 cmpon := dh.portStats.collectPONMetrics(intfID)
2692 if cmpon == nil {
2693 //TODO define the error reason
2694 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2695 }
2696 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2697 return &singleValResp
2698 }
2699 }
2700 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2701}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302702
2703func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2704
2705 singleValResp := extension.SingleGetValueResponse{
2706 Response: &extension.GetValueResponse{
2707 Response: &extension.GetValueResponse_OnuPonCounters{
2708 OnuPonCounters: &extension.GetOnuCountersResponse{},
2709 },
2710 },
2711 }
2712
2713 errResp := func(status extension.GetValueResponse_Status,
2714 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2715 return &extension.SingleGetValueResponse{
2716 Response: &extension.GetValueResponse{
2717 Status: status,
2718 ErrReason: reason,
2719 },
2720 }
2721 }
2722 intfID := onuPonInfo.IntfId
2723 onuID := onuPonInfo.OnuId
2724 onuKey := dh.formOnuKey(intfID, onuID)
2725
2726 if _, ok := dh.onus.Load(onuKey); !ok {
2727 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2728 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2729 }
2730 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2731 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2732 if cmnni == nil {
2733 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2734 }
2735 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2736 return &singleValResp
2737
2738}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002739
2740func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2741
2742 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2743 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2744 if err != nil {
2745 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2746 return generateSingleGetValueErrorResponse(err)
2747 }
2748 return &extension.SingleGetValueResponse{
2749 Response: &extension.GetValueResponse{
2750 Status: extension.GetValueResponse_OK,
2751 Response: &extension.GetValueResponse_RxPower{
2752 RxPower: &extension.GetRxPowerResponse{
2753 IntfId: rxPowerRequest.IntfId,
2754 OnuId: rxPowerRequest.OnuId,
2755 Status: rxPower.Status,
2756 FailReason: rxPower.FailReason.String(),
2757 RxPower: rxPower.RxPowerMeanDbm,
2758 },
2759 },
2760 },
2761 }
2762}
2763
2764func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2765 errResp := func(status extension.GetValueResponse_Status,
2766 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2767 return &extension.SingleGetValueResponse{
2768 Response: &extension.GetValueResponse{
2769 Status: status,
2770 ErrReason: reason,
2771 },
2772 }
2773 }
2774
2775 if err != nil {
2776 if e, ok := status.FromError(err); ok {
2777 switch e.Code() {
2778 case codes.Internal:
2779 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2780 case codes.DeadlineExceeded:
2781 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2782 case codes.Unimplemented:
2783 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2784 case codes.NotFound:
2785 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2786 }
2787 }
2788 }
2789
2790 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2791}
khenaidoo106c61a2021-08-11 18:05:46 -04002792
2793/*
2794Helper functions to communicate with Core
2795*/
2796
2797func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2798 cClient, err := dh.coreClient.GetCoreServiceClient()
2799 if err != nil || cClient == nil {
2800 return nil, err
2801 }
2802 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2803 defer cancel()
2804 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
2805}
2806
2807func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ic.ChildDeviceFilter) (*voltha.Device, error) {
2808 cClient, err := dh.coreClient.GetCoreServiceClient()
2809 if err != nil || cClient == nil {
2810 return nil, err
2811 }
2812 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2813 defer cancel()
2814 return cClient.GetChildDevice(subCtx, childDeviceFilter)
2815}
2816
2817func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ic.DeviceStateFilter) error {
2818 cClient, err := dh.coreClient.GetCoreServiceClient()
2819 if err != nil || cClient == nil {
2820 return err
2821 }
2822 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2823 defer cancel()
2824 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
2825 return err
2826}
2827
2828func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
2829 cClient, err := dh.coreClient.GetCoreServiceClient()
2830 if err != nil || cClient == nil {
2831 return nil, err
2832 }
2833 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2834 defer cancel()
2835 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
2836}
2837
2838func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
2839 cClient, err := dh.coreClient.GetCoreServiceClient()
2840 if err != nil || cClient == nil {
2841 return nil, err
2842 }
2843 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2844 defer cancel()
2845 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
2846}
2847
2848func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
2849 cClient, err := dh.coreClient.GetCoreServiceClient()
2850 if err != nil || cClient == nil {
2851 return err
2852 }
2853 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2854 defer cancel()
2855 _, err = cClient.DeviceUpdate(subCtx, device)
2856 return err
2857}
2858
2859func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ic.DeviceDiscovery) (*voltha.Device, error) {
2860 cClient, err := dh.coreClient.GetCoreServiceClient()
2861 if err != nil || cClient == nil {
2862 return nil, err
2863 }
2864 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2865 defer cancel()
2866 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
2867}
2868
2869func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ic.PacketIn) error {
2870 cClient, err := dh.coreClient.GetCoreServiceClient()
2871 if err != nil || cClient == nil {
2872 return err
2873 }
2874 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2875 defer cancel()
2876 _, err = cClient.SendPacketIn(subCtx, pkt)
2877 return err
2878}
2879
2880func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
2881 cClient, err := dh.coreClient.GetCoreServiceClient()
2882 if err != nil || cClient == nil {
2883 return err
2884 }
2885 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2886 defer cancel()
2887 _, err = cClient.PortCreated(subCtx, port)
2888 return err
2889}
2890
2891func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ic.PortStateFilter) error {
2892 cClient, err := dh.coreClient.GetCoreServiceClient()
2893 if err != nil || cClient == nil {
2894 return err
2895 }
2896 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2897 defer cancel()
2898 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
2899 return err
2900}
2901
2902func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ic.PortState) error {
2903 cClient, err := dh.coreClient.GetCoreServiceClient()
2904 if err != nil || cClient == nil {
2905 return err
2906 }
2907 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2908 defer cancel()
2909 _, err = cClient.PortStateUpdate(subCtx, portState)
2910 return err
2911}
2912
2913func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ic.PortFilter) (*voltha.Port, error) {
2914 cClient, err := dh.coreClient.GetCoreServiceClient()
2915 if err != nil || cClient == nil {
2916 return nil, err
2917 }
2918 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2919 defer cancel()
2920 return cClient.GetDevicePort(subCtx, portFilter)
2921}
2922
2923/*
2924Helper functions to communicate with child adapter
2925*/
2926
2927func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ic.OmciMessage) error {
2928 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2929 if err != nil || aClient == nil {
2930 return err
2931 }
2932 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
2933 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2934 defer cancel()
2935 _, err = aClient.OmciIndication(subCtx, response)
2936 return err
2937}
2938
2939func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ic.OnuIndicationMessage) error {
2940 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2941 if err != nil || aClient == nil {
2942 return err
2943 }
2944 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
2945 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2946 defer cancel()
2947 _, err = aClient.OnuIndication(subCtx, onuInd)
2948 return err
2949}
2950
2951func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ic.DeleteTcontMessage) error {
2952 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2953 if err != nil || aClient == nil {
2954 return err
2955 }
2956 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
2957 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2958 defer cancel()
2959 _, err = aClient.DeleteTCont(subCtx, tContInfo)
2960 return err
2961}
2962
2963func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ic.DeleteGemPortMessage) error {
2964 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2965 if err != nil || aClient == nil {
2966 return err
2967 }
2968 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
2969 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2970 defer cancel()
2971 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
2972 return err
2973}
2974
2975func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ic.TechProfileDownloadMessage) error {
2976 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2977 if err != nil || aClient == nil {
2978 return err
2979 }
2980 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
2981 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2982 defer cancel()
2983 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
2984 return err
2985}
2986
2987/*
2988Helper functions for remote communication
2989*/
2990
2991// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
2992// supports is deleted
2993func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
2994 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
2995
2996 dh.lockChildAdapterClients.Lock()
2997 defer dh.lockChildAdapterClients.Unlock()
2998 if _, ok := dh.childAdapterClients[endpoint]; ok {
2999 // Already set
3000 return nil
3001 }
3002
3003 // Setup child's adapter grpc connection
3004 var err error
3005 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(endpoint,
3006 dh.onuAdapterRestarted,
3007 vgrpc.ActivityCheck(true)); err != nil {
3008 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3009 return err
3010 }
3011 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), setAndTestAdapterServiceHandler)
3012
3013 // Wait until we have a connection to the child adapter.
3014 // Unlimited retries or until context expires
3015 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3016 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3017 for {
3018 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3019 if err == nil && client != nil {
3020 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3021 break
3022 }
3023 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3024 // Backoff
3025 if err = backoff.Backoff(subCtx); err != nil {
3026 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3027 break
3028 }
3029 }
3030 return nil
3031}
3032
3033// func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (adapter_services.OnuInterAdapterServiceClient, error) {
3034// dh.lockChildAdapterClients.RLock()
3035// defer dh.lockChildAdapterClients.RUnlock()
3036// if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3037// return cgClient.GetOnuInterAdapterServiceClient()
3038// }
3039// return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3040// }
3041
3042func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (adapter_services.OnuInterAdapterServiceClient, error) {
3043
3044 // First check from cache
3045 dh.lockChildAdapterClients.RLock()
3046 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3047 dh.lockChildAdapterClients.RUnlock()
3048 return cgClient.GetOnuInterAdapterServiceClient()
3049 }
3050 dh.lockChildAdapterClients.RUnlock()
3051
3052 // Set the child connection - can occur on restarts
3053 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3054 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3055 cancel()
3056 if err != nil {
3057 return nil, err
3058 }
3059
3060 // Get the child client now
3061 dh.lockChildAdapterClients.RLock()
3062 defer dh.lockChildAdapterClients.RUnlock()
3063 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3064 return cgClient.GetOnuInterAdapterServiceClient()
3065 }
3066 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3067}
3068
3069func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3070 dh.lockChildAdapterClients.Lock()
3071 defer dh.lockChildAdapterClients.Unlock()
3072 for key, client := range dh.childAdapterClients {
3073 client.Stop(ctx)
3074 delete(dh.childAdapterClients, key)
3075 }
3076}
3077
3078// TODO: Any action the adapter needs to do following a onu adapter restart?
3079func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
3080 logger.Warnw(ctx, "onu-adapter-restarted", log.Fields{"endpoint": endPoint})
3081 return nil
3082}
3083
3084// setAndTestAdapterServiceHandler is used to test whether the remote gRPC service is up
3085func setAndTestAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3086 svc := adapter_services.NewOnuInterAdapterServiceClient(conn)
3087 if h, err := svc.GetHealthStatus(ctx, &empty.Empty{}); err != nil || h.State != voltha.HealthStatus_HEALTHY {
3088 return nil
3089 }
3090 return svc
3091}