blob: fa8dd52a027efb67d63489eb3e5aca4d73635341 [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
Matteo Scandolo945e4012019-12-12 14:16:11 -080033 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070034 "github.com/gogo/protobuf/proto"
35 "github.com/golang/protobuf/ptypes"
Girish Kumar93e91742020-07-27 16:43:19 +000036 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
37 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070038 "github.com/opencord/voltha-lib-go/v4/pkg/adapters/adapterif"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080039 "github.com/opencord/voltha-lib-go/v4/pkg/config"
Himani Chawlacd407802020-12-10 12:08:59 +053040 "github.com/opencord/voltha-lib-go/v4/pkg/events/eventif"
Girish Gowdra491a9c62021-01-06 16:43:07 -080041 flow_utils "github.com/opencord/voltha-lib-go/v4/pkg/flows"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070042 "github.com/opencord/voltha-lib-go/v4/pkg/log"
43 "github.com/opencord/voltha-lib-go/v4/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080044
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080046 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070047 "github.com/opencord/voltha-protos/v4/go/common"
48 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
49 of "github.com/opencord/voltha-protos/v4/go/openflow_13"
50 oop "github.com/opencord/voltha-protos/v4/go/openolt"
51 "github.com/opencord/voltha-protos/v4/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070052 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040053 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040054 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053055)
56
salmansiddiqui7ac62132019-08-22 03:58:50 +000057// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040058const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080059 InvalidPort = 0xffffffff
60 MaxNumOfGroupHandlerChannels = 256
61
62 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
63 McastFlowOrGroupModify = "McastFlowOrGroupModify"
64 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
Manikkaraj kb1d51442019-07-23 10:41:02 -040065)
66
Phaneendra Manda4c62c802019-03-06 21:37:49 +053067//DeviceHandler will interact with the OLT device.
68type DeviceHandler struct {
Matteo Scandolodfa7a972020-11-06 13:03:40 -080069 cm *config.ConfigManager
cuilin20187b2a8c32019-03-26 19:52:28 -070070 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053071 coreProxy adapterif.CoreProxy
72 AdapterProxy adapterif.AdapterProxy
Himani Chawlacd407802020-12-10 12:08:59 +053073 EventProxy eventif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070074 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070075 exitChannel chan int
76 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053077 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070078 transitionMap *TransitionMap
79 clientCon *grpc.ClientConn
Girish Gowdra9602eb42020-09-09 15:50:39 -070080 flowMgr []*OpenOltFlowMgr
81 groupMgr *OpenOltGroupMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040082 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053083 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053084
Girish Gowdra3ab6d212020-03-24 17:33:15 -070085 discOnus sync.Map
86 onus sync.Map
87 portStats *OpenOltStatisticsMgr
88 metrics *pmmetrics.PmMetrics
89 stopCollector chan bool
90 stopHeartbeatCheck chan bool
91 activePorts sync.Map
92 stopIndications chan bool
93 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070094
Mahir Gunyel2fb81472020-12-16 23:18:34 -080095 totalPonPorts uint32
96 perOnuChannel map[string]onuIndicationChannels
97 perOnuChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -080098
99 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
100 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
101 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700102}
103
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700104//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700105type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700106 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107 deviceType string
108 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109 onuID uint32
110 intfID uint32
111 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530112 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400113 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700114}
115
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800116type perOnuIndication struct {
117 ctx context.Context
118 indication *oop.Indication
119 serialNumber string
120}
121
122type onuIndicationChannels struct {
123 indicationChannel chan perOnuIndication
124 stopChannel chan struct{}
125}
126
Girish Gowdra491a9c62021-01-06 16:43:07 -0800127//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
128//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
129//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
130//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
131type McastFlowOrGroupControlBlock struct {
132 ctx context.Context // Flow/group handler context
133 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
134 flow *voltha.OfpFlowStats // Flow message (can be nil or valid flow)
135 group *voltha.OfpGroupEntry // Group message (can be nil or valid group)
136 errChan *chan error // channel to report the mcast Flow/group handling error
137}
138
Naga Manjunath7615e552019-10-11 22:35:47 +0530139var pmNames = []string{
140 "rx_bytes",
141 "rx_packets",
142 "rx_mcast_packets",
143 "rx_bcast_packets",
144 "tx_bytes",
145 "tx_packets",
146 "tx_mcast_packets",
147 "tx_bcast_packets",
148}
149
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700150//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530151func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700152 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700154 device.deviceType = deviceTp
155 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700156 device.onuID = onuID
157 device.intfID = intfID
158 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530159 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700160 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530161}
162
163//NewDeviceHandler creates a new device handler
Himani Chawlacd407802020-12-10 12:08:59 +0530164func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700165 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800166 dh.cm = cm
cuilin20187b2a8c32019-03-26 19:52:28 -0700167 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400168 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400169 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700170 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700171 dh.device = cloned
172 dh.openOLT = adapter
173 dh.exitChannel = make(chan int, 1)
174 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530175 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530176 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530177 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 -0500178 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400179 dh.stopIndications = make(chan bool, 1)
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800180 dh.perOnuChannel = make(map[string]onuIndicationChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800181 // Create a slice of buffered channels for handling concurrent mcast flow/group.
182 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
183 for i := range dh.incomingMcastFlowOrGroup {
184 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
185 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
186 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
187 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
188 // for incoming mcast flow/group to be processed serially.
189 go dh.mcastFlowOrGroupChannelHandlerRoutine(dh.incomingMcastFlowOrGroup[i])
190 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700191 //TODO initialize the support classes.
192 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530193}
194
195// start save the device to the data model
196func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700197 dh.lockDevice.Lock()
198 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000199 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700200 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000201 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530202}
203
204// stop stops the device dh. Not much to do for now
205func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700206 dh.lockDevice.Lock()
207 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000208 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700209 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000210 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530211}
212
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400213func macifyIP(ip net.IP) string {
214 if len(ip) > 0 {
215 oct1 := strconv.FormatInt(int64(ip[12]), 16)
216 oct2 := strconv.FormatInt(int64(ip[13]), 16)
217 oct3 := strconv.FormatInt(int64(ip[14]), 16)
218 oct4 := strconv.FormatInt(int64(ip[15]), 16)
219 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
220 }
221 return ""
222}
223
Neha Sharma96b7bf22020-06-15 10:37:32 +0000224func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400225 var genmac string
226 var addr net.IP
227 var ips []string
228 var err error
229
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400231
232 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000233 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400234
235 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000236 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400237 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000238 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400239 }
240 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000241 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530242 log.Fields{"host": ips[0],
243 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400244 return genmac, nil
245 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000246 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400247 }
248
249 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000250 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530251 log.Fields{"host": host,
252 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400253 return genmac, nil
254}
255
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530256func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700257 slist := strings.Split(mac, ":")
258 result := make([]uint32, len(slist))
259 var err error
260 var tmp int64
261 for index, val := range slist {
262 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
263 return []uint32{1, 2, 3, 4, 5, 6}
264 }
265 result[index] = uint32(tmp)
266 }
267 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530268}
269
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270//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 -0800271func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530272
David K. Bainbridge794735f2020-02-11 21:01:37 -0800273 switch portType {
274 case voltha.Port_ETHERNET_NNI:
275 return fmt.Sprintf("nni-%d", portNum), nil
276 case voltha.Port_PON_OLT:
277 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700278 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800279
Girish Kumarf26e4882020-03-05 06:49:10 +0000280 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530281}
282
Neha Sharma96b7bf22020-06-15 10:37:32 +0000283func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000284 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700285 if state == "up" {
286 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500287 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500288 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 } else {
290 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500291 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700292 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700293 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400294 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800295 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000296 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400297 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500298
Neha Sharma8f4e4322020-08-06 10:51:53 +0000299 if port, err := dh.coreProxy.GetDevicePort(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, portNum); err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000300 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000301 if err := dh.coreProxy.PortStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, portType, portNum, operStatus); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400302 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
303 "device-id": dh.device.Id,
304 "port-type": portType,
305 "port-number": portNum,
306 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500307 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400308 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500309 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400310 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700311 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400312 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 PortNo: portNum,
314 Label: label,
315 Type: portType,
316 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700317 OfpPort: &of.OfpPort{
318 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
319 Config: 0,
320 State: uint32(of.OfpPortState_OFPPS_LIVE),
321 Curr: capacity,
322 Advertised: capacity,
323 Peer: capacity,
324 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
325 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
326 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700327 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700329 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000330 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000331 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800332 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000333 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400334 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530336 return nil
337}
338
Kent Hagermane6ff1012020-07-14 15:07:53 -0400339func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530340 dh.lockDevice.Lock()
341 defer dh.lockDevice.Unlock()
Neha Sharma8f4e4322020-08-06 10:51:53 +0000342 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530343 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400344 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
345 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530346 }
347 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530348}
349
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700350// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530351// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800352func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000353 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700354 defer func() {
355 dh.lockDevice.Lock()
356 dh.isReadIndicationRoutineActive = false
357 dh.lockDevice.Unlock()
358 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700359 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700360 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700361 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700362 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400363 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530364 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400365 if err != nil || device == nil {
366 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000367 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400368 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400369
David Bainbridgef5879ca2019-12-13 21:17:54 +0000370 // Create an exponential backoff around re-enabling indications. The
371 // maximum elapsed time for the back off is set to 0 so that we will
372 // continue to retry. The max interval defaults to 1m, but is set
373 // here for code clarity
374 indicationBackoff := backoff.NewExponentialBackOff()
375 indicationBackoff.MaxElapsedTime = 0
376 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700377
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700378 dh.lockDevice.Lock()
379 dh.isReadIndicationRoutineActive = true
380 dh.lockDevice.Unlock()
381
Girish Gowdra3f974912020-03-23 20:35:18 -0700382Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700383 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400384 select {
385 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000386 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700387 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 default:
389 indication, err := indications.Recv()
390 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000391 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530392 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530393 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400394 // Use an exponential back off to prevent getting into a tight loop
395 duration := indicationBackoff.NextBackOff()
396 if duration == backoff.Stop {
397 // If we reach a maximum then warn and reset the backoff
398 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000399 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530400 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530401 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400402 indicationBackoff.Reset()
403 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700404
405 // On failure process a backoff timer while watching for stopIndications
406 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700407 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700408 select {
409 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000410 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700411 if !backoffTimer.Stop() {
412 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700413 }
414 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700415 case <-backoffTimer.C:
416 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700417 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700418 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
419 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400420 }
421 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000422 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530423 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000424 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530425 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530426 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700427 // Close the stream, and re-initialize it
428 if err = indications.CloseSend(); err != nil {
429 // Ok to ignore here, because we landed here due to a problem on the stream
430 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000431 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530432 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530433 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700434 }
435 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
436 return err
437 }
438 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400439 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530440 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400441 // Reset backoff if we have a successful receive
442 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400443 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530444 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000445 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530446 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530447 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400448 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400449 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400450 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700451 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700452 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700453 // Close the send stream
454 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700455
Girish Gowdra3f974912020-03-23 20:35:18 -0700456 return nil
457}
458
459func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
460
461 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
462 if err != nil {
463 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
464 }
465 if indications == nil {
466 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
467 }
468
469 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400470}
471
472// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
473func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
474 switch indication.Data.(type) {
475 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
476 return true
477
478 default:
479 return false
480 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700481}
482
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000484 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000485 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530486 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530488 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000490 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000491 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530492 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000493 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800494 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000495 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800496 }
497 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700498}
499
David K. Bainbridge794735f2020-02-11 21:01:37 -0800500// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530501func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400502 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 switch indication.Data.(type) {
504 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000505 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
506 defer span.Finish()
507
David K. Bainbridge794735f2020-02-11 21:01:37 -0800508 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800510 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000512 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
513 defer span.Finish()
514
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700515 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800516 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000517 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400518 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800519 }
520 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000521 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000523 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
524 defer span.Finish()
525
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 intfOperInd := indication.GetIntfOperInd()
527 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800528 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000529 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400530 _ = 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 -0800531 }
532 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400533 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
534 logger.Warn(ctx, err)
535 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 } else if intfOperInd.GetType() == "pon" {
537 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
538 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800539 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000540 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400541 _ = 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 -0800542 }
543 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700545 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000546 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530547 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530548 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700549 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000550 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
551 defer span.Finish()
552
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000554 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800556 //put message to channel and return immediately
557 dh.putOnuIndicationToChannel(ctx, indication, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000559 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
560 defer span.Finish()
561
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000563 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800564 sn := dh.stringifySerialNumber(onuInd.SerialNumber)
565 //put message to channel and return immediately
566 dh.putOnuIndicationToChannel(ctx, indication, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000568 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
569 defer span.Finish()
570
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700571 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 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 -0800573 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400575 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800576 }
577 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700578 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000579 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
580 defer span.Finish()
581
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000583 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700584 "intf-type": pktInd.IntfId,
585 "intf-id": pktInd.IntfId,
586 "gem-port-id": pktInd.GemportId,
587 "port-no": pktInd.PortNo,
588 "device-id": dh.device.Id,
589 })
590
591 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000592 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700593 "intf-type": pktInd.IntfId,
594 "intf-id": pktInd.IntfId,
595 "gem-port-id": pktInd.GemportId,
596 "port-no": pktInd.PortNo,
597 "packet": hex.EncodeToString(pktInd.Pkt),
598 "device-id": dh.device.Id,
599 })
600 }
601
David K. Bainbridge794735f2020-02-11 21:01:37 -0800602 go func() {
603 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400604 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800605 }
606 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700607 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000608 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
609 defer span.Finish()
610
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700612 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000614 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
615 defer span.Finish()
616
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000618 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000620 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
621 defer span.Finish()
622
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700623 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000624 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
625 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700626 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530627}
628
629// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530630func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530631 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000632 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530633
Girish Gowdru0c588b22019-04-23 23:24:56 -0400634 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530635 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400636 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000637 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000639
640 //Clear olt communication failure event
641 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
642 dh.device.OperStatus = voltha.OperStatus_ACTIVE
643 raisedTs := time.Now().UnixNano()
644 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
645
Girish Gowdru0c588b22019-04-23 23:24:56 -0400646 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530647}
648
649// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530650func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700651 dh.lockDevice.Lock()
652 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000653 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400654
npujarec5762e2020-01-01 14:08:48 +0530655 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400656 if err != nil || device == nil {
657 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000658 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400659 }
660
661 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400662
663 //Update the device oper state and connection status
664 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400665 dh.device = cloned
666
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000668 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400669 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400670
671 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530672 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400673 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000674 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400675 }
676 for _, onuDevice := range onuDevices.Items {
677
678 // Update onu state as down in onu adapter
679 onuInd := oop.OnuIndication{}
680 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800681 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300682 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800683 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400684 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300685 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800686 "onu-indicator": onuInd,
687 "device-type": onuDevice.Type,
688 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700689 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400691 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700692 /* Discovered ONUs entries need to be cleared , since after OLT
693 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530694 dh.discOnus = sync.Map{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700696 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530697}
698
699// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530700func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400701 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000702 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
703 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
704 grpc.WithInsecure(),
705 grpc.WithBlock(),
706 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000707 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000708 )),
709 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000710 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000711 )))
712
713 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530714 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530715 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000716 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400717 }
718 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530719}
720
721// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530722func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400723 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530724 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400725 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530726}
727
728// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530729func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530730 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000731 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400732
733 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530734 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
735 if err != nil || device == nil {
736 /*TODO: needs to handle error scenarios */
737 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
738 }
739 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000740 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400741
742 cloned := proto.Clone(device).(*voltha.Device)
743 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
744 cloned.OperStatus = voltha.OperStatus_UNKNOWN
745 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530746 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
747 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 -0400748 }
749
Chaitrashree G S44124192019-08-07 20:21:36 -0400750 // 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 +0530751 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400752 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530753 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400754 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400755 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
756 // all the modules initialized and ready to handle incoming ONUs.
757
Thomas Lee S985938d2020-05-04 11:40:41 +0530758 err = dh.initializeDeviceHandlerModules(ctx)
759 if err != nil {
760 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 -0400761 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400762
763 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800764 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530765 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400766 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800767 }
768 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700769
770 go startHeartbeatCheck(ctx, dh)
771
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400772 return nil
773 }
774
Neha Sharma8f4e4322020-08-06 10:51:53 +0000775 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400776 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400777 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400778 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400779 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400780 dh.populateActivePorts(ctx, ports)
781 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
782 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400783 }
784
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400785 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530786 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 -0400787 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530788
cuilin20187b2a8c32019-03-26 19:52:28 -0700789 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800790 go func() {
791 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400792 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800793 }
794 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000795 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000796
797 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000799 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700800
801 go startHeartbeatCheck(ctx, dh)
802
cuilin20187b2a8c32019-03-26 19:52:28 -0700803 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530804}
805
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400806func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000807 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400808
809 if err != nil {
810 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
811 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700812 dh.totalPonPorts = deviceInfo.GetPonPorts()
813
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400814 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800815 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400816 return olterrors.ErrResourceManagerInstantiating
817 }
818
Girish Gowdra9602eb42020-09-09 15:50:39 -0700819 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400820
Girish Gowdra9602eb42020-09-09 15:50:39 -0700821 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
822 for i := range dh.flowMgr {
823 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700824 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700825 return olterrors.ErrResourceManagerInstantiating
826 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400827 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700828
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400829 /* TODO: Instantiate Alarm , stats , BW managers */
830 /* Instantiating Event Manager to handle Alarms and KPIs */
831 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
832
833 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400835
836 return nil
837
838}
839
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400841 var err error
842 var deviceInfo *oop.DeviceInfo
843
Neha Sharma8f4e4322020-08-06 10:51:53 +0000844 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400845
846 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000847 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400848 }
849 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000850 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400851 }
852
Neha Sharma96b7bf22020-06-15 10:37:32 +0000853 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400854 dh.device.Root = true
855 dh.device.Vendor = deviceInfo.Vendor
856 dh.device.Model = deviceInfo.Model
857 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
858 dh.device.HardwareVersion = deviceInfo.HardwareVersion
859 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
860
861 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400863 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000864 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400865 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000866 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400867 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000868 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400869 dh.device.MacAddress = genmac
870 } else {
871 dh.device.MacAddress = deviceInfo.DeviceId
872 }
873
874 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000875 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000876 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400877 }
878
879 return deviceInfo, nil
880}
881
Neha Sharma96b7bf22020-06-15 10:37:32 +0000882func startCollector(ctx context.Context, dh *DeviceHandler) {
883 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530884 for {
885 select {
886 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000887 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530888 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000889 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700890
Neha Sharma8f4e4322020-08-06 10:51:53 +0000891 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400892 if err != nil {
893 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
894 continue
895 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530896 for _, port := range ports {
897 // NNI Stats
898 if port.Type == voltha.Port_ETHERNET_NNI {
899 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
900 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000901 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000902 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000903 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530904 }
905 // PON Stats
906 if port.Type == voltha.Port_PON_OLT {
907 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
908 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
909 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000910 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000911 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530912 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000913 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000914
915 //ONU & Gem Stats
916 onuGemInfo := dh.flowMgr[intfID].onuGemInfo
917 if len(onuGemInfo) != 0 {
918 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfo)
919 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500920 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530921 }
922 }
923 }
924}
925
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530927func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400928 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000929 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530930 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530931
932 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400933 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
934 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530935 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530936}
937
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530939func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700940 return &ic.SwitchCapability{
941 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530942 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700943 HwDesc: "open_pon",
944 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700945 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700946 },
947 SwitchFeatures: &of.OfpSwitchFeatures{
948 NBuffers: 256,
949 NTables: 2,
950 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
951 of.OfpCapabilities_OFPC_TABLE_STATS |
952 of.OfpCapabilities_OFPC_PORT_STATS |
953 of.OfpCapabilities_OFPC_GROUP_STATS),
954 },
955 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530956}
957
Neha Sharma96b7bf22020-06-15 10:37:32 +0000958func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
959 logger.Debugw(ctx, "omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700960 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700961 var deviceID string
962 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700963
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400964 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700965 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 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 -0700967 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
968 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400969
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700970 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530971
972 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
973
Neha Sharma96b7bf22020-06-15 10:37:32 +0000974 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})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700976 kwargs := make(map[string]interface{})
977 kwargs["onu_id"] = omciInd.OnuId
978 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700979
Neha Sharma8f4e4322020-08-06 10:51:53 +0000980 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530982 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700983 "intf-id": omciInd.IntfId,
984 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700985 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986 deviceType = onuDevice.Type
987 deviceID = onuDevice.Id
988 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
989 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530990 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700991 } else {
992 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000993 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 +0530994 deviceType = onuInCache.(*OnuDevice).deviceType
995 deviceID = onuInCache.(*OnuDevice).deviceID
996 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700997 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700998
999 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001000 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001001 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301003 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001004 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 "destination": deviceType,
1006 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001007 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001008 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001009 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301010}
1011
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012//ProcessInterAdapterMessage sends the proxied messages to the target device
1013// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1014// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001015func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1016 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001017 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -07001019 fromTopic := msg.Header.FromTopic
1020 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 toDeviceID := msg.Header.ToDeviceId
1022 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001023
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 logger.Debugw(ctx, "omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -07001025
1026 msgBody := msg.GetBody()
1027
1028 omciMsg := &ic.InterAdapterOmciMessage{}
1029 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001030 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001031 }
1032
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001033 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001034 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301036 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001038 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001039 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001040 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1041 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301042 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001044 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001046 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1048 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301049 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001050 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001051 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001052 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001053 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001054 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001055 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001056 }
1057 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301058}
1059
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001061 var intfID uint32
1062 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001063 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001064 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001065 intfID = onuDevice.ProxyAddress.GetChannelId()
1066 onuID = onuDevice.ProxyAddress.GetOnuId()
1067 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001068 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001069 intfID = omciMsg.GetProxyAddress().GetChannelId()
1070 onuID = omciMsg.GetProxyAddress().GetOnuId()
1071 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001072 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001073 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001074 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 -08001075
Thomas Lee S94109f12020-03-03 16:39:29 +05301076 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001077 "intf-id": intfID,
1078 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001079 }
1080
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001081 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1082 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001083 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001084 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1085 hex.Encode(hexPkt, omciMsg.Message)
1086 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1087
1088 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1089 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1090 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001091 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001092 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001093
Neha Sharma8f4e4322020-08-06 10:51:53 +00001094 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001095 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301096 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001097 "intf-id": intfID,
1098 "onu-id": onuID,
1099 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001102}
1103
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301105 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 Gowdra9602eb42020-09-09 15:50:39 -07001106 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001107 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001108 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001109 // TODO: need resource manager
1110 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301111 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301112 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001113 st, _ := status.FromError(err)
1114 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001115 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1116
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001117 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301118 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001119 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001120 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001121 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001122 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001124}
1125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001127 channelID := onuDiscInd.GetIntfId()
1128 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001129
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301131
cuilin20187b2a8c32019-03-26 19:52:28 -07001132 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001133 if sn != "" {
1134 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001135 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001136 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001137 }
1138
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301139 var alarmInd oop.OnuAlarmIndication
1140 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001141 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301142
1143 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1144 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1145 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1146 OnuLosRaise event sent for it */
1147 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1148 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1149 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001150 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301151 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1152 "currentIntfId": onuDiscInd.GetIntfId()})
1153 // TODO:: Should we need to ignore raising OnuLosClear event
1154 // when onu connected to different PON?
1155 }
1156 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1157 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1158 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001159 go func() {
1160 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1161 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1162 }
1163 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301164 }
1165 return true
1166 })
1167
Neha Sharma96b7bf22020-06-15 10:37:32 +00001168 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001170 }
1171
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001172 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001173
1174 // check the ONU is already know to the OLT
1175 // NOTE the second time the ONU is discovered this should return a device
1176 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1177
1178 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001179 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 -08001180 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001181 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 -08001182 switch e.Code() {
1183 case codes.Internal:
1184 // this probably means NOT FOUND, so just create a new device
1185 onuDevice = nil
1186 case codes.DeadlineExceeded:
1187 // if the call times out, cleanup and exit
1188 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001189 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001190 }
1191 }
1192 }
1193
1194 if onuDevice == nil {
1195 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001196 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001197 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001198 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301199 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001200
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001202
1203 if err != nil {
1204 // if we can't create an ID in resource manager,
1205 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001206 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001207 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001208 "pon-intf-id": ponintfid,
1209 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001210 }
1211
Neha Sharma8f4e4322020-08-06 10:51:53 +00001212 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001213 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001214 dh.discOnus.Delete(sn)
1215 dh.resourceMgr.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 +05301216 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001217 "pon-intf-id": ponintfid,
1218 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001219 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001220 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1221 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1222 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001223 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301224 log.Fields{"onuDevice": onuDevice,
1225 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001226 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301227 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001228 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001229
1230 // we can now use the existing ONU Id
1231 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001232 //Insert the ONU into cache to use in OnuIndication.
1233 //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 +00001234 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001235 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301236 "intfId": onuDiscInd.GetIntfId(),
1237 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001238 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001239
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301240 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301241 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001242 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301243 log.Fields{"onu": onuDev,
1244 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001245
Kent Hagermane6ff1012020-07-14 15:07:53 -04001246 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301247 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001248 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001249 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001250 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001251 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001252 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301253 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001255 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 }
1257 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001258}
1259
Mahir Gunyel2fb81472020-12-16 23:18:34 -08001260func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication, serialNumber string) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001261
1262 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001263 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001264 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001266 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001267 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301268 log.Fields{"onuId": onuInd.OnuId,
1269 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301270 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001271 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301272
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273 errFields := log.Fields{"device-id": dh.device.Id}
1274
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301275 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1276
Mahir Gunyele77977b2019-06-27 05:36:22 -07001277 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1278 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001279 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001280 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001281 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001282 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1283 if serialNumber != "" {
1284 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001286 } else {
1287 kwargs["onu_id"] = onuInd.OnuId
1288 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 errFields["onu-id"] = onuInd.OnuId
1290 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001291 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001292 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001293 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001294
David K. Bainbridge794735f2020-02-11 21:01:37 -08001295 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001296 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001297 }
1298
David K. Bainbridge794735f2020-02-11 21:01:37 -08001299 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001300 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 "previousIntfId": onuDevice.ParentPortNo,
1302 "currentIntfId": ponPort})
1303 }
1304
1305 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001306 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301307 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1308 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301309 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 }
1311 if !foundInCache {
1312 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1313
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301314 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001315
1316 }
kesavand7cf3a052020-08-28 12:49:18 +05301317 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
1318 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().UnixNano()); err != nil {
1319 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1320 }
1321 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001324 }
1325 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001326}
1327
Neha Sharma96b7bf22020-06-15 10:37:32 +00001328func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001329 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 -07001330 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1331 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1332 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1333 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001334 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001335 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1336 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001337 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001338 onuInd.OperState = "down"
1339 }
1340 }
1341
David K. Bainbridge794735f2020-02-11 21:01:37 -08001342 switch onuInd.OperState {
1343 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301346 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001347 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301349 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001351 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001353 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001355 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001356 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001357 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301358 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001359 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301361 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001363 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001365 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001368 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001370 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371}
1372
cuilin20187b2a8c32019-03-26 19:52:28 -07001373func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1374 if serialNum != nil {
1375 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001376 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001377 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001378}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001379func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1380 decodedStr, err := hex.DecodeString(serialNum[4:])
1381 if err != nil {
1382 return nil, err
1383 }
1384 return &oop.SerialNumber{
1385 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001386 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001387 }, nil
1388}
cuilin20187b2a8c32019-03-26 19:52:28 -07001389
1390func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1391 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001393 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1394 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1395 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1396 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1397 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1398 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1399 return tmp
1400}
1401
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402//UpdateFlowsBulk upates the bulk flow
1403func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301404 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001405}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001406
1407//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001408func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1409 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301410 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001411 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301412 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001413 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001414 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001415 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001416 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001417 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001418 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001419 "intf-id": parentPort,
1420 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001421 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001422 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 -08001423 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301424}
1425
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426// SendPacketInToCore sends packet-in to core
1427// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1428// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001429func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001430 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001431 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001432 "port": logicalPort,
1433 "packet": hex.EncodeToString(packetPayload),
1434 "device-id": dh.device.Id,
1435 })
1436 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001437 if err := dh.coreProxy.SendPacketIn(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301438 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001439 "source": "adapter",
1440 "destination": "core",
1441 "device-id": dh.device.Id,
1442 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001443 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001444 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001445 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001446 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001447 "packet": hex.EncodeToString(packetPayload),
1448 "device-id": dh.device.Id,
1449 })
1450 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001451 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001452}
1453
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001454// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001455func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001456 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001457
1458 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1459 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001461 }
1462
Kent Hagermane6ff1012020-07-14 15:07:53 -04001463 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001464 metrics := dh.metrics.GetSubscriberMetrics()
1465 for _, m := range pmConfigs.Metrics {
1466 metrics[m.Name].Enabled = m.Enabled
1467
1468 }
1469 }
1470}
1471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301473func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001474 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001475
Girish Gowdra491a9c62021-01-06 16:43:07 -08001476 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001477 var errorsList []error
1478
Girish Gowdru0c588b22019-04-23 23:24:56 -04001479 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001480 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001481 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001482
Neha Sharma96b7bf22020-06-15 10:37:32 +00001483 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301484 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001485 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301486 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001487 if flow_utils.HasGroup(flow) {
1488 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1489 } else {
1490 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1491 }
Girish Gowdracefae192020-03-19 18:14:10 -07001492 if err != nil {
1493 errorsList = append(errorsList, err)
1494 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001495 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301496
1497 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001498 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001499 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301500 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001501 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301502 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001503 if flow_utils.HasGroup(flow) {
1504 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1505 } else {
1506 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1507 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001508 if err != nil {
1509 errorsList = append(errorsList, err)
1510 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301511 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001512 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001513
Girish Gowdracefae192020-03-19 18:14:10 -07001514 // 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 +00001515 if groups != nil {
1516 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001517 // err = dh.groupMgr.AddGroup(ctx, group)
1518 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001519 if err != nil {
1520 errorsList = append(errorsList, err)
1521 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001522 }
1523 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001524 // err = dh.groupMgr.ModifyGroup(ctx, group)
1525 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001526 if err != nil {
1527 errorsList = append(errorsList, err)
1528 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001529 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001530 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001531 // err = dh.groupMgr.DeleteGroup(ctx, group)
1532 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001533 if err != nil {
1534 errorsList = append(errorsList, err)
1535 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001536 }
1537 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001538 if len(errorsList) > 0 {
1539 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1540 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001541 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001542 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301543}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001544
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545//DisableDevice disables the given device
1546//It marks the following for the given device:
1547//Device-Handler Admin-State : down
1548//Device Port-State: UNKNOWN
1549//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001550func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001551 /* On device disable ,admin state update has to be done prior sending request to agent since
1552 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001553 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001554 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001555 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001556 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001557 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001558 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001559 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001560 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001561 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001562 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301563
1564 dh.discOnus = sync.Map{}
1565 dh.onus = sync.Map{}
1566
Thomas Lee S85f37312020-04-03 17:06:12 +05301567 //stopping the stats collector
1568 dh.stopCollector <- true
1569
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001571 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301572 //Update device Admin state
1573 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001574 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
Neha Sharma8f4e4322020-08-06 10:51:53 +00001575 if err := dh.coreProxy.PortsStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), cloned.Id, ^uint32(1<<voltha.Port_PON_OLT), voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001576 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001579 return nil
1580}
1581
Neha Sharma96b7bf22020-06-15 10:37:32 +00001582func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001583 // Update onu state as unreachable in onu adapter
1584 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301585 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001586 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001587 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001588 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001589 logger.Errorw(ctx, "failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001590 }
1591 if onuDevices != nil {
1592 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001593 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001594 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001595 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001597 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001598 }
1599
1600 }
1601 }
1602
1603}
1604
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001605//ReenableDevice re-enables the olt device after disable
1606//It marks the following for the given device:
1607//Device-Handler Admin-State : up
1608//Device Port-State: ACTIVE
1609//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001610func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001611 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301612 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001613 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301614 }
1615 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001616 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001617
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001618 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001619
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001620 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1621 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001622 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001623 }
1624 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001625 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001626 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001627 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001628 device.OperStatus = voltha.OperStatus_ACTIVE
1629 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001630
Neha Sharma8f4e4322020-08-06 10:51:53 +00001631 if err := dh.coreProxy.DeviceStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), device.Id, device.ConnectStatus, device.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301632 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001633 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001634 "connect-status": device.ConnectStatus,
1635 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001636 }
kesavand39e0aa32020-01-28 20:58:50 -05001637
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001639
1640 return nil
1641}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001642
npujarec5762e2020-01-01 14:08:48 +05301643func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001644 var uniID uint32
1645 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301646 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001647 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001649 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001650 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001652 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001653 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301654 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001655 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301656 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001658 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301660 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001662 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301664 }
npujarec5762e2020-01-01 14:08:48 +05301665 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1666 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301668 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001670 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 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 +00001672 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001673 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1674 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1675 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001676 }
1677 return nil
1678}
1679
npujarec5762e2020-01-01 14:08:48 +05301680func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001681 nniUniID := -1
1682 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301683
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001684 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301685 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001686 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001687 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301688 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301689 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001690 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001691 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001692 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301693 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301694 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001695 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1696
Devmalya Paul495b94a2019-08-27 19:42:00 -04001697 }
npujarec5762e2020-01-01 14:08:48 +05301698 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001699 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301700 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001701
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001703}
1704
1705// 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 +05301706func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001707 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001708 /* Clear the KV store data associated with the all the UNI ports
1709 This clears up flow data and also resource map data for various
1710 other pon resources like alloc_id and gemport_id
1711 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001712 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001714 // Stop the Stats collector
1715 dh.stopCollector <- true
1716 // stop the heartbeat check routine
1717 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301718 dh.lockDevice.RLock()
1719 // Stop the read indication only if it the routine is active
1720 if dh.isReadIndicationRoutineActive {
1721 dh.stopIndications <- true
1722 }
1723 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001724 //Reset the state
1725 if dh.Client != nil {
1726 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301727 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001728 }
1729 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001730 // There is no need to update the core about operation status and connection status of the OLT.
1731 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1732 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1733 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001734 return nil
1735}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001736func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001737
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001738 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301739 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001740 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301741 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301742 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301743 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001744 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001745 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001746 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301747 }
1748 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301749 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001750 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301751 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001752 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301753 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301754 // Clear flowids for gem cache.
1755 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301756 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301757 }
1758 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301759 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301760 }
npujarec5762e2020-01-01 14:08:48 +05301761 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301762 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301763 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301764 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001766 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001767 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001768 /* Clear the flows from KV store associated with NNI port.
1769 There are mostly trap rules from NNI port (like LLDP)
1770 */
npujarec5762e2020-01-01 14:08:48 +05301771 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001773 }
A R Karthick1f85b802019-10-11 05:06:05 +00001774
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001775 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001776 go func() {
1777 if err := dh.resourceMgr.Delete(ctx); err != nil {
1778 logger.Debug(ctx, err)
1779 }
1780 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001781 }
A R Karthick1f85b802019-10-11 05:06:05 +00001782
Devmalya Paul495b94a2019-08-27 19:42:00 -04001783 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301784 dh.onus.Range(func(key interface{}, value interface{}) bool {
1785 dh.onus.Delete(key)
1786 return true
1787 })
1788
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001789 /*Delete discovered ONU map for the device*/
1790 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1791 dh.discOnus.Delete(key)
1792 return true
1793 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001794}
1795
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001796//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001798 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301799 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001800 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001802 return nil
1803}
1804
David K. Bainbridge794735f2020-02-11 21:01:37 -08001805func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001806 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001808 "packet-indication": *packetIn,
1809 "device-id": dh.device.Id,
1810 "packet": hex.EncodeToString(packetIn.Pkt),
1811 })
1812 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001813 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001814 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001815 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001816 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001817 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001819 "logical-port-num": logicalPortNum,
1820 "device-id": dh.device.Id,
1821 "packet": hex.EncodeToString(packetIn.Pkt),
1822 })
1823 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824
Neha Sharma8f4e4322020-08-06 10:51:53 +00001825 if err := dh.coreProxy.SendPacketIn(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301826 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001827 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301828 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001829 "device-id": dh.device.Id,
1830 "packet": hex.EncodeToString(packetIn.Pkt),
1831 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001832 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001833
Matteo Scandolo92186242020-06-12 10:54:18 -07001834 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001836 "packet": hex.EncodeToString(packetIn.Pkt),
1837 "device-id": dh.device.Id,
1838 })
1839 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001840 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001841}
1842
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001843// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301844func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001845 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001846 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001847 "device-id": dh.device.Id,
1848 "egress-port-no": egressPortNo,
1849 "pkt-length": len(packet.Data),
1850 "packet": hex.EncodeToString(packet.Data),
1851 })
1852 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001853
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001854 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001855 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001856 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1857 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301858 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1859 // Do not packet-out lldp packets on uni port.
1860 // ONOS has no clue about uni/nni ports, it just packets out on all
1861 // available ports on the Logical Switch. It should not be interested
1862 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001863 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001864 "device-id": dh.device.Id,
1865 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301866 return nil
1867 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001868 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1869 if innerEthType == 0x8100 {
1870 // q-in-q 802.1ad or 802.1q double tagged packet.
1871 // slice out the outer tag.
1872 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001873 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001875 "packet-data": hex.EncodeToString(packet.Data),
1876 "device-id": dh.device.Id,
1877 })
1878 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001879 }
1880 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001881 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1882 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001883 uniID := UniIDFromPortNum(uint32(egressPortNo))
1884
Girish Gowdra9602eb42020-09-09 15:50:39 -07001885 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001886 if err != nil {
1887 // In this case the openolt agent will receive the gemPortID as 0.
1888 // The agent tries to retrieve the gemPortID in this case.
1889 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001890 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001891 "intf-id": intfID,
1892 "onu-id": onuID,
1893 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001894 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301895 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001896 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001897 }
1898
1899 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001900 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001901 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001902 "egress-port-no": egressPortNo,
1903 "intf-id": intfID,
1904 "onu-id": onuID,
1905 "uni-id": uniID,
1906 "gem-port-id": gemPortID,
1907 "packet": hex.EncodeToString(packet.Data),
1908 "device-id": dh.device.Id,
1909 })
1910 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001911
npujarec5762e2020-01-01 14:08:48 +05301912 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301913 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001914 "source": "adapter",
1915 "destination": "onu",
1916 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001917 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001918 "oni-id": onuID,
1919 "uni-id": uniID,
1920 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001921 "packet": hex.EncodeToString(packet.Data),
1922 "device-id": dh.device.Id,
1923 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001924 }
1925 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001926 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001927 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001928 return olterrors.NewErrInvalidValue(log.Fields{
1929 "egress-nni-port": egressPortNo,
1930 "device-id": dh.device.Id,
1931 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001932 }
1933 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001934
Matteo Scandolo92186242020-06-12 10:54:18 -07001935 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001936 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001937 "uplink-pkt": uplinkPkt,
1938 "packet": hex.EncodeToString(packet.Data),
1939 "device-id": dh.device.Id,
1940 })
1941 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001942
npujarec5762e2020-01-01 14:08:48 +05301943 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001944 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1945 "packet": hex.EncodeToString(packet.Data),
1946 "device-id": dh.device.Id,
1947 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001948 }
1949 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001950 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301951 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001952 "egressPortType": egressPortType,
1953 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301954 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001955 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001956 }
1957 return nil
1958}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001959
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001960func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1961 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001962}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301963
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001964func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001965
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301966 // start the heartbeat check towards the OLT.
1967 var timerCheck *time.Timer
1968
1969 for {
1970 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1971 select {
1972 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001973 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001974 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301976 if timerCheck == nil {
1977 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001978 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301979 }
1980 } else {
1981 if timerCheck != nil {
1982 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001983 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301984 }
1985 timerCheck = nil
1986 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001987 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301988 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301989 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301990 }
1991 cancel()
1992 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001993 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301994 return
1995 }
1996 }
1997}
1998
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001999func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2000 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2001 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002002 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2003 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2004 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2005 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2006 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002007 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002008 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2009 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002010 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302011
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002012 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2013 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002014 _ = 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 -04002015 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002016 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002017 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002018 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002019
2020 //raise olt communication failure event
2021 raisedTs := time.Now().UnixNano()
2022 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2023 device.OperStatus = voltha.OperStatus_UNKNOWN
2024 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2025
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002026 go dh.cleanupDeviceResources(ctx)
2027
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002028 dh.lockDevice.RLock()
2029 // Stop the read indication only if it the routine is active
2030 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2031 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2032 // on next execution of the readIndication routine.
2033 if dh.isReadIndicationRoutineActive {
2034 dh.stopIndications <- true
2035 }
2036 dh.lockDevice.RUnlock()
2037
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002038 dh.transitionMap.Handle(ctx, DeviceInit)
2039
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302040 }
2041}
kesavand39e0aa32020-01-28 20:58:50 -05002042
2043// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2045 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2046 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002047}
2048
2049// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2051 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2052 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002053}
2054
kdarapu1afeceb2020-02-12 01:38:09 -05002055//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 +00002056func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2057 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002058 if port.GetType() == voltha.Port_ETHERNET_NNI {
2059 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302061 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302062 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002063 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002064 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002065 }
2066 // fetch interfaceid from PortNo
2067 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2068 ponIntf := &oop.Interface{IntfId: ponID}
2069 var operStatus voltha.OperStatus_Types
2070 if enablePort {
2071 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302072 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002073
2074 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302075 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002076 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002077 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002078 }
2079 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002080 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002082 } else {
2083 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302084 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002085 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302086 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002088 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002089 }
2090 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002091 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002092 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002093 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302094 if err := dh.coreProxy.PortStateUpdate(ctx, dh.device.Id, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302095 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302096 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002097 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002098 }
2099 return nil
2100}
2101
kdarapu1afeceb2020-02-12 01:38:09 -05002102//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002103func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002104 // Disable the port and update the oper_port_status to core
2105 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002106 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002107 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002108 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302109 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302110 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002111 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002112 }
2113 }
2114 }
2115 return nil
2116}
2117
2118//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002119func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2120 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2121 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002122 if port.Type == voltha.Port_ETHERNET_NNI {
2123 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002124 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002125 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002126 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002127 }
2128 }
2129 if port.Type == voltha.Port_PON_OLT {
2130 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002131 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002132 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002133 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002134 }
2135 }
2136 }
2137}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002138
2139// ChildDeviceLost deletes ONU and clears pon resources related to it.
2140func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
divyadesai3af43e12020-08-18 07:10:54 +00002141 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002142 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2143 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002144 onuDevice, ok := dh.onus.Load(onuKey)
2145 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302146 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002147 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002148 "device-id": dh.device.Id,
2149 "onu-id": onuID,
2150 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002151 }
2152 var sn *oop.SerialNumber
2153 var err error
2154 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302155 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002156 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302157 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002158 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2159 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002160
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002161 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002162 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302163 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302164 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002165 "onu-id": onuID}, err).Log()
2166 }
2167 //clear PON resources associated with ONU
2168 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002169 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002170 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002171 "device-id": dh.device.Id,
2172 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002173 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002174 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002175 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002176 "device-id": dh.device.Id,
2177 "intf-id": intfID,
2178 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002179 } else {
2180 for i, onu := range onuGemData {
2181 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002183 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302185 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002186 "onu-device": onu,
2187 "error": err})
2188 }
2189 // Clear flowids for gem cache.
2190 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002191 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002192 }
2193 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002194 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002195 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002196 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002197 "intf-id": intfID,
2198 "onu-device": onu,
2199 "onu-gem": onuGemData,
2200 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002201 //Not returning error on cleanup.
2202 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002203 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002204 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002205 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002206 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002207 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002208 }
2209 }
2210 dh.onus.Delete(onuKey)
2211 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002212 dh.removeOnuIndicationChannels(ctx, onuDevice.(*OnuDevice).serialNumber)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002213 return nil
2214}
Girish Gowdracefae192020-03-19 18:14:10 -07002215
2216func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002217 for _, field := range flow_utils.GetOfbFields(flow) {
2218 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002219 return field.GetPort()
2220 }
2221 }
2222 return InvalidPort
2223}
2224
2225func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002226 for _, action := range flow_utils.GetActions(flow) {
2227 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002228 if out := action.GetOutput(); out != nil {
2229 return out.GetPort()
2230 }
2231 }
2232 }
2233 return InvalidPort
2234}
2235
Girish Gowdracefae192020-03-19 18:14:10 -07002236func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2237 inPort := getInPortFromFlow(flow)
2238 outPort := getOutPortFromFlow(flow)
2239
2240 if inPort == InvalidPort || outPort == InvalidPort {
2241 return inPort, outPort
2242 }
2243
2244 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2245 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2246 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002247 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002248 return uniPort, outPort
2249 }
2250 }
2251 } else {
2252 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2253 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002254 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002255 return inPort, uniPort
2256 }
2257 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2258 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002259 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002260 return uniPort, outPort
2261 }
2262 }
2263 }
2264
2265 return InvalidPort, InvalidPort
2266}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002267
2268func extractOmciTransactionID(omciPkt []byte) uint16 {
2269 if len(omciPkt) > 3 {
2270 d := omciPkt[0:2]
2271 transid := binary.BigEndian.Uint16(d)
2272 return transid
2273 }
2274 return 0
2275}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002276
2277// StoreOnuDevice stores the onu parameters to the local cache.
2278func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2279 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2280 dh.onus.Store(onuKey, onuDevice)
2281}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002282
Neha Sharma8f4e4322020-08-06 10:51:53 +00002283func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002284 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002285 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002286 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002287 resp := new(voltha.ReturnValues)
2288 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002289 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002290 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002291 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2292 return nil, err
2293 }
2294 ID = device.ProxyAddress.GetOnuId()
2295 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2296 valueparam.Onu = &Onu
2297 valueparam.Value = value
2298
2299 // This API is unsupported until agent patch is added
2300 resp.Unsupported = uint32(value)
2301 _ = ctx
2302
2303 // Uncomment this code once agent changes are complete and tests
2304 /*
2305 resp, err = dh.Client.GetValue(ctx, valueparam)
2306 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002307 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002308 return nil, err
2309 }
2310 */
2311
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002312 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 -08002313 return resp, nil
2314}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002315
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002316func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002317 // Default to PON0
2318 var intfID uint32
2319 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002320 if inPort != InvalidPort && outPort != InvalidPort {
2321 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2322 }
2323 return intfID
2324}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002325
2326func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, sn string) chan perOnuIndication {
2327 dh.perOnuChannelLock.Lock()
2328 if ch, ok := dh.perOnuChannel[sn]; ok {
2329 dh.perOnuChannelLock.Unlock()
2330 return ch.indicationChannel
2331 }
2332 channels := onuIndicationChannels{
2333 //We create a buffered channel here to avoid calling function to be blocked
2334 //in case of multiple indications from the same ONU,
2335 //especially in the case where indications are buffered in OLT.
2336 indicationChannel: make(chan perOnuIndication, 5),
2337 stopChannel: make(chan struct{}),
2338 }
2339 dh.perOnuChannel[sn] = channels
2340 dh.perOnuChannelLock.Unlock()
2341 go dh.perOnuIndicationsRoutine(&channels)
2342 return channels.indicationChannel
2343
2344}
2345
2346func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context, sn string) {
2347 logger.Debugw(ctx, "remove-onu-indication-channels", log.Fields{"sn": sn})
2348 dh.perOnuChannelLock.Lock()
2349 defer dh.perOnuChannelLock.Unlock()
2350 if ch, ok := dh.perOnuChannel[sn]; ok {
2351 close(ch.stopChannel)
2352 delete(dh.perOnuChannel, sn)
2353 }
2354
2355}
2356
2357func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, sn string) {
2358 ind := perOnuIndication{
2359 ctx: ctx,
2360 indication: indication,
2361 serialNumber: sn,
2362 }
2363 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "sn": sn})
2364 // Send the onuIndication on the ONU channel
2365 dh.getOnuIndicationChannel(ctx, sn) <- ind
2366}
2367
2368func (dh *DeviceHandler) perOnuIndicationsRoutine(onuChannels *onuIndicationChannels) {
2369 for {
2370 select {
2371 // process one indication per onu, before proceeding to the next one
2372 case onuInd := <-onuChannels.indicationChannel:
2373 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
2374 "ind": onuInd.indication, "sn": onuInd.serialNumber})
2375 switch onuInd.indication.Data.(type) {
2376 case *oop.Indication_OnuInd:
2377 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd(), onuInd.serialNumber); err != nil {
2378 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2379 "type": "onu-indication",
2380 "device-id": dh.device.Id,
2381 "sn": onuInd.serialNumber}, err).Log()
2382 }
2383 case *oop.Indication_OnuDiscInd:
2384 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd(), onuInd.serialNumber); err != nil {
2385 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2386 "type": "onu-discovery",
2387 "device-id": dh.device.Id,
2388 "sn": onuInd.serialNumber}, err).Log()
2389 }
2390 }
2391 case <-onuChannels.stopChannel:
2392 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2393 close(onuChannels.indicationChannel)
2394 return
2395 }
2396 }
2397}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002398
2399// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2400// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2401func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2402 // Step1 : Fill McastFlowOrGroupControlBlock
2403 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2404 // Step3 : Wait on response channel for response
2405 // Step4 : Return error value
2406 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2407 errChan := make(chan error)
2408 var groupID uint32
2409 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2410 ctx: ctx,
2411 flowOrGroupAction: action,
2412 flow: flow,
2413 group: group,
2414 errChan: &errChan,
2415 }
2416 if flow != nil {
2417 groupID = flow_utils.GetGroup(flow)
2418 } else if group != nil {
2419 groupID = group.Desc.GroupId
2420 } else {
2421 return errors.New("flow-and-group-both-nil")
2422 }
2423 // Derive the appropriate go routine to handle the request by a simple module operation.
2424 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2425 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2426 // Wait for handler to return error value
2427 err := <-errChan
2428 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"flow": flow, "group": group, "action": action, "err": err})
2429 return err
2430}
2431
2432// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
2433func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock) {
2434 for {
2435 // block on the channel to receive an incoming mcast flow/group
2436 // process the flow completely before proceeding to handle the next flow
2437 mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel
2438 if mcastFlowOrGroupCb.flow != nil {
2439 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2440 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2441 log.Fields{"device-id": dh.device.Id,
2442 "flowToAdd": mcastFlowOrGroupCb.flow})
2443 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2444 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2445 // Pass the return value over the return channel
2446 *mcastFlowOrGroupCb.errChan <- err
2447 } else { // flow remove
2448 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2449 log.Fields{"device-id": dh.device.Id,
2450 "flowToRemove": mcastFlowOrGroupCb.flow})
2451 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2452 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2453 // Pass the return value over the return channel
2454 *mcastFlowOrGroupCb.errChan <- err
2455 }
2456 } else { // mcast group
2457 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2458 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2459 log.Fields{"device-id": dh.device.Id,
2460 "groupToAdd": mcastFlowOrGroupCb.group})
2461 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2462 // Pass the return value over the return channel
2463 *mcastFlowOrGroupCb.errChan <- err
2464 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2465 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2466 log.Fields{"device-id": dh.device.Id,
2467 "groupToModify": mcastFlowOrGroupCb.group})
2468 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2469 // Pass the return value over the return channel
2470 *mcastFlowOrGroupCb.errChan <- err
2471 } else { // group remove
2472 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2473 log.Fields{"device-id": dh.device.Id,
2474 "groupToRemove": mcastFlowOrGroupCb.group})
2475 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2476 // Pass the return value over the return channel
2477 *mcastFlowOrGroupCb.errChan <- err
2478 }
2479 }
2480 }
2481}