blob: effbc0858c5fd2f7f8636f3ee63c1bb7bfa0080f [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"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
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
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
khenaidoo106c61a2021-08-11 18:05:46 -040049 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053050 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080051 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040053 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053076 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040077)
78
Phaneendra Manda4c62c802019-03-06 21:37:49 +053079//DeviceHandler will interact with the OLT device.
80type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040081 cm *config.ConfigManager
82 device *voltha.Device
83 cfg *conf.AdapterFlags
84 coreClient *vgrpc.Client
85 childAdapterClients map[string]*vgrpc.Client
86 lockChildAdapterClients sync.RWMutex
87 EventProxy eventif.EventProxy
88 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050089 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040090 lockDevice sync.RWMutex
91 Client oop.OpenoltClient
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 flowMgr []*OpenOltFlowMgr
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053098 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070099
100 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530101
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700102 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
103 // if the value is true that means the OnuDiscovery indication
104 // is currently being processed and thus we can ignore concurrent requests
105 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
106 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700107 discOnus sync.Map
108 onus sync.Map
109 portStats *OpenOltStatisticsMgr
110 metrics *pmmetrics.PmMetrics
111 stopCollector chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000112 isCollectorActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700113 stopHeartbeatCheck chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000114 isHeartbeatCheckActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700115 activePorts sync.Map
116 stopIndications chan bool
117 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700118
Mahir Gunyelb0046752021-02-26 13:51:05 -0800119 totalPonPorts uint32
120 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
121 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800122
123 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
124 // 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 -0700125 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
126 stopMcastHandlerRoutine []chan bool
127 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000128
129 adapterPreviouslyConnected bool
130 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700131
132 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530133 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134}
135
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700136//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400138 deviceID string
139 deviceType string
140 serialNumber string
141 onuID uint32
142 intfID uint32
143 proxyDeviceID string
144 losRaised bool
145 rdiRaised bool
146 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700147}
148
Mahir Gunyelb0046752021-02-26 13:51:05 -0800149type onuIndicationMsg struct {
150 ctx context.Context
151 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800152}
153
154type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800155 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800156 stopChannel chan struct{}
157}
158
Girish Gowdra491a9c62021-01-06 16:43:07 -0800159//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
160//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
161//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
162//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
163type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400164 ctx context.Context // Flow/group handler context
165 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
166 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
167 group *of.OfpGroupEntry // Group message (can be nil or valid group)
168 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800169}
170
Naga Manjunath7615e552019-10-11 22:35:47 +0530171var pmNames = []string{
172 "rx_bytes",
173 "rx_packets",
174 "rx_mcast_packets",
175 "rx_bcast_packets",
176 "tx_bytes",
177 "tx_packets",
178 "tx_mcast_packets",
179 "tx_bcast_packets",
180}
181
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700182//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400183func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700184 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700186 device.deviceType = deviceTp
187 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700188 device.onuID = onuID
189 device.intfID = intfID
190 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530191 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400192 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700193 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530194}
195
196//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400197func 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 -0700198 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530199 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800200 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400201 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400202 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 dh.device = cloned
205 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500206 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700207 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000208 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
209 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530210 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 -0500211 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800212 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800213 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400214 dh.childAdapterClients = make(map[string]*vgrpc.Client)
215 dh.cfg = cfg
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530216 kvStoreDevicePath := fmt.Sprintf(dh.cm.Backend.PathPrefix, "/%s/", dh.device.Id)
217 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, kvStoreDevicePath)
218 if dh.kvStore == nil {
219 logger.Error(ctx, "Failed to setup KV store")
220 return nil
221 }
222
Girish Gowdra491a9c62021-01-06 16:43:07 -0800223 // Create a slice of buffered channels for handling concurrent mcast flow/group.
224 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700225 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
226 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800227 for i := range dh.incomingMcastFlowOrGroup {
228 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800229 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800230 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
231 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
232 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
233 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700234 dh.mcastHandlerRoutineActive[i] = true
235 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 //TODO initialize the support classes.
238 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530239}
240
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530241func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
242 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
243 switch storeType {
244 case "etcd":
245 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
246 }
247 return nil, errors.New("unsupported-kv-store")
248}
249
250// SetKVClient sets the KV client and return a kv backend
251func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
252 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
253 if err != nil {
254 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
255 return nil
256 }
257
258 kvbackend := &db.Backend{
259 Client: kvClient,
260 StoreType: backend,
261 Address: addr,
262 Timeout: rsrcMgr.KvstoreTimeout,
263 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
264
265 return kvbackend
266}
267
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530268// start save the device to the data model
269func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700270 dh.lockDevice.Lock()
271 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700273 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530275}
276
khenaidooefff76e2021-12-15 16:51:30 -0500277// Stop stops the device handler
278func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700279 dh.lockDevice.Lock()
280 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000281 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500282 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400283
khenaidooefff76e2021-12-15 16:51:30 -0500284 // Delete (which will stop also) all grpc connections to the child adapters
285 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000286 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530287}
288
ssiddiqui04386ee2021-08-23 21:58:25 +0530289func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
290 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
291 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
292 if pooledIntfID == intfID {
293 return resourceRanges.GetTechnology()
294 }
295 }
296 }
297 return ""
298}
299
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400300func macifyIP(ip net.IP) string {
301 if len(ip) > 0 {
302 oct1 := strconv.FormatInt(int64(ip[12]), 16)
303 oct2 := strconv.FormatInt(int64(ip[13]), 16)
304 oct3 := strconv.FormatInt(int64(ip[14]), 16)
305 oct4 := strconv.FormatInt(int64(ip[15]), 16)
306 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
307 }
308 return ""
309}
310
Neha Sharma96b7bf22020-06-15 10:37:32 +0000311func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400312 var genmac string
313 var addr net.IP
314 var ips []string
315 var err error
316
Neha Sharma96b7bf22020-06-15 10:37:32 +0000317 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400318
319 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400321
322 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000323 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400324 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000325 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400326 }
327 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530329 log.Fields{"host": ips[0],
330 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400331 return genmac, nil
332 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000333 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400334 }
335
336 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530338 log.Fields{"host": host,
339 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340 return genmac, nil
341}
342
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530343func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700344 slist := strings.Split(mac, ":")
345 result := make([]uint32, len(slist))
346 var err error
347 var tmp int64
348 for index, val := range slist {
349 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
350 return []uint32{1, 2, 3, 4, 5, 6}
351 }
352 result[index] = uint32(tmp)
353 }
354 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530355}
356
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700357//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 -0800358func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530359
David K. Bainbridge794735f2020-02-11 21:01:37 -0800360 switch portType {
361 case voltha.Port_ETHERNET_NNI:
362 return fmt.Sprintf("nni-%d", portNum), nil
363 case voltha.Port_PON_OLT:
364 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700365 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800366
Girish Kumarf26e4882020-03-05 06:49:10 +0000367 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530368}
369
Elia Battiston596406d2022-02-02 12:19:00 +0100370func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
371 if speedMbps == 0 {
372 //In case it was not set in the indication
373 //and no other value was provided
374 speedMbps = defaultPortSpeedMbps
375 }
376
377 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
378 switch speedMbps {
379 case 1000000:
380 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
381 case 100000:
382 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
383 case 40000:
384 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
385 case 10000:
386 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
387 case 1000:
388 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
389 case 100:
390 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
391 case 10:
392 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
393 }
394
395 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
396
397 port := &of.OfpPort{
398 HwAddr: macAddressToUint32Array(macAddress),
399 Config: 0,
400 State: uint32(of.OfpPortState_OFPPS_LIVE),
401 Curr: capacity,
402 Advertised: capacity,
403 Peer: capacity,
404 CurrSpeed: speedMbps * 1000, //kbps
405 MaxSpeed: speedMbps * 1000, //kbps
406 }
407
408 return port
409}
410
411func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000412 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 if state == "up" {
414 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500415 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500416 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700417 } else {
418 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500419 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700420 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700421 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400422 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800423 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000424 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400425 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500426
khenaidoo106c61a2021-08-11 18:05:46 -0400427 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400428 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400429 DeviceId: dh.device.Id,
430 Port: portNum,
431 })
432 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000433 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400434 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400435 DeviceId: dh.device.Id,
436 PortType: portType,
437 PortNo: portNum,
438 OperStatus: operStatus})
439 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400440 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
441 "device-id": dh.device.Id,
442 "port-type": portType,
443 "port-number": portNum,
444 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500445 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400446 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500447 }
khenaidoo106c61a2021-08-11 18:05:46 -0400448
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400449 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400450 port = &voltha.Port{
451 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 PortNo: portNum,
453 Label: label,
454 Type: portType,
455 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100456 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000458 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700459 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400460 err = dh.createPortInCore(ctx, port)
461 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000462 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800463 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000464 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400465 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000466 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530467 return nil
468}
469
Kent Hagermane6ff1012020-07-14 15:07:53 -0400470func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400471 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530472 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400473 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
474 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530475 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800476 dh.lockDevice.Lock()
477 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530478 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530479}
480
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700481// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530482// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000484 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700485 defer func() {
486 dh.lockDevice.Lock()
487 dh.isReadIndicationRoutineActive = false
488 dh.lockDevice.Unlock()
489 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700490 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700492 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700493 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400494
David Bainbridgef5879ca2019-12-13 21:17:54 +0000495 // Create an exponential backoff around re-enabling indications. The
496 // maximum elapsed time for the back off is set to 0 so that we will
497 // continue to retry. The max interval defaults to 1m, but is set
498 // here for code clarity
499 indicationBackoff := backoff.NewExponentialBackOff()
500 indicationBackoff.MaxElapsedTime = 0
501 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700502
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700503 dh.lockDevice.Lock()
504 dh.isReadIndicationRoutineActive = true
505 dh.lockDevice.Unlock()
506
Girish Gowdra3f974912020-03-23 20:35:18 -0700507Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700508 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400509 select {
510 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000511 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700512 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400513 default:
514 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100515
516 select {
517 case <-indications.Context().Done():
518 if err != nil {
519 logger.Warnw(ctx, "error-during-enable-indications",
520 log.Fields{"err": err,
521 "device-id": dh.device.Id})
522 }
523
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400524 // Use an exponential back off to prevent getting into a tight loop
525 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100526 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
527 "device-id": dh.device.Id,
528 "duration": duration,
529 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400530 if duration == backoff.Stop {
531 // If we reach a maximum then warn and reset the backoff
532 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100533 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530534 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530535 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400536 indicationBackoff.Reset()
537 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700538
539 // On failure process a backoff timer while watching for stopIndications
540 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700541 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700542 select {
543 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000544 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700545 if !backoffTimer.Stop() {
546 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700547 }
548 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700549 case <-backoffTimer.C:
550 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700551 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700552 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
553 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400554 }
555 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100556 default:
557 if err != nil {
558 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530559 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530560 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100561 // Close the stream, and re-initialize it
562 if err = indications.CloseSend(); err != nil {
563 // Ok to ignore here, because we landed here due to a problem on the stream
564 // In all probability, the closeSend call may fail
565 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
566 log.Fields{"err": err,
567 "device-id": dh.device.Id})
568 }
569 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
570 return err
571 }
572 // once we re-initialized the indication stream, continue to read indications
573 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700574 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100575 // Reset backoff if we have a successful receive
576 indicationBackoff.Reset()
577 // When OLT is admin down, ignore all indications.
578 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
579 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
580 log.Fields{"indication": indication,
581 "device-id": dh.device.Id})
582 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700583 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100584 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530585 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700586 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700588 // Close the send stream
589 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700590
Girish Gowdra3f974912020-03-23 20:35:18 -0700591 return nil
592}
593
594func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700595 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700596 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
597 if err != nil {
598 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
599 }
600 if indications == nil {
601 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
602 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700603 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700604 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400605}
606
607// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
608func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
609 switch indication.Data.(type) {
610 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
611 return true
612
613 default:
614 return false
615 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616}
617
David K. Bainbridge794735f2020-02-11 21:01:37 -0800618func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700619 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000620 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530621 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530623 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000625 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530627 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000628 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800629 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000630 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800631 }
632 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633}
634
David K. Bainbridge794735f2020-02-11 21:01:37 -0800635// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530636func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700637 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 switch indication.Data.(type) {
639 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000640 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
641 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700642 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 -0800643 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400644 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000647 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
648 defer span.Finish()
649
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100652 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400653 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800654 }
655 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000658 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
659 defer span.Finish()
660
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 intfOperInd := indication.GetIntfOperInd()
662 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800663 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100664 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400665 _ = 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 -0800666 }
667 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 } else if intfOperInd.GetType() == "pon" {
669 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
670 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100672 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400673 _ = 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 -0800674 }
675 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000676 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700677 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000678 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530679 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530680 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000682 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
683 defer span.Finish()
684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000686 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800687 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800688 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000690 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
691 defer span.Finish()
692
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000694 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800695 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800696 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000698 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
699 defer span.Finish()
700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 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 -0800703 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400705 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800706 }
707 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000709 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
710 defer span.Finish()
711
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700714 "intf-type": pktInd.IntfId,
715 "intf-id": pktInd.IntfId,
716 "gem-port-id": pktInd.GemportId,
717 "port-no": pktInd.PortNo,
718 "device-id": dh.device.Id,
719 })
720
721 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000722 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700723 "intf-type": pktInd.IntfId,
724 "intf-id": pktInd.IntfId,
725 "gem-port-id": pktInd.GemportId,
726 "port-no": pktInd.PortNo,
727 "packet": hex.EncodeToString(pktInd.Pkt),
728 "device-id": dh.device.Id,
729 })
730 }
731
David K. Bainbridge794735f2020-02-11 21:01:37 -0800732 go func() {
733 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400734 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800735 }
736 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700737 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000738 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
739 defer span.Finish()
740
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700742 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700743 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000744 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
745 defer span.Finish()
746
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000748 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000750 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
751 defer span.Finish()
752
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700753 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000754 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
755 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700756 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530757}
758
759// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530760func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530761 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000762 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530763
Girish Gowdra618fa572021-09-01 17:19:29 -0700764 // instantiate the mcast handler routines.
765 for i := range dh.incomingMcastFlowOrGroup {
766 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
767 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
768 if !dh.mcastHandlerRoutineActive[i] {
769 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
770 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
771 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
772 // for incoming mcast flow/group to be processed serially.
773 dh.mcastHandlerRoutineActive[i] = true
774 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
775 }
776 }
777
Girish Gowdru0c588b22019-04-23 23:24:56 -0400778 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400779 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400780 DeviceId: dh.device.Id,
781 OperStatus: voltha.OperStatus_ACTIVE,
782 ConnStatus: voltha.ConnectStatus_REACHABLE,
783 }); err != nil {
784 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400785 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000786
787 //Clear olt communication failure event
788 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
789 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700790 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000791 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
792
Girish Gowdru0c588b22019-04-23 23:24:56 -0400793 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530794}
795
796// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530797func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400799
khenaidoo106c61a2021-08-11 18:05:46 -0400800 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400801 if err != nil || device == nil {
802 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000803 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400804 }
805
806 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400807
808 //Update the device oper state and connection status
809 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800810 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400811 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800812 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400813
khenaidoodc2116e2021-10-19 17:33:19 -0400814 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400815 DeviceId: cloned.Id,
816 OperStatus: cloned.OperStatus,
817 ConnStatus: cloned.ConnectStatus,
818 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000819 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400820 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400821
822 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400823 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400824 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000825 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400826 }
827 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400828 // Update onu state as down in onu adapter
829 onuInd := oop.OnuIndication{}
830 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400831
832 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
833 if err != nil {
834 return err
835 }
836 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400837 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400838 DeviceId: onuDevice.Id,
839 OnuIndication: &onuInd,
840 })
841 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800842 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400843 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400844 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800845 "onu-indicator": onuInd,
846 "device-type": onuDevice.Type,
847 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700848 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800849 } else {
850 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 -0700851 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400852 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800853 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700854 /* Discovered ONUs entries need to be cleared , since after OLT
855 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530856 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800857 dh.lockDevice.Unlock()
858
Neha Sharma96b7bf22020-06-15 10:37:32 +0000859 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700860 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530861}
862
863// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530864func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400865 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000866
867 // if the connection is already available, close the previous connection (olt reboot case)
868 if dh.clientCon != nil {
869 if err = dh.clientCon.Close(); err != nil {
870 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
871 } else {
872 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
873 }
874 }
875
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530876 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +0000877 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000878 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
879 grpc.WithInsecure(),
880 grpc.WithBlock(),
881 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000882 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000883 )),
884 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000885 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000886 )))
887
888 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530889 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530890 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000891 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400892 }
893 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530894}
895
896// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530897func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400898 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530899 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400900 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530901}
902
903// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530904func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530905 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400907
908 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400909 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530910 if err != nil || device == nil {
911 /*TODO: needs to handle error scenarios */
912 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
913 }
914 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400916
917 cloned := proto.Clone(device).(*voltha.Device)
918 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
919 cloned.OperStatus = voltha.OperStatus_UNKNOWN
920 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400921
khenaidoodc2116e2021-10-19 17:33:19 -0400922 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400923 DeviceId: cloned.Id,
924 OperStatus: cloned.OperStatus,
925 ConnStatus: cloned.ConnectStatus,
926 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530927 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 -0400928 }
929
Chaitrashree G S44124192019-08-07 20:21:36 -0400930 // 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 +0530931 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400932 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530933 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400934 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400935 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
936 // all the modules initialized and ready to handle incoming ONUs.
937
Thomas Lee S985938d2020-05-04 11:40:41 +0530938 err = dh.initializeDeviceHandlerModules(ctx)
939 if err != nil {
940 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 -0400941 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400942
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700943 go startHeartbeatCheck(ctx, dh)
944
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400945 return nil
946 }
947
khenaidoo106c61a2021-08-11 18:05:46 -0400948 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400949 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400950 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400951 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400952 }
khenaidoo106c61a2021-08-11 18:05:46 -0400953 dh.populateActivePorts(ctx, ports.Items)
954 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400955 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400956 }
957
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400958 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530959 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 -0400960 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530961
Neha Sharma96b7bf22020-06-15 10:37:32 +0000962 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000963
964 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000965 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000966 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700967
968 go startHeartbeatCheck(ctx, dh)
969
cuilin20187b2a8c32019-03-26 19:52:28 -0700970 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530971}
972
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400973func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700974 var err error
975 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400976
977 if err != nil {
978 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
979 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700980 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
981 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000982 // +1 is for NNI
983 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
984 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700985 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000986 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
987 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
988 // There is only one NNI manager since multiple NNI is not supported for now
989 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700990 // Instantiate resource manager
991 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 -0700992 return olterrors.ErrResourceManagerInstantiating
993 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400994 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700995 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
996 // the KV store to manage mcast group data. Provide the first instance (0th index)
997 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
998 return olterrors.ErrGroupManagerInstantiating
999 }
yasin saplid0566272021-12-21 09:10:30 +00001000 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001001 // Instantiate flow manager
1002 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
1003 return olterrors.ErrFlowManagerInstantiating
1004 }
Girish Gowdra76a1b092021-07-28 10:07:04 -07001005 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001006 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001007 /* TODO: Instantiate Alarm , stats , BW managers */
1008 /* Instantiating Event Manager to handle Alarms and KPIs */
1009 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1010
1011 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001013
1014 return nil
1015
1016}
1017
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001019 var err error
1020 var deviceInfo *oop.DeviceInfo
1021
Neha Sharma8f4e4322020-08-06 10:51:53 +00001022 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001023
1024 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001025 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001026 }
1027 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001028 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001029 }
1030
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001032 dh.device.Root = true
1033 dh.device.Vendor = deviceInfo.Vendor
1034 dh.device.Model = deviceInfo.Model
1035 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1036 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1037 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1038
1039 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001040 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001041 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001042 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001043 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001044 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001047 dh.device.MacAddress = genmac
1048 } else {
1049 dh.device.MacAddress = deviceInfo.DeviceId
1050 }
1051
1052 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001053 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001054 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001055 }
1056
1057 return deviceInfo, nil
1058}
1059
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001061 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001062
1063 defer func() {
1064 dh.lockDevice.Lock()
1065 dh.isCollectorActive = false
1066 dh.lockDevice.Unlock()
1067 }()
1068
1069 dh.lockDevice.Lock()
1070 dh.isCollectorActive = true
1071 dh.lockDevice.Unlock()
1072
Naga Manjunath7615e552019-10-11 22:35:47 +05301073 for {
1074 select {
1075 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001076 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301077 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001078 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001079
khenaidoo106c61a2021-08-11 18:05:46 -04001080 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001081 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001082 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001083 continue
1084 }
khenaidoo106c61a2021-08-11 18:05:46 -04001085 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301086 // NNI Stats
1087 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001088 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301089 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001091 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301093 }
1094 // PON Stats
1095 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001096 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301097 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1098 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001100 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301101 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001102 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001103
yasin sapli9e4c5092022-02-01 13:52:33 +00001104 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001105 if len(onuGemInfoLst) > 0 {
1106 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001107 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001108 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301109 }
1110 }
1111 }
1112}
1113
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301115func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001116 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001117 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301118 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301119
1120 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001121 cgClient, err := dh.coreClient.GetCoreServiceClient()
1122 if err != nil {
1123 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1124 return
1125 }
1126
1127 // Now, set the initial PM configuration for that device
1128 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001129 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301130 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301131}
1132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001134func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1135 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001136 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301137 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001138 HwDesc: "open_pon",
1139 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001140 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001141 },
1142 SwitchFeatures: &of.OfpSwitchFeatures{
1143 NBuffers: 256,
1144 NTables: 2,
1145 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1146 of.OfpCapabilities_OFPC_TABLE_STATS |
1147 of.OfpCapabilities_OFPC_PORT_STATS |
1148 of.OfpCapabilities_OFPC_GROUP_STATS),
1149 },
1150 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301151}
1152
khenaidoo106c61a2021-08-11 18:05:46 -04001153// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001154func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001155 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001156 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001157 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001158 }
khenaidoo106c61a2021-08-11 18:05:46 -04001159 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001160}
1161
Neha Sharma96b7bf22020-06-15 10:37:32 +00001162func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001163 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 -07001164 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001165 var deviceID string
1166 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001167 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001168
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001169 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001170 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 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 -07001172 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1173 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001174
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001175 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301176
1177 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1178
Neha Sharma96b7bf22020-06-15 10:37:32 +00001179 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 -07001180 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001181
khenaidoodc2116e2021-10-19 17:33:19 -04001182 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001183 ParentId: dh.device.Id,
1184 OnuId: omciInd.OnuId,
1185 ParentPortNo: ponPort,
1186 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301188 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001189 "intf-id": omciInd.IntfId,
1190 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001191 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 deviceType = onuDevice.Type
1193 deviceID = onuDevice.Id
1194 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001195 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001197 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001198 } else {
1199 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001200 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 +05301201 deviceType = onuInCache.(*OnuDevice).deviceType
1202 deviceID = onuInCache.(*OnuDevice).deviceID
1203 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001204 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001205 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001206
khenaidoodc2116e2021-10-19 17:33:19 -04001207 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001208 ParentDeviceId: proxyDeviceID,
1209 ChildDeviceId: deviceID,
1210 Message: omciInd.Pkt,
1211 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301212 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001213 "source": dh.openOLT.config.AdapterEndpoint,
1214 "device-type": deviceType,
1215 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001217 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001218 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301220}
1221
khenaidoo106c61a2021-08-11 18:05:46 -04001222// //ProcessInterAdapterMessage sends the proxied messages to the target device
1223// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1224// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001225// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001226// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001227// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001228// return dh.handleInterAdapterOmciMsg(ctx, msg)
1229// }
1230// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1231// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001232
kesavandb9f54fd2021-11-25 20:08:04 +05301233// ProxyOmciRequests sends the proxied OMCI message to the target device
1234func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1235 if omciMsgs.GetProxyAddress() == nil {
1236 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1237 if err != nil {
1238 return olterrors.NewErrNotFound("onu", log.Fields{
1239 "parent-device-id": dh.device.Id,
1240 "child-device-id": omciMsgs.ChildDeviceId}, err)
1241 }
1242 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1243 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1244 return olterrors.NewErrCommunication("send-failed", log.Fields{
1245 "parent-device-id": dh.device.Id,
1246 "child-device-id": omciMsgs.ChildDeviceId}, err)
1247 }
1248 } else {
1249 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1250 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1251 return olterrors.NewErrCommunication("send-failed", log.Fields{
1252 "parent-device-id": dh.device.Id,
1253 "child-device-id": omciMsgs.ChildDeviceId}, err)
1254 }
1255 }
1256 return nil
1257}
1258
1259func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1260 var intfID uint32
1261 var onuID uint32
1262 var connectStatus common.ConnectStatus_Types
1263 if onuDevice != nil {
1264 intfID = onuDevice.ProxyAddress.GetChannelId()
1265 onuID = onuDevice.ProxyAddress.GetOnuId()
1266 connectStatus = onuDevice.ConnectStatus
1267 } else {
1268 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1269 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1270 connectStatus = omciMsgs.GetConnectStatus()
1271 }
1272 if connectStatus != voltha.ConnectStatus_REACHABLE {
1273 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1274
1275 return olterrors.NewErrCommunication("unreachable", log.Fields{
1276 "intf-id": intfID,
1277 "onu-id": onuID}, nil)
1278 }
1279
1280 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1281 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1282
1283 onuSecOmciMsgList := omciMsgs.GetMessages()
1284
1285 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1286
1287 var omciMessage *oop.OmciMsg
1288 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1289 hex.Encode(hexPkt, onuSecOmciMsg)
1290 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1291
1292 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1293 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1294 //https://jira.opencord.org/browse/VOL-4604
1295 transid := extractOmciTransactionID(onuSecOmciMsg)
1296 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1297 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1298
1299 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1300 if err != nil {
1301 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1302 "intf-id": intfID,
1303 "onu-id": onuID,
1304 "message": omciMessage}, err)
1305 }
1306 }
1307 return nil
1308}
1309
khenaidoo106c61a2021-08-11 18:05:46 -04001310// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001311func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001312 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 -07001313
1314 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001315 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001316 if err != nil {
1317 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001318 "parent-device-id": dh.device.Id,
1319 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001320 }
khenaidoo106c61a2021-08-11 18:05:46 -04001321 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1322 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001323 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001324 "parent-device-id": dh.device.Id,
1325 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001326 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001327 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001328 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1329 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001330 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001331 "parent-device-id": dh.device.Id,
1332 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001333 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001334 }
1335 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301336}
1337
khenaidoodc2116e2021-10-19 17:33:19 -04001338func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 var intfID uint32
1340 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001341 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001342 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001343 intfID = onuDevice.ProxyAddress.GetChannelId()
1344 onuID = onuDevice.ProxyAddress.GetOnuId()
1345 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001346 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 intfID = omciMsg.GetProxyAddress().GetChannelId()
1348 onuID = omciMsg.GetProxyAddress().GetOnuId()
1349 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001350 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 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 -08001353
Thomas Lee S94109f12020-03-03 16:39:29 +05301354 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001355 "intf-id": intfID,
1356 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001357 }
1358
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001359 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1360 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301361 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001362 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001363 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1364 hex.Encode(hexPkt, omciMsg.Message)
1365 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1366
1367 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1368 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1369 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001370 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001371 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001372
Neha Sharma8f4e4322020-08-06 10:51:53 +00001373 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301375 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001376 "intf-id": intfID,
1377 "onu-id": onuID,
1378 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001381}
1382
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301384 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
yasin saplibddc2d72022-02-08 13:10:17 +00001385 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001386 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001387 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001388 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301389 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301390 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001391 st, _ := status.FromError(err)
1392 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001393 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1394
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001395 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301396 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001397 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001398 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001399 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001400 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001401 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001402}
1403
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301404//getChildDevice function can be used in general to get child device, if not found in cache the function will
1405//get from core and update the cache and return the child device.
1406func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1407 var InCacheOnuDev *OnuDevice
1408 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1409 if onuInCache.(*OnuDevice).serialNumber == sn {
1410 InCacheOnuDev = onuInCache.(*OnuDevice)
1411 return false
1412 }
1413 return true
1414 })
1415 //Got the onu device from cache return
1416 if InCacheOnuDev != nil {
1417 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1418 return InCacheOnuDev
1419 }
1420 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1421 ParentId: dh.device.Id,
1422 SerialNumber: sn,
1423 ParentPortNo: parentPortNo,
1424 })
1425 //No device found in core return nil
1426 if onuDevice == nil {
1427 return nil
1428 }
1429 onuID := onuDevice.ProxyAddress.OnuId
1430 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1431 onuKey := dh.formOnuKey(intfID, onuID)
1432
1433 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1434 dh.onus.Store(onuKey, onuDev)
1435 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1436 return onuDev
1437}
1438
1439func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001441 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301442 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001443
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301444 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1445 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1446 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1447 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1448 if onuDev != nil {
1449 var onuGemInfo *rsrcMgr.OnuGemInfo
1450 var err error
1451 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1452 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1453 return false, err
1454 }
1455 if onuGemInfo != nil {
1456 for _, uni := range onuGemInfo.UniPorts {
1457 uniID := plt.UniIDFromPortNum(uni)
1458 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1459 if len(tpIDs) != 0 {
1460 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1461 tpInstExists = true
1462 break
1463 }
1464 }
1465 }
1466 }
1467 return tpInstExists, nil
1468 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301469
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301470 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1471 ParentId: dh.device.Id,
1472 SerialNumber: sn,
1473 ParentPortNo: parentPortNo,
1474 })
1475 if onuDevice != nil {
1476 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1477 return true, nil
1478 }
1479 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1480
1481 return false, nil
1482
1483}
1484
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001485// processDiscONULOSClear clears the LOS Alarm if it's needed
1486func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301487 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001488 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301489
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001490 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1491 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1492 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1493 OnuLosRaise event sent for it */
1494 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1495 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1496 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1497 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1498 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1499 "currentIntfId": onuDiscInd.GetIntfId()})
1500 // TODO:: Should we need to ignore raising OnuLosClear event
1501 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301502 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001503 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1504 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1505 alarmInd.LosStatus = statusCheckOff
1506 go func() {
1507 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1508 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1509 }
1510 }()
1511 // stop iterating
1512 return false
1513 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301514 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001515 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301516}
1517
1518func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1519 channelID := onuDiscInd.GetIntfId()
1520 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1521
1522 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1523 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1524
1525 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1526 if errtp != nil {
1527 return errtp
1528 }
1529 if tpInstExists {
1530 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001531 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001532 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001533 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001534 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1535
1536 // if the ONU existed, handle the LOS Alarm
1537 if existing {
1538
1539 if inProcess.(bool) {
1540 // if we're currently processing the ONU on a different thread, do nothing
1541 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1542 return nil
1543 }
1544 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1545 // then continue processing it
1546 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1547
1548 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001549 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301550 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001551
1552 defer func() {
1553 // once the function completes set the value to false so that
1554 // we know the processing has inProcess.
1555 // Note that this is done after checking if we are already processing
1556 // to avoid changing the value from a different thread
1557 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1558 dh.discOnus.Store(sn, false)
1559 }()
1560
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001561 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001562
1563 // check the ONU is already know to the OLT
1564 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001565 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001566 ParentId: dh.device.Id,
1567 SerialNumber: sn,
1568 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001569
1570 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001571 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 -08001572 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001573 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 -08001574 switch e.Code() {
1575 case codes.Internal:
1576 // this probably means NOT FOUND, so just create a new device
1577 onuDevice = nil
1578 case codes.DeadlineExceeded:
1579 // if the call times out, cleanup and exit
1580 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001581 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001582 }
1583 }
1584 }
1585
1586 if onuDevice == nil {
1587 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001589 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001590 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001591 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001592
Neha Sharma96b7bf22020-06-15 10:37:32 +00001593 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001594
1595 if err != nil {
1596 // if we can't create an ID in resource manager,
1597 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001598 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001599 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001600 "pon-intf-id": ponintfid,
1601 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001602 }
1603
khenaidoodc2116e2021-10-19 17:33:19 -04001604 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001605 ParentId: dh.device.Id,
1606 ParentPortNo: parentPortNo,
1607 ChannelId: channelID,
1608 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1609 SerialNumber: sn,
1610 OnuId: onuID,
1611 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001612 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001613 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301614 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001615 "pon-intf-id": ponintfid,
1616 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001617 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001618 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 -07001619 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001620 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301622 log.Fields{"onuDevice": onuDevice,
1623 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001624 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301625 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001626 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001627
khenaidoo106c61a2021-08-11 18:05:46 -04001628 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1629 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1630 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1631 cancel()
1632 if err != nil {
1633 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1634 }
1635
Matteo Scandolo945e4012019-12-12 14:16:11 -08001636 // we can now use the existing ONU Id
1637 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001638 //Insert the ONU into cache to use in OnuIndication.
1639 //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 +00001640 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001641 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301642 "intfId": onuDiscInd.GetIntfId(),
1643 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001644 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001645
khenaidoo106c61a2021-08-11 18:05:46 -04001646 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301647 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301649 log.Fields{"onu": onuDev,
1650 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001651
khenaidoodc2116e2021-10-19 17:33:19 -04001652 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001653 DeviceId: onuDevice.Id,
1654 ParentDeviceId: dh.device.Id,
1655 OperStatus: common.OperStatus_DISCOVERED,
1656 ConnStatus: common.ConnectStatus_REACHABLE,
1657 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301658 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001659 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001660 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001661 }
khenaidoo106c61a2021-08-11 18:05:46 -04001662
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001664 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301665 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001667 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 }
1669 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001670}
1671
Mahir Gunyelb0046752021-02-26 13:51:05 -08001672func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001673
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001674 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001675 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001677 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301679 log.Fields{"onuId": onuInd.OnuId,
1680 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301681 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001682 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001683 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301684
David K. Bainbridge794735f2020-02-11 21:01:37 -08001685 errFields := log.Fields{"device-id": dh.device.Id}
1686
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301687 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1688
Mahir Gunyele77977b2019-06-27 05:36:22 -07001689 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1690 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001692 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001693 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001694 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1695 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001696 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001697 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001698 errFields["onu-id"] = onuInd.OnuId
1699 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001700 }
khenaidoodc2116e2021-10-19 17:33:19 -04001701 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001702 ParentId: dh.device.Id,
1703 SerialNumber: serialNumber,
1704 OnuId: onuInd.OnuId,
1705 ParentPortNo: ponPort,
1706 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001707 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001708
David K. Bainbridge794735f2020-02-11 21:01:37 -08001709 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001710 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001711 }
1712
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 "previousIntfId": onuDevice.ParentPortNo,
1716 "currentIntfId": ponPort})
1717 }
1718
1719 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301721 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1722 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301723 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724 }
1725 if !foundInCache {
1726 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1727
khenaidoo106c61a2021-08-11 18:05:46 -04001728 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 -08001729
1730 }
kesavand7cf3a052020-08-28 12:49:18 +05301731 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001732 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001733 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301734 }
1735 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001736 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001737 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001738 }
1739 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001740}
1741
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001743 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 -07001744 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1745 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1746 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1747 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001748 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001749 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1750 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001752 onuInd.OperState = "down"
1753 }
1754 }
1755
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001757 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 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 -04001759
khenaidoodc2116e2021-10-19 17:33:19 -04001760 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001761 DeviceId: onuDevice.Id,
1762 OnuIndication: onuInd,
1763 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001764 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301765 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001766 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001767 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001769 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001770 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001771 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001772 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001773 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001775}
1776
cuilin20187b2a8c32019-03-26 19:52:28 -07001777func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1778 if serialNum != nil {
1779 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001780 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001781 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001782}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001783func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1784 decodedStr, err := hex.DecodeString(serialNum[4:])
1785 if err != nil {
1786 return nil, err
1787 }
1788 return &oop.SerialNumber{
1789 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001790 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001791 }, nil
1792}
cuilin20187b2a8c32019-03-26 19:52:28 -07001793
1794func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001795 if len(vendorSpecific) > 3 {
1796 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1797 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1798 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1799 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1800 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1801 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1802 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1803 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1804 return tmp
1805 }
1806 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001807}
1808
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001809//UpdateFlowsBulk upates the bulk flow
1810func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301811 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001812}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001813
1814//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1816 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301817 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001818 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301819 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001820
khenaidoodc2116e2021-10-19 17:33:19 -04001821 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001822 ParentId: dh.device.Id,
1823 OnuId: onuID,
1824 ParentPortNo: parentPort,
1825 })
1826
Girish Gowdru0c588b22019-04-23 23:24:56 -04001827 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001828 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001829 "intf-id": parentPort,
1830 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001831 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001832 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 -08001833 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301834}
1835
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001836// SendPacketInToCore sends packet-in to core
1837// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1838// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001840 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001842 "port": logicalPort,
1843 "packet": hex.EncodeToString(packetPayload),
1844 "device-id": dh.device.Id,
1845 })
1846 }
khenaidoo106c61a2021-08-11 18:05:46 -04001847
khenaidoodc2116e2021-10-19 17:33:19 -04001848 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001849 DeviceId: dh.device.Id,
1850 Port: logicalPort,
1851 Packet: packetPayload,
1852 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301853 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001854 "source": "adapter",
1855 "destination": "core",
1856 "device-id": dh.device.Id,
1857 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001858 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001859 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001860 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001862 "packet": hex.EncodeToString(packetPayload),
1863 "device-id": dh.device.Id,
1864 })
1865 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001866 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001867}
1868
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001869// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001870func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001872
1873 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1874 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001876 }
1877
Kent Hagermane6ff1012020-07-14 15:07:53 -04001878 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001879 metrics := dh.metrics.GetSubscriberMetrics()
1880 for _, m := range pmConfigs.Metrics {
1881 metrics[m.Name].Enabled = m.Enabled
1882
1883 }
1884 }
1885}
1886
khenaidoodc2116e2021-10-19 17:33:19 -04001887func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001888 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001889 var errorsList []error
1890
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001891 if dh.getDeviceDeletionInProgressFlag() {
1892 // The device itself is going to be reset as part of deletion. So nothing to be done.
1893 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1894 return nil
1895 }
1896
Girish Gowdru0c588b22019-04-23 23:24:56 -04001897 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001898 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001899 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001900
Neha Sharma96b7bf22020-06-15 10:37:32 +00001901 logger.Debugw(ctx, "removing-flow",
Shrey Baid