blob: 3def7bcf609fe36e26f8a0670e9a544385e1bf26 [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
17//Package adaptercore provides the utility for olt devices, flows and statistics
Phaneendra Manda4c62c802019-03-06 21:37:49 +053018package adaptercore
19
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneret1359c732019-08-01 21:40:02 -040022 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070023 "errors"
24 "fmt"
25 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040032 "google.golang.org/grpc/codes"
33
David Bainbridgef5879ca2019-12-13 21:17:54 +000034 backoff "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Girish Gowdru0c588b22019-04-23 23:24:56 -040040 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000041 "github.com/opencord/voltha-protos/v3/go/common"
42 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
43 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
44 oop "github.com/opencord/voltha-protos/v3/go/openolt"
45 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070046 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040047 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053048)
49
salmansiddiqui7ac62132019-08-22 03:58:50 +000050// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040051const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000052 MaxRetry = 10
53 MaxTimeOutInMs = 500
Manikkaraj kb1d51442019-07-23 10:41:02 -040054)
55
kdarapu381c6902019-07-31 18:23:16 +053056func init() {
57 _, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
58}
59
Phaneendra Manda4c62c802019-03-06 21:37:49 +053060//DeviceHandler will interact with the OLT device.
61type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070062 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070063 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040064 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070065 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053066 coreProxy adapterif.CoreProxy
67 AdapterProxy adapterif.AdapterProxy
68 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070069 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070070 exitChannel chan int
71 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053072 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070073 transitionMap *TransitionMap
74 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053075 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040076 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053077 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053078
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053079 discOnus sync.Map
80 onus sync.Map
81 portStats *OpenOltStatisticsMgr
82 metrics *pmmetrics.PmMetrics
83 stopCollector chan bool
84 stopHeartbeatCheck chan bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070085}
86
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070088type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070090 deviceType string
91 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070092 onuID uint32
93 intfID uint32
94 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000095 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070096}
97
Naga Manjunath7615e552019-10-11 22:35:47 +053098var pmNames = []string{
99 "rx_bytes",
100 "rx_packets",
101 "rx_mcast_packets",
102 "rx_bcast_packets",
103 "tx_bytes",
104 "tx_packets",
105 "tx_mcast_packets",
106 "tx_bcast_packets",
107}
108
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113 device.deviceType = deviceTp
114 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 device.onuID = onuID
116 device.intfID = intfID
117 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000118 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530120}
121
122//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530123func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700124 var dh DeviceHandler
125 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400126 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400127 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700128 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700129 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700130 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400131 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700132 dh.device = cloned
133 dh.openOLT = adapter
134 dh.exitChannel = make(chan int, 1)
135 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530136 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530137 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530138 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
cuilin20187b2a8c32019-03-26 19:52:28 -0700139 //TODO initialize the support classes.
140 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530141}
142
143// start save the device to the data model
144func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700145 dh.lockDevice.Lock()
146 defer dh.lockDevice.Unlock()
147 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
148 // Add the initial device to the local model
149 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530150}
151
152// stop stops the device dh. Not much to do for now
153func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 dh.lockDevice.Lock()
155 defer dh.lockDevice.Unlock()
156 log.Debug("stopping-device-agent")
157 dh.exitChannel <- 1
158 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530159}
160
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400161func macifyIP(ip net.IP) string {
162 if len(ip) > 0 {
163 oct1 := strconv.FormatInt(int64(ip[12]), 16)
164 oct2 := strconv.FormatInt(int64(ip[13]), 16)
165 oct3 := strconv.FormatInt(int64(ip[14]), 16)
166 oct4 := strconv.FormatInt(int64(ip[15]), 16)
167 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
168 }
169 return ""
170}
171
172func generateMacFromHost(host string) (string, error) {
173 var genmac string
174 var addr net.IP
175 var ips []string
176 var err error
177
178 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
179
180 if addr = net.ParseIP(host); addr == nil {
181 log.Debugw("looking-up-hostname", log.Fields{"host": host})
182
183 if ips, err = net.LookupHost(host); err == nil {
184 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
185 if addr = net.ParseIP(ips[0]); addr == nil {
186 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
187 return "", errors.New("unable-to-parse-ip")
188 }
189 genmac = macifyIP(addr)
190 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
191 return genmac, nil
192 }
193 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
194 return "", err
195 }
196
197 genmac = macifyIP(addr)
198 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
199 return genmac, nil
200}
201
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530202func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 slist := strings.Split(mac, ":")
204 result := make([]uint32, len(slist))
205 var err error
206 var tmp int64
207 for index, val := range slist {
208 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
209 return []uint32{1, 2, 3, 4, 5, 6}
210 }
211 result[index] = uint32(tmp)
212 }
213 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530214}
215
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700216//GetportLabel returns the label for the NNI and the PON port based on port number and port type
manikkaraj kbf256be2019-03-25 00:13:48 +0530217func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530218
Girish Gowdru0c588b22019-04-23 23:24:56 -0400219 if portType == voltha.Port_ETHERNET_NNI {
220 return fmt.Sprintf("nni-%d", portNum)
221 } else if portType == voltha.Port_PON_OLT {
222 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700223 } else if portType == voltha.Port_ETHERNET_UNI {
224 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400225 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700226 }
227 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530228}
229
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
Esin Karamanccb714b2019-11-29 15:02:06 +0000231 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700232 if state == "up" {
233 operStatus = voltha.OperStatus_ACTIVE
234 } else {
235 operStatus = voltha.OperStatus_DISCOVERED
236 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700237 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400238 label := GetportLabel(portNum, portType)
239 if len(label) == 0 {
240 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
241 return
242 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500243
244 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
245 if err != nil || device == nil {
246 log.Errorw("Failed-to-fetch-device", log.Fields{"err": err})
247 return
248 }
249 if device.Ports != nil {
250 for _, dPort := range device.Ports {
251 if dPort.Type == portType && dPort.PortNo == portNum {
252 log.Debug("port-already-exists-updating-oper-status-of-port")
253 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
254 log.Errorw("failed-to-update-port-state", log.Fields{"err": err})
255 return
256 }
257 return
258 }
259 }
260 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400261 // Now create Port
262 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 PortNo: portNum,
264 Label: label,
265 Type: portType,
266 OperStatus: operStatus,
267 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500268 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700269 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500271 log.Errorw("Error-creating-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
272 return
Girish Gowdru1110ef22019-06-24 11:17:59 -0400273 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500274 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530275}
276
277// readIndications to read the indications from the OLT device
278func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400279 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400280 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700281 if err != nil {
282 log.Errorw("Failed to read indications", log.Fields{"err": err})
283 return
284 }
285 if indications == nil {
286 log.Errorw("Indications is nil", log.Fields{})
287 return
288 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400289 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700290 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400291 if err != nil || device == nil {
292 /*TODO: needs to handle error scenarios */
293 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700294 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400295 }
296 // When the device is in DISABLED and Adapter container restarts, we need to
297 // rebuild the locally maintained admin state.
298 if device.AdminState == voltha.AdminState_DISABLED {
299 dh.lockDevice.Lock()
300 dh.adminState = "down"
301 dh.lockDevice.Unlock()
302 }
303
David Bainbridgef5879ca2019-12-13 21:17:54 +0000304 // Create an exponential backoff around re-enabling indications. The
305 // maximum elapsed time for the back off is set to 0 so that we will
306 // continue to retry. The max interval defaults to 1m, but is set
307 // here for code clarity
308 indicationBackoff := backoff.NewExponentialBackOff()
309 indicationBackoff.MaxElapsedTime = 0
310 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 for {
312 indication, err := indications.Recv()
313 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530314 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000315 // Use an exponential back off to prevent getting into a tight loop
316 duration := indicationBackoff.NextBackOff()
317 if duration == backoff.Stop {
318 // If we reach a maximum then warn and reset the backoff
319 // timer and keep attempting.
320 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
321 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
322 indicationBackoff.Reset()
323 }
324 time.Sleep(indicationBackoff.NextBackOff())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530325 indications, err = dh.Client.EnableIndication(context.Background(), new(oop.Empty))
326 if err != nil {
327 log.Errorw("Failed to read indications", log.Fields{"err": err})
328 return
329 }
330 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700331 }
332 if err != nil {
333 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400334 if dh.adminState == "deleted" {
335 log.Debug("Device deleted stoping the read indication thread")
336 break
337 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400338 dh.transitionMap.Handle(DeviceDownInd)
339 dh.transitionMap.Handle(DeviceInit)
340 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700341 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000342 // Reset backoff if we have a successful receive
343 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400344 dh.lockDevice.RLock()
345 adminState := dh.adminState
346 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400347 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400348 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530349
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +0530350 log.Infow("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400351 continue
352 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700353 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530354
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700355 }
356}
357
358func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000359 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000360 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700361 dh.transitionMap.Handle(DeviceUpInd)
362 } else if oltIndication.OperState == "down" {
363 dh.transitionMap.Handle(DeviceDownInd)
364 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000365 // Send or clear Alarm
366 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700367}
368
369func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400370 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700371 switch indication.Data.(type) {
372 case *oop.Indication_OltInd:
373 dh.handleOltIndication(indication.GetOltInd())
374 case *oop.Indication_IntfInd:
375 intfInd := indication.GetIntfInd()
376 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
377 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
378 case *oop.Indication_IntfOperInd:
379 intfOperInd := indication.GetIntfOperInd()
380 if intfOperInd.GetType() == "nni" {
381 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530382 dh.resourceMgr.AddNNIToKVStore(intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700383 } else if intfOperInd.GetType() == "pon" {
384 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
385 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000386 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700387 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700388 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
389 case *oop.Indication_OnuDiscInd:
390 onuDiscInd := indication.GetOnuDiscInd()
391 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700392 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400393 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700394 case *oop.Indication_OnuInd:
395 onuInd := indication.GetOnuInd()
396 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
397 go dh.onuIndication(onuInd)
398 case *oop.Indication_OmciInd:
399 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700400 log.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
William Kurkianff524662019-08-20 10:34:30 -0400401 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700402 case *oop.Indication_PktInd:
403 pktInd := indication.GetPktInd()
404 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
405 go dh.handlePacketIndication(pktInd)
406 case *oop.Indication_PortStats:
407 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530408 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700409 case *oop.Indication_FlowStats:
410 flowStats := indication.GetFlowStats()
411 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
412 case *oop.Indication_AlarmInd:
413 alarmInd := indication.GetAlarmInd()
414 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530415 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700416 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530417}
418
419// doStateUp handle the olt up indication and update to voltha core
420func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400421 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700422 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400423 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700424 log.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400425 return err
426 }
427 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530428}
429
430// doStateDown handle the olt down indication
431func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700432 dh.lockDevice.Lock()
433 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400434 log.Debug("do-state-down-start")
435
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700436 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400437 if err != nil || device == nil {
438 /*TODO: needs to handle error scenarios */
439 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400441 }
442
443 cloned := proto.Clone(device).(*voltha.Device)
444 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700445 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
446 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
447 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400448 }
449
450 //Update the device oper state and connection status
451 cloned.OperStatus = voltha.OperStatus_UNKNOWN
452 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
453 dh.device = cloned
454
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700455 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
456 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
457 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400458 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400459
460 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700461 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400462 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400464 return err
465 }
466 for _, onuDevice := range onuDevices.Items {
467
468 // Update onu state as down in onu adapter
469 onuInd := oop.OnuIndication{}
470 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
472 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
473 if er != nil {
474 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
475 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700476 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700477 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400478 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700479 /* Discovered ONUs entries need to be cleared , since after OLT
480 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530481 dh.discOnus = sync.Map{}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700482 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700483 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530484}
485
486// doStateInit dial the grpc before going to init state
487func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400488 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400489 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400490 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700491 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400492 return err
493 }
494 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530495}
496
497// postInit create olt client instance to invoke RPC on the olt device
498func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400499 dh.Client = oop.NewOpenoltClient(dh.clientCon)
500 dh.transitionMap.Handle(GrpcConnected)
501 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530502}
503
504// doStateConnected get the device info and update to voltha core
505func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400506 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400507
508 // Case where OLT is disabled and then rebooted.
509 if dh.adminState == "down" {
510 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400512 if err != nil || device == nil {
513 /*TODO: needs to handle error scenarios */
514 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
515 }
516
517 cloned := proto.Clone(device).(*voltha.Device)
518 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
519 cloned.OperStatus = voltha.OperStatus_UNKNOWN
520 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700521 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
522 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400523 }
524
Chaitrashree G S44124192019-08-07 20:21:36 -0400525 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400526 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
527 if err != nil {
528 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
529 }
530
531 // Start reading indications
532 go dh.readIndications()
533 return nil
534 }
535
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400536 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700537 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400538 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700539 return err
540 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400541
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400543 if err != nil || device == nil {
544 /*TODO: needs to handle error scenarios */
545 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700546 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400547 }
548 cloned := proto.Clone(device).(*voltha.Device)
549 // Update the all ports (if available) on that device to ACTIVE.
550 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700551 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
552 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400553 return err
554 }
555
Girish Gowdru0c588b22019-04-23 23:24:56 -0400556 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
557 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400559 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700560 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400561 }
562 // Instantiate flow manager
563 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
564 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400566 }
567 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400568 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400569 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530570 // Stats config for new device
571 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530572
cuilin20187b2a8c32019-03-26 19:52:28 -0700573 // Start reading indications
574 go dh.readIndications()
575 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530576}
577
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400578func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
579 var err error
580 var deviceInfo *oop.DeviceInfo
581
582 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
583
584 if err != nil {
585 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
586 return nil, err
587 }
588 if deviceInfo == nil {
589 log.Errorw("Device info is nil", log.Fields{})
590 return nil, errors.New("failed to get device info from OLT")
591 }
592
593 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
594 dh.device.Root = true
595 dh.device.Vendor = deviceInfo.Vendor
596 dh.device.Model = deviceInfo.Model
597 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
598 dh.device.HardwareVersion = deviceInfo.HardwareVersion
599 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
600
601 if deviceInfo.DeviceId == "" {
602 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
603 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
604 genmac, err := generateMacFromHost(host)
605 if err != nil {
606 return nil, err
607 }
608 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
609 dh.device.MacAddress = genmac
610 } else {
611 dh.device.MacAddress = deviceInfo.DeviceId
612 }
613
614 // Synchronous call to update device - this method is run in its own go routine
615 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
616 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
617 return nil, err
618 }
619
620 return deviceInfo, nil
621}
622
Naga Manjunath7615e552019-10-11 22:35:47 +0530623func startCollector(dh *DeviceHandler) {
624 // Initial delay for OLT initialization
625 time.Sleep(1 * time.Minute)
626 log.Debugf("Starting-Collector")
627 context := make(map[string]string)
628 for {
629 select {
630 case <-dh.stopCollector:
631 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
632 return
633 default:
634 freq := dh.metrics.ToPmConfigs().DefaultFreq
635 time.Sleep(time.Duration(freq) * time.Second)
636 context["oltid"] = dh.deviceID
637 context["devicetype"] = dh.deviceType
638 // NNI Stats
639 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
640 log.Debugf("Collect-NNI-Metrics %v", cmnni)
641 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
642 log.Debugf("Publish-NNI-Metrics")
643 // PON Stats
644 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
645 for i := uint32(0); i < NumPonPORTS; i++ {
646 cmpon := dh.portStats.collectPONMetrics(i)
647 log.Debugf("Collect-PON-Metrics %v", cmpon)
648
649 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
650 log.Debugf("Publish-PON-Metrics")
651 }
652 }
653 }
654}
655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530657func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400658 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400660 dh.transitionMap.Handle(DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530661
662 // Now, set the initial PM configuration for that device
663 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
664 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
665 }
666
667 go startCollector(dh)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530668 go startHeartbeatCheck(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530669}
670
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530672func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700673 return &ic.SwitchCapability{
674 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530675 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700676 HwDesc: "open_pon",
677 SwDesc: "open_pon",
678 SerialNum: dh.device.SerialNumber,
679 },
680 SwitchFeatures: &of.OfpSwitchFeatures{
681 NBuffers: 256,
682 NTables: 2,
683 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
684 of.OfpCapabilities_OFPC_TABLE_STATS |
685 of.OfpCapabilities_OFPC_PORT_STATS |
686 of.OfpCapabilities_OFPC_GROUP_STATS),
687 },
688 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530689}
690
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530692func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700694 return &ic.PortCapability{
695 Port: &voltha.LogicalPort{
696 OfpPort: &of.OfpPort{
697 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
698 Config: 0,
699 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700700 Curr: capacity,
701 Advertised: capacity,
702 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700703 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
704 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
705 },
706 DeviceId: dh.device.Id,
707 DevicePortNo: uint32(portNo),
708 },
709 }, nil
710}
711
William Kurkianff524662019-08-20 10:34:30 -0400712func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700714 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700715 var deviceID string
716 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700717
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700718 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530719
720 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
721
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700722 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
723 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700724 kwargs := make(map[string]interface{})
725 kwargs["onu_id"] = omciInd.OnuId
726 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700727
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
729 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400730 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
731 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700732 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 deviceType = onuDevice.Type
734 deviceID = onuDevice.Id
735 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
736 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530737 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700738 } else {
739 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530741 deviceType = onuInCache.(*OnuDevice).deviceType
742 deviceID = onuInCache.(*OnuDevice).deviceID
743 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700744 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700745
746 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
747 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
748 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400750 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
751 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700752 }
William Kurkianff524662019-08-20 10:34:30 -0400753 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530754}
755
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700756//ProcessInterAdapterMessage sends the proxied messages to the target device
757// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
758// is meant, and then send the unmarshalled omci message to this onu
759func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
760 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700761 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700763 fromTopic := msg.Header.FromTopic
764 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 toDeviceID := msg.Header.ToDeviceId
766 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700767
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700769
770 msgBody := msg.GetBody()
771
772 omciMsg := &ic.InterAdapterOmciMessage{}
773 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
774 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
775 return err
776 }
777
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700778 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
780 if err != nil {
781 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700782 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700783 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
785 dh.sendProxiedMessage(onuDevice, omciMsg)
786
cuilin20187b2a8c32019-03-26 19:52:28 -0700787 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700788 log.Debugw("Proxy Address found in omci message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700789 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700790 }
791
792 } else {
793 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
794 }
795 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530796}
797
cuilin20187b2a8c32019-03-26 19:52:28 -0700798func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700799 var intfID uint32
800 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000801 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700802 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700803 intfID = onuDevice.ProxyAddress.GetChannelId()
804 onuID = onuDevice.ProxyAddress.GetOnuId()
805 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700806 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700807 intfID = omciMsg.GetProxyAddress().GetChannelId()
808 onuID = omciMsg.GetProxyAddress().GetOnuId()
809 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700810 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700811 if connectStatus != voltha.ConnectStatus_REACHABLE {
812 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700813 return
814 }
815
lcuie24ef182019-04-29 22:58:36 -0700816 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
817 isHexString := false
818 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
819 if decodeerr == nil {
820 isHexString = true
821 }
822
823 // TODO: OpenOLT Agent expects a hex string for OMCI packets rather than binary. Fix this in the agent and then we can pass binary Pkt: omciMsg.Message.
824 var omciMessage *oop.OmciMsg
825 if isHexString {
826 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
827 } else {
828 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
829 hex.Encode(hexPkt, omciMsg.Message)
830 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
831 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700832
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700833 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
834 if err != nil {
835 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
836 return
837 }
lcuie24ef182019-04-29 22:58:36 -0700838 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700839}
840
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700841func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
842 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
843 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700844 // TODO: need resource manager
845 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700846 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530847 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400848 st, _ := status.FromError(err)
849 if st.Code() == codes.AlreadyExists {
850 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
851 } else {
852 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
853 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700854 } else {
855 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
856 }
857}
858
Matt Jeanneret53539512019-07-20 14:47:02 -0400859func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700860 channelID := onuDiscInd.GetIntfId()
861 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400862
863 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530864
865 if _, ok := dh.discOnus.Load(sn); ok {
866
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400867 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400868 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700869 }
870
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530871 dh.discOnus.Store(sn, true)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400872
cuilin20187b2a8c32019-03-26 19:52:28 -0700873 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400874 if sn != "" {
875 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400876 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400877 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
878 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400879 }
880
881 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
882 var onuID uint32
883 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700884 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400885 ponintfid := onuDiscInd.GetIntfId()
886 dh.lockDevice.Lock()
887 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
888 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400889 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400890 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
891 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400892 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700893 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400894 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700895 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400896 log.Errorw("Create onu error",
897 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
898 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400899 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400900 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400901 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400902
903 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700904 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400905 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400906 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700907 //Insert the ONU into cache to use in OnuIndication.
908 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Scott Baker7eb0a932019-07-26 10:33:22 -0700909 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
910 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700911 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400912
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530913 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
914 dh.onus.Store(onuKey, onuDev)
915 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400916
Mahir Gunyele77977b2019-06-27 05:36:22 -0700917 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
918 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400919 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
920 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700921 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700922 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
923 //TODO: We put this sleep here to prevent the race between state update and onuIndication
924 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
925 //then the initialisation fails.
926 time.Sleep(1 * time.Second)
927 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400928 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700929}
930
931func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
932 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
933
934 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700935 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700936 var onuDevice *voltha.Device
937 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700938 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
939 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700940 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530941
942 if onuInCache, ok := dh.onus.Load(onuKey); ok {
943
Mahir Gunyele77977b2019-06-27 05:36:22 -0700944 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
945 foundInCache = true
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530946 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700947 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700948 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
949 if serialNumber != "" {
950 kwargs["serial_number"] = serialNumber
951 } else {
952 kwargs["onu_id"] = onuInd.OnuId
953 kwargs["parent_port_no"] = ponPort
954 }
955 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700956 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700957
958 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400959 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700960 //log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": intfIDFromPortNo(onuDevice.ParentPortNo), "currentIntfId": onuInd.GetIntfId()})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400961 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700962 }
963
964 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
965 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{"expected_onu_id": onuDevice.ProxyAddress.OnuId, "received_onu_id": onuInd.OnuId})
966 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700967 if !foundInCache {
968 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530969
970 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
971
Mahir Gunyele77977b2019-06-27 05:36:22 -0700972 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700973 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700974
cuilin20187b2a8c32019-03-26 19:52:28 -0700975 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700977 return
978 }
979
980}
981
Scott Baker7eb0a932019-07-26 10:33:22 -0700982func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400983 log.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 dh.updateOnuAdminState(onuInd)
985 // operState
986 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400987 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
989 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
990 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
991 if err != nil {
992 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
993 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
994 }
995 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700996 // Ignore operstatus if device was found in cache
997 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400998 log.Warnw("ignore-onu-indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700999 return
1000 }
Matt Jeanneret53539512019-07-20 14:47:02 -04001001 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1002 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1004 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1005 if err != nil {
1006 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +05301007 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008 return
1009 }
1010 } else {
1011 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
1012 }
1013}
1014
1015func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
1016 if onuInd.AdminState == "down" {
1017 if onuInd.OperState != "down" {
1018 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
1019 // Forcing the oper state change code to execute
1020 onuInd.OperState = "down"
1021 }
1022 // Port and logical port update is taken care of by oper state block
1023 } else if onuInd.AdminState == "up" {
1024 log.Debugln("received-onu-admin-state up")
1025 } else {
1026 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
1027 }
1028 log.Debugln("admin-state-dealt-with")
1029}
1030
cuilin20187b2a8c32019-03-26 19:52:28 -07001031func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1032 if serialNum != nil {
1033 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001034 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001036}
1037
1038func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1039 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001041 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1042 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1043 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1044 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1045 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1046 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1047 return tmp
1048}
1049
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050//UpdateFlowsBulk upates the bulk flow
1051func (dh *DeviceHandler) UpdateFlowsBulk() error {
1052 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -07001053}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001054
1055//GetChildDevice returns the child device for given parent port and onu id
1056func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
1057 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001058 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001059 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001060 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001061 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001062 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001063 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001064 return nil
1065 }
1066 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1067 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301068}
1069
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001070// SendPacketInToCore sends packet-in to core
1071// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1072// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001073func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001074 log.Debugw("send-packet-in-to-core", log.Fields{
1075 "port": logicalPort,
1076 "packet": hex.EncodeToString(packetPayload),
1077 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001079 log.Errorw("Error sending packetin to core", log.Fields{
1080 "error": err,
1081 "packet": hex.EncodeToString(packetPayload),
1082 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001083 return
1084 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001085 log.Debugw("Sent packet-in to core successfully", log.Fields{
1086 "packet": hex.EncodeToString(packetPayload),
1087 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001088}
1089
A R Karthick1f85b802019-10-11 05:06:05 +00001090// AddUniPortToOnu adds the uni port to the onu device
1091func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1092 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301093
1094 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001095 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301096 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1097 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001098 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1099 }
1100 }
1101}
1102
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001103//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001104func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1105 log.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001106 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001107 for _, flow := range flows.ToRemove.Items {
1108 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1109 dh.flowMgr.RemoveFlow(flow)
1110 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301111
1112 for _, flow := range flows.ToAdd.Items {
1113 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
1114 dh.flowMgr.AddFlow(flow, flowMetadata)
1115 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001116 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001117 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001118 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001119 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001120 // dh.flowMgr.RemoveFlow(flow)
1121 }
1122 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001123
1124 if groups != nil {
1125 for _, group := range groups.ToAdd.Items {
1126 dh.flowMgr.AddGroup(group)
1127 }
1128 for _, group := range groups.ToUpdate.Items {
1129 dh.flowMgr.ModifyGroup(group)
1130 }
1131 if len(groups.ToRemove.Items) != 0 {
1132 log.Debug("Group delete operation is not supported for now")
1133 }
1134 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001135 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001136 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301137}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001138
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001139//DisableDevice disables the given device
1140//It marks the following for the given device:
1141//Device-Handler Admin-State : down
1142//Device Port-State: UNKNOWN
1143//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001144func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001145 /* On device disable ,admin state update has to be done prior sending request to agent since
1146 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001147 dh.lockDevice.Lock()
1148 dh.adminState = "down"
1149 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001150 if dh.Client != nil {
1151 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1152 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1153 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1154 dh.lockDevice.Lock()
1155 dh.adminState = "up"
1156 dh.lockDevice.Unlock()
1157 return err
1158 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001159 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001160 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001161 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001162 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001163 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301164
1165 dh.discOnus = sync.Map{}
1166 dh.onus = sync.Map{}
1167
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301168 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001169 cloned := proto.Clone(device).(*voltha.Device)
1170 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1172 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001173 return err
1174 }
1175
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001176 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001177 return nil
1178}
1179
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301180func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001181
1182 // Update onu state as unreachable in onu adapter
1183 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301184 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001185 //get the child device for the parent device
1186 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1187 if err != nil {
1188 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1189 }
1190 if onuDevices != nil {
1191 for _, onuDevice := range onuDevices.Items {
1192 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1193 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1194 if err != nil {
1195 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1196 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1197 }
1198
1199 }
1200 }
1201
1202}
1203
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001204//ReenableDevice re-enables the olt device after disable
1205//It marks the following for the given device:
1206//Device-Handler Admin-State : up
1207//Device Port-State: ACTIVE
1208//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001209func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001210 dh.lockDevice.Lock()
1211 dh.adminState = "up"
1212 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301213
1214 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1215 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1216 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1217 dh.lockDevice.Lock()
1218 dh.adminState = "down"
1219 dh.lockDevice.Unlock()
1220 return err
1221 }
1222 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001223 log.Debug("olt-reenabled")
1224
1225 cloned := proto.Clone(device).(*voltha.Device)
1226 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1228 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001229 return err
1230 }
1231
1232 //Update the device oper status as ACTIVE
1233 cloned.OperStatus = voltha.OperStatus_ACTIVE
1234 dh.device = cloned
1235
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001236 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1237 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001238 return err
1239 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001240 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001241
1242 return nil
1243}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001244
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301245func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001246 var uniID uint32
1247 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301248 for _, port := range onu.UniPorts {
1249 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001250 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1251 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301252 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1253 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001254 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301255 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1256 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001257 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301258 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001259 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301260 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001261 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301262 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1263 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001264 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301265 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1266 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1267 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001268 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301269 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1270 }
1271 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1272 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1273 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1274 }
1275 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1276 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1277 log.Debugw("Failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001278 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001279 }
1280 return nil
1281}
1282
1283func (dh *DeviceHandler) clearNNIData() error {
1284 nniUniID := -1
1285 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301286
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001287 if dh.resourceMgr == nil {
1288 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1289 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001290 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301291 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1292 if err != nil {
1293 log.Error("Failed to fetch nni from kv store")
1294 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001295 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301296 log.Debugw("NNI are ", log.Fields{"nni": nni})
1297 for _, nniIntfID := range nni {
1298 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1299 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1300 for _, flowID := range flowIDs {
1301 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1302 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301303 dh.resourceMgr.RemoveResourceMap(nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001304 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301305 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1306 log.Error("Failed to clear nni from kv store")
1307 return err
1308 }
1309 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001310}
1311
1312// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1313func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1314 log.Debug("Function entry delete device")
1315 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001316 if dh.adminState == "deleted" {
1317 dh.lockDevice.Unlock()
1318 return nil
1319 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001320 dh.adminState = "deleted"
1321 dh.lockDevice.Unlock()
1322 /* Clear the KV store data associated with the all the UNI ports
1323 This clears up flow data and also resource map data for various
1324 other pon resources like alloc_id and gemport_id
1325 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001326 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301327 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1328 var ponPort uint32
1329 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1330 var onuGemData []rsrcMgr.OnuGemInfo
1331 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1332 if err != nil {
1333 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1334 return err
1335 }
1336 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301337 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301338 log.Debugw("onu data ", log.Fields{"onu": onu})
1339 if err = dh.clearUNIData(&onu); err != nil {
1340 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1341 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301342 // Clear flowids for gem cache.
1343 for _, gem := range onu.GemPorts {
1344 dh.resourceMgr.DeleteFlowIDsForGem(ponPort, gem)
1345 }
1346 onuID[0] = onu.OnuID
1347 dh.resourceMgr.FreeonuID(ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301348 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301349 dh.resourceMgr.DeleteIntfIDGempMapPath(ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301350 onuGemData = nil
1351 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1352 if err != nil {
1353 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001354 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001355 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001356 /* Clear the flows from KV store associated with NNI port.
1357 There are mostly trap rules from NNI port (like LLDP)
1358 */
1359 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301360 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001361 }
A R Karthick1f85b802019-10-11 05:06:05 +00001362
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001363 /* Clear the resource pool for each PON port in the background */
1364 go dh.resourceMgr.Delete()
1365 }
A R Karthick1f85b802019-10-11 05:06:05 +00001366
Devmalya Paul495b94a2019-08-27 19:42:00 -04001367 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301368 dh.onus.Range(func(key interface{}, value interface{}) bool {
1369 dh.onus.Delete(key)
1370 return true
1371 })
1372
Devmalya Paul495b94a2019-08-27 19:42:00 -04001373 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301374 // Stop the Stats collector
1375 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301376 // stop the heartbeat check routine
1377 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001378 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001379 if dh.Client != nil {
1380 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1381 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1382 return err
1383 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001384 }
1385 cloned := proto.Clone(device).(*voltha.Device)
1386 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1387 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1388 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1389 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1390 return err
1391 }
1392 return nil
1393}
1394
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001396func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1397 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001398 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001399 return err
1400 }
1401
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001403
1404 return nil
1405}
1406
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001407func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001408 log.Debugw("Received packet-in", log.Fields{
1409 "packet-indication": *packetIn,
1410 "packet": hex.EncodeToString(packetIn.Pkt),
1411 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001412 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1413 if err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001414 log.Errorw("Error getting logical port from packet-in", log.Fields{
1415 "error": err,
1416 "packet": hex.EncodeToString(packetIn.Pkt),
1417 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001418 return
1419 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001420 log.Debugw("sending packet-in to core", log.Fields{
1421 "logicalPortNum": logicalPortNum,
1422 "packet": hex.EncodeToString(packetIn.Pkt),
1423 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001424 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001425 log.Errorw("Error sending packet-in to core", log.Fields{
1426 "error": err,
1427 "packet": hex.EncodeToString(packetIn.Pkt),
1428 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001429 return
1430 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001431 log.Debugw("Success sending packet-in to core!", log.Fields{
1432 "packet": hex.EncodeToString(packetIn.Pkt),
1433 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001434}
1435
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001436// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1437func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001438 log.Debugw("incoming-packet-out", log.Fields{
1439 "deviceID": dh.deviceID,
1440 "egress_port_no": egressPortNo,
1441 "pkt-length": len(packet.Data),
1442 "packet": hex.EncodeToString(packet.Data),
1443 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001444
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001447 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1448 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301449 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1450 // Do not packet-out lldp packets on uni port.
1451 // ONOS has no clue about uni/nni ports, it just packets out on all
1452 // available ports on the Logical Switch. It should not be interested
1453 // in the UNI links.
1454 log.Debug("dropping-lldp-packet-out-on-uni")
1455 return nil
1456 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001457 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1458 if innerEthType == 0x8100 {
1459 // q-in-q 802.1ad or 802.1q double tagged packet.
1460 // slice out the outer tag.
1461 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1462 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001463 }
1464 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001465 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1466 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001467 uniID := UniIDFromPortNum(uint32(egressPortNo))
1468
1469 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1470 if err != nil {
1471 // In this case the openolt agent will receive the gemPortID as 0.
1472 // The agent tries to retrieve the gemPortID in this case.
1473 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001474 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1475 "packet": hex.EncodeToString(packet.Data),
1476 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001477 }
1478
1479 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001480
Matteo Scandolo6056e822019-11-13 14:05:29 -08001481 log.Debugw("sending-packet-to-onu", log.Fields{
1482 "egress_port_no": egressPortNo,
1483 "IntfId": intfID,
1484 "onuID": onuID,
1485 "uniID": uniID,
1486 "gemPortID": gemPortID,
1487 "packet": hex.EncodeToString(packet.Data),
1488 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001489
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001490 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001491 log.Errorw("Error while sending packet-out to ONU", log.Fields{
1492 "error": err,
1493 "packet": hex.EncodeToString(packet.Data),
1494 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001495 return err
1496 }
1497 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001498 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001499
Matteo Scandolo6056e822019-11-13 14:05:29 -08001500 log.Debugw("sending-packet-to-nni", log.Fields{
1501 "uplink_pkt": uplinkPkt,
1502 "packet": hex.EncodeToString(packet.Data),
1503 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001504
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001505 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001506 log.Errorw("Error while sending packet-out to NNI", log.Fields{
1507 "error": err,
1508 "packet": hex.EncodeToString(packet.Data),
1509 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001510 return err
1511 }
1512 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001513 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1514 "egress_port_no": egressPortNo,
1515 "egressPortType": egressPortType,
1516 "packet": hex.EncodeToString(packet.Data),
1517 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001518 }
1519 return nil
1520}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001521
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001522func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1523 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001524}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301525
1526func startHeartbeatCheck(dh *DeviceHandler) {
1527 // start the heartbeat check towards the OLT.
1528 var timerCheck *time.Timer
1529
1530 for {
1531 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1532 select {
1533 case <-heartbeatTimer.C:
1534 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1535 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1536 log.Error("Hearbeat failed")
1537 if timerCheck == nil {
1538 // start a after func, when expired will update the state to the core
1539 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1540 }
1541 } else {
1542 if timerCheck != nil {
1543 if timerCheck.Stop() {
1544 log.Debug("We got hearbeat within the timeout")
1545 } else {
1546
1547 log.Debug("We got hearbeat after the timeout expired, changing the states")
1548 go dh.notifyChildDevices("up")
1549 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
1550 voltha.OperStatus_ACTIVE); err != nil {
1551 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1552 }
1553 }
1554 timerCheck = nil
1555 }
1556 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1557 }
1558 cancel()
1559 case <-dh.stopHeartbeatCheck:
1560 log.Debug("Stopping heart beat check")
1561 return
1562 }
1563 }
1564}
1565
1566func (dh *DeviceHandler) updateStateUnreachable() {
1567
1568 go dh.notifyChildDevices("unreachable")
1569 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1570 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": err})
1571 return
1572 }
1573}