blob: d17d997e04cf717f62f322da671ab39e57c3bdf2 [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
Matteo Scandolo945e4012019-12-12 14:16:11 -080034 "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
Phaneendra Manda4c62c802019-03-06 21:37:49 +053056//DeviceHandler will interact with the OLT device.
57type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070059 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040060 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070061 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053062 coreProxy adapterif.CoreProxy
63 AdapterProxy adapterif.AdapterProxy
64 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070065 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070066 exitChannel chan int
67 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053068 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070069 transitionMap *TransitionMap
70 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053071 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040072 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053073 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053074
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053075 discOnus sync.Map
76 onus sync.Map
77 portStats *OpenOltStatisticsMgr
78 metrics *pmmetrics.PmMetrics
79 stopCollector chan bool
80 stopHeartbeatCheck chan bool
Chaitrashree G Sef088112020-02-03 21:39:27 -050081 activePorts sync.Map
Mahir Gunyela3f9add2019-06-06 15:13:19 -070082}
83
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070085type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070087 deviceType string
88 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 onuID uint32
90 intfID uint32
91 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000092 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070093}
94
Naga Manjunath7615e552019-10-11 22:35:47 +053095var pmNames = []string{
96 "rx_bytes",
97 "rx_packets",
98 "rx_mcast_packets",
99 "rx_bcast_packets",
100 "tx_bytes",
101 "tx_packets",
102 "tx_mcast_packets",
103 "tx_bcast_packets",
104}
105
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110 device.deviceType = deviceTp
111 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 device.onuID = onuID
113 device.intfID = intfID
114 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000115 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700116 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530117}
118
119//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530120func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700121 var dh DeviceHandler
122 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400123 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400124 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700125 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700127 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400128 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700129 dh.device = cloned
130 dh.openOLT = adapter
131 dh.exitChannel = make(chan int, 1)
132 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530133 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530134 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530135 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 -0500136 dh.activePorts = sync.Map{}
cuilin20187b2a8c32019-03-26 19:52:28 -0700137 //TODO initialize the support classes.
138 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530139}
140
141// start save the device to the data model
142func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700143 dh.lockDevice.Lock()
144 defer dh.lockDevice.Unlock()
145 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
146 // Add the initial device to the local model
147 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530148}
149
150// stop stops the device dh. Not much to do for now
151func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 dh.lockDevice.Lock()
153 defer dh.lockDevice.Unlock()
154 log.Debug("stopping-device-agent")
155 dh.exitChannel <- 1
156 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530157}
158
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400159func macifyIP(ip net.IP) string {
160 if len(ip) > 0 {
161 oct1 := strconv.FormatInt(int64(ip[12]), 16)
162 oct2 := strconv.FormatInt(int64(ip[13]), 16)
163 oct3 := strconv.FormatInt(int64(ip[14]), 16)
164 oct4 := strconv.FormatInt(int64(ip[15]), 16)
165 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
166 }
167 return ""
168}
169
170func generateMacFromHost(host string) (string, error) {
171 var genmac string
172 var addr net.IP
173 var ips []string
174 var err error
175
176 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
177
178 if addr = net.ParseIP(host); addr == nil {
179 log.Debugw("looking-up-hostname", log.Fields{"host": host})
180
181 if ips, err = net.LookupHost(host); err == nil {
182 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
183 if addr = net.ParseIP(ips[0]); addr == nil {
184 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
185 return "", errors.New("unable-to-parse-ip")
186 }
187 genmac = macifyIP(addr)
188 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
189 return genmac, nil
190 }
191 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
192 return "", err
193 }
194
195 genmac = macifyIP(addr)
196 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
197 return genmac, nil
198}
199
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530200func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 slist := strings.Split(mac, ":")
202 result := make([]uint32, len(slist))
203 var err error
204 var tmp int64
205 for index, val := range slist {
206 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
207 return []uint32{1, 2, 3, 4, 5, 6}
208 }
209 result[index] = uint32(tmp)
210 }
211 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530212}
213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214//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 +0530215func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530216
Girish Gowdru0c588b22019-04-23 23:24:56 -0400217 if portType == voltha.Port_ETHERNET_NNI {
218 return fmt.Sprintf("nni-%d", portNum)
219 } else if portType == voltha.Port_PON_OLT {
220 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 } else if portType == voltha.Port_ETHERNET_UNI {
222 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400223 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700224 }
225 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
Esin Karamanccb714b2019-11-29 15:02:06 +0000229 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 if state == "up" {
231 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500232 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500233 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 } else {
235 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500236 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700238 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400239 label := GetportLabel(portNum, portType)
240 if len(label) == 0 {
241 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
242 return
243 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500244
245 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
246 if err != nil || device == nil {
247 log.Errorw("Failed-to-fetch-device", log.Fields{"err": err})
248 return
249 }
250 if device.Ports != nil {
251 for _, dPort := range device.Ports {
252 if dPort.Type == portType && dPort.PortNo == portNum {
253 log.Debug("port-already-exists-updating-oper-status-of-port")
254 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
255 log.Errorw("failed-to-update-port-state", log.Fields{"err": err})
256 return
257 }
258 return
259 }
260 }
261 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400262 // Now create Port
263 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 PortNo: portNum,
265 Label: label,
266 Type: portType,
267 OperStatus: operStatus,
268 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500269 log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700270 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500272 log.Errorw("Error-creating-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
273 return
Girish Gowdru1110ef22019-06-24 11:17:59 -0400274 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500275 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530276}
277
278// readIndications to read the indications from the OLT device
npujarec5762e2020-01-01 14:08:48 +0530279func (dh *DeviceHandler) readIndications(ctx context.Context) {
William Kurkianff524662019-08-20 10:34:30 -0400280 defer log.Errorw("Indications ended", log.Fields{})
npujarec5762e2020-01-01 14:08:48 +0530281 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700282 if err != nil {
283 log.Errorw("Failed to read indications", log.Fields{"err": err})
284 return
285 }
286 if indications == nil {
287 log.Errorw("Indications is nil", log.Fields{})
288 return
289 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400290 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530291 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400292 if err != nil || device == nil {
293 /*TODO: needs to handle error scenarios */
294 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700295 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400296 }
297 // When the device is in DISABLED and Adapter container restarts, we need to
298 // rebuild the locally maintained admin state.
299 if device.AdminState == voltha.AdminState_DISABLED {
300 dh.lockDevice.Lock()
301 dh.adminState = "down"
302 dh.lockDevice.Unlock()
303 }
304
David Bainbridgef5879ca2019-12-13 21:17:54 +0000305 // Create an exponential backoff around re-enabling indications. The
306 // maximum elapsed time for the back off is set to 0 so that we will
307 // continue to retry. The max interval defaults to 1m, but is set
308 // here for code clarity
309 indicationBackoff := backoff.NewExponentialBackOff()
310 indicationBackoff.MaxElapsedTime = 0
311 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700312 for {
313 indication, err := indications.Recv()
314 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530315 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000316 // Use an exponential back off to prevent getting into a tight loop
317 duration := indicationBackoff.NextBackOff()
318 if duration == backoff.Stop {
319 // If we reach a maximum then warn and reset the backoff
320 // timer and keep attempting.
321 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
322 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
323 indicationBackoff.Reset()
324 }
325 time.Sleep(indicationBackoff.NextBackOff())
npujarec5762e2020-01-01 14:08:48 +0530326 indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530327 if err != nil {
328 log.Errorw("Failed to read indications", log.Fields{"err": err})
329 return
330 }
331 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700332 }
333 if err != nil {
334 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400335 if dh.adminState == "deleted" {
336 log.Debug("Device deleted stoping the read indication thread")
337 break
338 }
npujarec5762e2020-01-01 14:08:48 +0530339 dh.transitionMap.Handle(ctx, DeviceDownInd)
340 dh.transitionMap.Handle(ctx, DeviceInit)
Girish Gowdrud4245152019-05-10 00:47:31 -0400341 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700342 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000343 // Reset backoff if we have a successful receive
344 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400345 dh.lockDevice.RLock()
346 adminState := dh.adminState
347 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400348 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400349 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530350
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +0530351 log.Infow("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400352 continue
353 }
npujarec5762e2020-01-01 14:08:48 +0530354 dh.handleIndication(ctx, indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530355
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700356 }
357}
358
npujarec5762e2020-01-01 14:08:48 +0530359func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000360 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000361 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530362 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700363 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530364 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700365 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000366 // Send or clear Alarm
367 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368}
369
npujarec5762e2020-01-01 14:08:48 +0530370func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400371 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372 switch indication.Data.(type) {
373 case *oop.Indication_OltInd:
npujarec5762e2020-01-01 14:08:48 +0530374 dh.handleOltIndication(ctx, indication.GetOltInd())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700375 case *oop.Indication_IntfInd:
376 intfInd := indication.GetIntfInd()
377 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
378 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
379 case *oop.Indication_IntfOperInd:
380 intfOperInd := indication.GetIntfOperInd()
381 if intfOperInd.GetType() == "nni" {
382 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
npujarec5762e2020-01-01 14:08:48 +0530383 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700384 } else if intfOperInd.GetType() == "pon" {
385 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
386 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000387 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
kesavand39e0aa32020-01-28 20:58:50 -0500388 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700389 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700390 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
391 case *oop.Indication_OnuDiscInd:
392 onuDiscInd := indication.GetOnuDiscInd()
393 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700394 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
npujarec5762e2020-01-01 14:08:48 +0530395 go dh.onuDiscIndication(ctx, onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700396 case *oop.Indication_OnuInd:
397 onuInd := indication.GetOnuInd()
398 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
399 go dh.onuIndication(onuInd)
400 case *oop.Indication_OmciInd:
401 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700402 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 -0400403 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700404 case *oop.Indication_PktInd:
405 pktInd := indication.GetPktInd()
406 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
npujarec5762e2020-01-01 14:08:48 +0530407 go dh.handlePacketIndication(ctx, pktInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700408 case *oop.Indication_PortStats:
409 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530410 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700411 case *oop.Indication_FlowStats:
412 flowStats := indication.GetFlowStats()
413 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
414 case *oop.Indication_AlarmInd:
415 alarmInd := indication.GetAlarmInd()
416 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530417 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700418 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530419}
420
421// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530422func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400423 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530424 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400425 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700426 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 -0400427 return err
428 }
429 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530430}
431
432// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530433func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700434 dh.lockDevice.Lock()
435 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400436 log.Debug("do-state-down-start")
437
npujarec5762e2020-01-01 14:08:48 +0530438 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400439 if err != nil || device == nil {
440 /*TODO: needs to handle error scenarios */
441 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700442 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400443 }
444
445 cloned := proto.Clone(device).(*voltha.Device)
446 // Update the all ports state on that device to disable
npujarec5762e2020-01-01 14:08:48 +0530447 if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700448 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
449 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400450 }
451
452 //Update the device oper state and connection status
453 cloned.OperStatus = voltha.OperStatus_UNKNOWN
454 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
455 dh.device = cloned
456
npujarec5762e2020-01-01 14:08:48 +0530457 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700458 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
459 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400460 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400461
462 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530463 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400464 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700465 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400466 return err
467 }
468 for _, onuDevice := range onuDevices.Items {
469
470 // Update onu state as down in onu adapter
471 onuInd := oop.OnuIndication{}
472 onuInd.OperState = "down"
npujarec5762e2020-01-01 14:08:48 +0530473 er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
475 if er != nil {
476 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
477 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700478 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400480 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700481 /* Discovered ONUs entries need to be cleared , since after OLT
482 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530483 dh.discOnus = sync.Map{}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700484 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700485 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530486}
487
488// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530489func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400490 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400491 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400492 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700493 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400494 return err
495 }
496 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530497}
498
499// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530500func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400501 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530502 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400503 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530504}
505
506// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530507func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400508 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400509
510 // Case where OLT is disabled and then rebooted.
511 if dh.adminState == "down" {
512 log.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530513 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400514 if err != nil || device == nil {
515 /*TODO: needs to handle error scenarios */
516 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
517 }
518
519 cloned := proto.Clone(device).(*voltha.Device)
520 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
521 cloned.OperStatus = voltha.OperStatus_UNKNOWN
522 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530523 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400525 }
526
Chaitrashree G S44124192019-08-07 20:21:36 -0400527 // 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 +0530528 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400529 if err != nil {
530 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
531 }
532
533 // Start reading indications
npujarec5762e2020-01-01 14:08:48 +0530534 go dh.readIndications(ctx)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400535 return nil
536 }
537
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400538 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700539 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400540 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700541 return err
542 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400543
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700544 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400545 if err != nil || device == nil {
546 /*TODO: needs to handle error scenarios */
547 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400549 }
kesavand39e0aa32020-01-28 20:58:50 -0500550 dh.populateActivePorts(device)
551 if err := dh.updatePortAdminState(device); err != nil {
552 log.Errorw("Error-on-updating-port-status", log.Fields{"device": device})
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
npujarec5762e2020-01-01 14:08:48 +0530558 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530563 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400564 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
npujarec5762e2020-01-01 14:08:48 +0530574 go dh.readIndications(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700575 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()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500645 for i := uint32(0); i < NumPonPORTS; i++ {
646 if val, ok := dh.activePorts.Load(i); ok && val == true {
647 cmpon := dh.portStats.collectPONMetrics(i)
648 log.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530649
Chaitrashree G Sef088112020-02-03 21:39:27 -0500650 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
651 log.Debugf("Publish-PON-Metrics")
652 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530653 }
654 }
655 }
656}
657
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530659func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400660 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530662 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530663
664 // Now, set the initial PM configuration for that device
665 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
666 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
667 }
668
669 go startCollector(dh)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530670 go startHeartbeatCheck(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530671}
672
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530674func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700675 return &ic.SwitchCapability{
676 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530677 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700678 HwDesc: "open_pon",
679 SwDesc: "open_pon",
680 SerialNum: dh.device.SerialNumber,
681 },
682 SwitchFeatures: &of.OfpSwitchFeatures{
683 NBuffers: 256,
684 NTables: 2,
685 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
686 of.OfpCapabilities_OFPC_TABLE_STATS |
687 of.OfpCapabilities_OFPC_PORT_STATS |
688 of.OfpCapabilities_OFPC_GROUP_STATS),
689 },
690 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530691}
692
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530694func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700696 return &ic.PortCapability{
697 Port: &voltha.LogicalPort{
698 OfpPort: &of.OfpPort{
699 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
700 Config: 0,
701 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 Curr: capacity,
703 Advertised: capacity,
704 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700705 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
706 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
707 },
708 DeviceId: dh.device.Id,
709 DevicePortNo: uint32(portNo),
710 },
711 }, nil
712}
713
William Kurkianff524662019-08-20 10:34:30 -0400714func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700715 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700716 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 var deviceID string
718 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700719
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700720 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530721
722 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
723
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
725 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700726 kwargs := make(map[string]interface{})
727 kwargs["onu_id"] = omciInd.OnuId
728 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700729
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
731 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400732 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
733 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700734 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 deviceType = onuDevice.Type
736 deviceID = onuDevice.Id
737 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
738 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530739 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700740 } else {
741 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530743 deviceType = onuInCache.(*OnuDevice).deviceType
744 deviceID = onuInCache.(*OnuDevice).deviceID
745 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700746 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700747
748 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
749 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
750 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400752 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
753 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700754 }
William Kurkianff524662019-08-20 10:34:30 -0400755 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530756}
757
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758//ProcessInterAdapterMessage sends the proxied messages to the target device
759// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
760// is meant, and then send the unmarshalled omci message to this onu
761func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
762 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700763 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700765 fromTopic := msg.Header.FromTopic
766 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 toDeviceID := msg.Header.ToDeviceId
768 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700769
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700771
772 msgBody := msg.GetBody()
773
774 omciMsg := &ic.InterAdapterOmciMessage{}
775 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
776 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
777 return err
778 }
779
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700780 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
782 if err != nil {
783 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700784 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700785 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700786 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
787 dh.sendProxiedMessage(onuDevice, omciMsg)
788
cuilin20187b2a8c32019-03-26 19:52:28 -0700789 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700790 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 -0700791 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700792 }
793
794 } else {
795 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
796 }
797 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530798}
799
cuilin20187b2a8c32019-03-26 19:52:28 -0700800func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 var intfID uint32
802 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000803 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700804 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805 intfID = onuDevice.ProxyAddress.GetChannelId()
806 onuID = onuDevice.ProxyAddress.GetOnuId()
807 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700808 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700809 intfID = omciMsg.GetProxyAddress().GetChannelId()
810 onuID = omciMsg.GetProxyAddress().GetOnuId()
811 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700812 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700813 if connectStatus != voltha.ConnectStatus_REACHABLE {
814 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700815 return
816 }
817
lcuie24ef182019-04-29 22:58:36 -0700818 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
819 isHexString := false
820 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
821 if decodeerr == nil {
822 isHexString = true
823 }
824
825 // 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.
826 var omciMessage *oop.OmciMsg
827 if isHexString {
828 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
829 } else {
830 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
831 hex.Encode(hexPkt, omciMsg.Message)
832 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
833 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700834
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700835 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
836 if err != nil {
837 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
838 return
839 }
lcuie24ef182019-04-29 22:58:36 -0700840 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700841}
842
npujarec5762e2020-01-01 14:08:48 +0530843func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530845 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700846 // TODO: need resource manager
847 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530849 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400850 st, _ := status.FromError(err)
851 if st.Code() == codes.AlreadyExists {
852 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
853 } else {
854 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
855 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700856 } else {
857 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
858 }
859}
860
npujarec5762e2020-01-01 14:08:48 +0530861func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800862
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700863 channelID := onuDiscInd.GetIntfId()
864 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400865
Matteo Scandolo945e4012019-12-12 14:16:11 -0800866 log.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530867
868 if _, ok := dh.discOnus.Load(sn); ok {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800869 log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400870 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700871 }
872
873 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 {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800877 log.Errorw("invalid-onu-serial-number", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400878 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400879 }
880
Matteo Scandolo945e4012019-12-12 14:16:11 -0800881 dh.discOnus.Store(sn, true)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400882 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -0800883
884 // check the ONU is already know to the OLT
885 // NOTE the second time the ONU is discovered this should return a device
886 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
887
888 if err != nil {
889 log.Errorw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
890 if e, ok := status.FromError(err); ok {
891 log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
892 switch e.Code() {
893 case codes.Internal:
894 // this probably means NOT FOUND, so just create a new device
895 onuDevice = nil
896 case codes.DeadlineExceeded:
897 // if the call times out, cleanup and exit
898 dh.discOnus.Delete(sn)
899 return
900 }
901 }
902 }
903
904 if onuDevice == nil {
905 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
906 log.Infow("creating-new-onu", log.Fields{"sn": sn})
907 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -0400908 ponintfid := onuDiscInd.GetIntfId()
909 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +0530910 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -0400911 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400912
Matteo Scandolo945e4012019-12-12 14:16:11 -0800913 log.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
914
915 if err != nil {
916 // if we can't create an ID in resource manager,
917 // cleanup and exit
918 log.Warnw("resource-manage-get-onu-id-failed", log.Fields{"pon-intf-id": ponintfid, "err": err, "sn": sn})
919 dh.discOnus.Delete(sn)
920 return
921 }
922
923 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
924 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
925 log.Warnw("core-proxy-child-device-detected-failed", log.Fields{"pon-intf-id": ponintfid, "err": err, "sn": sn})
926 dh.discOnus.Delete(sn)
927 dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
928 return
929 }
930
931 log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400932 }
Matteo Scandolo945e4012019-12-12 14:16:11 -0800933
934 // we can now use the existing ONU Id
935 onuID = onuDevice.ProxyAddress.OnuId
936
Mahir Gunyele77977b2019-06-27 05:36:22 -0700937 //Insert the ONU into cache to use in OnuIndication.
938 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Matteo Scandolo945e4012019-12-12 14:16:11 -0800939 log.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
940 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700941 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400942
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530943 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
944 dh.onus.Store(onuKey, onuDev)
Matteo Scandolo945e4012019-12-12 14:16:11 -0800945 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400946
npujarec5762e2020-01-01 14:08:48 +0530947 err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700948 if err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800949 log.Errorw("failed-to-update-device-state", log.Fields{"DeviceID": onuDevice.Id, "sn": sn, "err": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400950 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700951 }
Matteo Scandolo945e4012019-12-12 14:16:11 -0800952 log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700953 //TODO: We put this sleep here to prevent the race between state update and onuIndication
954 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
955 //then the initialisation fails.
956 time.Sleep(1 * time.Second)
npujarec5762e2020-01-01 14:08:48 +0530957 dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400958 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700959}
960
961func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
962 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
963
964 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700966 var onuDevice *voltha.Device
967 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700968 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
969 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700970 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530971
972 if onuInCache, ok := dh.onus.Load(onuKey); ok {
973
Mahir Gunyele77977b2019-06-27 05:36:22 -0700974 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
975 foundInCache = true
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530976 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700977 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700978 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
979 if serialNumber != "" {
980 kwargs["serial_number"] = serialNumber
981 } else {
982 kwargs["onu_id"] = onuInd.OnuId
983 kwargs["parent_port_no"] = ponPort
984 }
985 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700986 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700987
988 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400989 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700990 //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 -0400991 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700992 }
993
994 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
995 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})
996 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700997 if !foundInCache {
998 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530999
1000 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
1001
Mahir Gunyele77977b2019-06-27 05:36:22 -07001002 }
Scott Baker7eb0a932019-07-26 10:33:22 -07001003 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -07001004
cuilin20187b2a8c32019-03-26 19:52:28 -07001005 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001006 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -07001007 return
1008 }
1009
1010}
1011
Scott Baker7eb0a932019-07-26 10:33:22 -07001012func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
npujarec5762e2020-01-01 14:08:48 +05301013 ctx := context.TODO()
Matt Jeanneret53539512019-07-20 14:47:02 -04001014 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 -07001015 dh.updateOnuAdminState(onuInd)
1016 // operState
1017 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -04001018 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 -07001019 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301020 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1022 if err != nil {
1023 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
1024 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
1025 }
1026 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -07001027 // Ignore operstatus if device was found in cache
1028 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -04001029 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 -07001030 return
1031 }
Matt Jeanneret53539512019-07-20 14:47:02 -04001032 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
1033 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301034 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1036 if err != nil {
1037 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +05301038 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 return
1040 }
1041 } else {
1042 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
1043 }
1044}
1045
1046func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
1047 if onuInd.AdminState == "down" {
1048 if onuInd.OperState != "down" {
1049 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
1050 // Forcing the oper state change code to execute
1051 onuInd.OperState = "down"
1052 }
1053 // Port and logical port update is taken care of by oper state block
1054 } else if onuInd.AdminState == "up" {
1055 log.Debugln("received-onu-admin-state up")
1056 } else {
1057 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
1058 }
1059 log.Debugln("admin-state-dealt-with")
1060}
1061
cuilin20187b2a8c32019-03-26 19:52:28 -07001062func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1063 if serialNum != nil {
1064 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001065 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001066 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001067}
1068
1069func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1070 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001072 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1073 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1074 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1075 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1076 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1077 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1078 return tmp
1079}
1080
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081//UpdateFlowsBulk upates the bulk flow
1082func (dh *DeviceHandler) UpdateFlowsBulk() error {
1083 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -07001084}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085
1086//GetChildDevice returns the child device for given parent port and onu id
1087func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
1088 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001089 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001091 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001093 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001094 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001095 return nil
1096 }
1097 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1098 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301099}
1100
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101// SendPacketInToCore sends packet-in to core
1102// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1103// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001104func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001105 log.Debugw("send-packet-in-to-core", log.Fields{
1106 "port": logicalPort,
1107 "packet": hex.EncodeToString(packetPayload),
1108 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001109 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001110 log.Errorw("Error sending packetin to core", log.Fields{
1111 "error": err,
1112 "packet": hex.EncodeToString(packetPayload),
1113 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001114 return
1115 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001116 log.Debugw("Sent packet-in to core successfully", log.Fields{
1117 "packet": hex.EncodeToString(packetPayload),
1118 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001119}
1120
A R Karthick1f85b802019-10-11 05:06:05 +00001121// AddUniPortToOnu adds the uni port to the onu device
1122func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1123 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301124
1125 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001126 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301127 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1128 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001129 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1130 }
1131 }
1132}
1133
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001134//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301135func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001136 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 -04001137 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001138 for _, flow := range flows.ToRemove.Items {
1139 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
npujarec5762e2020-01-01 14:08:48 +05301140 dh.flowMgr.RemoveFlow(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001141 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301142
1143 for _, flow := range flows.ToAdd.Items {
1144 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
npujarec5762e2020-01-01 14:08:48 +05301145 dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301146 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001147 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001148 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001149 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001151 // dh.flowMgr.RemoveFlow(flow)
1152 }
1153 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001154
1155 if groups != nil {
1156 for _, group := range groups.ToAdd.Items {
npujarec5762e2020-01-01 14:08:48 +05301157 dh.flowMgr.AddGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001158 }
1159 for _, group := range groups.ToUpdate.Items {
npujarec5762e2020-01-01 14:08:48 +05301160 dh.flowMgr.ModifyGroup(ctx, group)
Esin Karamanccb714b2019-11-29 15:02:06 +00001161 }
1162 if len(groups.ToRemove.Items) != 0 {
1163 log.Debug("Group delete operation is not supported for now")
1164 }
1165 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001166 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001167 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301168}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001169
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001170//DisableDevice disables the given device
1171//It marks the following for the given device:
1172//Device-Handler Admin-State : down
1173//Device Port-State: UNKNOWN
1174//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001175func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001176 /* On device disable ,admin state update has to be done prior sending request to agent since
1177 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001178 dh.lockDevice.Lock()
1179 dh.adminState = "down"
1180 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001181 if dh.Client != nil {
1182 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1183 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1184 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1185 dh.lockDevice.Lock()
1186 dh.adminState = "up"
1187 dh.lockDevice.Unlock()
1188 return err
1189 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001190 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001191 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001192 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001193 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001194 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301195
1196 dh.discOnus = sync.Map{}
1197 dh.onus = sync.Map{}
1198
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301199 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001200 cloned := proto.Clone(device).(*voltha.Device)
1201 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1203 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001204 return err
1205 }
1206
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001207 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001208 return nil
1209}
1210
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301211func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001212
1213 // Update onu state as unreachable in onu adapter
1214 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301215 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001216 //get the child device for the parent device
1217 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1218 if err != nil {
1219 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1220 }
1221 if onuDevices != nil {
1222 for _, onuDevice := range onuDevices.Items {
1223 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1224 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1225 if err != nil {
1226 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1227 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1228 }
1229
1230 }
1231 }
1232
1233}
1234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235//ReenableDevice re-enables the olt device after disable
1236//It marks the following for the given device:
1237//Device-Handler Admin-State : up
1238//Device Port-State: ACTIVE
1239//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001240func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001241 dh.lockDevice.Lock()
1242 dh.adminState = "up"
1243 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301244
1245 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1246 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1247 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1248 dh.lockDevice.Lock()
1249 dh.adminState = "down"
1250 dh.lockDevice.Unlock()
1251 return err
1252 }
1253 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001254 log.Debug("olt-reenabled")
1255
1256 cloned := proto.Clone(device).(*voltha.Device)
1257 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001258
1259 if err := dh.updatePortAdminState(device); err != nil {
1260 log.Errorw("Error-on-updating-port-status-after-reenabling-olt", log.Fields{"device": device})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001261 return err
1262 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001263 //Update the device oper status as ACTIVE
1264 cloned.OperStatus = voltha.OperStatus_ACTIVE
1265 dh.device = cloned
1266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1268 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001269 return err
1270 }
kesavand39e0aa32020-01-28 20:58:50 -05001271
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001272 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001273
1274 return nil
1275}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001276
npujarec5762e2020-01-01 14:08:48 +05301277func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001278 var uniID uint32
1279 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301280 for _, port := range onu.UniPorts {
1281 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001282 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1283 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301284 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301285 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001286 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301287 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301288 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001289 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301290 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001291 }
npujarec5762e2020-01-01 14:08:48 +05301292 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001293 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301294 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301295 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001296 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301297 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301298 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301299 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001300 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301301 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1302 }
npujarec5762e2020-01-01 14:08:48 +05301303 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1304 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301305 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1306 }
1307 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301308 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301309 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 +00001310 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001311 }
1312 return nil
1313}
1314
npujarec5762e2020-01-01 14:08:48 +05301315func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001316 nniUniID := -1
1317 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301318
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001319 if dh.resourceMgr == nil {
1320 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1321 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001322 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301323 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301324 if err != nil {
1325 log.Error("Failed to fetch nni from kv store")
1326 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001327 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301328 log.Debugw("NNI are ", log.Fields{"nni": nni})
1329 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301330 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301331 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1332 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301333 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301334 }
npujarec5762e2020-01-01 14:08:48 +05301335 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001336 }
npujarec5762e2020-01-01 14:08:48 +05301337 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301338 log.Error("Failed to clear nni from kv store")
1339 return err
1340 }
1341 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001342}
1343
1344// 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 +05301345func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001346 log.Debug("Function entry delete device")
1347 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001348 if dh.adminState == "deleted" {
1349 dh.lockDevice.Unlock()
1350 return nil
1351 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001352 dh.adminState = "deleted"
1353 dh.lockDevice.Unlock()
1354 /* Clear the KV store data associated with the all the UNI ports
1355 This clears up flow data and also resource map data for various
1356 other pon resources like alloc_id and gemport_id
1357 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001358 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301359 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1360 var ponPort uint32
1361 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1362 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301363 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301364 if err != nil {
1365 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1366 return err
1367 }
1368 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301369 onuID := make([]uint32, 1)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301370 log.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301371 if err = dh.clearUNIData(ctx, &onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301372 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1373 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301374 // Clear flowids for gem cache.
1375 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301376 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301377 }
1378 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301379 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301380 }
npujarec5762e2020-01-01 14:08:48 +05301381 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301382 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301383 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301384 if err != nil {
1385 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001386 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001387 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001388 /* Clear the flows from KV store associated with NNI port.
1389 There are mostly trap rules from NNI port (like LLDP)
1390 */
npujarec5762e2020-01-01 14:08:48 +05301391 if err := dh.clearNNIData(ctx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301392 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001393 }
A R Karthick1f85b802019-10-11 05:06:05 +00001394
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001395 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301396 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001397 }
A R Karthick1f85b802019-10-11 05:06:05 +00001398
Devmalya Paul495b94a2019-08-27 19:42:00 -04001399 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301400 dh.onus.Range(func(key interface{}, value interface{}) bool {
1401 dh.onus.Delete(key)
1402 return true
1403 })
1404
Devmalya Paul495b94a2019-08-27 19:42:00 -04001405 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301406 // Stop the Stats collector
1407 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301408 // stop the heartbeat check routine
1409 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001410 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001411 if dh.Client != nil {
npujarec5762e2020-01-01 14:08:48 +05301412 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001413 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1414 return err
1415 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001416 }
1417 cloned := proto.Clone(device).(*voltha.Device)
1418 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1419 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
npujarec5762e2020-01-01 14:08:48 +05301420 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001421 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1422 return err
1423 }
1424 return nil
1425}
1426
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001428func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1429 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001430 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001431 return err
1432 }
1433
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001435
1436 return nil
1437}
1438
npujarec5762e2020-01-01 14:08:48 +05301439func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001440 log.Debugw("Received packet-in", log.Fields{
1441 "packet-indication": *packetIn,
1442 "packet": hex.EncodeToString(packetIn.Pkt),
1443 })
npujarec5762e2020-01-01 14:08:48 +05301444 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001445 if err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001446 log.Errorw("Error getting logical port from packet-in", log.Fields{
1447 "error": err,
1448 "packet": hex.EncodeToString(packetIn.Pkt),
1449 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001450 return
1451 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001452 log.Debugw("sending packet-in to core", log.Fields{
1453 "logicalPortNum": logicalPortNum,
1454 "packet": hex.EncodeToString(packetIn.Pkt),
1455 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001457 log.Errorw("Error sending packet-in to core", log.Fields{
1458 "error": err,
1459 "packet": hex.EncodeToString(packetIn.Pkt),
1460 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001461 return
1462 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001463 log.Debugw("Success sending packet-in to core!", log.Fields{
1464 "packet": hex.EncodeToString(packetIn.Pkt),
1465 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001466}
1467
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001468// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301469func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001470 log.Debugw("incoming-packet-out", log.Fields{
1471 "deviceID": dh.deviceID,
1472 "egress_port_no": egressPortNo,
1473 "pkt-length": len(packet.Data),
1474 "packet": hex.EncodeToString(packet.Data),
1475 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001476
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001477 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001478 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001479 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1480 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301481 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1482 // Do not packet-out lldp packets on uni port.
1483 // ONOS has no clue about uni/nni ports, it just packets out on all
1484 // available ports on the Logical Switch. It should not be interested
1485 // in the UNI links.
1486 log.Debug("dropping-lldp-packet-out-on-uni")
1487 return nil
1488 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001489 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1490 if innerEthType == 0x8100 {
1491 // q-in-q 802.1ad or 802.1q double tagged packet.
1492 // slice out the outer tag.
1493 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1494 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001495 }
1496 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1498 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001499 uniID := UniIDFromPortNum(uint32(egressPortNo))
1500
npujarec5762e2020-01-01 14:08:48 +05301501 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001502 if err != nil {
1503 // In this case the openolt agent will receive the gemPortID as 0.
1504 // The agent tries to retrieve the gemPortID in this case.
1505 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001506 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1507 "packet": hex.EncodeToString(packet.Data),
1508 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001509 }
1510
1511 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001512
Matteo Scandolo6056e822019-11-13 14:05:29 -08001513 log.Debugw("sending-packet-to-onu", log.Fields{
1514 "egress_port_no": egressPortNo,
1515 "IntfId": intfID,
1516 "onuID": onuID,
1517 "uniID": uniID,
1518 "gemPortID": gemPortID,
1519 "packet": hex.EncodeToString(packet.Data),
1520 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001521
npujarec5762e2020-01-01 14:08:48 +05301522 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001523 log.Errorw("Error while sending packet-out to ONU", log.Fields{
1524 "error": err,
1525 "packet": hex.EncodeToString(packet.Data),
1526 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001527 return err
1528 }
1529 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001530 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001531
Matteo Scandolo6056e822019-11-13 14:05:29 -08001532 log.Debugw("sending-packet-to-nni", log.Fields{
1533 "uplink_pkt": uplinkPkt,
1534 "packet": hex.EncodeToString(packet.Data),
1535 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001536
npujarec5762e2020-01-01 14:08:48 +05301537 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001538 log.Errorw("Error while sending packet-out to NNI", log.Fields{
1539 "error": err,
1540 "packet": hex.EncodeToString(packet.Data),
1541 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001542 return err
1543 }
1544 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001545 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1546 "egress_port_no": egressPortNo,
1547 "egressPortType": egressPortType,
1548 "packet": hex.EncodeToString(packet.Data),
1549 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001550 }
1551 return nil
1552}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001553
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001554func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1555 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001556}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301557
1558func startHeartbeatCheck(dh *DeviceHandler) {
1559 // start the heartbeat check towards the OLT.
1560 var timerCheck *time.Timer
1561
1562 for {
1563 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1564 select {
1565 case <-heartbeatTimer.C:
1566 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1567 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1568 log.Error("Hearbeat failed")
1569 if timerCheck == nil {
1570 // start a after func, when expired will update the state to the core
1571 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1572 }
1573 } else {
1574 if timerCheck != nil {
1575 if timerCheck.Stop() {
1576 log.Debug("We got hearbeat within the timeout")
1577 } else {
1578
1579 log.Debug("We got hearbeat after the timeout expired, changing the states")
1580 go dh.notifyChildDevices("up")
npujarec5762e2020-01-01 14:08:48 +05301581 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301582 voltha.OperStatus_ACTIVE); err != nil {
1583 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1584 }
1585 }
1586 timerCheck = nil
1587 }
1588 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1589 }
1590 cancel()
1591 case <-dh.stopHeartbeatCheck:
1592 log.Debug("Stopping heart beat check")
1593 return
1594 }
1595 }
1596}
1597
1598func (dh *DeviceHandler) updateStateUnreachable() {
1599
1600 go dh.notifyChildDevices("unreachable")
1601 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1602 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": err})
1603 return
1604 }
1605}
kesavand39e0aa32020-01-28 20:58:50 -05001606
1607// EnablePort to enable Pon interface
1608func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
1609 log.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
1610 return dh.invokeDisableorEnablePort(port, true)
1611}
1612
1613// DisablePort to disable pon interface
1614func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
1615 log.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
1616 return dh.invokeDisableorEnablePort(port, false)
1617}
1618
1619func (dh *DeviceHandler) invokeDisableorEnablePort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301620 ctx := context.Background()
kesavand39e0aa32020-01-28 20:58:50 -05001621 log.Infow("invokeDisableorEnablePort", log.Fields{"port": port, "Enable": enablePort})
1622 if port.GetType() == voltha.Port_ETHERNET_NNI {
1623 // Bug is opened for VOL-2505 to support NNI disable feature.
1624 log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
1625 log.Fields{"Device": dh.device, "port": port})
1626 return fmt.Errorf("received-disable-enable-nni-port-request, received-port %s", port.GetType())
1627 }
1628 // fetch interfaceid from PortNo
1629 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1630 ponIntf := &oop.Interface{IntfId: ponID}
1631 var operStatus voltha.OperStatus_Types
1632 if enablePort {
1633 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301634 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001635
1636 if err != nil {
1637 log.Errorw("error-while-enable-Pon-port", log.Fields{"DeviceID": dh.device, "Port": port, "error": err})
1638 return err
1639 }
1640 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001641 dh.activePorts.Store(ponID, true)
kesavand39e0aa32020-01-28 20:58:50 -05001642 log.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1643 } else {
1644 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301645 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001646 if err != nil {
1647 log.Errorw("error-while-disabling-interface", log.Fields{"DeviceID": dh.device, "Port": port})
1648 return err
1649 }
1650 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001651 dh.activePorts.Store(ponID, false)
kesavand39e0aa32020-01-28 20:58:50 -05001652 log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
1653 }
npujarec5762e2020-01-01 14:08:48 +05301654 if errs := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); errs != nil {
kesavand39e0aa32020-01-28 20:58:50 -05001655 log.Errorw("portstate-update-failed", log.Fields{"Device": dh.deviceID, "port": port.PortNo, "error": errs})
1656 return errs
1657 }
1658 return nil
1659}
1660
1661//updatePortAdminState update the ports on reboot and re-enable device.
1662func (dh *DeviceHandler) updatePortAdminState(device *voltha.Device) error {
1663 cloned := proto.Clone(device).(*voltha.Device)
1664 // Disable the port and update the oper_port_status to core
1665 // if the Admin state of the port is disabled on reboot and re-enable device.
1666 for _, port := range cloned.Ports {
1667 if port.AdminState == common.AdminState_DISABLED {
1668 if err := dh.invokeDisableorEnablePort(port, false); err != nil {
1669 log.Errorw("error-occurred-while-disabling-port", log.Fields{"DeviceId": dh.deviceID, "port": port, "error": err})
1670 return err
1671 }
1672 }
1673 }
1674 return nil
1675}
1676
1677//populateActivePorts to populate activePorts map
1678func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
1679 log.Info("populateActiveports", log.Fields{"Device": device})
1680 for _, port := range device.Ports {
1681 if port.Type == voltha.Port_ETHERNET_NNI {
1682 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001683 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001684 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001685 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001686 }
1687 }
1688 if port.Type == voltha.Port_PON_OLT {
1689 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001690 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001691 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001692 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001693 }
1694 }
1695 }
1696}