blob: b9f1e2e5730f76d36264aa439abe85e154a00def [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"
khenaidoo106c61a2021-08-11 18:05:46 -040035
Matteo Scandolo945e4012019-12-12 14:16:11 -080036 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070037 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000038 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
39 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040040 "github.com/opencord/voltha-lib-go/v7/pkg/config"
41 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
42 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
43 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070044 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040045 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080046
khenaidoo106c61a2021-08-11 18:05:46 -040047 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053048 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080049 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040050 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040051 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040053 "github.com/opencord/voltha-protos/v5/go/health"
54 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
55 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040056 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
57 oop "github.com/opencord/voltha-protos/v5/go/openolt"
58 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070059 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040060 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040061 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053062)
63
salmansiddiqui7ac62132019-08-22 03:58:50 +000064// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040065const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080066 InvalidPort = 0xffffffff
67 MaxNumOfGroupHandlerChannels = 256
68
69 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
70 McastFlowOrGroupModify = "McastFlowOrGroupModify"
71 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050072 oltPortInfoTimeout = 3
Manikkaraj kb1d51442019-07-23 10:41:02 -040073)
74
Phaneendra Manda4c62c802019-03-06 21:37:49 +053075//DeviceHandler will interact with the OLT device.
76type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040077 cm *config.ConfigManager
78 device *voltha.Device
79 cfg *conf.AdapterFlags
80 coreClient *vgrpc.Client
81 childAdapterClients map[string]*vgrpc.Client
82 lockChildAdapterClients sync.RWMutex
83 EventProxy eventif.EventProxy
84 openOLT *OpenOLT
85 exitChannel chan int
86 lockDevice sync.RWMutex
87 Client oop.OpenoltClient
88 transitionMap *TransitionMap
89 clientCon *grpc.ClientConn
90 flowMgr []*OpenOltFlowMgr
91 groupMgr *OpenOltGroupMgr
92 eventMgr *OpenOltEventMgr
93 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070094
95 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053096
Girish Gowdra3ab6d212020-03-24 17:33:15 -070097 discOnus sync.Map
98 onus sync.Map
99 portStats *OpenOltStatisticsMgr
100 metrics *pmmetrics.PmMetrics
101 stopCollector chan bool
102 stopHeartbeatCheck chan bool
103 activePorts sync.Map
104 stopIndications chan bool
105 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700106
Mahir Gunyelb0046752021-02-26 13:51:05 -0800107 totalPonPorts uint32
108 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
109 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800110
111 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
112 // 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 -0700113 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
114 stopMcastHandlerRoutine []chan bool
115 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000116
117 adapterPreviouslyConnected bool
118 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700119
120 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700121}
122
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700124type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400125 deviceID string
126 deviceType string
127 serialNumber string
128 onuID uint32
129 intfID uint32
130 proxyDeviceID string
131 losRaised bool
132 rdiRaised bool
133 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134}
135
Mahir Gunyelb0046752021-02-26 13:51:05 -0800136type onuIndicationMsg struct {
137 ctx context.Context
138 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800139}
140
141type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800142 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800143 stopChannel chan struct{}
144}
145
Girish Gowdra491a9c62021-01-06 16:43:07 -0800146//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
147//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
148//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
149//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
150type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400151 ctx context.Context // Flow/group handler context
152 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
153 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
154 group *of.OfpGroupEntry // Group message (can be nil or valid group)
155 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800156}
157
Naga Manjunath7615e552019-10-11 22:35:47 +0530158var pmNames = []string{
159 "rx_bytes",
160 "rx_packets",
161 "rx_mcast_packets",
162 "rx_bcast_packets",
163 "tx_bytes",
164 "tx_packets",
165 "tx_mcast_packets",
166 "tx_bcast_packets",
167}
168
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700169//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400170func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700171 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700172 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700173 device.deviceType = deviceTp
174 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700175 device.onuID = onuID
176 device.intfID = intfID
177 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530178 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400179 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700180 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530181}
182
183//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400184func 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 -0700185 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800186 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400187 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400188 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700189 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700190 dh.device = cloned
191 dh.openOLT = adapter
192 dh.exitChannel = make(chan int, 1)
193 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530194 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530195 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530196 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 -0500197 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400198 dh.stopIndications = make(chan bool, 1)
Mahir Gunyelb0046752021-02-26 13:51:05 -0800199 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400200 dh.childAdapterClients = make(map[string]*vgrpc.Client)
201 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800202 // Create a slice of buffered channels for handling concurrent mcast flow/group.
203 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700204 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
205 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800206 for i := range dh.incomingMcastFlowOrGroup {
207 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700208 dh.stopMcastHandlerRoutine[i] = make(chan bool, 1)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800209 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
210 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
211 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
212 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700213 dh.mcastHandlerRoutineActive[i] = true
214 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800215 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700216 //TODO initialize the support classes.
217 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530218}
219
220// start save the device to the data model
221func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700222 dh.lockDevice.Lock()
223 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000224 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700225 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530227}
228
229// stop stops the device dh. Not much to do for now
230func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 dh.lockDevice.Lock()
232 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000233 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 dh.exitChannel <- 1
khenaidoo106c61a2021-08-11 18:05:46 -0400235
Neha Sharma96b7bf22020-06-15 10:37:32 +0000236 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530237}
238
ssiddiqui04386ee2021-08-23 21:58:25 +0530239func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
240 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
241 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
242 if pooledIntfID == intfID {
243 return resourceRanges.GetTechnology()
244 }
245 }
246 }
247 return ""
248}
249
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400250func macifyIP(ip net.IP) string {
251 if len(ip) > 0 {
252 oct1 := strconv.FormatInt(int64(ip[12]), 16)
253 oct2 := strconv.FormatInt(int64(ip[13]), 16)
254 oct3 := strconv.FormatInt(int64(ip[14]), 16)
255 oct4 := strconv.FormatInt(int64(ip[15]), 16)
256 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
257 }
258 return ""
259}
260
Neha Sharma96b7bf22020-06-15 10:37:32 +0000261func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400262 var genmac string
263 var addr net.IP
264 var ips []string
265 var err error
266
Neha Sharma96b7bf22020-06-15 10:37:32 +0000267 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400268
269 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400271
272 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000273 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400274 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000275 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400276 }
277 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000278 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530279 log.Fields{"host": ips[0],
280 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400281 return genmac, nil
282 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000283 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400284 }
285
286 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000287 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530288 log.Fields{"host": host,
289 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400290 return genmac, nil
291}
292
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 slist := strings.Split(mac, ":")
295 result := make([]uint32, len(slist))
296 var err error
297 var tmp int64
298 for index, val := range slist {
299 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
300 return []uint32{1, 2, 3, 4, 5, 6}
301 }
302 result[index] = uint32(tmp)
303 }
304 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530305}
306
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700307//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 -0800308func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309
David K. Bainbridge794735f2020-02-11 21:01:37 -0800310 switch portType {
311 case voltha.Port_ETHERNET_NNI:
312 return fmt.Sprintf("nni-%d", portNum), nil
313 case voltha.Port_PON_OLT:
314 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700315 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800316
Girish Kumarf26e4882020-03-05 06:49:10 +0000317 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530318}
319
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000321 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700322 if state == "up" {
323 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500324 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500325 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700326 } else {
327 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500328 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700329 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700330 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400331 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800332 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000333 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400334 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500335
khenaidoo106c61a2021-08-11 18:05:46 -0400336 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400337 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400338 DeviceId: dh.device.Id,
339 Port: portNum,
340 })
341 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000342 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400343 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400344 DeviceId: dh.device.Id,
345 PortType: portType,
346 PortNo: portNum,
347 OperStatus: operStatus})
348 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400349 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
350 "device-id": dh.device.Id,
351 "port-type": portType,
352 "port-number": portNum,
353 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500354 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400355 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500356 }
khenaidoo106c61a2021-08-11 18:05:46 -0400357
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400358 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700359 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
khenaidoo106c61a2021-08-11 18:05:46 -0400360 port = &voltha.Port{
361 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700362 PortNo: portNum,
363 Label: label,
364 Type: portType,
365 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700366 OfpPort: &of.OfpPort{
367 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
368 Config: 0,
369 State: uint32(of.OfpPortState_OFPPS_LIVE),
370 Curr: capacity,
371 Advertised: capacity,
372 Peer: capacity,
373 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
374 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
375 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700376 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000377 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700378 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400379 err = dh.createPortInCore(ctx, port)
380 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000381 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000383 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400384 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000385 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530386 return nil
387}
388
Kent Hagermane6ff1012020-07-14 15:07:53 -0400389func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400390 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530391 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400392 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
393 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530394 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800395 dh.lockDevice.Lock()
396 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530397 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530398}
399
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700400// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530401// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800402func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000403 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700404 defer func() {
405 dh.lockDevice.Lock()
406 dh.isReadIndicationRoutineActive = false
407 dh.lockDevice.Unlock()
408 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700409 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700410 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700411 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700412 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400413
David Bainbridgef5879ca2019-12-13 21:17:54 +0000414 // Create an exponential backoff around re-enabling indications. The
415 // maximum elapsed time for the back off is set to 0 so that we will
416 // continue to retry. The max interval defaults to 1m, but is set
417 // here for code clarity
418 indicationBackoff := backoff.NewExponentialBackOff()
419 indicationBackoff.MaxElapsedTime = 0
420 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700421
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700422 dh.lockDevice.Lock()
423 dh.isReadIndicationRoutineActive = true
424 dh.lockDevice.Unlock()
425
Girish Gowdra3f974912020-03-23 20:35:18 -0700426Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700427 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400428 select {
429 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000430 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700431 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400432 default:
433 indication, err := indications.Recv()
434 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000435 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530436 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530437 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400438 // Use an exponential back off to prevent getting into a tight loop
439 duration := indicationBackoff.NextBackOff()
440 if duration == backoff.Stop {
441 // If we reach a maximum then warn and reset the backoff
442 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530444 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530445 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400446 indicationBackoff.Reset()
447 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700448
449 // On failure process a backoff timer while watching for stopIndications
450 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700451 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700452 select {
453 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000454 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700455 if !backoffTimer.Stop() {
456 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700457 }
458 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700459 case <-backoffTimer.C:
460 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700461 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700462 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
463 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400464 }
465 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000466 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530467 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530469 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530470 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700471 // Close the stream, and re-initialize it
472 if err = indications.CloseSend(); err != nil {
473 // Ok to ignore here, because we landed here due to a problem on the stream
474 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530476 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530477 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700478 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000479 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700480 return err
481 }
482 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400483 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530484 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400485 // Reset backoff if we have a successful receive
486 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400487 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700488 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530490 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530491 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400492 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400493 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400494 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700495 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700496 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700497 // Close the send stream
498 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700499
Girish Gowdra3f974912020-03-23 20:35:18 -0700500 return nil
501}
502
503func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700504 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700505 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
506 if err != nil {
507 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
508 }
509 if indications == nil {
510 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
511 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700512 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700513 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400514}
515
516// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
517func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
518 switch indication.Data.(type) {
519 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
520 return true
521
522 default:
523 return false
524 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525}
526
David K. Bainbridge794735f2020-02-11 21:01:37 -0800527func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700528 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000529 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530530 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530532 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000534 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000535 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530536 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000537 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800538 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000539 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800540 }
541 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542}
543
David K. Bainbridge794735f2020-02-11 21:01:37 -0800544// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530545func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700546 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 switch indication.Data.(type) {
548 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000549 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
550 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700551 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 -0800552 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400553 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800554 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000556 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
557 defer span.Finish()
558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800560 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400562 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800563 }
564 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000567 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
568 defer span.Finish()
569
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570 intfOperInd := indication.GetIntfOperInd()
571 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400574 _ = 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 -0800575 }
576 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 } else if intfOperInd.GetType() == "pon" {
578 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
579 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800580 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000581 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400582 _ = 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 -0800583 }
584 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700586 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000587 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530588 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530589 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000591 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
592 defer span.Finish()
593
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800596 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800597 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000599 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
600 defer span.Finish()
601
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700602 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000603 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800604 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800605 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000607 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
608 defer span.Finish()
609
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700610 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000611 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 -0800612 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000613 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400614 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800615 }
616 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000618 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
619 defer span.Finish()
620
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000622 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700623 "intf-type": pktInd.IntfId,
624 "intf-id": pktInd.IntfId,
625 "gem-port-id": pktInd.GemportId,
626 "port-no": pktInd.PortNo,
627 "device-id": dh.device.Id,
628 })
629
630 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000631 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700632 "intf-type": pktInd.IntfId,
633 "intf-id": pktInd.IntfId,
634 "gem-port-id": pktInd.GemportId,
635 "port-no": pktInd.PortNo,
636 "packet": hex.EncodeToString(pktInd.Pkt),
637 "device-id": dh.device.Id,
638 })
639 }
640
David K. Bainbridge794735f2020-02-11 21:01:37 -0800641 go func() {
642 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400643 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644 }
645 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000647 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
648 defer span.Finish()
649
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700651 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000653 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
654 defer span.Finish()
655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000657 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000659 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
660 defer span.Finish()
661
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000663 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
664 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700665 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530666}
667
668// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530669func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530670 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000671 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530672
Girish Gowdra618fa572021-09-01 17:19:29 -0700673 // instantiate the mcast handler routines.
674 for i := range dh.incomingMcastFlowOrGroup {
675 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
676 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
677 if !dh.mcastHandlerRoutineActive[i] {
678 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
679 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
680 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
681 // for incoming mcast flow/group to be processed serially.
682 dh.mcastHandlerRoutineActive[i] = true
683 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
684 }
685 }
686
Girish Gowdru0c588b22019-04-23 23:24:56 -0400687 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400688 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400689 DeviceId: dh.device.Id,
690 OperStatus: voltha.OperStatus_ACTIVE,
691 ConnStatus: voltha.ConnectStatus_REACHABLE,
692 }); err != nil {
693 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400694 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000695
696 //Clear olt communication failure event
697 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
698 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700699 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000700 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
701
Gamze Abakac2c32a62021-03-11 11:44:18 +0000702 //check adapter and agent reconcile status
703 //reboot olt if needed (olt disconnection case)
704 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
705 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
706 log.Fields{
707 "device-id": dh.device.Id,
708 "adapter-status": dh.adapterPreviouslyConnected,
709 "agent-status": dh.agentPreviouslyConnected,
710 })
711 _ = dh.RebootDevice(ctx, dh.device)
712 }
713
Girish Gowdru0c588b22019-04-23 23:24:56 -0400714 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530715}
716
717// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530718func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400720
khenaidoo106c61a2021-08-11 18:05:46 -0400721 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400722 if err != nil || device == nil {
723 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000724 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400725 }
726
727 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400728
729 //Update the device oper state and connection status
730 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800731 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400732 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800733 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400734
khenaidoodc2116e2021-10-19 17:33:19 -0400735 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400736 DeviceId: cloned.Id,
737 OperStatus: cloned.OperStatus,
738 ConnStatus: cloned.ConnectStatus,
739 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000740 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400741 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400742
743 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400744 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400745 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000746 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400747 }
748 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400749 // Update onu state as down in onu adapter
750 onuInd := oop.OnuIndication{}
751 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400752
753 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
754 if err != nil {
755 return err
756 }
757 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400758 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400759 DeviceId: onuDevice.Id,
760 OnuIndication: &onuInd,
761 })
762 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800763 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400764 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400765 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 "onu-indicator": onuInd,
767 "device-type": onuDevice.Type,
768 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700769 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800770 } else {
771 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 -0700772 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400773 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800774 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700775 /* Discovered ONUs entries need to be cleared , since after OLT
776 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530777 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800778 dh.lockDevice.Unlock()
779
Neha Sharma96b7bf22020-06-15 10:37:32 +0000780 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700781 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530782}
783
784// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530785func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400786 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000787
788 // if the connection is already available, close the previous connection (olt reboot case)
789 if dh.clientCon != nil {
790 if err = dh.clientCon.Close(); err != nil {
791 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
792 } else {
793 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
794 }
795 }
796
797 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000798 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
799 grpc.WithInsecure(),
800 grpc.WithBlock(),
801 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000802 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000803 )),
804 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000805 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000806 )))
807
808 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530809 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530810 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000811 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400812 }
813 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530814}
815
816// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530817func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400818 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530819 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400820 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530821}
822
823// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530824func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530825 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000826 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400827
828 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400829 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530830 if err != nil || device == nil {
831 /*TODO: needs to handle error scenarios */
832 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
833 }
834 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000835 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400836
837 cloned := proto.Clone(device).(*voltha.Device)
838 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
839 cloned.OperStatus = voltha.OperStatus_UNKNOWN
840 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400841
khenaidoodc2116e2021-10-19 17:33:19 -0400842 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400843 DeviceId: cloned.Id,
844 OperStatus: cloned.OperStatus,
845 ConnStatus: cloned.ConnectStatus,
846 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530847 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 -0400848 }
849
Chaitrashree G S44124192019-08-07 20:21:36 -0400850 // 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 +0530851 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400852 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530853 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400854 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400855 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
856 // all the modules initialized and ready to handle incoming ONUs.
857
Thomas Lee S985938d2020-05-04 11:40:41 +0530858 err = dh.initializeDeviceHandlerModules(ctx)
859 if err != nil {
860 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 -0400861 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400862
863 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800864 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530865 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400866 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800867 }
868 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700869
870 go startHeartbeatCheck(ctx, dh)
871
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400872 return nil
873 }
874
khenaidoo106c61a2021-08-11 18:05:46 -0400875 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400876 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400877 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400878 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400879 }
khenaidoo106c61a2021-08-11 18:05:46 -0400880 dh.populateActivePorts(ctx, ports.Items)
881 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400882 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400883 }
884
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400885 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530886 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 -0400887 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530888
cuilin20187b2a8c32019-03-26 19:52:28 -0700889 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800890 go func() {
891 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400892 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800893 }
894 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000895 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000896
897 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000898 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000899 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700900
901 go startHeartbeatCheck(ctx, dh)
902
cuilin20187b2a8c32019-03-26 19:52:28 -0700903 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530904}
905
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400906func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700907 var err error
908 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400909
910 if err != nil {
911 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
912 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700913 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
914 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700915
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700916 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700917 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700918 var i uint32
919 for i = 0; i < dh.totalPonPorts; i++ {
920 // Instantiate resource manager
921 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 -0700922 return olterrors.ErrResourceManagerInstantiating
923 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400924 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700925 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
926 // the KV store to manage mcast group data. Provide the first instance (0th index)
927 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
928 return olterrors.ErrGroupManagerInstantiating
929 }
930 for i = 0; i < dh.totalPonPorts; i++ {
931 // Instantiate flow manager
932 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
933 return olterrors.ErrFlowManagerInstantiating
934 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700935 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700936 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400937 /* TODO: Instantiate Alarm , stats , BW managers */
938 /* Instantiating Event Manager to handle Alarms and KPIs */
939 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
940
941 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400943
944 return nil
945
946}
947
Neha Sharma96b7bf22020-06-15 10:37:32 +0000948func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400949 var err error
950 var deviceInfo *oop.DeviceInfo
951
Neha Sharma8f4e4322020-08-06 10:51:53 +0000952 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400953
954 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000955 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400956 }
957 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000958 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400959 }
960
Neha Sharma96b7bf22020-06-15 10:37:32 +0000961 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400962 dh.device.Root = true
963 dh.device.Vendor = deviceInfo.Vendor
964 dh.device.Model = deviceInfo.Model
965 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
966 dh.device.HardwareVersion = deviceInfo.HardwareVersion
967 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
968
969 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000970 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400971 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400973 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000974 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400975 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000976 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400977 dh.device.MacAddress = genmac
978 } else {
979 dh.device.MacAddress = deviceInfo.DeviceId
980 }
981
982 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400983 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000984 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400985 }
986
987 return deviceInfo, nil
988}
989
Neha Sharma96b7bf22020-06-15 10:37:32 +0000990func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -0700991 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530992 for {
993 select {
994 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000995 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530996 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000997 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700998
khenaidoo106c61a2021-08-11 18:05:46 -0400999 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001000 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001001 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001002 continue
1003 }
khenaidoo106c61a2021-08-11 18:05:46 -04001004 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301005 // NNI Stats
1006 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001007 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301008 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001009 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001010 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001011 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301012 }
1013 // PON Stats
1014 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001015 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301016 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1017 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001019 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301020 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001021 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001022
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001023 onuGemInfoLst := dh.flowMgr[intfID].getOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001024 if len(onuGemInfoLst) > 0 {
1025 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001026 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001027 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301028 }
1029 }
1030 }
1031}
1032
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001033//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301034func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001035 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301037 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301038
1039 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001040 cgClient, err := dh.coreClient.GetCoreServiceClient()
1041 if err != nil {
1042 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1043 return
1044 }
1045
1046 // Now, set the initial PM configuration for that device
1047 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001048 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301049 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301050}
1051
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001053func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1054 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001055 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301056 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001057 HwDesc: "open_pon",
1058 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001059 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001060 },
1061 SwitchFeatures: &of.OfpSwitchFeatures{
1062 NBuffers: 256,
1063 NTables: 2,
1064 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1065 of.OfpCapabilities_OFPC_TABLE_STATS |
1066 of.OfpCapabilities_OFPC_PORT_STATS |
1067 of.OfpCapabilities_OFPC_GROUP_STATS),
1068 },
1069 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301070}
1071
khenaidoo106c61a2021-08-11 18:05:46 -04001072// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001073func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001074 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001075 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001076 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001077 }
khenaidoo106c61a2021-08-11 18:05:46 -04001078 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001079}
1080
Neha Sharma96b7bf22020-06-15 10:37:32 +00001081func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001082 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 -07001083 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 var deviceID string
1085 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001086 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001087
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001088 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001089 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 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 -07001091 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1092 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001093
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001094 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301095
1096 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1097
Neha Sharma96b7bf22020-06-15 10:37:32 +00001098 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 -07001099 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001100
khenaidoodc2116e2021-10-19 17:33:19 -04001101 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001102 ParentId: dh.device.Id,
1103 OnuId: omciInd.OnuId,
1104 ParentPortNo: ponPort,
1105 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001106 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301107 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001108 "intf-id": omciInd.IntfId,
1109 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001110 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001111 deviceType = onuDevice.Type
1112 deviceID = onuDevice.Id
1113 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001114 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001115 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001116 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001117 } else {
1118 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 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 +05301120 deviceType = onuInCache.(*OnuDevice).deviceType
1121 deviceID = onuInCache.(*OnuDevice).deviceID
1122 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001123 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001124 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001125
khenaidoodc2116e2021-10-19 17:33:19 -04001126 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001127 ParentDeviceId: proxyDeviceID,
1128 ChildDeviceId: deviceID,
1129 Message: omciInd.Pkt,
1130 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301131 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001132 "source": dh.openOLT.config.AdapterEndpoint,
1133 "device-type": deviceType,
1134 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001136 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001137 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301139}
1140
khenaidoo106c61a2021-08-11 18:05:46 -04001141// //ProcessInterAdapterMessage sends the proxied messages to the target device
1142// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1143// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001144// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001145// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001146// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001147// return dh.handleInterAdapterOmciMsg(ctx, msg)
1148// }
1149// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1150// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001151
khenaidoo106c61a2021-08-11 18:05:46 -04001152// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001153func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001154 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 -07001155
1156 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001157 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001158 if err != nil {
1159 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001160 "parent-device-id": dh.device.Id,
1161 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 }
khenaidoo106c61a2021-08-11 18:05:46 -04001163 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1164 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001165 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001166 "parent-device-id": dh.device.Id,
1167 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001168 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001169 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001170 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1171 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001172 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001173 "parent-device-id": dh.device.Id,
1174 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001175 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001176 }
1177 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301178}
1179
khenaidoodc2116e2021-10-19 17:33:19 -04001180func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 var intfID uint32
1182 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001183 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001184 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001185 intfID = onuDevice.ProxyAddress.GetChannelId()
1186 onuID = onuDevice.ProxyAddress.GetOnuId()
1187 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001188 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 intfID = omciMsg.GetProxyAddress().GetChannelId()
1190 onuID = omciMsg.GetProxyAddress().GetOnuId()
1191 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001192 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001194 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 -08001195
Thomas Lee S94109f12020-03-03 16:39:29 +05301196 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001197 "intf-id": intfID,
1198 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001199 }
1200
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001201 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1202 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001203 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001204 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1205 hex.Encode(hexPkt, omciMsg.Message)
1206 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1207
1208 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1209 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1210 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001212 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001213
Neha Sharma8f4e4322020-08-06 10:51:53 +00001214 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301216 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001217 "intf-id": intfID,
1218 "onu-id": onuID,
1219 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001222}
1223
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301225 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 -07001226 if err := dh.flowMgr[intfID].AddOnuInfoToFlowMgrCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001227 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001228 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001229 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301230 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301231 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001232 st, _ := status.FromError(err)
1233 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001234 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1235
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001236 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301237 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001238 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001239 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001241 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001243}
1244
Mahir Gunyelb0046752021-02-26 13:51:05 -08001245func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001247 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001248
Mahir Gunyelb0046752021-02-26 13:51:05 -08001249 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001250 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301251
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301252 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001253 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001254 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301255
1256 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1257 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1258 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1259 OnuLosRaise event sent for it */
1260 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1261 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1262 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301264 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1265 "currentIntfId": onuDiscInd.GetIntfId()})
1266 // TODO:: Should we need to ignore raising OnuLosClear event
1267 // when onu connected to different PON?
1268 }
1269 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1270 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1271 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001272 go func() {
1273 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001274 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001275 }
1276 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301277 }
1278 return true
1279 })
1280
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001283 }
1284
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001285 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001286
1287 // check the ONU is already know to the OLT
1288 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001289 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001290 ParentId: dh.device.Id,
1291 SerialNumber: sn,
1292 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001293
1294 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001295 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 -08001296 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001297 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 -08001298 switch e.Code() {
1299 case codes.Internal:
1300 // this probably means NOT FOUND, so just create a new device
1301 onuDevice = nil
1302 case codes.DeadlineExceeded:
1303 // if the call times out, cleanup and exit
1304 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001305 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001306 }
1307 }
1308 }
1309
1310 if onuDevice == nil {
1311 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001312 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001313 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001314 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001315 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001316
Neha Sharma96b7bf22020-06-15 10:37:32 +00001317 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001318
1319 if err != nil {
1320 // if we can't create an ID in resource manager,
1321 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001322 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001324 "pon-intf-id": ponintfid,
1325 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001326 }
1327
khenaidoodc2116e2021-10-19 17:33:19 -04001328 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001329 ParentId: dh.device.Id,
1330 ParentPortNo: parentPortNo,
1331 ChannelId: channelID,
1332 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1333 SerialNumber: sn,
1334 OnuId: onuID,
1335 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001336 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001337 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 +05301338 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001339 "pon-intf-id": ponintfid,
1340 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001341 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001342 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 -07001343 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001344 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001345 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301346 log.Fields{"onuDevice": onuDevice,
1347 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001348 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301349 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001350 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001351
khenaidoo106c61a2021-08-11 18:05:46 -04001352 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1353 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1354 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1355 cancel()
1356 if err != nil {
1357 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1358 }
1359
Matteo Scandolo945e4012019-12-12 14:16:11 -08001360 // we can now use the existing ONU Id
1361 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001362 //Insert the ONU into cache to use in OnuIndication.
1363 //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 +00001364 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001365 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301366 "intfId": onuDiscInd.GetIntfId(),
1367 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001368 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001369
khenaidoo106c61a2021-08-11 18:05:46 -04001370 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301371 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001372 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301373 log.Fields{"onu": onuDev,
1374 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001375
khenaidoodc2116e2021-10-19 17:33:19 -04001376 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001377 DeviceId: onuDevice.Id,
1378 ParentDeviceId: dh.device.Id,
1379 OperStatus: common.OperStatus_DISCOVERED,
1380 ConnStatus: common.ConnectStatus_REACHABLE,
1381 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301382 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001384 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001385 }
khenaidoo106c61a2021-08-11 18:05:46 -04001386
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001388 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001391 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 }
1393 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001394}
1395
Mahir Gunyelb0046752021-02-26 13:51:05 -08001396func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001397
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001398 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001399 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001401 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001402 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301403 log.Fields{"onuId": onuInd.OnuId,
1404 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301405 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001406 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001407 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301408
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 errFields := log.Fields{"device-id": dh.device.Id}
1410
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301411 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1412
Mahir Gunyele77977b2019-06-27 05:36:22 -07001413 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1414 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001415 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001416 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001417 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001418 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1419 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001421 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001422 errFields["onu-id"] = onuInd.OnuId
1423 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001424 }
khenaidoodc2116e2021-10-19 17:33:19 -04001425 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001426 ParentId: dh.device.Id,
1427 SerialNumber: serialNumber,
1428 OnuId: onuInd.OnuId,
1429 ParentPortNo: ponPort,
1430 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001431 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001432
David K. Bainbridge794735f2020-02-11 21:01:37 -08001433 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001434 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001435 }
1436
David K. Bainbridge794735f2020-02-11 21:01:37 -08001437 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001438 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001439 "previousIntfId": onuDevice.ParentPortNo,
1440 "currentIntfId": ponPort})
1441 }
1442
1443 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001444 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301445 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1446 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301447 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001448 }
1449 if !foundInCache {
1450 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1451
khenaidoo106c61a2021-08-11 18:05:46 -04001452 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 -08001453
1454 }
kesavand7cf3a052020-08-28 12:49:18 +05301455 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001456 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001457 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301458 }
1459 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001461 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001462 }
1463 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001464}
1465
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001467 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 -07001468 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1469 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1470 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1471 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001472 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001473 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1474 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001475 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001476 onuInd.OperState = "down"
1477 }
1478 }
1479
David K. Bainbridge794735f2020-02-11 21:01:37 -08001480 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001481 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001482 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 -04001483
khenaidoodc2116e2021-10-19 17:33:19 -04001484 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001485 DeviceId: onuDevice.Id,
1486 OnuIndication: onuInd,
1487 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001488 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301489 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001490 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001491 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001492 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001493 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001494 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001495 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001496 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001498 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499}
1500
cuilin20187b2a8c32019-03-26 19:52:28 -07001501func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1502 if serialNum != nil {
1503 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001504 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001506}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001507func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1508 decodedStr, err := hex.DecodeString(serialNum[4:])
1509 if err != nil {
1510 return nil, err
1511 }
1512 return &oop.SerialNumber{
1513 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001514 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001515 }, nil
1516}
cuilin20187b2a8c32019-03-26 19:52:28 -07001517
1518func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001519 if len(vendorSpecific) > 3 {
1520 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1521 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1522 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1523 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1524 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1525 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1526 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1527 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1528 return tmp
1529 }
1530 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001531}
1532
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533//UpdateFlowsBulk upates the bulk flow
1534func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301535 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001536}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537
1538//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1540 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301541 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001542 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301543 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001544
khenaidoodc2116e2021-10-19 17:33:19 -04001545 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001546 ParentId: dh.device.Id,
1547 OnuId: onuID,
1548 ParentPortNo: parentPort,
1549 })
1550
Girish Gowdru0c588b22019-04-23 23:24:56 -04001551 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001552 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001553 "intf-id": parentPort,
1554 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001555 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556 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 -08001557 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301558}
1559
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560// SendPacketInToCore sends packet-in to core
1561// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1562// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001563func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001564 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001565 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001566 "port": logicalPort,
1567 "packet": hex.EncodeToString(packetPayload),
1568 "device-id": dh.device.Id,
1569 })
1570 }
khenaidoo106c61a2021-08-11 18:05:46 -04001571
khenaidoodc2116e2021-10-19 17:33:19 -04001572 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001573 DeviceId: dh.device.Id,
1574 Port: logicalPort,
1575 Packet: packetPayload,
1576 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301577 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 "source": "adapter",
1579 "destination": "core",
1580 "device-id": dh.device.Id,
1581 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001582 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001583 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001584 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001586 "packet": hex.EncodeToString(packetPayload),
1587 "device-id": dh.device.Id,
1588 })
1589 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001590 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001591}
1592
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001593// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001596
1597 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1598 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001599 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001600 }
1601
Kent Hagermane6ff1012020-07-14 15:07:53 -04001602 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001603 metrics := dh.metrics.GetSubscriberMetrics()
1604 for _, m := range pmConfigs.Metrics {
1605 metrics[m.Name].Enabled = m.Enabled
1606
1607 }
1608 }
1609}
1610
khenaidoodc2116e2021-10-19 17:33:19 -04001611func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001612 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001613 var errorsList []error
1614
Girish Gowdru0c588b22019-04-23 23:24:56 -04001615 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001616 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001617 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001618
Neha Sharma96b7bf22020-06-15 10:37:32 +00001619 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301620 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001621 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301622 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001623 if flow_utils.HasGroup(flow) {
1624 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1625 } else {
1626 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1627 }
Girish Gowdracefae192020-03-19 18:14:10 -07001628 if err != nil {
1629 errorsList = append(errorsList, err)
1630 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001631 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301632
1633 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001634 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001635 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301636 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001637 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301638 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001639 if flow_utils.HasGroup(flow) {
1640 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1641 } else {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001642 if dh.flowMgr == nil || dh.flowMgr[ponIf] == nil {
1643 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1644 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1645 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1646 } else {
1647 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1648 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001649 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001650 if err != nil {
1651 errorsList = append(errorsList, err)
1652 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301653 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001654 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001655
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001656 return errorsList
1657}
1658
1659func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1660 var err error
1661 var errorsList []error
1662
Girish Gowdracefae192020-03-19 18:14:10 -07001663 // 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 +00001664 if groups != nil {
1665 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001666 // err = dh.groupMgr.AddGroup(ctx, group)
1667 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001668 if err != nil {
1669 errorsList = append(errorsList, err)
1670 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001671 }
1672 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001673 // err = dh.groupMgr.ModifyGroup(ctx, group)
1674 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001675 if err != nil {
1676 errorsList = append(errorsList, err)
1677 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001678 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001679 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001680 // err = dh.groupMgr.DeleteGroup(ctx, group)
1681 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001682 if err != nil {
1683 errorsList = append(errorsList, err)
1684 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001685 }
1686 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001687
1688 return errorsList
1689}
1690
1691//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001692func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *of.FlowMetadata) error {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001693
1694 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001695
1696 if dh.getDeviceDeletionInProgressFlag() {
1697 // The device itself is going to be reset as part of deletion. So nothing to be done.
1698 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1699 return nil
1700 }
1701
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001702 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1703 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1704 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001705 if len(errorsList) > 0 {
1706 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1707 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001708 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001709 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301710}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001711
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001712//DisableDevice disables the given device
1713//It marks the following for the given device:
1714//Device-Handler Admin-State : down
1715//Device Port-State: UNKNOWN
1716//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001717func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001718 /* On device disable ,admin state update has to be done prior sending request to agent since
1719 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001720 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001721 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001722 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001723 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001724 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001725 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001726 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001727 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001728 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001729 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301730
1731 dh.discOnus = sync.Map{}
1732 dh.onus = sync.Map{}
1733
Thomas Lee S85f37312020-04-03 17:06:12 +05301734 //stopping the stats collector
1735 dh.stopCollector <- true
1736
Neha Sharma96b7bf22020-06-15 10:37:32 +00001737 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001738 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301739 //Update device Admin state
1740 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001741
kdarapu1afeceb2020-02-12 01:38:09 -05001742 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
khenaidoodc2116e2021-10-19 17:33:19 -04001743 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001744 DeviceId: cloned.Id,
1745 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1746 OperStatus: voltha.OperStatus_UNKNOWN,
1747 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001748 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001749 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001750 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001751 return nil
1752}
1753
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001755 // Update onu state as unreachable in onu adapter
1756 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301757 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001758
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001759 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001760 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001761 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001762 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 -04001763 }
1764 if onuDevices != nil {
1765 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001766 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001767 DeviceId: onuDevice.Id,
1768 OnuIndication: &onuInd,
1769 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001770 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001771 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001772 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001773 }
1774
1775 }
1776 }
1777
1778}
1779
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001780//ReenableDevice re-enables the olt device after disable
1781//It marks the following for the given device:
1782//Device-Handler Admin-State : up
1783//Device Port-State: ACTIVE
1784//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001786 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301787 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001788 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301789 }
1790 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001792
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001793 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001794 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001795 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001796 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001797 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1798 } else {
1799 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1800 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1801 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001802 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001803 if retError == nil {
1804 //Update the device oper status as ACTIVE
1805 device.OperStatus = voltha.OperStatus_ACTIVE
1806 } else {
1807 //Update the device oper status as FAILED
1808 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001809 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001810 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001811
khenaidoodc2116e2021-10-19 17:33:19 -04001812 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001813 DeviceId: device.Id,
1814 OperStatus: device.OperStatus,
1815 ConnStatus: device.ConnectStatus,
1816 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301817 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001818 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001819 "connect-status": device.ConnectStatus,
1820 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001821 }
kesavand39e0aa32020-01-28 20:58:50 -05001822
Neha Sharma96b7bf22020-06-15 10:37:32 +00001823 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001824
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001825 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001826}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001827
npujarec5762e2020-01-01 14:08:48 +05301828func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001829 var uniID uint32
1830 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301831 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001832 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001833 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001834 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001835 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001836 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001837 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001839 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001840 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001841 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001842 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001843 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001845 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001846 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001847 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001848 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301849 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001850 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1851 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301853 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001854 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001855 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 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 +00001857 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001858 }
1859 return nil
1860}
1861
Devmalya Paul495b94a2019-08-27 19:42:00 -04001862// 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 +05301863func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001864 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001865 /* Clear the KV store data associated with the all the UNI ports
1866 This clears up flow data and also resource map data for various
1867 other pon resources like alloc_id and gemport_id
1868 */
Girish Gowdra950326e2021-11-05 12:43:24 -07001869
1870 dh.setDeviceDeletionInProgressFlag(true)
1871
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001872 dh.cleanupDeviceResources(ctx)
1873 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 -04001874 // Stop the Stats collector
1875 dh.stopCollector <- true
1876 // stop the heartbeat check routine
1877 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301878 dh.lockDevice.RLock()
1879 // Stop the read indication only if it the routine is active
1880 if dh.isReadIndicationRoutineActive {
1881 dh.stopIndications <- true
1882 }
1883 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001884 dh.removeOnuIndicationChannels(ctx)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001885 go dh.StopAllMcastHandlerRoutines(ctx)
1886 for _, flMgr := range dh.flowMgr {
1887 go flMgr.StopAllFlowHandlerRoutines(ctx)
1888 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001889 //Reset the state
1890 if dh.Client != nil {
1891 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301892 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001893 }
1894 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001895 // There is no need to update the core about operation status and connection status of the OLT.
1896 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1897 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1898 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001899
khenaidoo7eb2d672021-10-22 19:08:50 -04001900 // Stop the adapter grpc clients for that parent device
1901 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001902 return nil
1903}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001904func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001905
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001906 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301907 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001908 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001909 var err error
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001910 onuGemData := dh.flowMgr[ponPort].getOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001911 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001912 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001913 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001914 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301915 }
1916 }
Girish Gowdra950326e2021-11-05 12:43:24 -07001917 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
1918 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001919 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
1920 logger.Debug(ctx, err)
1921 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001922 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001923 }
A R Karthick1f85b802019-10-11 05:06:05 +00001924
Devmalya Paul495b94a2019-08-27 19:42:00 -04001925 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301926 dh.onus.Range(func(key interface{}, value interface{}) bool {
1927 dh.onus.Delete(key)
1928 return true
1929 })
1930
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001931 /*Delete discovered ONU map for the device*/
1932 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1933 dh.discOnus.Delete(key)
1934 return true
1935 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001936}
1937
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001938//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001939func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001940 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301941 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001942 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001943 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001944 return nil
1945}
1946
David K. Bainbridge794735f2020-02-11 21:01:37 -08001947func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001948 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001949 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001950 "packet-indication": *packetIn,
1951 "device-id": dh.device.Id,
1952 "packet": hex.EncodeToString(packetIn.Pkt),
1953 })
1954 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001955 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001956 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001957 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001958 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001959 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001961 "logical-port-num": logicalPortNum,
1962 "device-id": dh.device.Id,
1963 "packet": hex.EncodeToString(packetIn.Pkt),
1964 })
1965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001966
khenaidoodc2116e2021-10-19 17:33:19 -04001967 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001968 DeviceId: dh.device.Id,
1969 Port: logicalPortNum,
1970 Packet: packetIn.Pkt,
1971 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301972 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001973 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301974 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001975 "device-id": dh.device.Id,
1976 "packet": hex.EncodeToString(packetIn.Pkt),
1977 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001978 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979
Matteo Scandolo92186242020-06-12 10:54:18 -07001980 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001982 "packet": hex.EncodeToString(packetIn.Pkt),
1983 "device-id": dh.device.Id,
1984 })
1985 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001986 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001987}
1988
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001989// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04001990func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001991 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001993 "device-id": dh.device.Id,
1994 "egress-port-no": egressPortNo,
1995 "pkt-length": len(packet.Data),
1996 "packet": hex.EncodeToString(packet.Data),
1997 })
1998 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001999
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002000 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002001 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002002 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2003 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302004 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2005 // Do not packet-out lldp packets on uni port.
2006 // ONOS has no clue about uni/nni ports, it just packets out on all
2007 // available ports on the Logical Switch. It should not be interested
2008 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002009 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002010 "device-id": dh.device.Id,
2011 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302012 return nil
2013 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002014 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2015 if innerEthType == 0x8100 {
2016 // q-in-q 802.1ad or 802.1q double tagged packet.
2017 // slice out the outer tag.
2018 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002019 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002020 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002021 "packet-data": hex.EncodeToString(packet.Data),
2022 "device-id": dh.device.Id,
2023 })
2024 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002025 }
2026 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002027 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2028 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2029 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002030
Girish Gowdra9602eb42020-09-09 15:50:39 -07002031 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002032 if err != nil {
2033 // In this case the openolt agent will receive the gemPortID as 0.
2034 // The agent tries to retrieve the gemPortID in this case.
2035 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002036 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002037 "intf-id": intfID,
2038 "onu-id": onuID,
2039 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002040 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302041 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002042 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002043 }
2044
2045 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002046 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002047 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002048 "egress-port-no": egressPortNo,
2049 "intf-id": intfID,
2050 "onu-id": onuID,
2051 "uni-id": uniID,
2052 "gem-port-id": gemPortID,
2053 "packet": hex.EncodeToString(packet.Data),
2054 "device-id": dh.device.Id,
2055 })
2056 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002057
npujarec5762e2020-01-01 14:08:48 +05302058 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302059 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002060 "source": "adapter",
2061 "destination": "onu",
2062 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002063 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002064 "oni-id": onuID,
2065 "uni-id": uniID,
2066 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002067 "packet": hex.EncodeToString(packet.Data),
2068 "device-id": dh.device.Id,
2069 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002070 }
2071 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002072 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002073 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002074 return olterrors.NewErrInvalidValue(log.Fields{
2075 "egress-nni-port": egressPortNo,
2076 "device-id": dh.device.Id,
2077 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002078 }
2079 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002080
Matteo Scandolo92186242020-06-12 10:54:18 -07002081 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002082 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002083 "uplink-pkt": uplinkPkt,
2084 "packet": hex.EncodeToString(packet.Data),
2085 "device-id": dh.device.Id,
2086 })
2087 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002088
npujarec5762e2020-01-01 14:08:48 +05302089 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002090 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2091 "packet": hex.EncodeToString(packet.Data),
2092 "device-id": dh.device.Id,
2093 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002094 }
2095 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002096 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302097 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002098 "egressPortType": egressPortType,
2099 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302100 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002101 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002102 }
2103 return nil
2104}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002105
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002106func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2107 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002108}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302109
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002110func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002111
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302112 // start the heartbeat check towards the OLT.
2113 var timerCheck *time.Timer
2114
2115 for {
2116 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2117 select {
2118 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002119 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002120 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002121 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302122 if timerCheck == nil {
2123 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002124 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302125 }
2126 } else {
2127 if timerCheck != nil {
2128 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002129 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302130 }
2131 timerCheck = nil
2132 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002133 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302134 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302135 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302136 }
2137 cancel()
2138 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002139 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302140 return
2141 }
2142 }
2143}
2144
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002145func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002146 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002147 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002148 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2149 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2150 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2151 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2152 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002153 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002154 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2155 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002156 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302157
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002158 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2159 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002160 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002161 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002162 DeviceId: dh.device.Id,
2163 OperStatus: voltha.OperStatus_UNKNOWN,
2164 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2165 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002166 _ = 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 -04002167 }
khenaidoo106c61a2021-08-11 18:05:46 -04002168
khenaidoodc2116e2021-10-19 17:33:19 -04002169 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002170 DeviceId: dh.device.Id,
2171 PortTypeFilter: 0,
2172 OperStatus: voltha.OperStatus_UNKNOWN,
2173 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002174 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002175 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002176
2177 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002178 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002179 cloned := proto.Clone(device).(*voltha.Device)
2180 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2181 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2182 dh.device = cloned // update local copy of the device
2183 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002184
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002185 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002186 // Stop the Stats collector
2187 dh.stopCollector <- true
2188 // stop the heartbeat check routine
2189 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002190
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002191 dh.lockDevice.RLock()
2192 // Stop the read indication only if it the routine is active
2193 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2194 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2195 // on next execution of the readIndication routine.
2196 if dh.isReadIndicationRoutineActive {
2197 dh.stopIndications <- true
2198 }
2199 dh.lockDevice.RUnlock()
2200
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002201 go dh.StopAllMcastHandlerRoutines(ctx)
2202 for _, flMgr := range dh.flowMgr {
2203 go flMgr.StopAllFlowHandlerRoutines(ctx)
2204 }
2205
Gamze Abakac2c32a62021-03-11 11:44:18 +00002206 //reset adapter reconcile flag
2207 dh.adapterPreviouslyConnected = false
2208
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002209 dh.transitionMap.Handle(ctx, DeviceInit)
2210
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302211 }
2212}
kesavand39e0aa32020-01-28 20:58:50 -05002213
2214// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002215func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2216 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2217 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002218}
2219
2220// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2222 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2223 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002224}
2225
kdarapu1afeceb2020-02-12 01:38:09 -05002226//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 +00002227func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2228 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002229 if port.GetType() == voltha.Port_ETHERNET_NNI {
2230 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302232 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302233 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002234 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002235 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002236 }
2237 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002238 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002239 ponIntf := &oop.Interface{IntfId: ponID}
2240 var operStatus voltha.OperStatus_Types
2241 if enablePort {
2242 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302243 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002244
2245 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302246 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002247 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002248 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002249 }
2250 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002251 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002253 } else {
2254 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302255 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002256 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302257 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002258 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002259 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002260 }
2261 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002262 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002264 }
khenaidoodc2116e2021-10-19 17:33:19 -04002265 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002266 DeviceId: dh.device.Id,
2267 PortType: voltha.Port_PON_OLT,
2268 PortNo: port.PortNo,
2269 OperStatus: operStatus,
2270 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302271 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302272 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002273 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002274 }
2275 return nil
2276}
2277
kdarapu1afeceb2020-02-12 01:38:09 -05002278//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002279func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002280 // Disable the port and update the oper_port_status to core
2281 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002282 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002283 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302285 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302286 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002287 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002288 }
2289 }
2290 }
2291 return nil
2292}
2293
2294//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002295func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2296 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2297 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002298 if port.Type == voltha.Port_ETHERNET_NNI {
2299 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002300 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002301 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002302 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002303 }
2304 }
2305 if port.Type == voltha.Port_PON_OLT {
2306 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002307 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002308 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002309 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002310 }
2311 }
2312 }
2313}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002314
2315// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002316func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002317 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002318 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002319 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002320
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002321 var sn *oop.SerialNumber
2322 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002323 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302324 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002325 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302326 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002327 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002328 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002329
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002330 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002331 //clear PON resources associated with ONU
2332 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2333 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2334 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2335 "device-id": dh.device.Id,
2336 "intf-id": intfID,
2337 "onuID": onuID,
2338 "err": err})
2339 } else {
2340 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2341 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2342 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2343 "device-id": dh.device.Id,
2344 "onu-device": onu,
2345 "err": err})
2346 }
2347 // Clear flowids for gem cache.
2348 for _, gem := range onuGem.GemPorts {
2349 dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
2350 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002351 if err := dh.flowMgr[intfID].RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002352 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2353 "intf-id": intfID,
2354 "onu-device": onu,
2355 "onu-gem": onuGem,
2356 "err": err})
2357 //Not returning error on cleanup.
2358 }
2359 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302360
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002361 }
Himani Chawlabcc95852021-10-27 10:55:40 +05302362 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002363 dh.onus.Delete(onuKey)
2364 dh.discOnus.Delete(onuSn)
2365
2366 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002367 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302368 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302369 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002370 "onu-id": onuID}, err).Log()
2371 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002372
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002373 return nil
2374}
Girish Gowdracefae192020-03-19 18:14:10 -07002375
2376func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002377 for _, field := range flow_utils.GetOfbFields(flow) {
2378 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002379 return field.GetPort()
2380 }
2381 }
2382 return InvalidPort
2383}
2384
2385func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002386 for _, action := range flow_utils.GetActions(flow) {
2387 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002388 if out := action.GetOutput(); out != nil {
2389 return out.GetPort()
2390 }
2391 }
2392 }
2393 return InvalidPort
2394}
2395
Girish Gowdracefae192020-03-19 18:14:10 -07002396func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2397 inPort := getInPortFromFlow(flow)
2398 outPort := getOutPortFromFlow(flow)
2399
2400 if inPort == InvalidPort || outPort == InvalidPort {
2401 return inPort, outPort
2402 }
2403
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002404 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002405 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002406 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002407 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002408 return uniPort, outPort
2409 }
2410 }
2411 } else {
2412 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002413 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002414 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002415 return inPort, uniPort
2416 }
2417 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002418 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002419 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002420 return uniPort, outPort
2421 }
2422 }
2423 }
2424
2425 return InvalidPort, InvalidPort
2426}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002427
2428func extractOmciTransactionID(omciPkt []byte) uint16 {
2429 if len(omciPkt) > 3 {
2430 d := omciPkt[0:2]
2431 transid := binary.BigEndian.Uint16(d)
2432 return transid
2433 }
2434 return 0
2435}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002436
2437// StoreOnuDevice stores the onu parameters to the local cache.
2438func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2439 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2440 dh.onus.Store(onuKey, onuDevice)
2441}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002442
khenaidoodc2116e2021-10-19 17:33:19 -04002443func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002444 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002445 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002446 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002447 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002448 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002449 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002450 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002451 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2452 return nil, err
2453 }
2454 ID = device.ProxyAddress.GetOnuId()
2455 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2456 valueparam.Onu = &Onu
2457 valueparam.Value = value
2458
2459 // This API is unsupported until agent patch is added
2460 resp.Unsupported = uint32(value)
2461 _ = ctx
2462
2463 // Uncomment this code once agent changes are complete and tests
2464 /*
2465 resp, err = dh.Client.GetValue(ctx, valueparam)
2466 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002467 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002468 return nil, err
2469 }
2470 */
2471
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002472 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 -08002473 return resp, nil
2474}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002475
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002476func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002477 // Default to PON0
2478 var intfID uint32
2479 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002480 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002481 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002482 }
2483 return intfID
2484}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002485
Mahir Gunyelb0046752021-02-26 13:51:05 -08002486func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2487 dh.perPonOnuIndicationChannelLock.Lock()
2488 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2489 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002490 return ch.indicationChannel
2491 }
2492 channels := onuIndicationChannels{
2493 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002494 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002495 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002496 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002497 stopChannel: make(chan struct{}),
2498 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002499 dh.perPonOnuIndicationChannel[intfID] = channels
2500 dh.perPonOnuIndicationChannelLock.Unlock()
2501 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002502 return channels.indicationChannel
2503
2504}
2505
Mahir Gunyelb0046752021-02-26 13:51:05 -08002506func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2507 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2508 dh.perPonOnuIndicationChannelLock.Lock()
2509 defer dh.perPonOnuIndicationChannelLock.Unlock()
2510 for _, v := range dh.perPonOnuIndicationChannel {
2511 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002512 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002513 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002514}
2515
Mahir Gunyelb0046752021-02-26 13:51:05 -08002516func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2517 ind := onuIndicationMsg{
2518 ctx: ctx,
2519 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002520 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002521 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002522 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002523 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002524}
2525
Mahir Gunyelb0046752021-02-26 13:51:05 -08002526func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002527 for {
2528 select {
2529 // process one indication per onu, before proceeding to the next one
2530 case onuInd := <-onuChannels.indicationChannel:
2531 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Mahir Gunyelb0046752021-02-26 13:51:05 -08002532 "ind": onuInd.indication})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002533 switch onuInd.indication.Data.(type) {
2534 case *oop.Indication_OnuInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002535 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002536 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2537 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002538 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002539 }
2540 case *oop.Indication_OnuDiscInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002541 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002542 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2543 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002544 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002545 }
2546 }
2547 case <-onuChannels.stopChannel:
2548 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2549 close(onuChannels.indicationChannel)
2550 return
2551 }
2552 }
2553}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002554
2555// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2556// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002557func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002558 // Step1 : Fill McastFlowOrGroupControlBlock
2559 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2560 // Step3 : Wait on response channel for response
2561 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002562 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002563 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2564 errChan := make(chan error)
2565 var groupID uint32
2566 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2567 ctx: ctx,
2568 flowOrGroupAction: action,
2569 flow: flow,
2570 group: group,
2571 errChan: &errChan,
2572 }
2573 if flow != nil {
2574 groupID = flow_utils.GetGroup(flow)
2575 } else if group != nil {
2576 groupID = group.Desc.GroupId
2577 } else {
2578 return errors.New("flow-and-group-both-nil")
2579 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002580 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2581 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2582 // Derive the appropriate go routine to handle the request by a simple module operation.
2583 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2584 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2585 // Wait for handler to return error value
2586 err := <-errChan
2587 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2588 return err
2589 }
2590 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2591 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002592}
2593
2594// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002595func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002596 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002597 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002598 // block on the channel to receive an incoming mcast flow/group
2599 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002600 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2601 if mcastFlowOrGroupCb.flow != nil {
2602 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2603 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2604 log.Fields{"device-id": dh.device.Id,
2605 "flowToAdd": mcastFlowOrGroupCb.flow})
2606 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2607 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2608 // Pass the return value over the return channel
2609 *mcastFlowOrGroupCb.errChan <- err
2610 } else { // flow remove
2611 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2612 log.Fields{"device-id": dh.device.Id,
2613 "flowToRemove": mcastFlowOrGroupCb.flow})
2614 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2615 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2616 // Pass the return value over the return channel
2617 *mcastFlowOrGroupCb.errChan <- err
2618 }
2619 } else { // mcast group
2620 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2621 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2622 log.Fields{"device-id": dh.device.Id,
2623 "groupToAdd": mcastFlowOrGroupCb.group})
2624 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2625 // Pass the return value over the return channel
2626 *mcastFlowOrGroupCb.errChan <- err
2627 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2628 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2629 log.Fields{"device-id": dh.device.Id,
2630 "groupToModify": mcastFlowOrGroupCb.group})
2631 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2632 // Pass the return value over the return channel
2633 *mcastFlowOrGroupCb.errChan <- err
2634 } else { // group remove
2635 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2636 log.Fields{"device-id": dh.device.Id,
2637 "groupToRemove": mcastFlowOrGroupCb.group})
2638 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2639 // Pass the return value over the return channel
2640 *mcastFlowOrGroupCb.errChan <- err
2641 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002642 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002643 case <-stopHandler:
2644 dh.mcastHandlerRoutineActive[routineIndex] = false
2645 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002646 }
2647 }
2648}
kesavand62126212021-01-12 04:56:06 -05002649
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002650// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2651func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context) {
2652 for i, v := range dh.stopMcastHandlerRoutine {
2653 if dh.mcastHandlerRoutineActive[i] {
2654 v <- true
2655 }
2656 }
2657 logger.Debug(ctx, "stopped all mcast handler routines")
2658}
2659
kesavand62126212021-01-12 04:56:06 -05002660func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2661
2662 singleValResp := extension.SingleGetValueResponse{
2663 Response: &extension.GetValueResponse{
2664 Response: &extension.GetValueResponse_PortCoutners{
2665 PortCoutners: &extension.GetOltPortCountersResponse{},
2666 },
2667 },
2668 }
2669
2670 errResp := func(status extension.GetValueResponse_Status,
2671 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2672 return &extension.SingleGetValueResponse{
2673 Response: &extension.GetValueResponse{
2674 Status: status,
2675 ErrReason: reason,
2676 },
2677 }
2678 }
2679
2680 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2681 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2682 //send error response
2683 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2684 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2685 }
2686 statIndChn := make(chan bool, 1)
2687 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2688 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2689 //request openOlt agent to send the the port statistics indication
2690
2691 go func() {
2692 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2693 if err != nil {
2694 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2695 }
2696 }()
2697 select {
2698 case <-statIndChn:
2699 //indication received for ports stats
2700 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2701 case <-time.After(oltPortInfoTimeout * time.Second):
2702 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2703 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2704 case <-ctx.Done():
2705 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2706 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2707 }
2708 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2709 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002710 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002711 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2712 cmnni := dh.portStats.collectNNIMetrics(intfID)
2713 if cmnni == nil {
2714 //TODO define the error reason
2715 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2716 }
2717 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2718 return &singleValResp
2719
2720 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2721 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002722 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002723 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2724 cmpon := dh.portStats.collectPONMetrics(intfID)
2725 if cmpon == nil {
2726 //TODO define the error reason
2727 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2728 }
2729 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2730 return &singleValResp
2731 }
2732 }
2733 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2734}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302735
2736func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2737
2738 singleValResp := extension.SingleGetValueResponse{
2739 Response: &extension.GetValueResponse{
2740 Response: &extension.GetValueResponse_OnuPonCounters{
2741 OnuPonCounters: &extension.GetOnuCountersResponse{},
2742 },
2743 },
2744 }
2745
2746 errResp := func(status extension.GetValueResponse_Status,
2747 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2748 return &extension.SingleGetValueResponse{
2749 Response: &extension.GetValueResponse{
2750 Status: status,
2751 ErrReason: reason,
2752 },
2753 }
2754 }
2755 intfID := onuPonInfo.IntfId
2756 onuID := onuPonInfo.OnuId
2757 onuKey := dh.formOnuKey(intfID, onuID)
2758
2759 if _, ok := dh.onus.Load(onuKey); !ok {
2760 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2761 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2762 }
2763 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2764 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2765 if cmnni == nil {
2766 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2767 }
2768 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2769 return &singleValResp
2770
2771}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002772
2773func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2774
2775 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2776 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2777 if err != nil {
2778 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2779 return generateSingleGetValueErrorResponse(err)
2780 }
2781 return &extension.SingleGetValueResponse{
2782 Response: &extension.GetValueResponse{
2783 Status: extension.GetValueResponse_OK,
2784 Response: &extension.GetValueResponse_RxPower{
2785 RxPower: &extension.GetRxPowerResponse{
2786 IntfId: rxPowerRequest.IntfId,
2787 OnuId: rxPowerRequest.OnuId,
2788 Status: rxPower.Status,
2789 FailReason: rxPower.FailReason.String(),
2790 RxPower: rxPower.RxPowerMeanDbm,
2791 },
2792 },
2793 },
2794 }
2795}
2796
2797func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2798 errResp := func(status extension.GetValueResponse_Status,
2799 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2800 return &extension.SingleGetValueResponse{
2801 Response: &extension.GetValueResponse{
2802 Status: status,
2803 ErrReason: reason,
2804 },
2805 }
2806 }
2807
2808 if err != nil {
2809 if e, ok := status.FromError(err); ok {
2810 switch e.Code() {
2811 case codes.Internal:
2812 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2813 case codes.DeadlineExceeded:
2814 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2815 case codes.Unimplemented:
2816 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2817 case codes.NotFound:
2818 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2819 }
2820 }
2821 }
2822
2823 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2824}
khenaidoo106c61a2021-08-11 18:05:46 -04002825
2826/*
2827Helper functions to communicate with Core
2828*/
2829
2830func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2831 cClient, err := dh.coreClient.GetCoreServiceClient()
2832 if err != nil || cClient == nil {
2833 return nil, err
2834 }
2835 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2836 defer cancel()
2837 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
2838}
2839
khenaidoodc2116e2021-10-19 17:33:19 -04002840func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002841 cClient, err := dh.coreClient.GetCoreServiceClient()
2842 if err != nil || cClient == nil {
2843 return nil, err
2844 }
2845 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2846 defer cancel()
2847 return cClient.GetChildDevice(subCtx, childDeviceFilter)
2848}
2849
khenaidoodc2116e2021-10-19 17:33:19 -04002850func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002851 cClient, err := dh.coreClient.GetCoreServiceClient()
2852 if err != nil || cClient == nil {
2853 return err
2854 }
2855 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2856 defer cancel()
2857 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
2858 return err
2859}
2860
2861func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
2862 cClient, err := dh.coreClient.GetCoreServiceClient()
2863 if err != nil || cClient == nil {
2864 return nil, err
2865 }
2866 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2867 defer cancel()
2868 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
2869}
2870
2871func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
2872 cClient, err := dh.coreClient.GetCoreServiceClient()
2873 if err != nil || cClient == nil {
2874 return nil, err
2875 }
2876 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2877 defer cancel()
2878 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
2879}
2880
2881func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
2882 cClient, err := dh.coreClient.GetCoreServiceClient()
2883 if err != nil || cClient == nil {
2884 return err
2885 }
2886 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2887 defer cancel()
2888 _, err = cClient.DeviceUpdate(subCtx, device)
2889 return err
2890}
2891
khenaidoodc2116e2021-10-19 17:33:19 -04002892func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002893 cClient, err := dh.coreClient.GetCoreServiceClient()
2894 if err != nil || cClient == nil {
2895 return nil, err
2896 }
2897 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2898 defer cancel()
2899 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
2900}
2901
khenaidoodc2116e2021-10-19 17:33:19 -04002902func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002903 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.SendPacketIn(subCtx, pkt)
2910 return err
2911}
2912
2913func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
2914 cClient, err := dh.coreClient.GetCoreServiceClient()
2915 if err != nil || cClient == nil {
2916 return err
2917 }
2918 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2919 defer cancel()
2920 _, err = cClient.PortCreated(subCtx, port)
2921 return err
2922}
2923
khenaidoodc2116e2021-10-19 17:33:19 -04002924func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002925 cClient, err := dh.coreClient.GetCoreServiceClient()
2926 if err != nil || cClient == nil {
2927 return err
2928 }
2929 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2930 defer cancel()
2931 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
2932 return err
2933}
2934
khenaidoodc2116e2021-10-19 17:33:19 -04002935func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002936 cClient, err := dh.coreClient.GetCoreServiceClient()
2937 if err != nil || cClient == nil {
2938 return err
2939 }
2940 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2941 defer cancel()
2942 _, err = cClient.PortStateUpdate(subCtx, portState)
2943 return err
2944}
2945
khenaidoodc2116e2021-10-19 17:33:19 -04002946func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002947 cClient, err := dh.coreClient.GetCoreServiceClient()
2948 if err != nil || cClient == nil {
2949 return nil, err
2950 }
2951 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2952 defer cancel()
2953 return cClient.GetDevicePort(subCtx, portFilter)
2954}
2955
2956/*
2957Helper functions to communicate with child adapter
2958*/
2959
khenaidoodc2116e2021-10-19 17:33:19 -04002960func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002961 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2962 if err != nil || aClient == nil {
2963 return err
2964 }
2965 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
2966 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2967 defer cancel()
2968 _, err = aClient.OmciIndication(subCtx, response)
2969 return err
2970}
2971
khenaidoodc2116e2021-10-19 17:33:19 -04002972func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002973 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2974 if err != nil || aClient == nil {
2975 return err
2976 }
2977 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
2978 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2979 defer cancel()
2980 _, err = aClient.OnuIndication(subCtx, onuInd)
2981 return err
2982}
2983
khenaidoodc2116e2021-10-19 17:33:19 -04002984func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002985 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2986 if err != nil || aClient == nil {
2987 return err
2988 }
2989 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
2990 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2991 defer cancel()
2992 _, err = aClient.DeleteTCont(subCtx, tContInfo)
2993 return err
2994}
2995
khenaidoodc2116e2021-10-19 17:33:19 -04002996func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002997 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
2998 if err != nil || aClient == nil {
2999 return err
3000 }
3001 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3002 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3003 defer cancel()
3004 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3005 return err
3006}
3007
khenaidoodc2116e2021-10-19 17:33:19 -04003008func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003009 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3010 if err != nil || aClient == nil {
3011 return err
3012 }
3013 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3014 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3015 defer cancel()
3016 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3017 return err
3018}
3019
3020/*
3021Helper functions for remote communication
3022*/
3023
3024// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3025// supports is deleted
3026func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3027 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3028
3029 dh.lockChildAdapterClients.Lock()
3030 defer dh.lockChildAdapterClients.Unlock()
3031 if _, ok := dh.childAdapterClients[endpoint]; ok {
3032 // Already set
3033 return nil
3034 }
3035
3036 // Setup child's adapter grpc connection
3037 var err error
3038 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(endpoint,
3039 dh.onuAdapterRestarted,
3040 vgrpc.ActivityCheck(true)); err != nil {
3041 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3042 return err
3043 }
3044 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), setAndTestAdapterServiceHandler)
3045
3046 // Wait until we have a connection to the child adapter.
3047 // Unlimited retries or until context expires
3048 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3049 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3050 for {
3051 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3052 if err == nil && client != nil {
3053 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3054 break
3055 }
3056 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3057 // Backoff
3058 if err = backoff.Backoff(subCtx); err != nil {
3059 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3060 break
3061 }
3062 }
3063 return nil
3064}
3065
khenaidoodc2116e2021-10-19 17:33:19 -04003066func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003067
3068 // First check from cache
3069 dh.lockChildAdapterClients.RLock()
3070 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3071 dh.lockChildAdapterClients.RUnlock()
3072 return cgClient.GetOnuInterAdapterServiceClient()
3073 }
3074 dh.lockChildAdapterClients.RUnlock()
3075
3076 // Set the child connection - can occur on restarts
3077 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3078 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3079 cancel()
3080 if err != nil {
3081 return nil, err
3082 }
3083
3084 // Get the child client now
3085 dh.lockChildAdapterClients.RLock()
3086 defer dh.lockChildAdapterClients.RUnlock()
3087 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3088 return cgClient.GetOnuInterAdapterServiceClient()
3089 }
3090 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3091}
3092
3093func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3094 dh.lockChildAdapterClients.Lock()
3095 defer dh.lockChildAdapterClients.Unlock()
3096 for key, client := range dh.childAdapterClients {
3097 client.Stop(ctx)
3098 delete(dh.childAdapterClients, key)
3099 }
3100}
3101
3102// TODO: Any action the adapter needs to do following a onu adapter restart?
3103func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003104 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003105 return nil
3106}
3107
3108// setAndTestAdapterServiceHandler is used to test whether the remote gRPC service is up
3109func setAndTestAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
khenaidoodc2116e2021-10-19 17:33:19 -04003110 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
3111 if h, err := svc.GetHealthStatus(ctx, &empty.Empty{}); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003112 return nil
3113 }
3114 return svc
3115}
Girish Gowdra950326e2021-11-05 12:43:24 -07003116
3117func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3118 dh.lockDevice.Lock()
3119 defer dh.lockDevice.Unlock()
3120 dh.isDeviceDeletionInProgress = flag
3121}
3122
3123func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3124 dh.lockDevice.RLock()
3125 defer dh.lockDevice.RUnlock()
3126 return dh.isDeviceDeletionInProgress
3127}