blob: 86cce43d39c5e33f2e7a08dce279a57ea5b59638 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Girish Gowdra491a9c62021-01-06 16:43:07 -080024 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "fmt"
26 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
khenaidoo106c61a2021-08-11 18:05:46 -040033 "github.com/golang/protobuf/ptypes/empty"
34 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040035
Matteo Scandolo945e4012019-12-12 14:16:11 -080036 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070037 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000038 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
39 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040040 "github.com/opencord/voltha-lib-go/v7/pkg/config"
41 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
42 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
43 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070044 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040045 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080046
khenaidoo106c61a2021-08-11 18:05:46 -040047 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053048 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080049 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040050 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040051 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040053 "github.com/opencord/voltha-protos/v5/go/health"
54 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
55 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040056 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
57 oop "github.com/opencord/voltha-protos/v5/go/openolt"
58 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070059 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040060 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040061 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053062)
63
salmansiddiqui7ac62132019-08-22 03:58:50 +000064// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040065const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080066 InvalidPort = 0xffffffff
67 MaxNumOfGroupHandlerChannels = 256
68
69 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
70 McastFlowOrGroupModify = "McastFlowOrGroupModify"
71 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050072 oltPortInfoTimeout = 3
Manikkaraj kb1d51442019-07-23 10:41:02 -040073)
74
Phaneendra Manda4c62c802019-03-06 21:37:49 +053075//DeviceHandler will interact with the OLT device.
76type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040077 cm *config.ConfigManager
78 device *voltha.Device
79 cfg *conf.AdapterFlags
80 coreClient *vgrpc.Client
81 childAdapterClients map[string]*vgrpc.Client
82 lockChildAdapterClients sync.RWMutex
83 EventProxy eventif.EventProxy
84 openOLT *OpenOLT
85 exitChannel chan int
86 lockDevice sync.RWMutex
87 Client oop.OpenoltClient
88 transitionMap *TransitionMap
89 clientCon *grpc.ClientConn
90 flowMgr []*OpenOltFlowMgr
91 groupMgr *OpenOltGroupMgr
92 eventMgr *OpenOltEventMgr
93 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070094
95 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053096
Girish Gowdra3ab6d212020-03-24 17:33:15 -070097 discOnus sync.Map
98 onus sync.Map
99 portStats *OpenOltStatisticsMgr
100 metrics *pmmetrics.PmMetrics
101 stopCollector chan bool
102 stopHeartbeatCheck chan bool
103 activePorts sync.Map
104 stopIndications chan bool
105 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700106
Mahir Gunyelb0046752021-02-26 13:51:05 -0800107 totalPonPorts uint32
108 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
109 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800110
111 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
112 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700113 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
114 stopMcastHandlerRoutine []chan bool
115 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000116
117 adapterPreviouslyConnected bool
118 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700119
120 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700121}
122
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700124type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400125 deviceID string
126 deviceType string
127 serialNumber string
128 onuID uint32
129 intfID uint32
130 proxyDeviceID string
131 losRaised bool
132 rdiRaised bool
133 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134}
135
Mahir Gunyelb0046752021-02-26 13:51:05 -0800136type onuIndicationMsg struct {
137 ctx context.Context
138 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800139}
140
141type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800142 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800143 stopChannel chan struct{}
144}
145
Girish Gowdra491a9c62021-01-06 16:43:07 -0800146//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
147//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
148//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
149//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
150type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400151 ctx context.Context // Flow/group handler context
152 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
153 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
154 group *of.OfpGroupEntry // Group message (can be nil or valid group)
155 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800156}
157
Naga Manjunath7615e552019-10-11 22:35:47 +0530158var pmNames = []string{
159 "rx_bytes",
160 "rx_packets",
161 "rx_mcast_packets",
162 "rx_bcast_packets",
163 "tx_bytes",
164 "tx_packets",
165 "tx_mcast_packets",
166 "tx_bcast_packets",
167}
168
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700169//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400170func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700171 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700172 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700173 device.deviceType = deviceTp
174 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700175 device.onuID = onuID
176 device.intfID = intfID
177 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530178 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400179 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700180 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530181}
182
183//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400184func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700185 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800186 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400187 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400188 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700189 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700190 dh.device = cloned
191 dh.openOLT = adapter
192 dh.exitChannel = make(chan int, 1)
193 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530194 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530195 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530196 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500197 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400198 dh.stopIndications = make(chan bool, 1)
Mahir Gunyelb0046752021-02-26 13:51:05 -0800199 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400200 dh.childAdapterClients = make(map[string]*vgrpc.Client)
201 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800202 // Create a slice of buffered channels for handling concurrent mcast flow/group.
203 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700204 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
205 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800206 for i := range dh.incomingMcastFlowOrGroup {
207 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700208 dh.stopMcastHandlerRoutine[i] = make(chan bool, 1)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800209 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
210 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
211 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
212 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700213 dh.mcastHandlerRoutineActive[i] = true
214 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800215 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700216 //TODO initialize the support classes.
217 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530218}
219
220// start save the device to the data model
221func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700222 dh.lockDevice.Lock()
223 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000224 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700225 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530227}
228
229// stop stops the device dh. Not much to do for now
230func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 dh.lockDevice.Lock()
232 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000233 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 dh.exitChannel <- 1
khenaidoo106c61a2021-08-11 18:05:46 -0400235
Neha Sharma96b7bf22020-06-15 10:37:32 +0000236 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530237}
238
ssiddiqui04386ee2021-08-23 21:58:25 +0530239func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
240 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
241 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
242 if pooledIntfID == intfID {
243 return resourceRanges.GetTechnology()
244 }
245 }
246 }
247 return ""
248}
249
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400250func macifyIP(ip net.IP) string {
251 if len(ip) > 0 {
252 oct1 := strconv.FormatInt(int64(ip[12]), 16)
253 oct2 := strconv.FormatInt(int64(ip[13]), 16)
254 oct3 := strconv.FormatInt(int64(ip[14]), 16)
255 oct4 := strconv.FormatInt(int64(ip[15]), 16)
256 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
257 }
258 return ""
259}
260
Neha Sharma96b7bf22020-06-15 10:37:32 +0000261func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400262 var genmac string
263 var addr net.IP
264 var ips []string
265 var err error
266
Neha Sharma96b7bf22020-06-15 10:37:32 +0000267 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400268
269 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400271
272 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000273 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400274 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000275 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400276 }
277 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000278 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530279 log.Fields{"host": ips[0],
280 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400281 return genmac, nil
282 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000283 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400284 }
285
286 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000287 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530288 log.Fields{"host": host,
289 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400290 return genmac, nil
291}
292
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 slist := strings.Split(mac, ":")
295 result := make([]uint32, len(slist))
296 var err error
297 var tmp int64
298 for index, val := range slist {
299 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
300 return []uint32{1, 2, 3, 4, 5, 6}
301 }
302 result[index] = uint32(tmp)
303 }
304 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530305}
306
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700307//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800308func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309
David K. Bainbridge794735f2020-02-11 21:01:37 -0800310 switch portType {
311 case voltha.Port_ETHERNET_NNI:
312 return fmt.Sprintf("nni-%d", portNum), nil
313 case voltha.Port_PON_OLT:
314 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700315 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800316
Girish Kumarf26e4882020-03-05 06:49:10 +0000317 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530318}
319
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000321 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700322 if state == "up" {
323 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500324 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500325 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700326 } else {
327 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500328 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700329 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700330 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400331 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800332 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000333 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400334 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500335
khenaidoo106c61a2021-08-11 18:05:46 -0400336 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400337 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400338 DeviceId: dh.device.Id,
339 Port: portNum,
340 })
341 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000342 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400343 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400344 DeviceId: dh.device.Id,
345 PortType: portType,
346 PortNo: portNum,
347 OperStatus: operStatus})
348 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400349 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
350 "device-id": dh.device.Id,
351 "port-type": portType,
352 "port-number": portNum,
353 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500354 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400355 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500356 }
khenaidoo106c61a2021-08-11 18:05:46 -0400357
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400358 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700359 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
khenaidoo106c61a2021-08-11 18:05:46 -0400360 port = &voltha.Port{
361 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700362 PortNo: portNum,
363 Label: label,
364 Type: portType,
365 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700366 OfpPort: &of.OfpPort{
367 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
368 Config: 0,
369 State: uint32(of.OfpPortState_OFPPS_LIVE),
370 Curr: capacity,
371 Advertised: capacity,
372 Peer: capacity,
373 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
374 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
375 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700376 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000377 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700378 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400379 err = dh.createPortInCore(ctx, port)
380 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000381 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000383 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400384 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000385 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530386 return nil
387}
388
Kent Hagermane6ff1012020-07-14 15:07:53 -0400389func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400390 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530391 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400392 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
393 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530394 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800395 dh.lockDevice.Lock()
396 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530397 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530398}
399
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700400// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530401// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800402func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000403 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700404 defer func() {
405 dh.lockDevice.Lock()
406 dh.isReadIndicationRoutineActive = false
407 dh.lockDevice.Unlock()
408 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700409 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700410 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700411 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700412 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400413
David Bainbridgef5879ca2019-12-13 21:17:54 +0000414 // Create an exponential backoff around re-enabling indications. The
415 // maximum elapsed time for the back off is set to 0 so that we will
416 // continue to retry. The max interval defaults to 1m, but is set
417 // here for code clarity
418 indicationBackoff := backoff.NewExponentialBackOff()
419 indicationBackoff.MaxElapsedTime = 0
420 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700421
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700422 dh.lockDevice.Lock()
423 dh.isReadIndicationRoutineActive = true
424 dh.lockDevice.Unlock()
425
Girish Gowdra3f974912020-03-23 20:35:18 -0700426Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700427 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400428 select {
429 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000430 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700431 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400432 default:
433 indication, err := indications.Recv()
434 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000435 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530436 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530437 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400438 // Use an exponential back off to prevent getting into a tight loop
439 duration := indicationBackoff.NextBackOff()
440 if duration == backoff.Stop {
441 // If we reach a maximum then warn and reset the backoff
442 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530444 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530445 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400446 indicationBackoff.Reset()
447 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700448
449 // On failure process a backoff timer while watching for stopIndications
450 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700451 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700452 select {
453 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000454 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700455 if !backoffTimer.Stop() {
456 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700457 }
458 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700459 case <-backoffTimer.C:
460 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700461 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700462 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
463 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400464 }
465 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000466 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530467 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530469 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530470 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700471 // Close the stream, and re-initialize it
472 if err = indications.CloseSend(); err != nil {
473 // Ok to ignore here, because we landed here due to a problem on the stream
474 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530476 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530477 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700478 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000479 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700480 return err
481 }
482 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400483 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530484 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400485 // Reset backoff if we have a successful receive
486 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400487 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700488 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530490 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530491 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400492 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400493 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400494 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700495 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700496 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700497 // Close the send stream
498 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700499
Girish Gowdra3f974912020-03-23 20:35:18 -0700500 return nil
501}
502
503func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700504 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700505 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
506 if err != nil {
507 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
508 }
509 if indications == nil {
510 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
511 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700512 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700513 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400514}
515
516// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
517func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
518 switch indication.Data.(type) {
519 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
520 return true
521
522 default:
523 return false
524 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525}
526
David K. Bainbridge794735f2020-02-11 21:01:37 -0800527func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700528 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000529 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530530 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530532 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000534 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000535 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530536 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000537 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800538 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000539 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800540 }
541 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542}
543
David K. Bainbridge794735f2020-02-11 21:01:37 -0800544// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530545func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700546 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 switch indication.Data.(type) {
548 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000549 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
550 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700551 logger.Infow(ctx, "received olt indication", log.Fields{"device-id": dh.device.Id, "olt-ind": indication.GetOltInd()})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800552 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400553 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800554 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000556 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
557 defer span.Finish()
558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800560 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400562 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800563 }
564 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000567 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
568 defer span.Finish()
569
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570 intfOperInd := indication.GetIntfOperInd()
571 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400574 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800575 }
576 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 } else if intfOperInd.GetType() == "pon" {
578 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
579 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800580 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000581 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400582 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800583 }
584 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700586 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000587 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530588 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530589 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000591 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
592 defer span.Finish()
593
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800596 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800597 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000599 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
600 defer span.Finish()
601
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700602 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000603 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800604 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800605 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000607 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
608 defer span.Finish()
609
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700610 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000611 logger.Debugw(ctx, "received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800612 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000613 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400614 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800615 }
616 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000618 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
619 defer span.Finish()
620
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000622 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700623 "intf-type": pktInd.IntfId,
624 "intf-id": pktInd.IntfId,
625 "gem-port-id": pktInd.GemportId,
626 "port-no": pktInd.PortNo,
627 "device-id": dh.device.Id,
628 })
629
630 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000631 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700632 "intf-type": pktInd.IntfId,
633 "intf-id": pktInd.IntfId,
634 "gem-port-id": pktInd.GemportId,
635 "port-no": pktInd.PortNo,
636 "packet": hex.EncodeToString(pktInd.Pkt),
637 "device-id": dh.device.Id,
638 })
639 }
640
David K. Bainbridge794735f2020-02-11 21:01:37 -0800641 go func() {
642 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400643 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644 }
645 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000647 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
648 defer span.Finish()
649
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700651 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000653 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
654 defer span.Finish()
655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000657 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000659 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
660 defer span.Finish()
661
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000663 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
664 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700665 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530666}
667
668// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530669func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530670 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000671 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530672
Girish Gowdra618fa572021-09-01 17:19:29 -0700673 // instantiate the mcast handler routines.
674 for i := range dh.incomingMcastFlowOrGroup {
675 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
676 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
677 if !dh.mcastHandlerRoutineActive[i] {
678 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
679 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
680 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
681 // for incoming mcast flow/group to be processed serially.
682 dh.mcastHandlerRoutineActive[i] = true
683 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
684 }
685 }
686
Girish Gowdru0c588b22019-04-23 23:24:56 -0400687 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400688 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400689 DeviceId: dh.device.Id,
690 OperStatus: voltha.OperStatus_ACTIVE,
691 ConnStatus: voltha.ConnectStatus_REACHABLE,
692 }); err != nil {
693 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400694 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000695
696 //Clear olt communication failure event
697 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
698 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700699 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000700 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
701
Gamze Abakac2c32a62021-03-11 11:44:18 +0000702 //check adapter and agent reconcile status
703 //reboot olt if needed (olt disconnection case)
704 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
705 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
706 log.Fields{
707 "device-id": dh.device.Id,
708 "adapter-status": dh.adapterPreviouslyConnected,
709 "agent-status": dh.agentPreviouslyConnected,
710 })
711 _ = dh.RebootDevice(ctx, dh.device)
712 }
713
Girish Gowdru0c588b22019-04-23 23:24:56 -0400714 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530715}
716
717// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530718func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400720
khenaidoo106c61a2021-08-11 18:05:46 -0400721 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400722 if err != nil || device == nil {
723 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000724 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400725 }
726
727 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400728
729 //Update the device oper state and connection status
730 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800731 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400732 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800733 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400734
khenaidoodc2116e2021-10-19 17:33:19 -0400735 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400736 DeviceId: cloned.Id,
737 OperStatus: cloned.OperStatus,
738 ConnStatus: cloned.ConnectStatus,
739 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000740 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400741 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400742
743 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400744 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400745 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000746 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400747 }
748 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400749 // Update onu state as down in onu adapter
750 onuInd := oop.OnuIndication{}
751 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400752
753 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
754 if err != nil {
755 return err
756 }
757 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400758 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400759 DeviceId: onuDevice.Id,
760 OnuIndication: &onuInd,
761 })
762 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800763 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400764 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400765 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 "onu-indicator": onuInd,
767 "device-type": onuDevice.Type,
768 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700769 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800770 } else {
771 logger.Debugw(ctx, "sending inter adapter down ind to onu success", log.Fields{"olt-device-id": device.Id, "onu-device-id": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400773 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800774 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700775 /* Discovered ONUs entries need to be cleared , since after OLT
776 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530777 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800778 dh.lockDevice.Unlock()
779
Neha Sharma96b7bf22020-06-15 10:37:32 +0000780 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700781 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530782}
783
784// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530785func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400786 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000787
788 // if the connection is already available, close the previous connection (olt reboot case)
789 if dh.clientCon != nil {
790 if err = dh.clientCon.Close(); err != nil {
791 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
792 } else {
793 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
794 }
795 }
796
797 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000798 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
799 grpc.WithInsecure(),
800 grpc.WithBlock(),
801 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000802 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000803 )),
804 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000805 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000806 )))
807
808 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530809 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530810 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000811 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400812 }
813 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530814}
815
816// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530817func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400818 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530819 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400820 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530821}
822
823// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530824func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530825 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000826 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400827
828 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400829 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530830 if err != nil || device == nil {
831 /*TODO: needs to handle error scenarios */
832 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
833 }
834 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000835 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400836
837 cloned := proto.Clone(device).(*voltha.Device)
838 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
839 cloned.OperStatus = voltha.OperStatus_UNKNOWN
840 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400841
khenaidoodc2116e2021-10-19 17:33:19 -0400842 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400843 DeviceId: cloned.Id,
844 OperStatus: cloned.OperStatus,
845 ConnStatus: cloned.ConnectStatus,
846 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530847 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400848 }
849
Chaitrashree G S44124192019-08-07 20:21:36 -0400850 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +0530851 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400852 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530853 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400854 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400855 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
856 // all the modules initialized and ready to handle incoming ONUs.
857
Thomas Lee S985938d2020-05-04 11:40:41 +0530858 err = dh.initializeDeviceHandlerModules(ctx)
859 if err != nil {
860 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400861 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400862
863 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800864 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530865 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400866 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800867 }
868 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700869
870 go startHeartbeatCheck(ctx, dh)
871
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400872 return nil
873 }
874
khenaidoo106c61a2021-08-11 18:05:46 -0400875 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400876 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400877 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400878 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400879 }
khenaidoo106c61a2021-08-11 18:05:46 -0400880 dh.populateActivePorts(ctx, ports.Items)
881 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400882 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400883 }
884
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400885 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530886 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400887 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530888
cuilin20187b2a8c32019-03-26 19:52:28 -0700889 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800890 go func() {
891 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400892 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800893 }
894 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000895 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000896
897 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000898 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000899 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700900
901 go startHeartbeatCheck(ctx, dh)
902
cuilin20187b2a8c32019-03-26 19:52:28 -0700903 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530904}
905
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400906func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700907 var err error
908 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400909
910 if err != nil {
911 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
912 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700913 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
914 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700915
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700916 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700917 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700918 var i uint32
919 for i = 0; i < dh.totalPonPorts; i++ {
920 // Instantiate resource manager
921 if dh.resourceMgr[i] = rsrcMgr.NewResourceMgr(ctx, i, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, dh.deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700922 return olterrors.ErrResourceManagerInstantiating
923 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400924 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700925 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
926 // the KV store to manage mcast group data. Provide the first instance (0th index)
927 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
928 return olterrors.ErrGroupManagerInstantiating
929 }
930 for i = 0; i < dh.totalPonPorts; i++ {
931 // Instantiate flow manager
932 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
933 return olterrors.ErrFlowManagerInstantiating
934 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700935 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700936 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400937 /* TODO: Instantiate Alarm , stats , BW managers */
938 /* Instantiating Event Manager to handle Alarms and KPIs */
939 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
940
941 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400943
944 return nil
945
946}
947
Neha Sharma96b7bf22020-06-15 10:37:32 +0000948func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400949 var err error
950 var deviceInfo *oop.DeviceInfo
951
Neha Sharma8f4e4322020-08-06 10:51:53 +0000952 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400953
954 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000955 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400956 }
957 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000958 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400959 }
960
Neha Sharma96b7bf22020-06-15 10:37:32 +0000961 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400962 dh.device.Root = true
963 dh.device.Vendor = deviceInfo.Vendor
964 dh.device.Model = deviceInfo.Model
965 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
966 dh.device.HardwareVersion = deviceInfo.HardwareVersion
967 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
968
969 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000970 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400971 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400973 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000974 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400975 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000976 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400977 dh.device.MacAddress = genmac
978 } else {
979 dh.device.MacAddress = deviceInfo.DeviceId
980 }
981
982 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400983 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000984 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400985 }
986
987 return deviceInfo, nil
988}
989
Neha Sharma96b7bf22020-06-15 10:37:32 +0000990func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -0700991 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530992 for {
993 select {
994 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000995 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530996 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000997 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700998
khenaidoo106c61a2021-08-11 18:05:46 -0400999 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001000 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001001 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001002 continue
1003 }
khenaidoo106c61a2021-08-11 18:05:46 -04001004 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301005 // NNI Stats
1006 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001007 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301008 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001009 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001010 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001011 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301012 }
1013 // PON Stats
1014 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001015 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301016 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1017 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001019 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301020 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001021 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001022
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001023 onuGemInfoLst := dh.flowMgr[intfID].getOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001024 if len(onuGemInfoLst) > 0 {
1025 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001026 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001027 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301028 }
1029 }
1030 }
1031}
1032
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001033//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301034func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001035 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301037 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301038
1039 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001040 cgClient, err := dh.coreClient.GetCoreServiceClient()
1041 if err != nil {
1042 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1043 return
1044 }
1045
1046 // Now, set the initial PM configuration for that device
1047 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001048 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301049 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301050}
1051
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001053func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1054 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001055 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301056 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001057 HwDesc: "open_pon",
1058 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001059 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001060 },
1061 SwitchFeatures: &of.OfpSwitchFeatures{
1062 NBuffers: 256,
1063 NTables: 2,
1064 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1065 of.OfpCapabilities_OFPC_TABLE_STATS |
1066 of.OfpCapabilities_OFPC_PORT_STATS |
1067 of.OfpCapabilities_OFPC_GROUP_STATS),
1068 },
1069 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301070}
1071
khenaidoo106c61a2021-08-11 18:05:46 -04001072// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001073func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001074 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001075 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001076 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001077 }
khenaidoo106c61a2021-08-11 18:05:46 -04001078 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001079}
1080
Neha Sharma96b7bf22020-06-15 10:37:32 +00001081func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001082 logger.Debugw(ctx, "omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "parent-device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001083 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 var deviceID string
1085 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001086 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001087
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001088 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001089 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 logger.Debugw(ctx, "recv-omci-msg", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id,
Matteo Scandolo92186242020-06-12 10:54:18 -07001091 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1092 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001093
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001094 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301095
1096 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1097
Neha Sharma96b7bf22020-06-15 10:37:32 +00001098 logger.Debugw(ctx, "omci-indication-for-a-device-not-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001099 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001100
khenaidoodc2116e2021-10-19 17:33:19 -04001101 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001102 ParentId: dh.device.Id,
1103 OnuId: omciInd.OnuId,
1104 ParentPortNo: ponPort,
1105 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001106 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301107 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001108 "intf-id": omciInd.IntfId,
1109 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001110 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001111 deviceType = onuDevice.Type
1112 deviceID = onuDevice.Id
1113 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001114 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001115 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001116 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001117 } else {
1118 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Debugw(ctx, "omci-indication-for-a-device-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301120 deviceType = onuInCache.(*OnuDevice).deviceType
1121 deviceID = onuInCache.(*OnuDevice).deviceID
1122 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001123 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001124 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001125
khenaidoodc2116e2021-10-19 17:33:19 -04001126 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001127 ParentDeviceId: proxyDeviceID,
1128 ChildDeviceId: deviceID,
1129 Message: omciInd.Pkt,
1130 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301131 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001132 "source": dh.openOLT.config.AdapterEndpoint,
1133 "device-type": deviceType,
1134 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001136 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001137 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301139}
1140
khenaidoo106c61a2021-08-11 18:05:46 -04001141// //ProcessInterAdapterMessage sends the proxied messages to the target device
1142// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1143// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001144// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001145// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001146// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001147// return dh.handleInterAdapterOmciMsg(ctx, msg)
1148// }
1149// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1150// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001151
khenaidoo106c61a2021-08-11 18:05:46 -04001152// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001153func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001154 logger.Debugw(ctx, "proxy-omci-message", log.Fields{"parent-device-id": omciMsg.ParentDeviceId, "child-device-id": omciMsg.ChildDeviceId, "proxy-address": omciMsg.ProxyAddress, "connect-status": omciMsg.ConnectStatus})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001155
1156 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001157 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001158 if err != nil {
1159 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001160 "parent-device-id": dh.device.Id,
1161 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 }
khenaidoo106c61a2021-08-11 18:05:46 -04001163 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1164 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001165 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001166 "parent-device-id": dh.device.Id,
1167 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001168 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001169 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001170 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1171 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001172 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001173 "parent-device-id": dh.device.Id,
1174 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001175 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001176 }
1177 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301178}
1179
khenaidoodc2116e2021-10-19 17:33:19 -04001180func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 var intfID uint32
1182 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001183 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001184 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001185 intfID = onuDevice.ProxyAddress.GetChannelId()
1186 onuID = onuDevice.ProxyAddress.GetOnuId()
1187 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001188 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 intfID = omciMsg.GetProxyAddress().GetChannelId()
1190 onuID = omciMsg.GetProxyAddress().GetOnuId()
1191 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001192 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001194 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195
Thomas Lee S94109f12020-03-03 16:39:29 +05301196 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001197 "intf-id": intfID,
1198 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001199 }
1200
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001201 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1202 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001203 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001204 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1205 hex.Encode(hexPkt, omciMsg.Message)
1206 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1207
1208 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1209 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1210 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001212 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001213
Neha Sharma8f4e4322020-08-06 10:51:53 +00001214 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301216 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001217 "intf-id": intfID,
1218 "onu-id": onuID,
1219 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001222}
1223
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301225 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
Girish Gowdra197acc12021-08-16 10:59:45 -07001226 if err := dh.flowMgr[intfID].AddOnuInfoToFlowMgrCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001227 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001228 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001229 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301230 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301231 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001232 st, _ := status.FromError(err)
1233 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001234 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1235
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001236 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301237 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001238 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001239 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001241 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001243}
1244
Mahir Gunyelb0046752021-02-26 13:51:05 -08001245func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001247 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001248
Mahir Gunyelb0046752021-02-26 13:51:05 -08001249 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001250 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301251
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301252 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001253 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001254 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301255
1256 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1257 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1258 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1259 OnuLosRaise event sent for it */
1260 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1261 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1262 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301264 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1265 "currentIntfId": onuDiscInd.GetIntfId()})
1266 // TODO:: Should we need to ignore raising OnuLosClear event
1267 // when onu connected to different PON?
1268 }
1269 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1270 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1271 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001272 go func() {
1273 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001274 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001275 }
1276 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301277 }
1278 return true
1279 })
1280
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001283 }
1284
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001285 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001286
1287 // check the ONU is already know to the OLT
1288 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001289 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001290 ParentId: dh.device.Id,
1291 SerialNumber: sn,
1292 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001293
1294 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001295 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001296 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001297 logger.Debugw(ctx, "core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001298 switch e.Code() {
1299 case codes.Internal:
1300 // this probably means NOT FOUND, so just create a new device
1301 onuDevice = nil
1302 case codes.DeadlineExceeded:
1303 // if the call times out, cleanup and exit
1304 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001305 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001306 }
1307 }
1308 }
1309
1310 if onuDevice == nil {
1311 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001312 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001313 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001314 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001315 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001316
Neha Sharma96b7bf22020-06-15 10:37:32 +00001317 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001318
1319 if err != nil {
1320 // if we can't create an ID in resource manager,
1321 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001322 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001324 "pon-intf-id": ponintfid,
1325 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001326 }
1327
khenaidoodc2116e2021-10-19 17:33:19 -04001328 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001329 ParentId: dh.device.Id,
1330 ParentPortNo: parentPortNo,
1331 ChannelId: channelID,
1332 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1333 SerialNumber: sn,
1334 OnuId: onuID,
1335 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001336 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001337 dh.resourceMgr[ponintfid].FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301338 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001339 "pon-intf-id": ponintfid,
1340 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001341 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001342 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001343 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001344 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001345 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301346 log.Fields{"onuDevice": onuDevice,
1347 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001348 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301349 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001350 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001351
khenaidoo106c61a2021-08-11 18:05:46 -04001352 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1353 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1354 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1355 cancel()
1356 if err != nil {
1357 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1358 }
1359
Matteo Scandolo945e4012019-12-12 14:16:11 -08001360 // we can now use the existing ONU Id
1361 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001362 //Insert the ONU into cache to use in OnuIndication.
1363 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001364 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001365 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301366 "intfId": onuDiscInd.GetIntfId(),
1367 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001368 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001369
khenaidoo106c61a2021-08-11 18:05:46 -04001370 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301371 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001372 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301373 log.Fields{"onu": onuDev,
1374 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001375
khenaidoodc2116e2021-10-19 17:33:19 -04001376 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001377 DeviceId: onuDevice.Id,
1378 ParentDeviceId: dh.device.Id,
1379 OperStatus: common.OperStatus_DISCOVERED,
1380 ConnStatus: common.ConnectStatus_REACHABLE,
1381 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301382 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001384 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001385 }
khenaidoo106c61a2021-08-11 18:05:46 -04001386
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001388 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001391 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 }
1393 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001394}
1395
Mahir Gunyelb0046752021-02-26 13:51:05 -08001396func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001397
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001398 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001399 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001401 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001402 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301403 log.Fields{"onuId": onuInd.OnuId,
1404 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301405 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001406 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001407 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301408
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 errFields := log.Fields{"device-id": dh.device.Id}
1410
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301411 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1412
Mahir Gunyele77977b2019-06-27 05:36:22 -07001413 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1414 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001415 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001416 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001417 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001418 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1419 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001421 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001422 errFields["onu-id"] = onuInd.OnuId
1423 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001424 }
khenaidoodc2116e2021-10-19 17:33:19 -04001425 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001426 ParentId: dh.device.Id,
1427 SerialNumber: serialNumber,
1428 OnuId: onuInd.OnuId,
1429 ParentPortNo: ponPort,
1430 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001431 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001432
David K. Bainbridge794735f2020-02-11 21:01:37 -08001433 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001434 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001435 }
1436
David K. Bainbridge794735f2020-02-11 21:01:37 -08001437 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001438 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001439 "previousIntfId": onuDevice.ParentPortNo,
1440 "currentIntfId": ponPort})
1441 }
1442
1443 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001444 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301445 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1446 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301447 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001448 }
1449 if !foundInCache {
1450 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1451
khenaidoo106c61a2021-08-11 18:05:46 -04001452 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001453
1454 }
kesavand7cf3a052020-08-28 12:49:18 +05301455 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001456 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001457 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301458 }
1459 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001461 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001462 }
1463 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001464}
1465
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001467 logger.Debugw(ctx, "onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdra748de5c2020-07-01 10:27:52 -07001468 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1469 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1470 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1471 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001472 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001473 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1474 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001475 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001476 onuInd.OperState = "down"
1477 }
1478 }
1479
David K. Bainbridge794735f2020-02-11 21:01:37 -08001480 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001481 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001482 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
khenaidoo106c61a2021-08-11 18:05:46 -04001483
khenaidoodc2116e2021-10-19 17:33:19 -04001484 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001485 DeviceId: onuDevice.Id,
1486 OnuIndication: onuInd,
1487 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001488 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301489 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001490 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001491 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001492 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001493 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001494 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001495 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001496 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001498 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499}
1500
cuilin20187b2a8c32019-03-26 19:52:28 -07001501func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1502 if serialNum != nil {
1503 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001504 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001506}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001507func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1508 decodedStr, err := hex.DecodeString(serialNum[4:])
1509 if err != nil {
1510 return nil, err
1511 }
1512 return &oop.SerialNumber{
1513 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001514 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001515 }, nil
1516}
cuilin20187b2a8c32019-03-26 19:52:28 -07001517
1518func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001519 if len(vendorSpecific) > 3 {
1520 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1521 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1522 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1523 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1524 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1525 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1526 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1527 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1528 return tmp
1529 }
1530 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001531}
1532
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533//UpdateFlowsBulk upates the bulk flow
1534func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301535 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001536}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537
1538//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1540 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301541 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001542 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301543 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001544
khenaidoodc2116e2021-10-19 17:33:19 -04001545 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001546 ParentId: dh.device.Id,
1547 OnuId: onuID,
1548 ParentPortNo: parentPort,
1549 })
1550
Girish Gowdru0c588b22019-04-23 23:24:56 -04001551 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001552 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001553 "intf-id": parentPort,
1554 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001555 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556 logger.Debugw(ctx, "successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001557 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301558}
1559
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560// SendPacketInToCore sends packet-in to core
1561// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1562// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001563func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001564 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001565 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001566 "port": logicalPort,
1567 "packet": hex.EncodeToString(packetPayload),
1568 "device-id": dh.device.Id,
1569 })
1570 }
khenaidoo106c61a2021-08-11 18:05:46 -04001571
khenaidoodc2116e2021-10-19 17:33:19 -04001572 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001573 DeviceId: dh.device.Id,
1574 Port: logicalPort,
1575 Packet: packetPayload,
1576 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301577 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 "source": "adapter",
1579 "destination": "core",
1580 "device-id": dh.device.Id,
1581 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001582 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001583 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001584 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001586 "packet": hex.EncodeToString(packetPayload),
1587 "device-id": dh.device.Id,
1588 })
1589 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001590 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001591}
1592
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001593// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001596
1597 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1598 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001599 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001600 }
1601
Kent Hagermane6ff1012020-07-14 15:07:53 -04001602 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001603 metrics := dh.metrics.GetSubscriberMetrics()
1604 for _, m := range pmConfigs.Metrics {
1605 metrics[m.Name].Enabled = m.Enabled
1606
1607 }
1608 }
1609}
1610
khenaidoodc2116e2021-10-19 17:33:19 -04001611func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001612 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001613 var errorsList []error
1614
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001615 if dh.getDeviceDeletionInProgressFlag() {
1616 // The device itself is going to be reset as part of deletion. So nothing to be done.
1617 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1618 return nil
1619 }
1620
Girish Gowdru0c588b22019-04-23 23:24:56 -04001621 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001622 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001623 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001624
Neha Sharma96b7bf22020-06-15 10:37:32 +00001625 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301626 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001627 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301628 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001629 if flow_utils.HasGroup(flow) {
1630 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1631 } else {
1632 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1633 }
Girish Gowdracefae192020-03-19 18:14:10 -07001634 if err != nil {
1635 errorsList = append(errorsList, err)
1636 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001637 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301638
1639 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001640 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301642 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001643 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301644 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001645 if flow_utils.HasGroup(flow) {
1646 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1647 } else {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001648 if dh.flowMgr == nil || dh.flowMgr[ponIf] == nil {
1649 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1650 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1651 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1652 } else {
1653 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1654 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001655 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001656 if err != nil {
1657 errorsList = append(errorsList, err)
1658 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301659 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001660 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001661
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001662 return errorsList
1663}
1664
1665func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1666 var err error
1667 var errorsList []error
1668
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001669 if dh.getDeviceDeletionInProgressFlag() {
1670 // The device itself is going to be reset as part of deletion. So nothing to be done.
1671 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1672 return nil
1673 }
1674
Girish Gowdracefae192020-03-19 18:14:10 -07001675 // Whether we need to synchronize multicast group adds and modifies like flow add and delete needs to be investigated
Esin Karamanccb714b2019-11-29 15:02:06 +00001676 if groups != nil {
1677 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001678 // err = dh.groupMgr.AddGroup(ctx, group)
1679 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001680 if err != nil {
1681 errorsList = append(errorsList, err)
1682 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001683 }
1684 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001685 // err = dh.groupMgr.ModifyGroup(ctx, group)
1686 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001687 if err != nil {
1688 errorsList = append(errorsList, err)
1689 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001690 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001691 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001692 // err = dh.groupMgr.DeleteGroup(ctx, group)
1693 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001694 if err != nil {
1695 errorsList = append(errorsList, err)
1696 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001697 }
1698 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001699
1700 return errorsList
1701}
1702
1703//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001704func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *of.FlowMetadata) error {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001705
1706 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001707
1708 if dh.getDeviceDeletionInProgressFlag() {
1709 // The device itself is going to be reset as part of deletion. So nothing to be done.
1710 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1711 return nil
1712 }
1713
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001714 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1715 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1716 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001717 if len(errorsList) > 0 {
1718 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1719 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001721 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301722}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001723
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001724//DisableDevice disables the given device
1725//It marks the following for the given device:
1726//Device-Handler Admin-State : down
1727//Device Port-State: UNKNOWN
1728//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001729func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001730 /* On device disable ,admin state update has to be done prior sending request to agent since
1731 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001732 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001733 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001734 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001735 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001736 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001737 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001738 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001740 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001741 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301742
1743 dh.discOnus = sync.Map{}
1744 dh.onus = sync.Map{}
1745
Thomas Lee S85f37312020-04-03 17:06:12 +05301746 //stopping the stats collector
1747 dh.stopCollector <- true
1748
Neha Sharma96b7bf22020-06-15 10:37:32 +00001749 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001750 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301751 //Update device Admin state
1752 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001753
kdarapu1afeceb2020-02-12 01:38:09 -05001754 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
khenaidoodc2116e2021-10-19 17:33:19 -04001755 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001756 DeviceId: cloned.Id,
1757 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1758 OperStatus: voltha.OperStatus_UNKNOWN,
1759 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001760 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001763 return nil
1764}
1765
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001767 // Update onu state as unreachable in onu adapter
1768 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301769 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001770
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001771 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001772 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001773 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001774 logger.Errorw(ctx, "failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001775 }
1776 if onuDevices != nil {
1777 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001778 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001779 DeviceId: onuDevice.Id,
1780 OnuIndication: &onuInd,
1781 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001782 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001784 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001785 }
1786
1787 }
1788 }
1789
1790}
1791
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001792//ReenableDevice re-enables the olt device after disable
1793//It marks the following for the given device:
1794//Device-Handler Admin-State : up
1795//Device Port-State: ACTIVE
1796//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001798 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301799 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001800 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301801 }
1802 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001804
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001805 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001806 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001807 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001808 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001809 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1810 } else {
1811 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1812 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1813 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001814 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001815 if retError == nil {
1816 //Update the device oper status as ACTIVE
1817 device.OperStatus = voltha.OperStatus_ACTIVE
1818 } else {
1819 //Update the device oper status as FAILED
1820 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001821 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001822 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001823
khenaidoodc2116e2021-10-19 17:33:19 -04001824 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001825 DeviceId: device.Id,
1826 OperStatus: device.OperStatus,
1827 ConnStatus: device.ConnectStatus,
1828 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301829 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001830 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001831 "connect-status": device.ConnectStatus,
1832 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001833 }
kesavand39e0aa32020-01-28 20:58:50 -05001834
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001836
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001837 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001838}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001839
npujarec5762e2020-01-01 14:08:48 +05301840func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001841 var uniID uint32
1842 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301843 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001844 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001845 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001846 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001847 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001848 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001849 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001851 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001852 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001853 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001854 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001857 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001859 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301861 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001862 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1863 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001864 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301865 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001867 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868 logger.Debugw(ctx, "failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001869 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001870 }
1871 return nil
1872}
1873
Devmalya Paul495b94a2019-08-27 19:42:00 -04001874// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
npujarec5762e2020-01-01 14:08:48 +05301875func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001876 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001877 /* Clear the KV store data associated with the all the UNI ports
1878 This clears up flow data and also resource map data for various
1879 other pon resources like alloc_id and gemport_id
1880 */
Girish Gowdra950326e2021-11-05 12:43:24 -07001881
1882 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001883 var wg sync.WaitGroup
1884 wg.Add(1) // for the mcast routine below to finish
1885 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
1886 for _, flMgr := range dh.flowMgr {
1887 wg.Add(1) // for the flow handler routine below to finish
1888 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
1889 }
1890 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
1891 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
1892 } else {
1893 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
1894 }
Girish Gowdra950326e2021-11-05 12:43:24 -07001895
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001896 dh.cleanupDeviceResources(ctx)
1897 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001898 // Stop the Stats collector
1899 dh.stopCollector <- true
1900 // stop the heartbeat check routine
1901 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301902 dh.lockDevice.RLock()
1903 // Stop the read indication only if it the routine is active
1904 if dh.isReadIndicationRoutineActive {
1905 dh.stopIndications <- true
1906 }
1907 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001908 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001909 //Reset the state
1910 if dh.Client != nil {
1911 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301912 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001913 }
1914 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001915 // There is no need to update the core about operation status and connection status of the OLT.
1916 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1917 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1918 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001919
khenaidoo7eb2d672021-10-22 19:08:50 -04001920 // Stop the adapter grpc clients for that parent device
1921 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001922 return nil
1923}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001924func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001925
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001926 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301927 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001928 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001929 var err error
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001930 onuGemData := dh.flowMgr[ponPort].getOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001931 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001933 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001934 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301935 }
1936 }
Girish Gowdra950326e2021-11-05 12:43:24 -07001937 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
1938 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001939 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
1940 logger.Debug(ctx, err)
1941 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001942 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001943 }
A R Karthick1f85b802019-10-11 05:06:05 +00001944
Devmalya Paul495b94a2019-08-27 19:42:00 -04001945 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301946 dh.onus.Range(func(key interface{}, value interface{}) bool {
1947 dh.onus.Delete(key)
1948 return true
1949 })
1950
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001951 /*Delete discovered ONU map for the device*/
1952 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1953 dh.discOnus.Delete(key)
1954 return true
1955 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001956}
1957
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001958//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001959func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001960 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301961 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001962 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001963 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001964 return nil
1965}
1966
David K. Bainbridge794735f2020-02-11 21:01:37 -08001967func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001968 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001969 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001970 "packet-indication": *packetIn,
1971 "device-id": dh.device.Id,
1972 "packet": hex.EncodeToString(packetIn.Pkt),
1973 })
1974 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001975 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001976 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001977 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001978 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001979 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001980 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001981 "logical-port-num": logicalPortNum,
1982 "device-id": dh.device.Id,
1983 "packet": hex.EncodeToString(packetIn.Pkt),
1984 })
1985 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001986
khenaidoodc2116e2021-10-19 17:33:19 -04001987 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001988 DeviceId: dh.device.Id,
1989 Port: logicalPortNum,
1990 Packet: packetIn.Pkt,
1991 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301992 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001993 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301994 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001995 "device-id": dh.device.Id,
1996 "packet": hex.EncodeToString(packetIn.Pkt),
1997 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001998 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001999
Matteo Scandolo92186242020-06-12 10:54:18 -07002000 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002001 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002002 "packet": hex.EncodeToString(packetIn.Pkt),
2003 "device-id": dh.device.Id,
2004 })
2005 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002006 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002007}
2008
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002009// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002010func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002011 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002012 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002013 "device-id": dh.device.Id,
2014 "egress-port-no": egressPortNo,
2015 "pkt-length": len(packet.Data),
2016 "packet": hex.EncodeToString(packet.Data),
2017 })
2018 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002019
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002020 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002021 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002022 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2023 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302024 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2025 // Do not packet-out lldp packets on uni port.
2026 // ONOS has no clue about uni/nni ports, it just packets out on all
2027 // available ports on the Logical Switch. It should not be interested
2028 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002030 "device-id": dh.device.Id,
2031 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302032 return nil
2033 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002034 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2035 if innerEthType == 0x8100 {
2036 // q-in-q 802.1ad or 802.1q double tagged packet.
2037 // slice out the outer tag.
2038 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002039 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002041 "packet-data": hex.EncodeToString(packet.Data),
2042 "device-id": dh.device.Id,
2043 })
2044 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002045 }
2046 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002047 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2048 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2049 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002050
Girish Gowdra9602eb42020-09-09 15:50:39 -07002051 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002052 if err != nil {
2053 // In this case the openolt agent will receive the gemPortID as 0.
2054 // The agent tries to retrieve the gemPortID in this case.
2055 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002057 "intf-id": intfID,
2058 "onu-id": onuID,
2059 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002060 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302061 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002062 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002063 }
2064
2065 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002066 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002067 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002068 "egress-port-no": egressPortNo,
2069 "intf-id": intfID,
2070 "onu-id": onuID,
2071 "uni-id": uniID,
2072 "gem-port-id": gemPortID,
2073 "packet": hex.EncodeToString(packet.Data),
2074 "device-id": dh.device.Id,
2075 })
2076 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002077
npujarec5762e2020-01-01 14:08:48 +05302078 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302079 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002080 "source": "adapter",
2081 "destination": "onu",
2082 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002083 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002084 "oni-id": onuID,
2085 "uni-id": uniID,
2086 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002087 "packet": hex.EncodeToString(packet.Data),
2088 "device-id": dh.device.Id,
2089 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002090 }
2091 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002092 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002093 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002094 return olterrors.NewErrInvalidValue(log.Fields{
2095 "egress-nni-port": egressPortNo,
2096 "device-id": dh.device.Id,
2097 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002098 }
2099 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002100
Matteo Scandolo92186242020-06-12 10:54:18 -07002101 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002102 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002103 "uplink-pkt": uplinkPkt,
2104 "packet": hex.EncodeToString(packet.Data),
2105 "device-id": dh.device.Id,
2106 })
2107 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002108
npujarec5762e2020-01-01 14:08:48 +05302109 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002110 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2111 "packet": hex.EncodeToString(packet.Data),
2112 "device-id": dh.device.Id,
2113 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002114 }
2115 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302117 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002118 "egressPortType": egressPortType,
2119 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302120 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002121 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002122 }
2123 return nil
2124}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002125
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002126func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2127 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002128}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302129
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002130func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002131
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302132 // start the heartbeat check towards the OLT.
2133 var timerCheck *time.Timer
2134
2135 for {
2136 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2137 select {
2138 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002139 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002140 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002141 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302142 if timerCheck == nil {
2143 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002144 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302145 }
2146 } else {
2147 if timerCheck != nil {
2148 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002149 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302150 }
2151 timerCheck = nil
2152 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002153 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302154 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302155 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302156 }
2157 cancel()
2158 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002159 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302160 return
2161 }
2162 }
2163}
2164
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002165func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002166 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002167 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002168 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2169 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2170 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2171 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2172 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002173 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002174 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2175 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002176 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302177
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002178 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2179 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002180 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002181 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002182 DeviceId: dh.device.Id,
2183 OperStatus: voltha.OperStatus_UNKNOWN,
2184 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2185 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002186 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002187 }
khenaidoo106c61a2021-08-11 18:05:46 -04002188
khenaidoodc2116e2021-10-19 17:33:19 -04002189 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002190 DeviceId: dh.device.Id,
2191 PortTypeFilter: 0,
2192 OperStatus: voltha.OperStatus_UNKNOWN,
2193 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002194 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002195 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002196
2197 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002198 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002199 cloned := proto.Clone(device).(*voltha.Device)
2200 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2201 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2202 dh.device = cloned // update local copy of the device
2203 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002204
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002205 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002206 // Stop the Stats collector
2207 dh.stopCollector <- true
2208 // stop the heartbeat check routine
2209 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002210
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002211 dh.lockDevice.RLock()
2212 // Stop the read indication only if it the routine is active
2213 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2214 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2215 // on next execution of the readIndication routine.
2216 if dh.isReadIndicationRoutineActive {
2217 dh.stopIndications <- true
2218 }
2219 dh.lockDevice.RUnlock()
2220
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002221 var wg sync.WaitGroup
2222 wg.Add(1) // for the multicast handler routine
2223 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002224 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002225 wg.Add(1) // for the flow handler routine
2226 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2227 }
2228 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2229 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2230 } else {
2231 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002232 }
2233
Gamze Abakac2c32a62021-03-11 11:44:18 +00002234 //reset adapter reconcile flag
2235 dh.adapterPreviouslyConnected = false
2236
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002237 dh.transitionMap.Handle(ctx, DeviceInit)
2238
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302239 }
2240}
kesavand39e0aa32020-01-28 20:58:50 -05002241
2242// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2244 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2245 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002246}
2247
2248// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002249func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2250 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2251 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002252}
2253
kdarapu1afeceb2020-02-12 01:38:09 -05002254//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2256 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002257 if port.GetType() == voltha.Port_ETHERNET_NNI {
2258 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002259 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302260 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302261 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002262 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002263 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002264 }
2265 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002266 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002267 ponIntf := &oop.Interface{IntfId: ponID}
2268 var operStatus voltha.OperStatus_Types
2269 if enablePort {
2270 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302271 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002272
2273 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302274 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002275 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002276 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002277 }
2278 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002279 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002281 } else {
2282 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302283 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002284 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302285 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002286 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002287 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002288 }
2289 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002290 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002292 }
khenaidoodc2116e2021-10-19 17:33:19 -04002293 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002294 DeviceId: dh.device.Id,
2295 PortType: voltha.Port_PON_OLT,
2296 PortNo: port.PortNo,
2297 OperStatus: operStatus,
2298 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302299 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302300 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002301 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002302 }
2303 return nil
2304}
2305
kdarapu1afeceb2020-02-12 01:38:09 -05002306//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002307func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002308 // Disable the port and update the oper_port_status to core
2309 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002310 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002311 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302313 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302314 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002315 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002316 }
2317 }
2318 }
2319 return nil
2320}
2321
2322//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002323func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2324 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2325 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002326 if port.Type == voltha.Port_ETHERNET_NNI {
2327 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002328 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002329 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002330 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002331 }
2332 }
2333 if port.Type == voltha.Port_PON_OLT {
2334 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002335 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002336 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002337 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002338 }
2339 }
2340 }
2341}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002342
2343// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002344func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002345 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002346 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002347 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002348
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002349 var sn *oop.SerialNumber
2350 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002351 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302352 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002353 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302354 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002355 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002356 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002357
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002358 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002359 //clear PON resources associated with ONU
2360 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2361 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2362 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2363 "device-id": dh.device.Id,
2364 "intf-id": intfID,
2365 "onuID": onuID,
2366 "err": err})
2367 } else {
2368 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2369 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2370 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2371 "device-id": dh.device.Id,
2372 "onu-device": onu,
2373 "err": err})
2374 }
2375 // Clear flowids for gem cache.
2376 for _, gem := range onuGem.GemPorts {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002377 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002378 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002379 if err := dh.flowMgr[intfID].RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002380 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2381 "intf-id": intfID,
2382 "onu-device": onu,
2383 "onu-gem": onuGem,
2384 "err": err})
2385 //Not returning error on cleanup.
2386 }
2387 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302388
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002389 }
Himani Chawlabcc95852021-10-27 10:55:40 +05302390 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002391 dh.onus.Delete(onuKey)
2392 dh.discOnus.Delete(onuSn)
2393
2394 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002395 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302396 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302397 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002398 "onu-id": onuID}, err).Log()
2399 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002400
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002401 return nil
2402}
Girish Gowdracefae192020-03-19 18:14:10 -07002403
2404func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002405 for _, field := range flow_utils.GetOfbFields(flow) {
2406 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002407 return field.GetPort()
2408 }
2409 }
2410 return InvalidPort
2411}
2412
2413func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002414 for _, action := range flow_utils.GetActions(flow) {
2415 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002416 if out := action.GetOutput(); out != nil {
2417 return out.GetPort()
2418 }
2419 }
2420 }
2421 return InvalidPort
2422}
2423
Girish Gowdracefae192020-03-19 18:14:10 -07002424func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2425 inPort := getInPortFromFlow(flow)
2426 outPort := getOutPortFromFlow(flow)
2427
2428 if inPort == InvalidPort || outPort == InvalidPort {
2429 return inPort, outPort
2430 }
2431
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002432 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002433 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002434 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002435 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002436 return uniPort, outPort
2437 }
2438 }
2439 } else {
2440 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002441 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002442 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002443 return inPort, uniPort
2444 }
2445 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002446 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002447 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002448 return uniPort, outPort
2449 }
2450 }
2451 }
2452
2453 return InvalidPort, InvalidPort
2454}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002455
2456func extractOmciTransactionID(omciPkt []byte) uint16 {
2457 if len(omciPkt) > 3 {
2458 d := omciPkt[0:2]
2459 transid := binary.BigEndian.Uint16(d)
2460 return transid
2461 }
2462 return 0
2463}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002464
2465// StoreOnuDevice stores the onu parameters to the local cache.
2466func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2467 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2468 dh.onus.Store(onuKey, onuDevice)
2469}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002470
khenaidoodc2116e2021-10-19 17:33:19 -04002471func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002472 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002473 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002474 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002475 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002476 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002477 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002478 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002479 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2480 return nil, err
2481 }
2482 ID = device.ProxyAddress.GetOnuId()
2483 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2484 valueparam.Onu = &Onu
2485 valueparam.Value = value
2486
2487 // This API is unsupported until agent patch is added
2488 resp.Unsupported = uint32(value)
2489 _ = ctx
2490
2491 // Uncomment this code once agent changes are complete and tests
2492 /*
2493 resp, err = dh.Client.GetValue(ctx, valueparam)
2494 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002495 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002496 return nil, err
2497 }
2498 */
2499
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002500 logger.Infow(ctx, "get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002501 return resp, nil
2502}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002503
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002504func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002505 // Default to PON0
2506 var intfID uint32
2507 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002508 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002509 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002510 }
2511 return intfID
2512}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002513
Mahir Gunyelb0046752021-02-26 13:51:05 -08002514func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2515 dh.perPonOnuIndicationChannelLock.Lock()
2516 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2517 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002518 return ch.indicationChannel
2519 }
2520 channels := onuIndicationChannels{
2521 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002522 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002523 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002524 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002525 stopChannel: make(chan struct{}),
2526 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002527 dh.perPonOnuIndicationChannel[intfID] = channels
2528 dh.perPonOnuIndicationChannelLock.Unlock()
2529 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002530 return channels.indicationChannel
2531
2532}
2533
Mahir Gunyelb0046752021-02-26 13:51:05 -08002534func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2535 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2536 dh.perPonOnuIndicationChannelLock.Lock()
2537 defer dh.perPonOnuIndicationChannelLock.Unlock()
2538 for _, v := range dh.perPonOnuIndicationChannel {
2539 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002540 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002541 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002542}
2543
Mahir Gunyelb0046752021-02-26 13:51:05 -08002544func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2545 ind := onuIndicationMsg{
2546 ctx: ctx,
2547 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002548 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002549 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002550 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002551 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002552}
2553
Mahir Gunyelb0046752021-02-26 13:51:05 -08002554func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002555 for {
2556 select {
2557 // process one indication per onu, before proceeding to the next one
2558 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002559 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002560 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002561 "ind": indication})
2562 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002563 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002564 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002565 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2566 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002567 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002568 }
2569 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002570 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002571 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2572 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002573 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002574 }
2575 }
2576 case <-onuChannels.stopChannel:
2577 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2578 close(onuChannels.indicationChannel)
2579 return
2580 }
2581 }
2582}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002583
2584// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2585// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002586func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002587 if dh.getDeviceDeletionInProgressFlag() {
2588 // The device itself is going to be reset as part of deletion. So nothing to be done.
2589 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2590 return nil
2591 }
2592
Girish Gowdra491a9c62021-01-06 16:43:07 -08002593 // Step1 : Fill McastFlowOrGroupControlBlock
2594 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2595 // Step3 : Wait on response channel for response
2596 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002597 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002598 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2599 errChan := make(chan error)
2600 var groupID uint32
2601 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2602 ctx: ctx,
2603 flowOrGroupAction: action,
2604 flow: flow,
2605 group: group,
2606 errChan: &errChan,
2607 }
2608 if flow != nil {
2609 groupID = flow_utils.GetGroup(flow)
2610 } else if group != nil {
2611 groupID = group.Desc.GroupId
2612 } else {
2613 return errors.New("flow-and-group-both-nil")
2614 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002615 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2616 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2617 // Derive the appropriate go routine to handle the request by a simple module operation.
2618 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2619 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2620 // Wait for handler to return error value
2621 err := <-errChan
2622 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2623 return err
2624 }
2625 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2626 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002627}
2628
2629// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002630func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002631 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002632 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002633 // block on the channel to receive an incoming mcast flow/group
2634 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002635 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2636 if mcastFlowOrGroupCb.flow != nil {
2637 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2638 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2639 log.Fields{"device-id": dh.device.Id,
2640 "flowToAdd": mcastFlowOrGroupCb.flow})
2641 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2642 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2643 // Pass the return value over the return channel
2644 *mcastFlowOrGroupCb.errChan <- err
2645 } else { // flow remove
2646 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2647 log.Fields{"device-id": dh.device.Id,
2648 "flowToRemove": mcastFlowOrGroupCb.flow})
2649 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2650 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2651 // Pass the return value over the return channel
2652 *mcastFlowOrGroupCb.errChan <- err
2653 }
2654 } else { // mcast group
2655 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2656 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2657 log.Fields{"device-id": dh.device.Id,
2658 "groupToAdd": mcastFlowOrGroupCb.group})
2659 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2660 // Pass the return value over the return channel
2661 *mcastFlowOrGroupCb.errChan <- err
2662 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2663 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2664 log.Fields{"device-id": dh.device.Id,
2665 "groupToModify": mcastFlowOrGroupCb.group})
2666 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2667 // Pass the return value over the return channel
2668 *mcastFlowOrGroupCb.errChan <- err
2669 } else { // group remove
2670 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2671 log.Fields{"device-id": dh.device.Id,
2672 "groupToRemove": mcastFlowOrGroupCb.group})
2673 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2674 // Pass the return value over the return channel
2675 *mcastFlowOrGroupCb.errChan <- err
2676 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002677 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002678 case <-stopHandler:
2679 dh.mcastHandlerRoutineActive[routineIndex] = false
2680 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002681 }
2682 }
2683}
kesavand62126212021-01-12 04:56:06 -05002684
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002685// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002686func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002687 for i, v := range dh.stopMcastHandlerRoutine {
2688 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002689 select {
2690 case v <- true:
2691 case <-time.After(time.Second * 5):
2692 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2693 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002694 }
2695 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002696 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002697 logger.Debug(ctx, "stopped all mcast handler routines")
2698}
2699
kesavand62126212021-01-12 04:56:06 -05002700func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2701
2702 singleValResp := extension.SingleGetValueResponse{
2703 Response: &extension.GetValueResponse{
2704 Response: &extension.GetValueResponse_PortCoutners{
2705 PortCoutners: &extension.GetOltPortCountersResponse{},
2706 },
2707 },
2708 }
2709
2710 errResp := func(status extension.GetValueResponse_Status,
2711 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2712 return &extension.SingleGetValueResponse{
2713 Response: &extension.GetValueResponse{
2714 Status: status,
2715 ErrReason: reason,
2716 },
2717 }
2718 }
2719
2720 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2721 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2722 //send error response
2723 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2724 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2725 }
2726 statIndChn := make(chan bool, 1)
2727 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2728 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2729 //request openOlt agent to send the the port statistics indication
2730
2731 go func() {
2732 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2733 if err != nil {
2734 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2735 }
2736 }()
2737 select {
2738 case <-statIndChn:
2739 //indication received for ports stats
2740 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2741 case <-time.After(oltPortInfoTimeout * time.Second):
2742 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2743 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2744 case <-ctx.Done():
2745 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2746 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2747 }
2748 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2749 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002750 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002751 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2752 cmnni := dh.portStats.collectNNIMetrics(intfID)
2753 if cmnni == nil {
2754 //TODO define the error reason
2755 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2756 }
2757 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2758 return &singleValResp
2759
2760 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2761 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002762 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002763 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2764 cmpon := dh.portStats.collectPONMetrics(intfID)
2765 if cmpon == nil {
2766 //TODO define the error reason
2767 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2768 }
2769 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2770 return &singleValResp
2771 }
2772 }
2773 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2774}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302775
2776func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2777
2778 singleValResp := extension.SingleGetValueResponse{
2779 Response: &extension.GetValueResponse{
2780 Response: &extension.GetValueResponse_OnuPonCounters{
2781 OnuPonCounters: &extension.GetOnuCountersResponse{},
2782 },
2783 },
2784 }
2785
2786 errResp := func(status extension.GetValueResponse_Status,
2787 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2788 return &extension.SingleGetValueResponse{
2789 Response: &extension.GetValueResponse{
2790 Status: status,
2791 ErrReason: reason,
2792 },
2793 }
2794 }
2795 intfID := onuPonInfo.IntfId
2796 onuID := onuPonInfo.OnuId
2797 onuKey := dh.formOnuKey(intfID, onuID)
2798
2799 if _, ok := dh.onus.Load(onuKey); !ok {
2800 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2801 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2802 }
2803 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2804 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2805 if cmnni == nil {
2806 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2807 }
2808 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2809 return &singleValResp
2810
2811}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002812
2813func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2814
2815 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2816 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2817 if err != nil {
2818 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2819 return generateSingleGetValueErrorResponse(err)
2820 }
2821 return &extension.SingleGetValueResponse{
2822 Response: &extension.GetValueResponse{
2823 Status: extension.GetValueResponse_OK,
2824 Response: &extension.GetValueResponse_RxPower{
2825 RxPower: &extension.GetRxPowerResponse{
2826 IntfId: rxPowerRequest.IntfId,
2827 OnuId: rxPowerRequest.OnuId,
2828 Status: rxPower.Status,
2829 FailReason: rxPower.FailReason.String(),
2830 RxPower: rxPower.RxPowerMeanDbm,
2831 },
2832 },
2833 },
2834 }
2835}
2836
2837func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2838 errResp := func(status extension.GetValueResponse_Status,
2839 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2840 return &extension.SingleGetValueResponse{
2841 Response: &extension.GetValueResponse{
2842 Status: status,
2843 ErrReason: reason,
2844 },
2845 }
2846 }
2847
2848 if err != nil {
2849 if e, ok := status.FromError(err); ok {
2850 switch e.Code() {
2851 case codes.Internal:
2852 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2853 case codes.DeadlineExceeded:
2854 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2855 case codes.Unimplemented:
2856 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2857 case codes.NotFound:
2858 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2859 }
2860 }
2861 }
2862
2863 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2864}
khenaidoo106c61a2021-08-11 18:05:46 -04002865
2866/*
2867Helper functions to communicate with Core
2868*/
2869
2870func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2871 cClient, err := dh.coreClient.GetCoreServiceClient()
2872 if err != nil || cClient == nil {
2873 return nil, err
2874 }
2875 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2876 defer cancel()
2877 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
2878}
2879
khenaidoodc2116e2021-10-19 17:33:19 -04002880func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002881 cClient, err := dh.coreClient.GetCoreServiceClient()
2882 if err != nil || cClient == nil {
2883 return nil, err
2884 }
2885 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2886 defer cancel()
2887 return cClient.GetChildDevice(subCtx, childDeviceFilter)
2888}
2889
khenaidoodc2116e2021-10-19 17:33:19 -04002890func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002891 cClient, err := dh.coreClient.GetCoreServiceClient()
2892 if err != nil || cClient == nil {
2893 return err
2894 }
2895 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2896 defer cancel()
2897 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
2898 return err
2899}
2900
2901func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
2902 cClient, err := dh.coreClient.GetCoreServiceClient()
2903 if err != nil || cClient == nil {
2904 return nil, err
2905 }
2906 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2907 defer cancel()
2908 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
2909}
2910
2911func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
2912 cClient, err := dh.coreClient.GetCoreServiceClient()
2913 if err != nil || cClient == nil {
2914 return nil, err
2915 }
2916 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2917 defer cancel()
2918 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
2919}
2920
2921func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
2922 cClient, err := dh.coreClient.GetCoreServiceClient()
2923 if err != nil || cClient == nil {
2924 return err
2925 }
2926 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2927 defer cancel()
2928 _, err = cClient.DeviceUpdate(subCtx, device)
2929 return err
2930}
2931
khenaidoodc2116e2021-10-19 17:33:19 -04002932func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002933 cClient, err := dh.coreClient.GetCoreServiceClient()
2934 if err != nil || cClient == nil {
2935 return nil, err
2936 }
2937 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2938 defer cancel()
2939 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
2940}
2941
khenaidoodc2116e2021-10-19 17:33:19 -04002942func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002943 cClient, err := dh.coreClient.GetCoreServiceClient()
2944 if err != nil || cClient == nil {
2945 return err
2946 }
2947 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2948 defer cancel()
2949 _, err = cClient.SendPacketIn(subCtx, pkt)
2950 return err
2951}
2952
2953func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
2954 cClient, err := dh.coreClient.GetCoreServiceClient()
2955 if err != nil || cClient == nil {
2956 return err
2957 }
2958 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2959 defer cancel()
2960 _, err = cClient.PortCreated(subCtx, port)
2961 return err
2962}
2963
khenaidoodc2116e2021-10-19 17:33:19 -04002964func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002965 cClient, err := dh.coreClient.GetCoreServiceClient()
2966 if err != nil || cClient == nil {
2967 return err
2968 }
2969 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2970 defer cancel()
2971 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
2972 return err
2973}
2974
khenaidoodc2116e2021-10-19 17:33:19 -04002975func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002976 cClient, err := dh.coreClient.GetCoreServiceClient()
2977 if err != nil || cClient == nil {
2978 return err
2979 }
2980 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2981 defer cancel()
2982 _, err = cClient.PortStateUpdate(subCtx, portState)
2983 return err
2984}
2985
khenaidoodc2116e2021-10-19 17:33:19 -04002986func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002987 cClient, err := dh.coreClient.GetCoreServiceClient()
2988 if err != nil || cClient == nil {
2989 return nil, err
2990 }
2991 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2992 defer cancel()
2993 return cClient.GetDevicePort(subCtx, portFilter)
2994}
2995
2996/*
2997Helper functions to communicate with child adapter
2998*/
2999
khenaidoodc2116e2021-10-19 17:33:19 -04003000func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003001 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3002 if err != nil || aClient == nil {
3003 return err
3004 }
3005 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3006 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3007 defer cancel()
3008 _, err = aClient.OmciIndication(subCtx, response)
3009 return err
3010}
3011
khenaidoodc2116e2021-10-19 17:33:19 -04003012func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003013 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3014 if err != nil || aClient == nil {
3015 return err
3016 }
3017 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3018 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3019 defer cancel()
3020 _, err = aClient.OnuIndication(subCtx, onuInd)
3021 return err
3022}
3023
khenaidoodc2116e2021-10-19 17:33:19 -04003024func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003025 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3026 if err != nil || aClient == nil {
3027 return err
3028 }
3029 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3030 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3031 defer cancel()
3032 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3033 return err
3034}
3035
khenaidoodc2116e2021-10-19 17:33:19 -04003036func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003037 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3038 if err != nil || aClient == nil {
3039 return err
3040 }
3041 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3042 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3043 defer cancel()
3044 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3045 return err
3046}
3047
khenaidoodc2116e2021-10-19 17:33:19 -04003048func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003049 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3050 if err != nil || aClient == nil {
3051 return err
3052 }
3053 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3054 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3055 defer cancel()
3056 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3057 return err
3058}
3059
3060/*
3061Helper functions for remote communication
3062*/
3063
3064// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3065// supports is deleted
3066func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3067 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3068
3069 dh.lockChildAdapterClients.Lock()
3070 defer dh.lockChildAdapterClients.Unlock()
3071 if _, ok := dh.childAdapterClients[endpoint]; ok {
3072 // Already set
3073 return nil
3074 }
3075
3076 // Setup child's adapter grpc connection
3077 var err error
3078 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(endpoint,
3079 dh.onuAdapterRestarted,
3080 vgrpc.ActivityCheck(true)); err != nil {
3081 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3082 return err
3083 }
3084 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), setAndTestAdapterServiceHandler)
3085
3086 // Wait until we have a connection to the child adapter.
3087 // Unlimited retries or until context expires
3088 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3089 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3090 for {
3091 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3092 if err == nil && client != nil {
3093 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3094 break
3095 }
3096 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3097 // Backoff
3098 if err = backoff.Backoff(subCtx); err != nil {
3099 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3100 break
3101 }
3102 }
3103 return nil
3104}
3105
khenaidoodc2116e2021-10-19 17:33:19 -04003106func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003107
3108 // First check from cache
3109 dh.lockChildAdapterClients.RLock()
3110 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3111 dh.lockChildAdapterClients.RUnlock()
3112 return cgClient.GetOnuInterAdapterServiceClient()
3113 }
3114 dh.lockChildAdapterClients.RUnlock()
3115
3116 // Set the child connection - can occur on restarts
3117 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3118 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3119 cancel()
3120 if err != nil {
3121 return nil, err
3122 }
3123
3124 // Get the child client now
3125 dh.lockChildAdapterClients.RLock()
3126 defer dh.lockChildAdapterClients.RUnlock()
3127 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3128 return cgClient.GetOnuInterAdapterServiceClient()
3129 }
3130 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3131}
3132
3133func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3134 dh.lockChildAdapterClients.Lock()
3135 defer dh.lockChildAdapterClients.Unlock()
3136 for key, client := range dh.childAdapterClients {
3137 client.Stop(ctx)
3138 delete(dh.childAdapterClients, key)
3139 }
3140}
3141
3142// TODO: Any action the adapter needs to do following a onu adapter restart?
3143func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003144 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003145 return nil
3146}
3147
3148// setAndTestAdapterServiceHandler is used to test whether the remote gRPC service is up
3149func setAndTestAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
khenaidoodc2116e2021-10-19 17:33:19 -04003150 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
3151 if h, err := svc.GetHealthStatus(ctx, &empty.Empty{}); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003152 return nil
3153 }
3154 return svc
3155}
Girish Gowdra950326e2021-11-05 12:43:24 -07003156
3157func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3158 dh.lockDevice.Lock()
3159 defer dh.lockDevice.Unlock()
3160 dh.isDeviceDeletionInProgress = flag
3161}
3162
3163func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3164 dh.lockDevice.RLock()
3165 defer dh.lockDevice.RUnlock()
3166 return dh.isDeviceDeletionInProgress
3167}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003168
3169// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3170// Returns false if waiting timed out.
3171func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3172 c := make(chan struct{})
3173 go func() {
3174 defer close(c)
3175 wg.Wait()
3176 }()
3177 select {
3178 case <-c:
3179 return true // completed normally
3180 case <-time.After(timeout):
3181 return false // timed out
3182 }
3183}